]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap-hibernate: Use sockets' st_dev and st_ino to verify that the passed fd is correct.
authorTimo Sirainen <tss@iki.fi>
Mon, 31 Aug 2015 20:46:05 +0000 (23:46 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 31 Aug 2015 20:46:05 +0000 (23:46 +0300)
src/imap-hibernate/imap-client.c
src/imap-hibernate/imap-client.h
src/imap-hibernate/imap-hibernate-client.c
src/imap/imap-client-hibernate.c
src/imap/imap-master-client.c

index 141c2785c5d9c1f15f7c153bbd4f45af3c8f61f7..e44d12e86120c8e09012474417cd91244ed1d69e 100644 (file)
@@ -117,10 +117,12 @@ imap_client_move_back_send_callback(void *context, struct ostream *output)
                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 @@ imap_client_create(int fd, const struct imap_client_state *state)
        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);
index c93fa5284acdb8af05bd305ee318eb73d86759fc..131b4047333f76c376b8467d420410ac75494e6c 100644 (file)
@@ -13,8 +13,8 @@ struct imap_client_state {
        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;
index b9468d271d0152e397ef50c4e2841f873d727035..c0efcaa95228c0c9c6a8e19289b0d4fd0fe4c6f5 100644 (file)
@@ -44,6 +44,7 @@ imap_hibernate_client_parse_input(const char *const *args, pool_t pool,
                                  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 @@ imap_hibernate_client_parse_input(const char *const *args, pool_t pool,
                                        "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 @@ imap_hibernate_client_parse_input(const char *const *args, pool_t pool,
                        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;
 }
 
index 830c421ae322313dd8bbc1df3fc8e1f078a80a2b..00b579bfcfa6d6cb67de0b11a3791a6a0a0b223c 100644 (file)
@@ -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 int imap_hibernate_handshake(int fd, const char *path)
 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) {
index 26bd082d65ee0025f76bc552615834d24ac1b977..c291267aea2f6f45fbcabaf9cdd1e9cb0399f395 100644 (file)
@@ -27,8 +27,8 @@ struct imap_master_input {
        /* 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 @@ imap_master_client_parse_input(const char *const *args, pool_t pool,
                               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 @@ imap_master_client_parse_input(const char *const *args, pool_t pool,
                                        "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 @@ imap_master_client_parse_input(const char *const *args, pool_t pool,
                        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;