changeset 4649:a3d6a3462745 HEAD

Send inode number in login requests and verify that they match.
author Timo Sirainen <tss@iki.fi>
date Wed, 11 Oct 2006 15:17:27 +0300
parents 93a6d2194c5d
children 4ff5080c5325
files src/login-common/master.c src/master/login-process.c src/master/master-login-interface.h
diffstat 3 files changed, 79 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/login-common/master.c	Wed Oct 11 13:33:20 2006 +0300
+++ b/src/login-common/master.c	Wed Oct 11 15:17:27 2006 +0300
@@ -50,6 +50,7 @@
 			  unsigned int auth_pid, unsigned int auth_id)
 {
 	struct master_login_request req;
+	struct stat st;
 
 	i_assert(auth_pid != 0);
 
@@ -63,6 +64,10 @@
 	req.local_ip = client->local_ip;
 	req.remote_ip = client->ip;
 
+	if (fstat(client->fd, &st) < 0)
+		i_fatal("fstat(client) failed: %m");
+	req.ino = st.st_ino;
+
 	if (fd_send(master_fd, client->fd, &req, sizeof(req)) != sizeof(req))
 		i_fatal("fd_send(%d) failed: %m", client->fd);
 
@@ -90,6 +95,7 @@
 	memset(&req, 0, sizeof(req));
 	req.version = MASTER_LOGIN_PROTOCOL_VERSION;
 	req.tag = state;
+	req.ino = (ino_t)-1;
 
 	/* sending -1 as fd does the notification */
 	if (fd_send(master_fd, -1, &req, sizeof(req)) != sizeof(req))
--- a/src/master/login-process.c	Wed Oct 11 13:33:20 2006 +0300
+++ b/src/master/login-process.c	Wed Oct 11 15:17:27 2006 +0300
@@ -18,6 +18,7 @@
 
 #include <unistd.h>
 #include <syslog.h>
+#include <sys/stat.h>
 
 struct login_process {
 	struct login_group *group;
@@ -283,6 +284,65 @@
 	return FALSE;
 }
 
+static int
+login_read_request(struct login_process *p, struct master_login_request *req,
+		   int *client_fd_r)
+{
+	struct stat st;
+	ssize_t ret;
+
+	*client_fd_r = -1;
+
+	ret = fd_read(p->fd, req, sizeof(*req), client_fd_r);
+	if (ret >= (ssize_t)sizeof(req->version) &&
+	    req->version != MASTER_LOGIN_PROTOCOL_VERSION) {
+		i_error("login: Protocol version mismatch "
+			"(mixed old and new binaries?)");
+		return -1;
+	}
+
+	if (ret != sizeof(*req)) {
+		if (ret == 0) {
+			/* disconnected, ie. the login process died */
+		} else if (ret > 0) {
+			/* request wasn't fully read */
+			i_error("login: fd_read() returned partial %d", ret);
+		} else {
+			if (errno == EAGAIN)
+				return 0;
+
+			i_error("login: fd_read() failed: %m");
+		}
+		return -1;
+	}
+
+	if (req->ino == (ino_t)-1) {
+		if (*client_fd_r != -1) {
+			i_error("login: Notification request sent "
+				"a file descriptor");
+			return -1;
+		}
+		return 1;
+	}
+
+	if (*client_fd_r == -1) {
+		i_error("login: Login request missing a file descriptor");
+		return -1;
+	}
+
+	if (fstat(*client_fd_r, &st) < 0) {
+		i_error("login: fstat(mail client) failed: %m");
+		return -1;
+	}
+
+	if (st.st_ino != req->ino) {
+		i_error("login: Login request inode mismatch: %s != %s",
+			dec2str(st.st_ino), dec2str(req->ino));
+		return -1;
+	}
+	return 1;
+}
+
 static void login_process_input(void *context)
 {
 	struct login_process *p = context;
@@ -299,39 +359,20 @@
 		return;
 	}
 
-	ret = fd_read(p->fd, &req, sizeof(req), &client_fd);
-	if (ret >= (ssize_t)sizeof(req.version) &&
-	    req.version != MASTER_LOGIN_PROTOCOL_VERSION) {
-		i_error("login: Protocol version mismatch "
-			"(mixed old and new binaries?)");
+	ret = login_read_request(p, &req, &client_fd);
+	if (ret == 0)
+		return;
+	if (ret < 0) {
+		if (client_fd != -1) {
+			if (close(client_fd) < 0)
+				i_error("login: close(mail client) failed: %m");
+		}
 		login_process_destroy(p);
 		return;
 	}
 
-	if (ret != sizeof(req)) {
-		if (ret == 0) {
-			/* disconnected, ie. the login process died */
-		} else if (ret > 0) {
-			/* req wasn't fully read */
-			i_error("login: fd_read() couldn't read all req");
-		} else {
-			if (errno == EAGAIN)
-				return;
-
-			i_error("login: fd_read() failed: %m");
-		}
-
-		if (client_fd != -1) {
-			if (close(client_fd) < 0)
-				i_error("close(mail client) failed: %m");
-		}
-
-		login_process_destroy(p);
-		return;
-	}
-
-	if (client_fd == -1) {
-		/* just a notification that the login process */
+	if (req.ino == (ino_t)-1) {
+		/* state notification */
 		enum master_login_state state = req.tag;
 
 		if (!p->initialized) {
--- a/src/master/master-login-interface.h	Wed Oct 11 13:33:20 2006 +0300
+++ b/src/master/master-login-interface.h	Wed Oct 11 15:17:27 2006 +0300
@@ -9,7 +9,7 @@
 
 /* Increase the version number every time master_login_request
    (or something else) is changed. */
-#define MASTER_LOGIN_PROTOCOL_VERSION 2
+#define MASTER_LOGIN_PROTOCOL_VERSION 3
 
 enum master_login_state {
 	/* process is accepting new connections */
@@ -31,6 +31,8 @@
 	uint32_t auth_pid;
 	uint32_t auth_id;
 
+	ino_t ino;
+
 	struct ip_addr local_ip, remote_ip;
 };