]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap-login: Log proxy state as human-readable string.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 9 Mar 2017 15:41:52 +0000 (10:41 -0500)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 9 Mar 2017 16:44:02 +0000 (11:44 -0500)
Separate sent/received state and log them as strings.

src/imap-login/imap-login-client.c
src/imap-login/imap-login-client.h
src/imap-login/imap-proxy.c
src/imap-login/imap-proxy.h

index f930b021d239bd00274b1c10f2d3084be4c86cdd..fe547b9f7f7c5ff8a156a4bf850b147ca9b89a41 100644 (file)
@@ -715,7 +715,8 @@ static struct client_vfuncs imap_client_vfuncs = {
        imap_client_auth_result,
        imap_proxy_reset,
        imap_proxy_parse_line,
-       imap_proxy_error
+       imap_proxy_error,
+       imap_proxy_get_state,
 };
 
 static const struct login_binary imap_login_binary = {
index 6589c1f7810c56fe607d626644fedeceaf74a4f8..847b2b7f7de057fbfbb74a07f0cef380ce73f4b9 100644 (file)
@@ -14,6 +14,30 @@ enum imap_client_id_state {
        IMAP_CLIENT_ID_STATE_VALUE
 };
 
+/* Multiple commands can be sent pipelined, so the sent_state is a bitmask */
+enum imap_proxy_sent_state {
+       IMAP_PROXY_SENT_STATE_ID                = 0x01,
+       IMAP_PROXY_SENT_STATE_STARTTLS          = 0x02,
+       IMAP_PROXY_SENT_STATE_CAPABILITY        = 0x04,
+       IMAP_PROXY_SENT_STATE_AUTHENTICATE      = 0x08,
+       IMAP_PROXY_SENT_STATE_AUTH_CONTINUE     = 0x10,
+       IMAP_PROXY_SENT_STATE_LOGIN             = 0x20,
+
+       IMAP_PROXY_SENT_STATE_COUNT = 6
+};
+
+enum imap_proxy_rcvd_state {
+       IMAP_PROXY_RCVD_STATE_NONE,
+       IMAP_PROXY_RCVD_STATE_BANNER,
+       IMAP_PROXY_RCVD_STATE_ID,
+       IMAP_PROXY_RCVD_STATE_STARTTLS,
+       IMAP_PROXY_RCVD_STATE_CAPABILITY,
+       IMAP_PROXY_RCVD_STATE_AUTH_CONTINUE,
+       IMAP_PROXY_RCVD_STATE_LOGIN,
+
+       IMAP_PROXY_RCVD_STATE_COUNT
+};
+
 struct imap_client_cmd_id {
        struct imap_parser *parser;
 
@@ -34,6 +58,9 @@ struct imap_client {
        const char *cmd_tag, *cmd_name;
        struct imap_client_cmd_id *cmd_id;
 
+       enum imap_proxy_sent_state proxy_sent_state;
+       enum imap_proxy_rcvd_state proxy_rcvd_state;
+
        bool cmd_finished:1;
        bool proxy_sasl_ir:1;
        bool proxy_logindisabled:1;
index 5e901e970a65777c1a2117ffc86a676e4603083f..1b6b25e65dd6824b83440eef26a85e3be5d0f1fe 100644 (file)
 #include "imap-quote.h"
 #include "imap-proxy.h"
 
-
-enum imap_proxy_state {
-       IMAP_PROXY_STATE_NONE,
-       IMAP_PROXY_STATE_BANNER,
-       IMAP_PROXY_STATE_ID,
-       IMAP_PROXY_STATE_STARTTLS,
-       IMAP_PROXY_STATE_CAPABILITY,
-       IMAP_PROXY_STATE_AUTH_CONTINUE,
-       IMAP_PROXY_STATE_LOGIN
+static const char *imap_proxy_sent_state_names[IMAP_PROXY_SENT_STATE_COUNT] = {
+       "id", "starttls", "capability",
+       "authenticate", "auth-continue", "login"
+};
+static const char *imap_proxy_rcvd_state_names[IMAP_PROXY_RCVD_STATE_COUNT] = {
+       "none", "banner", "id", "starttls", "capability",
+       "auth-continue", "login"
 };
 
 static void proxy_write_id(struct imap_client *client, string_t *str)
@@ -66,6 +64,7 @@ static int proxy_write_starttls(struct imap_client *client, string_t *str)
                        return -1;
                }
                str_append(str, "S STARTTLS\r\n");
+               client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_STARTTLS;
                return 1;
        }
        return 0;
@@ -88,6 +87,7 @@ static int proxy_write_login(struct imap_client *client, string_t *str)
            (client->proxy_backend_capability == NULL ||
             client->client_ignores_capability_resp_code)) {
                client->proxy_capability_request_sent = TRUE;
+               client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_CAPABILITY;
                str_append(str, "C CAPABILITY\r\n");
                if (client->common.proxy_nopipelining) {
                        /* authenticate only after receiving C OK reply. */
@@ -109,6 +109,7 @@ static int proxy_write_login(struct imap_client *client, string_t *str)
                imap_append_string(str, client->common.proxy_password);
                str_append(str, "\r\n");
 
+               client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_LOGIN;
                proxy_free_password(&client->common);
                return 0;
        }
@@ -141,6 +142,7 @@ static int proxy_write_login(struct imap_client *client, string_t *str)
        }
        str_append(str, "\r\n");
        proxy_free_password(&client->common);
+       client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_AUTHENTICATE;
        return 0;
 }
 
@@ -170,6 +172,7 @@ static int proxy_input_banner(struct imap_client *client,
                        i_strdup(t_strcut(line + 5 + 12, ']'));
                if (str_array_icase_find(capabilities, "ID") &&
                    !client->common.proxy_not_trusted) {
+                       client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID;
                        proxy_write_id(client, str);
                        if (client->common.proxy_nopipelining) {
                                /* write login or starttls after I OK */
@@ -240,7 +243,7 @@ int imap_proxy_parse_line(struct client *client, const char *line)
        output = login_proxy_get_ostream(client->login_proxy);
        if (!imap_client->proxy_seen_banner) {
                /* this is a banner */
-               client->proxy_state = IMAP_PROXY_STATE_BANNER;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_BANNER;
                imap_client->proxy_seen_banner = TRUE;
                if (proxy_input_banner(imap_client, output, line) < 0) {
                        client_proxy_failed(client, TRUE);
@@ -253,7 +256,8 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                        /* used literals with LOGIN command, just ignore. */
                        return 0;
                }
-               client->proxy_state = IMAP_PROXY_STATE_AUTH_CONTINUE;
+               imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_AUTHENTICATE;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_AUTH_CONTINUE;
 
                str = t_str_new(128);
                if (line[1] != ' ' ||
@@ -282,9 +286,13 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                base64_encode(data, data_len, str);
                str_append(str, "\r\n");
 
+               imap_client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_AUTH_CONTINUE;
                o_stream_nsend(output, str_data(str), str_len(str));
                return 0;
        } else if (strncmp(line, "S ", 2) == 0) {
+               imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_STARTTLS;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_STARTTLS;
+
                if (strncmp(line, "S OK ", 5) != 0) {
                        /* STARTTLS failed */
                        client_log_err(client, t_strdup_printf(
@@ -294,7 +302,6 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                        return -1;
                }
                /* STARTTLS successful, begin TLS negotiation. */
-               client->proxy_state = IMAP_PROXY_STATE_STARTTLS;
                if (login_proxy_starttls(client->login_proxy) < 0) {
                        client_proxy_failed(client, TRUE);
                        return -1;
@@ -310,7 +317,8 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                return 1;
        } else if (strncmp(line, "L OK ", 5) == 0) {
                /* Login successful. Send this line to client. */
-               client->proxy_state = IMAP_PROXY_STATE_LOGIN;
+               imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_LOGIN;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_LOGIN;
                str = t_str_new(128);
                client_send_login_reply(imap_client, str, line + 5);
                o_stream_nsend(client->output, str_data(str), str_len(str));
@@ -319,6 +327,9 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                client_proxy_finish_destroy_client(client);
                return 1;
        } else if (strncmp(line, "L ", 2) == 0) {
+               imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_LOGIN;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_LOGIN;
+
                line += 2;
                if (client->set->auth_verbose) {
                        const char *log_line = line;
@@ -364,7 +375,8 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                return 0;
        } else if (strncmp(line, "C ", 2) == 0) {
                /* Reply to CAPABILITY command we sent */
-               client->proxy_state = IMAP_PROXY_STATE_CAPABILITY;
+               imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_CAPABILITY;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_CAPABILITY;
                if (strncmp(line, "C OK ", 5) == 0 &&
                    client->proxy_password != NULL) {
                        /* pipelining was disabled, send the login now. */
@@ -379,7 +391,8 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                /* Reply to ID command we sent, ignore it unless
                   pipelining is disabled, in which case send
                   either STARTTLS or login */
-               client->proxy_state = IMAP_PROXY_STATE_ID;
+               imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_ID;
+               imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_ID;
 
                if (client->proxy_nopipelining) {
                        str = t_str_new(128);
@@ -417,7 +430,8 @@ void imap_proxy_reset(struct client *client)
        imap_client->proxy_logindisabled = FALSE;
        imap_client->proxy_seen_banner = FALSE;
        imap_client->proxy_capability_request_sent = FALSE;
-       client->proxy_state = IMAP_PROXY_STATE_NONE;
+       imap_client->proxy_sent_state = 0;
+       imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_NONE;
 }
 
 void imap_proxy_error(struct client *client, const char *text)
@@ -425,3 +439,19 @@ void imap_proxy_error(struct client *client, const char *text)
        client_send_reply_code(client, IMAP_CMD_REPLY_NO,
                               IMAP_RESP_CODE_UNAVAILABLE, text);
 }
+
+const char *imap_proxy_get_state(struct client *client)
+{
+       struct imap_client *imap_client = (struct imap_client *)client;
+       string_t *str = t_str_new(128);
+
+       for (unsigned int i = 0; i < IMAP_PROXY_SENT_STATE_COUNT; i++) {
+               if (str_len(str) > 0)
+                       str_append_c(str, '+');
+               if ((imap_client->proxy_sent_state & (1 << i)) != 0)
+                       str_append(str, imap_proxy_sent_state_names[i]);
+       }
+       str_append_c(str, '/');
+       str_append(str, imap_proxy_rcvd_state_names[imap_client->proxy_rcvd_state]);
+       return str_c(str);
+}
index 7db1d5a23b2b1d2829bc807151e8cd1b3d8a802c..b437ef509cf86485f0b2a7c24e14480117b52b10 100644 (file)
@@ -5,5 +5,6 @@ void imap_proxy_reset(struct client *client);
 int imap_proxy_parse_line(struct client *client, const char *line);
 
 void imap_proxy_error(struct client *client, const char *text);
+const char *imap_proxy_get_state(struct client *client);
 
 #endif