Mercurial > dovecot > original-hg > dovecot-1.2
changeset 919:5ebec31b49e0 HEAD
Login process now uses the same imap-parser as the imap process itself. This
fixes the problem of literals not working before logging in.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 07 Jan 2003 19:45:38 +0200 |
parents | 23b42ffe8756 |
children | 30babf122f97 |
files | src/login/Makefile.am src/login/client-authenticate.c src/login/client-authenticate.h src/login/client.c src/login/client.h |
diffstat | 5 files changed, 138 insertions(+), 97 deletions(-) [+] |
line wrap: on
line diff
--- a/src/login/Makefile.am Tue Jan 07 19:44:23 2003 +0200 +++ b/src/login/Makefile.am Tue Jan 07 19:45:38 2003 +0200 @@ -3,10 +3,12 @@ pkglibexec_PROGRAMS = imap-login INCLUDES = \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-imap imap_login_LDADD = \ ../lib/liblib.a \ + ../lib-imap/imap-parser.o \ $(SSL_LIBS) imap_login_SOURCES = \
--- a/src/login/client-authenticate.c Tue Jan 07 19:44:23 2003 +0200 +++ b/src/login/client-authenticate.c Tue Jan 07 19:45:38 2003 +0200 @@ -8,6 +8,7 @@ #include "ostream.h" #include "safe-memset.h" #include "str.h" +#include "imap-parser.h" #include "auth-connection.h" #include "../auth/auth-mech-desc.h" #include "client.h" @@ -128,7 +129,7 @@ case AUTH_RESULT_SUCCESS: client->auth_request = NULL; - master_request_imap(client->fd, auth_process, client->tag, + master_request_imap(client->fd, auth_process, client->cmd_tag, request->cookie, &client->ip, master_callback, client); @@ -180,9 +181,20 @@ } } -int cmd_login(struct client *client, const char *user, const char *pass) +int cmd_login(struct client *client, struct imap_arg *args) { - const char *error; + const char *user, *pass, *error; + + /* two arguments: username and password */ + if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING) + return FALSE; + if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING) + return FALSE; + if (args[2].type != IMAP_ARG_EOL) + return FALSE; + + user = IMAP_ARG_STR(&args[0]); + pass = IMAP_ARG_STR(&args[1]); if (!client->tls && disable_plaintext_auth) { client_send_tagline(client, @@ -239,6 +251,7 @@ if (!client_read(client)) return; + /* @UNSAFE */ line = i_stream_next_line(client->input); if (line == NULL) return; @@ -270,11 +283,18 @@ safe_memset(buffer_free_without_data(buf), 0, bufsize); } -int cmd_authenticate(struct client *client, const char *mech_name) +int cmd_authenticate(struct client *client, struct imap_arg *args) { struct auth_mech_desc *mech; - const char *error; + const char *mech_name, *error; + /* we want only one argument: authentication mechanism name */ + if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING) + return FALSE; + if (args[1].type != IMAP_ARG_EOL) + return FALSE; + + mech_name = IMAP_ARG_STR(&args[0]); if (*mech_name == '\0') return FALSE;
--- a/src/login/client-authenticate.h Tue Jan 07 19:44:23 2003 +0200 +++ b/src/login/client-authenticate.h Tue Jan 07 19:45:38 2003 +0200 @@ -3,7 +3,7 @@ const char *client_authenticate_get_capabilities(void); -int cmd_login(struct client *client, const char *user, const char *pass); -int cmd_authenticate(struct client *client, const char *method_name); +int cmd_login(struct client *client, struct imap_arg *args); +int cmd_authenticate(struct client *client, struct imap_arg *args); #endif
--- a/src/login/client.c Tue Jan 07 19:44:23 2003 +0200 +++ b/src/login/client.c Tue Jan 07 19:45:38 2003 +0200 @@ -9,12 +9,20 @@ #include "process-title.h" #include "safe-memset.h" #include "strescape.h" +#include "imap-parser.h" #include "client.h" #include "client-authenticate.h" #include "ssl-proxy.h" #include <syslog.h> +/* max. size of one parameter in line */ +#define MAX_INBUF_SIZE 512 + +/* max. number of IMAP argument elements to accept. The maximum memory usage + for command from user is around MAX_INBUF_SIZE * MAX_IMAP_ARG_ELEMENTS */ +#define MAX_IMAP_ARG_ELEMENTS 4 + /* Disconnect client after idling this many seconds */ #define CLIENT_LOGIN_IDLE_TIMEOUT 60 @@ -118,6 +126,95 @@ return TRUE; } +static int client_command_execute(struct client *client, const char *cmd, + struct imap_arg *args) +{ + cmd = str_ucase(t_strdup_noconst(cmd)); + if (strcmp(cmd, "LOGIN") == 0) + return cmd_login(client, args); + if (strcmp(cmd, "AUTHENTICATE") == 0) + return cmd_authenticate(client, args); + if (strcmp(cmd, "CAPABILITY") == 0) + return cmd_capability(client); + if (strcmp(cmd, "STARTTLS") == 0) + return cmd_starttls(client); + if (strcmp(cmd, "NOOP") == 0) + return cmd_noop(client); + if (strcmp(cmd, "LOGOUT") == 0) + return cmd_logout(client); + + return FALSE; +} + +/* Skip incoming data until newline is found, + returns TRUE if newline was found. */ +static int client_skip_line(struct client *client) +{ + const unsigned char *data; + size_t i, data_size; + + data = i_stream_get_data(client->input, &data_size); + + for (i = 0; i < data_size; i++) { + if (data[i] == '\n') { + i_stream_skip(client->input, i+1); + return TRUE; + } + } + + return FALSE; +} + +static void client_handle_input(struct client *client) +{ + struct imap_arg *args; + + if (client->cmd_finished) { + /* clear the previous command from memory. don't do this + immediately after handling command since we need the + cmd_tag to stay some time after authentication commands. */ + client->cmd_tag = NULL; + client->cmd_name = NULL; + imap_parser_reset(client->parser); + + /* remove \r\n */ + if (!client_skip_line(client)) + return; + + client->cmd_finished = FALSE; + } + + if (client->cmd_tag == NULL) { + client->cmd_tag = imap_parser_read_word(client->parser); + if (client->cmd_tag == NULL) + return; /* need more data */ + } + + if (client->cmd_name == NULL) { + client->cmd_name = imap_parser_read_word(client->parser); + if (client->cmd_name == NULL) + return; /* need more data */ + } + + switch (imap_parser_read_args(client->parser, 0, 0, &args)) { + case -1: + /* error */ + client_destroy(client, NULL); + return; + case -2: + /* not enough data */ + return; + } + + if (*client->cmd_tag == '\0' || + !client_command_execute(client, client->cmd_name, args)) { + client_send_tagline(client, + "BAD Error in IMAP command received by server."); + } + + client->cmd_finished = TRUE; +} + int client_read(struct client *client) { switch (i_stream_read(client->input)) { @@ -136,104 +233,20 @@ } } -static char *get_next_arg(char **linep) -{ - char *line, *start; - int quoted; - - line = *linep; - while (*line == ' ') line++; - - /* @UNSAFE: get next argument, unescape arg if it's quoted */ - if (*line == '"') { - quoted = TRUE; - line++; - - start = line; - while (*line != '\0' && *line != '"') { - if (*line == '\\' && line[1] != '\0') - line++; - line++; - } - - if (*line == '"') - *line++ = '\0'; - str_unescape(start); - } else { - start = line; - while (*line != '\0' && *line != ' ') - line++; - - if (*line == ' ') - *line++ = '\0'; - } - - *linep = line; - return start; -} - -static int client_command_execute(struct client *client, char *line) -{ - char *cmd; - int ret; - - cmd = get_next_arg(&line); - str_ucase(cmd); - - if (strcmp(cmd, "LOGIN") == 0) { - char *user, *pass; - - user = get_next_arg(&line); - pass = get_next_arg(&line); - ret = cmd_login(client, user, pass); - - safe_memset(pass, 0, strlen(pass)); - return ret; - } - if (strcmp(cmd, "AUTHENTICATE") == 0) - return cmd_authenticate(client, get_next_arg(&line)); - if (strcmp(cmd, "CAPABILITY") == 0) - return cmd_capability(client); - if (strcmp(cmd, "STARTTLS") == 0) - return cmd_starttls(client); - if (strcmp(cmd, "NOOP") == 0) - return cmd_noop(client); - if (strcmp(cmd, "LOGOUT") == 0) - return cmd_logout(client); - - return FALSE; -} - void client_input(void *context, int fd __attr_unused__, struct io *io __attr_unused__) { struct client *client = context; - char *line; client->last_input = ioloop_time; - i_free(client->tag); - client->tag = i_strdup("*"); - if (!client_read(client)) return; client_ref(client); + o_stream_cork(client->output); - - while ((line = i_stream_next_line(client->input)) != NULL) { - /* split the arguments, make sure we have at - least tag + command */ - i_free(client->tag); - client->tag = i_strdup(get_next_arg(&line)); - - if (*client->tag == '\0' || - !client_command_execute(client, line)) { - /* error */ - client_send_tagline(client, "BAD Error in IMAP command " - "received by server."); - } - } + client_handle_input(client); if (client_unref(client)) o_stream_flush(client->output); @@ -306,7 +319,11 @@ client->input = i_stream_create_file(fd, default_pool, 8192, FALSE); client->output = o_stream_create_file(fd, default_pool, 1024, IO_PRIORITY_DEFAULT, FALSE); + client->parser = imap_parser_create(client->input, client->output, + MAX_INBUF_SIZE, + MAX_IMAP_ARG_ELEMENTS); client->plain_login = buffer_create_dynamic(system_pool, 128, 8192); + client->last_input = ioloop_time; hash_insert(clients, client, client); @@ -324,6 +341,7 @@ hash_remove(clients, client); + imap_parser_destroy(client->parser); i_stream_close(client->input); o_stream_close(client->output); @@ -351,7 +369,6 @@ i_stream_unref(client->input); o_stream_unref(client->output); - i_free(client->tag); buffer_free(client->plain_login); i_free(client); @@ -367,7 +384,7 @@ void client_send_tagline(struct client *client, const char *line) { - client_send_line(client, t_strconcat(client->tag, " ", line, NULL)); + client_send_line(client, t_strconcat(client->cmd_tag, " ", line, NULL)); } void client_syslog(struct client *client, const char *text)
--- a/src/login/client.h Tue Jan 07 19:44:23 2003 +0200 +++ b/src/login/client.h Tue Jan 07 19:45:38 2003 +0200 @@ -12,14 +12,16 @@ struct io *io; struct istream *input; struct ostream *output; + struct imap_parser *parser; time_t last_input; - char *tag; + const char *cmd_tag, *cmd_name; buffer_t *plain_login; struct auth_request *auth_request; unsigned int tls:1; + unsigned int cmd_finished:1; }; struct client *client_create(int fd, struct ip_addr *ip, int imaps);