dovecot-2.2: imap-hibernate: Use sockets' st_dev and st_ino to v...

dovecot at dovecot.org dovecot at dovecot.org
Mon Aug 31 20:48:03 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/55cab04ef2af
changeset: 19052:55cab04ef2af
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Aug 31 23:46:05 2015 +0300
description:
imap-hibernate: Use sockets' st_dev and st_ino to verify that the passed fd is correct.

diffstat:

 src/imap-hibernate/imap-client.c           |  16 ++++-----
 src/imap-hibernate/imap-client.h           |   4 +-
 src/imap-hibernate/imap-hibernate-client.c |  21 ++++++++---
 src/imap/imap-client-hibernate.c           |  13 ++++---
 src/imap/imap-master-client.c              |  51 ++++++++++++++++++-----------
 5 files changed, 62 insertions(+), 43 deletions(-)

diffs (235 lines):

diff -r 9dd0f155731c -r 55cab04ef2af src/imap-hibernate/imap-client.c
--- a/src/imap-hibernate/imap-client.c	Mon Aug 31 23:25:12 2015 +0300
+++ b/src/imap-hibernate/imap-client.c	Mon Aug 31 23:46:05 2015 +0300
@@ -117,10 +117,12 @@
 		str_append(str, "\tuserdb_fields=");
 		str_append_tabescaped(str, state->userdb_fields);
 	}
-	if (state->peer_ip.family != 0)
-		str_printfa(str, "\tpeer_ip=%s", net_ip2addr(&state->peer_ip));
-	if (state->peer_port != 0)
-		str_printfa(str, "\tpeer_port=%u", state->peer_port);
+	if (major(state->peer_dev) != 0 || minor(state->peer_dev) != 0) {
+		str_printfa(str, "\tpeer_dev_major=%u\tpeer_dev_minor=%u",
+			    major(state->peer_dev), minor(state->peer_dev));
+	}
+	if (state->peer_ino != 0)
+		str_printfa(str, "\tpeer_ino=%llu", (unsigned long long)state->peer_ino);
 	if (state->state_size > 0) {
 		str_append(str, "\tstate=");
 		base64_encode(state->state, state->state_size, str);
@@ -411,15 +413,11 @@
 	client->fd = fd;
 	client->input = i_stream_create_fd(fd, IMAP_MAX_INBUF, FALSE);
 
+	client->state = *state;
 	client->state.username = p_strdup(pool, state->username);
 	client->state.session_id = p_strdup(pool, state->session_id);
 	client->state.userdb_fields = p_strdup(pool, state->userdb_fields);
 	client->state.stats = p_strdup(pool, state->stats);
-	client->state.local_ip = state->local_ip;
-	client->state.remote_ip = state->remote_ip;
-	client->state.imap_idle_notify_interval =
-		state->imap_idle_notify_interval;
-	client->state.idle_cmd = state->idle_cmd;
 
 	if (state->state_size > 0) {
 		client->state.state = statebuf = p_malloc(pool, state->state_size);
diff -r 9dd0f155731c -r 55cab04ef2af src/imap-hibernate/imap-client.h
--- a/src/imap-hibernate/imap-client.h	Mon Aug 31 23:25:12 2015 +0300
+++ b/src/imap-hibernate/imap-client.h	Mon Aug 31 23:46:05 2015 +0300
@@ -13,8 +13,8 @@
 	uid_t uid;
 	gid_t gid;
 
-	struct ip_addr peer_ip;
-	in_port_t peer_port;
+	dev_t peer_dev;
+	ino_t peer_ino;
 
 	const unsigned char *state;
 	size_t state_size;
diff -r 9dd0f155731c -r 55cab04ef2af src/imap-hibernate/imap-hibernate-client.c
--- a/src/imap-hibernate/imap-hibernate-client.c	Mon Aug 31 23:25:12 2015 +0300
+++ b/src/imap-hibernate/imap-hibernate-client.c	Mon Aug 31 23:46:05 2015 +0300
@@ -44,6 +44,7 @@
 				  const char **error_r)
 {
 	const char *key, *value;
+	unsigned int peer_dev_major = 0, peer_dev_minor = 0;
 
 	memset(state_r, 0, sizeof(*state_r));
 	if (args[0] == NULL) {
@@ -77,16 +78,22 @@
 					"Invalid rip value: %s", value);
 				return -1;
 			}
-		} else if (strcmp(key, "peer_ip") == 0) {
-			if (net_addr2ip(value, &state_r->peer_ip) < 0) {
+		} else if (strcmp(key, "peer_dev_major") == 0) {
+			if (str_to_uint(value, &peer_dev_major) < 0) {
 				*error_r = t_strdup_printf(
-					"Invalid peer_ip value: %s", value);
+					"Invalid peer_dev_major value: %s", value);
 				return -1;
 			}
-		} else if (strcmp(key, "peer_port") == 0) {
-			if (net_str2port(value, &state_r->peer_port) < 0) {
+		} else if (strcmp(key, "peer_dev_minor") == 0) {
+			if (str_to_uint(value, &peer_dev_minor) < 0) {
 				*error_r = t_strdup_printf(
-					"Invalid peer_port value: %s", value);
+					"Invalid peer_dev_minor value: %s", value);
+				return -1;
+			}
+		} else if (strcmp(key, "peer_ino") == 0) {
+			if (str_to_ino(value, &state_r->peer_ino) < 0) {
+				*error_r = t_strdup_printf(
+					"Invalid peer_ino value: %s", value);
 				return -1;
 			}
 		} else if (strcmp(key, "uid") == 0) {
@@ -131,6 +138,8 @@
 			state_r->state_size = state_buf->used;
 		}
 	}
+	if (peer_dev_major != 0 || peer_dev_minor != 0)
+		state_r->peer_dev = makedev(peer_dev_major, peer_dev_minor);
 	return 0;
 }
 
diff -r 9dd0f155731c -r 55cab04ef2af src/imap/imap-client-hibernate.c
--- a/src/imap/imap-client-hibernate.c	Mon Aug 31 23:25:12 2015 +0300
+++ b/src/imap/imap-client-hibernate.c	Mon Aug 31 23:46:05 2015 +0300
@@ -13,6 +13,8 @@
 #include "imap-state.h"
 #include "imap-client.h"
 
+#include <sys/stat.h>
+
 #define IMAP_HIBERNATE_SOCKET_NAME "imap-hibernate"
 #define IMAP_HIBERNATE_SEND_TIMEOUT_SECS 10
 #define IMAP_HIBERNATE_HANDSHAKE "VERSION\timap-hibernate\t1\t0\n"
@@ -41,18 +43,17 @@
 static void imap_hibernate_write_cmd(struct client *client, string_t *cmd,
 				     const buffer_t *state, int fd_notify)
 {
-	struct ip_addr peer_ip;
-	in_port_t peer_port;
+	struct stat peer_st;
 
 	str_append_tabescaped(cmd, client->user->username);
 	str_append_c(cmd, '\t');
 	str_append_tabescaped(cmd, client->user->set->mail_log_prefix);
 	str_printfa(cmd, "\tidle_notify_interval=%u",
 		    client->set->imap_idle_notify_interval);
-	if (net_getpeername(client->fd_in, &peer_ip, &peer_port) == 0 &&
-	    peer_port != 0) {
-		str_printfa(cmd, "\tpeer_ip=%s\tpeer_port=%u",
-			    net_ip2addr(&peer_ip), peer_port);
+	if (fstat(client->fd_in, &peer_st) == 0) {
+		str_printfa(cmd, "\tpeer_dev_major=%u\tpeer_dev_minor=%u\tpeer_ino=%llu",
+			    major(peer_st.st_dev), minor(peer_st.st_dev),
+			    (unsigned long long)peer_st.st_ino);
 	}
 
 	if (client->session_id != NULL) {
diff -r 9dd0f155731c -r 55cab04ef2af src/imap/imap-master-client.c
--- a/src/imap/imap-master-client.c	Mon Aug 31 23:25:12 2015 +0300
+++ b/src/imap/imap-master-client.c	Mon Aug 31 23:46:05 2015 +0300
@@ -27,8 +27,8 @@
 	/* IMAP connection state */
 	buffer_t *state;
 
-	struct ip_addr peer_ip;
-	in_port_t peer_port;
+	dev_t peer_dev;
+	ino_t peer_ino;
 
 	bool state_import_bad_idle_done;
 	bool state_import_idle_continue;
@@ -53,6 +53,7 @@
 			       const char **error_r)
 {
 	const char *key, *value;
+	unsigned int peer_dev_major = 0, peer_dev_minor = 0;
 
 	memset(input_r, 0, sizeof(*input_r));
 	memset(master_input_r, 0, sizeof(*master_input_r));
@@ -91,16 +92,22 @@
 					"Invalid rip value: %s", value);
 				return -1;
 			}
-		} else if (strcmp(key, "peer_ip") == 0) {
-			if (net_addr2ip(value, &master_input_r->peer_ip) < 0) {
+		} else if (strcmp(key, "peer_dev_major") == 0) {
+			if (str_to_uint(value, &peer_dev_major) < 0) {
 				*error_r = t_strdup_printf(
-					"Invalid peer_ip value: %s", value);
+					"Invalid peer_dev_major value: %s", value);
 				return -1;
 			}
-		} else if (strcmp(key, "peer_port") == 0) {
-			if (net_str2port(value, &master_input_r->peer_port) < 0) {
+		} else if (strcmp(key, "peer_dev_minor") == 0) {
+			if (str_to_uint(value, &peer_dev_minor) < 0) {
 				*error_r = t_strdup_printf(
-					"Invalid peer_port value: %s", value);
+					"Invalid peer_dev_minor value: %s", value);
+				return -1;
+			}
+		} else if (strcmp(key, "peer_ino") == 0) {
+			if (str_to_ino(value, &master_input_r->peer_ino) < 0) {
+				*error_r = t_strdup_printf(
+					"Invalid peer_ino value: %s", value);
 				return -1;
 			}
 		} else if (strcmp(key, "session") == 0) {
@@ -135,31 +142,35 @@
 			master_input_r->state_import_idle_continue = TRUE;
 		}
 	}
+	if (peer_dev_major != 0 || peer_dev_minor != 0) {
+		master_input_r->peer_dev =
+			makedev(peer_dev_major, peer_dev_minor);
+	}
 	return 0;
 }
 
 static int imap_master_client_verify(const struct imap_master_input *master_input,
 				     int fd_client, const char **error_r)
 {
-	struct ip_addr peer_ip;
-	in_port_t peer_port;
+	struct stat peer_st;
 
-	if (master_input->peer_port == 0)
+	if (master_input->peer_ino == 0)
 		return 0;
 
 	/* make sure we have the right fd */
-	if (net_getpeername(fd_client, &peer_ip, &peer_port) < 0) {
-		*error_r = t_strdup_printf("net_getpeername() failed: %m");
+	if (fstat(fd_client, &peer_st) < 0) {
+		*error_r = t_strdup_printf("fstat(peer) failed: %m");
 		return -1;
 	}
-	if (!net_ip_compare(&peer_ip, &master_input->peer_ip) ||
-	    peer_port != master_input->peer_port) {
+	if (peer_st.st_ino != master_input->peer_ino ||
+	    !CMP_DEV_T(peer_st.st_dev, master_input->peer_dev)) {
 		*error_r = t_strdup_printf(
-			"BUG: Expected peer_ip=%s peer_port=%u doesn't match "
-			"client fd's actual ip=%s port=%u",
-			net_ip2addr(&master_input->peer_ip),
-			master_input->peer_port,
-			net_ip2addr(&peer_ip), peer_port);
+			"BUG: Expected peer device=%u,%u inode=%s doesn't match "
+			"client fd's actual device=%u,%u inode=%s",
+			major(peer_st.st_dev), minor(peer_st.st_dev), dec2str(peer_st.st_ino),
+			major(master_input->peer_dev),
+			minor(master_input->peer_dev),
+			dec2str(master_input->peer_ino));
 		return -1;
 	}
 	return 0;


More information about the dovecot-cvs mailing list