]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
pop3-login: Read SASL-IR properly
authorAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 30 Jun 2020 11:02:34 +0000 (14:02 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 3 Jul 2020 06:56:42 +0000 (09:56 +0300)
This fixes issue where login would fail if SASL-IR message would
be too long.

src/pop3-login/client-authenticate.c
src/pop3-login/client-authenticate.h
src/pop3-login/client.c
src/pop3-login/client.h

index a42ea23f343700163c4329277e03ff2e88a21dff..0f5531be0ac9f374d4f8a1093580613c2279d073 100644 (file)
@@ -76,46 +76,61 @@ void pop3_client_auth_result(struct client *client,
        }
 }
 
-bool cmd_auth(struct pop3_client *pop3_client, const char *args)
+int cmd_auth(struct pop3_client *pop3_client, bool *parsed_r)
 {
+       /* NOTE: This command's input is handled specially because the
+          SASL-IR can be large. */
        struct client *client = &pop3_client->common;
-       const struct auth_mech_desc *mech;
-       const char *mech_name, *init_resp, *p;
-
-       if (*args == '\0') {
-               /* Old-style SASL discovery, used by MS Outlook */
-               unsigned int i, count;
-
-               client_send_raw(client, "+OK\r\n");
-               mech = sasl_server_get_advertised_mechs(client, &count);
-               for (i = 0; i < count; i++) {
-                       client_send_raw(client, mech[i].name);
-                       client_send_raw(client, "\r\n");
+       const unsigned char *data;
+       size_t i, size;
+       int ret;
+
+       *parsed_r = FALSE;
+
+       /* <auth mechanism name> [<initial SASL response>] */
+       if (!pop3_client->auth_mech_name_parsed) {
+               data = i_stream_get_data(client->input, &size);
+               for (i = 0; i < size; i++) {
+                       if (data[i] == ' ' ||
+                           data[i] == '\r' || data[i] == '\n')
+                               break;
                }
-               client_send_raw(client, ".\r\n");
-               return TRUE;
-       }
-
-       /* <mechanism name> <initial response> */
-       p = strchr(args, ' ');
-       if (p == NULL) {
-               mech_name = args;
-               /* no initial response */
-               init_resp = NULL;
-       } else {
-               mech_name = t_strdup_until(args, p);
-               init_resp = p + 1;
-               if (*init_resp == '\0') {
-                       /* no initial response */
-                       init_resp = NULL;
-               } else if (strcmp(init_resp, "=") == 0) {
-                       /* empty initial response */
-                       init_resp = "";
+               if (i == size)
+                       return 0;
+               if (i == 0) {
+                       /* Old-style SASL discovery, used by MS Outlook */
+                       unsigned int i, count;
+                       const struct auth_mech_desc *mech;
+
+                       client_send_raw(client, "+OK\r\n");
+                       mech = sasl_server_get_advertised_mechs(client, &count);
+                       for (i = 0; i < count; i++) {
+                               client_send_raw(client, mech[i].name);
+                               client_send_raw(client, "\r\n");
+                       }
+                       client_send_raw(client, ".\r\n");
+                       *parsed_r = TRUE;
+                       return 1;
                }
+               i_free(client->auth_mech_name);
+               client->auth_mech_name = i_strndup(data, i);
+               pop3_client->auth_mech_name_parsed = TRUE;
+               if (data[i] == ' ')
+                       i++;
+               i_stream_skip(client->input, i);
        }
 
-       (void)client_auth_begin(client, mech_name, init_resp);
-       return TRUE;
+       /* get SASL-IR, if any */
+       if ((ret = client_auth_read_line(client)) <= 0)
+               return ret;
+
+       const char *ir = NULL;
+       if (client->auth_response->used > 0)
+               ir = t_strdup(str_c(client->auth_response));
+
+       *parsed_r = TRUE;
+       pop3_client->auth_mech_name_parsed = FALSE;
+       return client_auth_begin(client, t_strdup(client->auth_mech_name), ir);
 }
 
 bool cmd_user(struct pop3_client *pop3_client, const char *args)
index e1eb55cd0fac94df935ba29f2ae66c96c7753cb9..b0a4b9d946fff72a819e61348e7ae2c1afaebe4f 100644 (file)
@@ -9,7 +9,7 @@ void pop3_client_auth_result(struct client *client,
 bool cmd_capa(struct pop3_client *client, const char *args);
 bool cmd_user(struct pop3_client *client, const char *args);
 bool cmd_pass(struct pop3_client *client, const char *args);
-bool cmd_auth(struct pop3_client *client, const char *args);
+int cmd_auth(struct pop3_client *client, bool *parsed_r);
 bool cmd_apop(struct pop3_client *client, const char *args);
 
 #endif
index cae6442046f1aa3704973f3505999dcb7ccae467..1cef4cc4eb07bc2aed3f5b27181b974a576c6572 100644 (file)
@@ -95,8 +95,6 @@ static bool client_command_execute(struct pop3_client *client, const char *cmd,
                return cmd_user(client, args);
        if (strcmp(cmd, "PASS") == 0)
                return cmd_pass(client, args);
-       if (strcmp(cmd, "AUTH") == 0)
-               return cmd_auth(client, args);
        if (strcmp(cmd, "APOP") == 0)
                return cmd_apop(client, args);
        if (strcmp(cmd, "STLS") == 0)
@@ -164,8 +162,19 @@ static bool pop3_client_input_next_cmd(struct client *client)
        const char *cmd, *args;
        bool parsed;
 
-       if (!client_read_cmd_name(client, &cmd))
+       if (!pop3_client->authenticating && !client_read_cmd_name(client, &cmd))
                return FALSE;
+
+       if (pop3_client->authenticating ||
+           strcmp(cmd, "AUTH") == 0) {
+               pop3_client->authenticating = TRUE;
+               int ret = cmd_auth(pop3_client, &parsed);
+               if (ret == 0 || !parsed)
+                       return FALSE;
+               pop3_client->authenticating = !parsed;
+               return parsed;
+       }
+
        if ((args = i_stream_next_line(client->input)) == NULL)
                return FALSE;
 
index 498fe82e194d99a5c404577f9bc11d89c494f69f..7a24f54fa11c7320a76cac5ef564f17bd5fe117c 100644 (file)
@@ -23,6 +23,8 @@ struct pop3_client {
        unsigned int apop_server_pid, apop_connect_uid;
        enum pop3_proxy_state proxy_state;
        bool proxy_xclient;
+       bool auth_mech_name_parsed;
+       bool authenticating;
 };
 
 enum pop3_cmd_reply {