Mercurial > dovecot > original-hg > dovecot-1.2
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; };