From: Timo Sirainen Date: Mon, 31 Aug 2015 20:46:05 +0000 (+0300) Subject: imap-hibernate: Use sockets' st_dev and st_ino to verify that the passed fd is correct. X-Git-Tag: 2.2.19.rc1~142 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2bc963ea051ddacefe0fa5e26280e8ef853fd6c6;p=thirdparty%2Fdovecot%2Fcore.git imap-hibernate: Use sockets' st_dev and st_ino to verify that the passed fd is correct. --- diff --git a/src/imap-hibernate/imap-client.c b/src/imap-hibernate/imap-client.c index 141c2785c5..e44d12e861 100644 --- a/src/imap-hibernate/imap-client.c +++ b/src/imap-hibernate/imap-client.c @@ -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); diff --git a/src/imap-hibernate/imap-client.h b/src/imap-hibernate/imap-client.h index c93fa5284a..131b404733 100644 --- a/src/imap-hibernate/imap-client.h +++ b/src/imap-hibernate/imap-client.h @@ -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; diff --git a/src/imap-hibernate/imap-hibernate-client.c b/src/imap-hibernate/imap-hibernate-client.c index b9468d271d..c0efcaa952 100644 --- a/src/imap-hibernate/imap-hibernate-client.c +++ b/src/imap-hibernate/imap-hibernate-client.c @@ -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; } diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c index 830c421ae3..00b579bfcf 100644 --- a/src/imap/imap-client-hibernate.c +++ b/src/imap/imap-client-hibernate.c @@ -13,6 +13,8 @@ #include "imap-state.h" #include "imap-client.h" +#include + #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) { diff --git a/src/imap/imap-master-client.c b/src/imap/imap-master-client.c index 26bd082d65..c291267aea 100644 --- a/src/imap/imap-master-client.c +++ b/src/imap/imap-master-client.c @@ -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;