]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Send login command OK reply in IMAP/POP3 process.
authorTimo Sirainen <tss@iki.fi>
Sat, 21 Jun 2008 09:50:28 +0000 (12:50 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 21 Jun 2008 09:50:28 +0000 (12:50 +0300)
--HG--
branch : HEAD

13 files changed:
src/imap-login/client-authenticate.c
src/imap-login/client.c
src/imap-login/client.h
src/imap/main.c
src/login-common/client-common.h
src/login-common/master.c
src/master/login-process.c
src/master/mail-process.c
src/master/mail-process.h
src/master/master-login-interface.h
src/master/master-settings.c
src/pop3-login/client-authenticate.c
src/pop3/main.c

index 77d11dc4b1b20564bce7129444ac24fecb682921..3f11587ad67f6d093e230b74cb3420261e1178ad 100644 (file)
@@ -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);
index 19001fe145fc99fee13d2d13a2eefd63f851c215..390c5ed630a18284428d17287a3960550c36d6bd 100644 (file)
@@ -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.");
index c3af585c5e9b3577cecf762b684195c54858152d..35f410a37ec2790d4bd8c2140afccdbc90cc4889 100644 (file)
@@ -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);
index 167f40b07d00778550bdbbadad61692d65361b82..e5d717201bbd0271b0a4c9c1662536346e808b6e 100644 (file)
@@ -24,7 +24,7 @@
 #include <syslog.h>
 
 #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 &&
index 7167aa71e913788e45b996203682b10f774c9a32..17c95d70a9254bbbe9870e74c763dd619ace952c 100644 (file)
@@ -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;
index 67047c132675a487dec84399d9decf9e901cdf93..1b2fe2f572aea6d600fdb2aae59cb5e7b28f68b3 100644 (file)
@@ -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);
index 333d876985f36956637e936ef283a1832533fbc6..1fc13670ae5b1ab9fad697ef45d9a07539965f3c 100644 (file)
@@ -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);
index 254873798cc3a4e8774d803c4ced91504b62b3ea..ae664a2196de9090845ec1dfc03e5faa1d115c03 100644 (file)
@@ -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));
        }
 
index b13a5560bd6996d5891f7b4268daed4c597eb9be..1a64e142155efe3071518bd8067146bc3a89edf4 100644 (file)
@@ -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);
index b5fb6d7d55dd0457612339d9c46b33f1f0fc42ce..0bf49200e7210ff749905ed4b8fdf57b114cc361 100644 (file)
@@ -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;
 
index ae1b28bbc0dd0f51f6db40e15369419896f3a10f..fad8af4e2e92248ec47c328088668a5af9290ffa 100644 (file)
@@ -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]);
index 7c072c25c6597cb67f9c8bc35fa1a57911276f31..d481452779c98ba66065dccac43259cdf5705178 100644 (file)
@@ -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:
index 67574f90b336cc6628aa06028437efe3fab20c0a..8ab66d3faa6bcc4d3041de7d5f1438dce49dca6d 100644 (file)
@@ -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);