From: Timo Sirainen Date: Sat, 21 Jun 2008 09:50:28 +0000 (+0300) Subject: Send login command OK reply in IMAP/POP3 process. X-Git-Tag: 1.2.alpha1~233 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7753eaa6a4275e074b4ce8428b85d9d04fc67f31;p=thirdparty%2Fdovecot%2Fcore.git Send login command OK reply in IMAP/POP3 process. --HG-- branch : HEAD --- diff --git a/src/imap-login/client-authenticate.c b/src/imap-login/client-authenticate.c index 77d11dc4b1..3f11587ad6 100644 --- a/src/imap-login/client-authenticate.c +++ b/src/imap-login/client-authenticate.c @@ -82,6 +82,7 @@ static void client_auth_failed(struct imap_client *client) io_remove(&client->io); client->io = io_add(client->common.fd, IO_READ, client_input, client); + client->common.auth_command_tag = NULL; } static bool client_handle_args(struct imap_client *client, @@ -207,14 +208,6 @@ static void sasl_callback(struct client *_client, enum sasl_server_reply reply, if (client_handle_args(client, args, TRUE)) break; } - - if (client->full_capability_sent) - client_send_tagline(client, "OK Logged in."); - else { - client_send_tagline(client, t_strdup_printf( - "OK [CAPABILITY %s] Logged in.", - capability_string)); - } client_destroy_success(client, "Login"); break; case SASL_SERVER_REPLY_AUTH_FAILED: @@ -271,6 +264,8 @@ static void sasl_callback(struct client *_client, enum sasl_server_reply reply, static int client_auth_begin(struct imap_client *client, const char *mech_name, const char *init_resp) { + client->common.auth_command_tag = client->cmd_tag; + client_ref(client); sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name, init_resp, sasl_callback); diff --git a/src/imap-login/client.c b/src/imap-login/client.c index 19001fe145..390c5ed630 100644 --- a/src/imap-login/client.c +++ b/src/imap-login/client.c @@ -108,7 +108,8 @@ static const char *get_capability(struct imap_client *client, bool full) static int cmd_capability(struct imap_client *client) { - client->full_capability_sent = TRUE; + client->common.master_login_flags |= + LOGIN_IMAP_FLAG_FULL_CAPABILITY_SENT; client_send_line(client, t_strconcat( "* CAPABILITY ", get_capability(client, TRUE), NULL)); client_send_tagline(client, "OK Capability completed."); diff --git a/src/imap-login/client.h b/src/imap-login/client.h index c3af585c5e..35f410a37e 100644 --- a/src/imap-login/client.h +++ b/src/imap-login/client.h @@ -31,7 +31,6 @@ struct imap_client { unsigned int destroyed:1; unsigned int greeting_sent:1; unsigned int id_logged:1; - unsigned int full_capability_sent:1; }; void client_destroy(struct imap_client *client, const char *reason); diff --git a/src/imap/main.c b/src/imap/main.c index 167f40b07d..e5d717201b 100644 --- a/src/imap/main.c +++ b/src/imap/main.c @@ -24,7 +24,7 @@ #include #define IS_STANDALONE() \ - (getenv("LOGGED_IN") == NULL && getenv("IMAPLOGINTAG") == NULL) + (getenv("IMAPLOGINTAG") == NULL) struct client_workaround_list { const char *name; @@ -167,7 +167,7 @@ static void main_init(void) struct client *client; struct ostream *output; struct mail_namespace *ns; - const char *user, *str; + const char *user, *str, *tag; lib_signals_init(); lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL); @@ -244,15 +244,21 @@ static void main_init(void) output = client->output; o_stream_ref(output); o_stream_cork(output); - if (IS_STANDALONE()) { + + /* IMAPLOGINTAG environment is compatible with mailfront */ + tag = getenv("IMAPLOGINTAG"); + if (tag == NULL) { client_send_line(client, t_strconcat( "* PREAUTH [CAPABILITY ", str_c(capability_string), "] " "Logged in as ", user, NULL)); - } else if (getenv("IMAPLOGINTAG") != NULL) { - /* Support for mailfront */ - client_send_line(client, t_strconcat(getenv("IMAPLOGINTAG"), - " OK Logged in.", NULL)); + } else if (getenv("CLIENT_SEND_CAPABILITY") == NULL) { + client_send_line(client, + t_strconcat(tag, " OK Logged in.", NULL)); + } else { + client_send_line(client, t_strconcat( + tag, " OK [CAPABILITY ", + str_c(capability_string), "] Logged in", NULL)); } str = getenv("CLIENT_INPUT"); if (str != NULL) T_BEGIN { @@ -290,7 +296,7 @@ static void main_deinit(void) int main(int argc ATTR_UNUSED, char *argv[], char *envp[]) { #ifdef DEBUG - if (getenv("LOGGED_IN") != NULL && getenv("GDB") == NULL) + if (!IS_STANDALONE() && getenv("GDB") == NULL) fd_debug_verify_leaks(3, 1024); #endif if (IS_STANDALONE() && getuid() == 0 && diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 7167aa71e9..17c95d70a9 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -23,10 +23,12 @@ struct client { int fd; struct istream *input; + const char *auth_command_tag; char *auth_mech_name; struct auth_request *auth_request; + enum master_login_flags master_login_flags; unsigned int master_tag; master_callback_t *master_callback; sasl_server_callback_t *sasl_callback; diff --git a/src/login-common/master.c b/src/login-common/master.c index 67047c1326..1b2fe2f572 100644 --- a/src/login-common/master.c +++ b/src/login-common/master.c @@ -66,13 +66,18 @@ void master_request_login(struct client *client, master_callback_t *callback, const unsigned char *data; size_t size; ssize_t ret; + unsigned int cmd_tag_size; i_assert(auth_pid != 0); data = i_stream_get_data(client->input, &size); + cmd_tag_size = client->auth_command_tag == NULL ? 0 : + strlen(client->auth_command_tag); + buf = buffer_create_dynamic(pool_datastack_create(), - sizeof(*req) + size); - buffer_write(buf, sizeof(*req), data, size); + sizeof(*req) + size + cmd_tag_size); + buffer_write(buf, sizeof(*req), client->auth_command_tag, cmd_tag_size); + buffer_write(buf, sizeof(*req) + cmd_tag_size, data, size); req = buffer_get_space_unsafe(buf, 0, sizeof(*req)); req->version = MASTER_LOGIN_PROTOCOL_VERSION; req->tag = ++master_tag_counter; @@ -82,8 +87,10 @@ void master_request_login(struct client *client, master_callback_t *callback, req->auth_id = auth_id; req->local_ip = client->local_ip; req->remote_ip = client->ip; - req->data_size = size; -#if LOGIN_MAX_INBUF_SIZE != MASTER_LOGIN_MAX_DATA_SIZE + req->flags = client->master_login_flags; + req->cmd_tag_size = cmd_tag_size; + req->data_size = req->cmd_tag_size + size; +#if (LOGIN_MAX_INBUF_SIZE*2) != MASTER_LOGIN_MAX_DATA_SIZE # error buffer max sizes unsynced #endif i_assert(req->data_size <= LOGIN_MAX_INBUF_SIZE); diff --git a/src/master/login-process.c b/src/master/login-process.c index 333d876985..1fc13670ae 100644 --- a/src/master/login-process.c +++ b/src/master/login-process.c @@ -44,12 +44,9 @@ struct login_process { struct login_auth_request { struct login_process *process; unsigned int tag; - unsigned int login_tag; - int fd; - unsigned int data_size; - struct ip_addr local_ip, remote_ip; + struct mail_login_request mail_request; unsigned char data[]; }; @@ -104,11 +101,8 @@ void auth_master_callback(const char *user, const char *const *args, master_reply.status = create_mail_process(group->mail_process_type, - group->set, - request->fd, &request->local_ip, - &request->remote_ip, user, args, - request->data_size, request->data, - FALSE); + group->set, &request->mail_request, + user, args, request->data, FALSE); } T_END; /* reply to login */ @@ -124,7 +118,7 @@ void auth_master_callback(const char *user, const char *const *args, login_process_destroy(request->process); } - if (close(request->fd) < 0) + if (close(request->mail_request.fd) < 0) i_error("close(mail client) failed: %m"); login_process_unref(request->process); i_free(request); @@ -441,10 +435,12 @@ static void login_process_input(struct login_process *p) authreq->process = p; authreq->tag = ++auth_id_counter; authreq->login_tag = req.tag; - authreq->fd = client_fd; - authreq->local_ip = req.local_ip; - authreq->remote_ip = req.remote_ip; - authreq->data_size = req.data_size; + authreq->mail_request.fd = client_fd; + authreq->mail_request.local_ip = req.local_ip; + authreq->mail_request.remote_ip = req.remote_ip; + authreq->mail_request.flags = req.flags; + authreq->mail_request.cmd_tag_size = req.cmd_tag_size; + authreq->mail_request.data_size = req.data_size; memcpy(authreq->data, data, req.data_size); auth_process = auth_process_find(req.auth_pid); diff --git a/src/master/mail-process.c b/src/master/mail-process.c index 254873798c..ae664a2196 100644 --- a/src/master/mail-process.c +++ b/src/master/mail-process.c @@ -522,11 +522,9 @@ static void nfs_warn_if_found(const char *mail, const char *full_home_dir) enum master_login_status create_mail_process(enum process_type process_type, struct settings *set, - int socket_fd, const struct ip_addr *local_ip, - const struct ip_addr *remote_ip, + const struct mail_login_request *request, const char *user, const char *const *args, - unsigned int input_size, const unsigned char *input, - bool dump_capability) + const unsigned char *data, bool dump_capability) { const struct var_expand_table *var_expand_table; const char *p, *addr, *mail, *chroot_dir, *home_dir, *full_home_dir; @@ -553,7 +551,8 @@ create_mail_process(enum process_type process_type, struct settings *set, /* check process limit for this user */ process_group = dump_capability ? NULL : - mail_process_group_lookup(process_type, user, remote_ip); + mail_process_group_lookup(process_type, user, + &request->remote_ip); process_count = process_group == NULL ? 0 : array_count(&process_group->processes); if (process_count >= set->mail_max_userip_connections && @@ -684,8 +683,8 @@ create_mail_process(enum process_type process_type, struct settings *set, var_expand_table = get_var_expand_table(process_names[process_type], user, home_given ? home_dir : NULL, - net_ip2addr(local_ip), - net_ip2addr(remote_ip), + net_ip2addr(&request->local_ip), + net_ip2addr(&request->remote_ip), pid != 0 ? pid : getpid(), uid); str = t_str_new(128); @@ -697,10 +696,9 @@ create_mail_process(enum process_type process_type, struct settings *set, log_set_prefix(log, str_c(str)); log_set_pid(log, pid); if (process_group == NULL) { - process_group = - mail_process_group_create(process_type, - user, - remote_ip); + process_group = mail_process_group_create( + process_type, user, + &request->remote_ip); } mail_process_group_add(process_group, pid); } @@ -724,9 +722,9 @@ create_mail_process(enum process_type process_type, struct settings *set, child_process_init_env(); /* move the client socket into stdin and stdout fds, log to stderr */ - if (dup2(dump_capability ? null_fd : socket_fd, 0) < 0) + if (dup2(dump_capability ? null_fd : request->fd, 0) < 0) i_fatal("dup2(stdin) failed: %m"); - if (dup2(socket_fd, 1) < 0) + if (dup2(request->fd, 1) < 0) i_fatal("dup2(stdout) failed: %m"); if (dup2(log_fd, 2) < 0) i_fatal("dup2(stderr) failed: %m"); @@ -831,13 +829,23 @@ create_mail_process(enum process_type process_type, struct settings *set, env_put(t_strconcat("HOME=", home_dir, NULL)); env_put(t_strconcat("USER=", user, NULL)); - addr = net_ip2addr(remote_ip); + addr = net_ip2addr(&request->remote_ip); env_put(t_strconcat("IP=", addr, NULL)); - if (input_size > 0) { + i_assert(request->cmd_tag_size <= request->data_size); + if (request->cmd_tag_size > 0) { + env_put(t_strconcat("IMAPLOGINTAG=", + t_strndup(data, request->cmd_tag_size), NULL)); + } + if ((request->flags & LOGIN_IMAP_FLAG_FULL_CAPABILITY_SENT) == 0 && + process_type == PROCESS_TYPE_IMAP) + env_put("CLIENT_SEND_CAPABILITY=1"); + + if (request->data_size > request->cmd_tag_size) { str_truncate(str, 0); str_append(str, "CLIENT_INPUT="); - base64_encode(input, input_size, str); + base64_encode(data + request->cmd_tag_size, + request->data_size - request->cmd_tag_size, str); env_put(str_c(str)); } diff --git a/src/master/mail-process.h b/src/master/mail-process.h index b13a5560bd..1a64e14215 100644 --- a/src/master/mail-process.h +++ b/src/master/mail-process.h @@ -1,8 +1,17 @@ #ifndef MAIL_PROCESS_H #define MAIL_PROCESS_H +#include "master-login-interface.h" #include "child-process.h" +struct mail_login_request { + int fd; + enum master_login_flags flags; + unsigned int cmd_tag_size; + unsigned int data_size; + struct ip_addr local_ip, remote_ip; +}; + struct login_group; struct auth_master_reply; @@ -10,11 +19,9 @@ void mail_process_exec(const char *protocol, const char **args) ATTR_NORETURN; enum master_login_status create_mail_process(enum process_type process_type, struct settings *set, - int socket_fd, const struct ip_addr *local_ip, - const struct ip_addr *remote_ip, + const struct mail_login_request *request, const char *user, const char *const *args, - unsigned int input_size, const unsigned char *input, - bool dump_capability); + const unsigned char *data, bool dump_capability); void mail_processes_init(void); void mail_processes_deinit(void); diff --git a/src/master/master-login-interface.h b/src/master/master-login-interface.h index b5fb6d7d55..0bf49200e7 100644 --- a/src/master/master-login-interface.h +++ b/src/master/master-login-interface.h @@ -9,8 +9,9 @@ (or something else) is changed. */ #define MASTER_LOGIN_PROTOCOL_VERSION 3 -/* This should be kept in sync with LOGIN_MAX_INBUF_SIZE */ -#define MASTER_LOGIN_MAX_DATA_SIZE 4096 +/* This should be kept in sync with LOGIN_MAX_INBUF_SIZE. Multiply it by two + to make sure there's space to transfer the command tag */ +#define MASTER_LOGIN_MAX_DATA_SIZE (4096*2) enum master_login_state { /* process is accepting new connections */ @@ -24,6 +25,10 @@ enum master_login_state { LOGIN_STATE_COUNT }; +enum master_login_flags { + LOGIN_IMAP_FLAG_FULL_CAPABILITY_SENT = 0x01 +}; + struct master_login_request { uint32_t version; /* if fd == -1, tag is used as master_login_state */ @@ -32,7 +37,9 @@ struct master_login_request { uint32_t auth_pid; uint32_t auth_id; /* request follows this many bytes of client input */ - uint32_t data_size; + uint16_t data_size; + uint16_t cmd_tag_size; + uint32_t flags; ino_t ino; diff --git a/src/master/master-settings.c b/src/master/master-settings.c index ae1b28bbc0..fad8af4e2e 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -614,7 +614,7 @@ static bool get_imap_capability(struct settings *set) NULL }; enum master_login_status login_status; - struct ip_addr ip; + struct mail_login_request request; char buf[4096]; int fd[2], status; ssize_t ret; @@ -638,16 +638,17 @@ static bool get_imap_capability(struct settings *set) args[1] = t_strdup_printf("gid=%s", dec2str(getegid())); } - memset(&ip, 0, sizeof(ip)); if (pipe(fd) < 0) { i_error("pipe() failed: %m"); return FALSE; } fd_close_on_exec(fd[0], TRUE); fd_close_on_exec(fd[1], TRUE); - login_status = create_mail_process(PROCESS_TYPE_IMAP, set, fd[1], - &ip, &ip, "dump-capability", - args, 0, NULL, TRUE); + + memset(&request, 0, sizeof(request)); + request.fd = fd[1]; + login_status = create_mail_process(PROCESS_TYPE_IMAP, set, &request, + "dump-capability", args, NULL, TRUE); if (login_status != MASTER_LOGIN_STATUS_OK) { (void)close(fd[0]); (void)close(fd[1]); diff --git a/src/pop3-login/client-authenticate.c b/src/pop3-login/client-authenticate.c index 7c072c25c6..d481452779 100644 --- a/src/pop3-login/client-authenticate.c +++ b/src/pop3-login/client-authenticate.c @@ -169,7 +169,6 @@ static void sasl_callback(struct client *_client, enum sasl_server_reply reply, break; } - client_send_line(client, "+OK Logged in."); client_destroy_success(client, "Login"); break; case SASL_SERVER_REPLY_AUTH_FAILED: diff --git a/src/pop3/main.c b/src/pop3/main.c index 67574f90b3..8ab66d3faa 100644 --- a/src/pop3/main.c +++ b/src/pop3/main.c @@ -242,6 +242,9 @@ static bool main_init(void) if (client == NULL) return FALSE; + if (!IS_STANDALONE()) + client_send_line(client, "+OK Logged in."); + str = getenv("CLIENT_INPUT"); if (str != NULL) T_BEGIN { buffer_t *buf = t_base64_decode_str(str);