]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-sasl, global: Change dsasl_client_input/output() to return enum
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 18 Jul 2025 10:55:43 +0000 (13:55 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 22 Jul 2025 06:18:51 +0000 (06:18 +0000)
16 files changed:
src/doveadm/doveadm-auth.c
src/imap-login/imap-proxy.c
src/lib-imap-client/imapc-connection.c
src/lib-sasl/dsasl-client-private.h
src/lib-sasl/dsasl-client.c
src/lib-sasl/dsasl-client.h
src/lib-sasl/mech-anonymous.c
src/lib-sasl/mech-external.c
src/lib-sasl/mech-login.c
src/lib-sasl/mech-oauthbearer.c
src/lib-sasl/mech-plain.c
src/lib-sasl/mech-scram.c
src/lib-sasl/test-sasl-client.c
src/lib-smtp/smtp-client-connection.c
src/pop3-login/pop3-proxy.c
src/submission-login/submission-proxy.c

index 939066c81df3193075127675c5d0a9915886dc73..1b015e874ce3a7c4d6916b04cdfd696157efb246 100644 (file)
@@ -204,12 +204,12 @@ auth_callback(struct auth_client_request *request,
                if (base64_decode(data_base64, input_len, buf) < 0)
                        i_fatal("Server sent invalid base64 input");
                if (dsasl_client_input(input->sasl_client, buf->data, buf->used,
-                                      &error) < 0) {
+                                      &error) != DSASL_CLIENT_RESULT_OK) {
                        e_error(input->event, "internal auth failure: %s", error);
                        auth_client_request_abort(&request, error);
                        break;
                } else if (dsasl_client_output(input->sasl_client, &sasl_output,
-                                              &sasl_output_len, &error) < 0) {
+                                              &sasl_output_len, &error) != DSASL_CLIENT_RESULT_OK) {
                        e_error(input->event, "internal auth failure: %s", error);
                        auth_client_request_abort(&request, error);
                        break;
@@ -285,7 +285,8 @@ static void auth_connected(struct auth_client *client,
                i_fatal("SASL mechanism '%s' not supported by server", mech);
 
        if (dsasl_client_output(input->sasl_client, &sasl_output,
-                               &sasl_output_len, &error) < 0)
+                               &sasl_output_len,
+                               &error) != DSASL_CLIENT_RESULT_OK)
                i_fatal("Failed to create initial SASL reply: %s", error);
        sasl_output_base64 =
                t_str_new(MAX_BASE64_ENCODED_SIZE(sasl_output_len));
index 15c5f800af018d62f6ad6d73f5b5effb1a554dba..b58bf1b9ad5b89c36aac36eaf51a9f65b82ff0c8 100644 (file)
@@ -162,7 +162,8 @@ static int proxy_write_login(struct imap_client *client, string_t *str)
        str_append(str, mech_name);
        if (client->proxy_sasl_ir) {
                if (dsasl_client_output(client->common.proxy_sasl_client,
-                                       &output, &len, &error) < 0) {
+                                       &output, &len,
+                                       &error) != DSASL_CLIENT_RESULT_OK) {
                        const char *reason = t_strdup_printf(
                                "SASL mechanism %s init failed: %s",
                                mech_name, error);
@@ -363,13 +364,14 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                                LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason);
                        return -1;
                }
-               ret = dsasl_client_input(client->proxy_sasl_client,
-                                        str_data(str), str_len(str), &error);
-               if (ret == 0) {
-                       ret = dsasl_client_output(client->proxy_sasl_client,
-                                                 &data, &data_len, &error);
+               enum dsasl_client_result sasl_res =
+                       dsasl_client_input(client->proxy_sasl_client,
+                                          str_data(str), str_len(str), &error);
+               if (sasl_res == DSASL_CLIENT_RESULT_OK) {
+                       sasl_res = dsasl_client_output(client->proxy_sasl_client,
+                                                      &data, &data_len, &error);
                }
-               if (ret < 0) {
+               if (sasl_res != DSASL_CLIENT_RESULT_OK) {
                        const char *reason = t_strdup_printf(
                                "Invalid authentication data: %s", error);
                        login_proxy_failed(client->login_proxy,
@@ -377,7 +379,6 @@ int imap_proxy_parse_line(struct client *client, const char *line)
                                LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason);
                        return -1;
                }
-               i_assert(ret == 0);
 
                str_truncate(str, 0);
                base64_encode(data, data_len, str);
index 4fab35f24142156dbca59073f43eb877145b0f1a..b88b00395ca855d34b78db47051e4515a37011ac 100644 (file)
@@ -987,10 +987,11 @@ imapc_connection_authenticate_cb(const struct imapc_command_reply *reply,
                imapc_auth_failed(conn, reply,
                                  t_strdup_printf("Server sent non-base64 input for AUTHENTICATE: %s",
                                                  reply->text_full));
-       } else if (dsasl_client_input(conn->sasl_client, buf->data, buf->used, &error) < 0) {
+       } else if (dsasl_client_input(conn->sasl_client, buf->data, buf->used,
+                                     &error) != DSASL_CLIENT_RESULT_OK) {
                imapc_auth_failed(conn, reply, error);
        } else if (dsasl_client_output(conn->sasl_client, &sasl_output,
-                                      &sasl_output_len, &error) < 0) {
+                                      &sasl_output_len, &error) != DSASL_CLIENT_RESULT_OK) {
                imapc_auth_failed(conn, reply, error);
        } else if (sasl_output_len == 0) {
                o_stream_nsend_str(conn->output, "\r\n");
@@ -1138,7 +1139,8 @@ static void imapc_connection_authenticate(struct imapc_connection *conn)
                const char *error;
 
                if (dsasl_client_output(conn->sasl_client, &sasl_output,
-                                       &sasl_output_len, &error) < 0) {
+                                       &sasl_output_len,
+                                       &error) != DSASL_CLIENT_RESULT_OK) {
                        e_error(conn->event,
                                "Failed to create initial SASL reply: %s",
                                error);
index 8a0cd4f6cb491fb4db5056857bf1a4209bb2c9dc..fc3982ea0f983b25b453b732340e284d6a11a345 100644 (file)
@@ -24,12 +24,14 @@ struct dsasl_client_mech {
        size_t struct_size;
        enum dsasl_mech_security_flags flags;
 
-       int (*input)(struct dsasl_client *client,
-                    const unsigned char *input, size_t input_len,
-                    const char **error_r);
-       int (*output)(struct dsasl_client *client,
-                     const unsigned char **output_r, size_t *output_len_r,
-                     const char **error_r);
+       enum dsasl_client_result
+               (*input)(struct dsasl_client *client,
+                        const unsigned char *input, size_t input_len,
+                        const char **error_r);
+       enum dsasl_client_result
+               (*output)(struct dsasl_client *client,
+                         const unsigned char **output_r, size_t *output_len_r,
+                         const char **error_r);
        int (*set_parameter)(struct dsasl_client *client,
                             const char *key, const char *value,
                             const char **error_r);
index d1e38fef3cb983b502df84ffc23af0a1eb0b7aad..983abd1e65111e17ed0708401bc88b9ecd60137b 100644 (file)
@@ -100,21 +100,23 @@ void dsasl_client_enable_channel_binding(
        client->cbinding_context = context;
 }
 
-int dsasl_client_input(struct dsasl_client *client,
-                      const unsigned char *input, size_t input_len,
-                      const char **error_r)
+enum dsasl_client_result
+dsasl_client_input(struct dsasl_client *client,
+                  const unsigned char *input, size_t input_len,
+                  const char **error_r)
 {
        if ((client->mech->flags & DSASL_MECH_SEC_ALLOW_NULS) == 0 &&
            memchr(input, '\0', input_len) != NULL) {
                *error_r = "Unexpected NUL in input data";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        return client->mech->input(client, input, input_len, error_r);
 }
 
-int dsasl_client_output(struct dsasl_client *client,
-                       const unsigned char **output_r, size_t *output_len_r,
-                       const char **error_r)
+enum dsasl_client_result
+dsasl_client_output(struct dsasl_client *client,
+                   const unsigned char **output_r, size_t *output_len_r,
+                   const char **error_r)
 {
        return client->mech->output(client, output_r, output_len_r, error_r);
 }
index 1fef8ba93b47d37d7f83de0c77342305a6d69b1d..38b2d345c922b5f166292fe1d928a2caed324f96 100644 (file)
@@ -13,6 +13,12 @@ struct dsasl_client_settings {
        const char *password;
 };
 
+enum dsasl_client_result {
+       DSASL_CLIENT_RESULT_OK,
+       /* Client sent invalid SASL protocol input */
+       DSASL_CLIENT_RESULT_ERR_PROTOCOL,
+};
+
 typedef int
 dsasl_client_channel_binding_callback_t(const char *type, void *context,
                                        const buffer_t **data_r,
@@ -36,14 +42,16 @@ void dsasl_client_enable_channel_binding(
        dsasl_client_channel_binding_callback_t *callback, void *context);
 
 /* Call for server input. */
-int dsasl_client_input(struct dsasl_client *client,
-                      const unsigned char *input, size_t input_len,
-                      const char **error_r);
+enum dsasl_client_result
+dsasl_client_input(struct dsasl_client *client,
+                  const unsigned char *input, size_t input_len,
+                  const char **error_r);
 /* Call for getting server output. Also used to get the initial SASL response
    if supported by the protocol. */
-int dsasl_client_output(struct dsasl_client *client,
-                       const unsigned char **output_r, size_t *output_len_r,
-                       const char **error_r);
+enum dsasl_client_result
+dsasl_client_output(struct dsasl_client *client,
+                   const unsigned char **output_r, size_t *output_len_r,
+                   const char **error_r);
 
 /* Call for setting extra parameters for authentication, these are mechanism
    dependent. -1 = error, 0 = not found, 1 = ok
index 1659085932335e79cd4c41329792890cdfdb2ae4..bab0b7f467880aca5494df6bc09463197e321c9b 100644 (file)
@@ -8,7 +8,7 @@ struct anonymous_dsasl_client {
        bool output_sent;
 };
 
-static int
+static enum dsasl_client_result
 mech_anonymous_input(struct dsasl_client *_client,
                    const unsigned char *input ATTR_UNUSED, size_t input_len,
                    const char **error_r)
@@ -19,16 +19,16 @@ mech_anonymous_input(struct dsasl_client *_client,
        if (!client->output_sent) {
                if (input_len > 0) {
                        *error_r = "Server sent non-empty initial response";
-                       return -1;
+                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                }
        } else if (input_len > 0) {
                *error_r = "Server sent non-empty response";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
-static int
+static enum dsasl_client_result
 mech_anonymous_output(struct dsasl_client *_client,
                     const unsigned char **output_r, size_t *output_len_r,
                     const char **error_r ATTR_UNUSED)
@@ -42,7 +42,7 @@ mech_anonymous_output(struct dsasl_client *_client,
        *output_r = (const unsigned char*)authid;
        *output_len_r = strlen(authid);
        client->output_sent = TRUE;
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
 const struct dsasl_client_mech dsasl_client_mech_anonymous = {
index 2484f2d5146d9c0f20cbae1d0a32c2ed99161642..5606fc0d5eca9a94b4f68ce0cfe71ccc848a4a9e 100644 (file)
@@ -8,7 +8,7 @@ struct external_dsasl_client {
        bool output_sent;
 };
 
-static int
+static enum dsasl_client_result
 mech_external_input(struct dsasl_client *_client,
                    const unsigned char *input ATTR_UNUSED, size_t input_len,
                    const char **error_r)
@@ -19,16 +19,16 @@ mech_external_input(struct dsasl_client *_client,
        if (!client->output_sent) {
                if (input_len > 0) {
                        *error_r = "Server sent non-empty initial response";
-                       return -1;
+                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                }
        } else {
                *error_r = "Server didn't finish authentication";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
-static int
+static enum dsasl_client_result
 mech_external_output(struct dsasl_client *_client,
                     const unsigned char **output_r, size_t *output_len_r,
                     const char **error_r ATTR_UNUSED)
@@ -47,7 +47,7 @@ mech_external_output(struct dsasl_client *_client,
        *output_r = (const void *)username;
        *output_len_r = strlen(username);
        client->output_sent = TRUE;
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
 const struct dsasl_client_mech dsasl_client_mech_external = {
index 83714f1fb366b8b41edcd689ace7827db7b9830d..66d7a4e831a67fcaa50fb666bddeb6f3d3314bf4 100644 (file)
@@ -15,7 +15,7 @@ struct login_dsasl_client {
        enum login_state state;
 };
 
-static int
+static enum dsasl_client_result
 mech_login_input(struct dsasl_client *_client,
                 const unsigned char *input ATTR_UNUSED,
                 size_t input_len ATTR_UNUSED,
@@ -26,13 +26,13 @@ mech_login_input(struct dsasl_client *_client,
 
        if (client->state == STATE_PASS) {
                *error_r = "Server didn't finish authentication";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        client->state++;
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
-static int
+static enum dsasl_client_result
 mech_login_output(struct dsasl_client *_client,
                  const unsigned char **output_r, size_t *output_len_r,
                  const char **error_r)
@@ -42,26 +42,26 @@ mech_login_output(struct dsasl_client *_client,
 
        if (_client->set.authid == NULL) {
                *error_r = "authid not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        if (_client->password == NULL) {
                *error_r = "password not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
 
        switch (client->state) {
        case STATE_INIT:
                *output_r = uchar_empty_ptr;
                *output_len_r = 0;
-               return 0;
+               return DSASL_CLIENT_RESULT_OK;
        case STATE_USER:
                *output_r = (const unsigned char *)_client->set.authid;
                *output_len_r = strlen(_client->set.authid);
-               return 0;
+               return DSASL_CLIENT_RESULT_OK;
        case STATE_PASS:
                *output_r = (const unsigned char *)_client->set.password;
                *output_len_r = strlen(_client->set.password);
-               return 0;
+               return DSASL_CLIENT_RESULT_OK;
        }
        i_unreached();
 }
index c9aee473228c2dc962e1ea5eb138a03a8d86d691..0d8c839fea7efe6aee80b992c14fea4724b3dd90 100644 (file)
@@ -15,7 +15,7 @@ struct oauthbearer_dsasl_client {
        bool output_sent;
 };
 
-static int
+static enum dsasl_client_result
 mech_oauthbearer_input(struct dsasl_client *_client,
                 const unsigned char *input, size_t input_len,
                 const char **error_r)
@@ -26,13 +26,13 @@ mech_oauthbearer_input(struct dsasl_client *_client,
        if (!client->output_sent) {
                if (input_len > 0) {
                        *error_r = "Server sent non-empty initial response";
-                       return -1;
+                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                }
        } else {
                client->status = "";
                /* if response is empty, authentication has *SUCCEEDED* */
                if (input_len == 0)
-                       return 0;
+                       return DSASL_CLIENT_RESULT_OK;
 
                /* authentication has failed, try parse status.
                   we are only interested in extracting status if possible
@@ -57,7 +57,7 @@ mech_oauthbearer_input(struct dsasl_client *_client,
                                if (!json_node_is_string(&jnode) &&
                                    !json_node_is_number(&jnode)) {
                                        *error_r = "Status field in response is not a string or a number.";
-                                       return -1;
+                                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                                }
                                client->status = p_strdup(
                                        _client->pool,
@@ -71,23 +71,23 @@ mech_oauthbearer_input(struct dsasl_client *_client,
                if (ret < 0) {
                        *error_r = t_strdup_printf(
                                "Error parsing JSON reply: %s", error);
-                       return -1;
+                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                }
 
                if (client->status == NULL) {
                        *error_r = "Error parsing JSON reply: "
                                "Status value missing";
-                       return -1;
+                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                }
 
                *error_r = t_strdup_printf("Failed to authenticate: %s",
                                           client->status);
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
-static int
+static enum dsasl_client_result
 mech_oauthbearer_output(struct dsasl_client *_client,
                  const unsigned char **output_r, size_t *output_len_r,
                  const char **error_r)
@@ -98,11 +98,11 @@ mech_oauthbearer_output(struct dsasl_client *_client,
 
        if (_client->set.authid == NULL) {
                *error_r = "authid not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        if (_client->password == NULL) {
                *error_r = "password not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
 
        str = str_new(_client->pool, 64);
@@ -118,10 +118,10 @@ mech_oauthbearer_output(struct dsasl_client *_client,
        *output_r = str_data(str);
        *output_len_r = str_len(str);
        client->output_sent = TRUE;
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
-static int
+static enum dsasl_client_result
 mech_xoauth2_output(struct dsasl_client *_client,
                    const unsigned char **output_r, size_t *output_len_r,
                    const char **error_r)
@@ -132,11 +132,11 @@ mech_xoauth2_output(struct dsasl_client *_client,
 
        if (_client->set.authid == NULL) {
                *error_r = "authid not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        if (_client->password == NULL) {
                *error_r = "password not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
 
        str = str_new(_client->pool, 64);
@@ -148,7 +148,7 @@ mech_xoauth2_output(struct dsasl_client *_client,
        *output_r = str_data(str);
        *output_len_r = str_len(str);
        client->output_sent = TRUE;
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
 static int
index 432fa1f3617d1e06cce0e77c27afe87400a1a495..95fe4fa1ef41184f5fa54ff72011f41608916459 100644 (file)
@@ -9,7 +9,7 @@ struct plain_dsasl_client {
        bool output_sent;
 };
 
-static int
+static enum dsasl_client_result
 mech_plain_input(struct dsasl_client *_client,
                 const unsigned char *input ATTR_UNUSED, size_t input_len,
                 const char **error_r)
@@ -20,16 +20,16 @@ mech_plain_input(struct dsasl_client *_client,
        if (!client->output_sent) {
                if (input_len > 0) {
                        *error_r = "Server sent non-empty initial response";
-                       return -1;
+                       return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
                }
        } else {
                *error_r = "Server didn't finish authentication";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
-static int
+static enum dsasl_client_result
 mech_plain_output(struct dsasl_client *_client,
                  const unsigned char **output_r, size_t *output_len_r,
                  const char **error_r)
@@ -40,11 +40,11 @@ mech_plain_output(struct dsasl_client *_client,
 
        if (_client->set.authid == NULL) {
                *error_r = "authid not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        if (_client->password == NULL) {
                *error_r = "password not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
 
        str = str_new(_client->pool, 64);
index 65f0c07b909cea91ef8bb58482c60d47d4f04735..94a5e372163ee23f0004360c4f5f54f525f30fb5 100644 (file)
@@ -87,7 +87,7 @@ static int mech_scram_init(struct scram_dsasl_client *sclient,
        return 0;
 }
 
-static int
+static enum dsasl_client_result
 mech_scram_input(struct dsasl_client *client,
                 const unsigned char *input, size_t input_len,
                 const char **error_r)
@@ -97,13 +97,15 @@ mech_scram_input(struct dsasl_client *client,
 
        if (sclient->scram_client.state == AUTH_SCRAM_CLIENT_STATE_INIT &&
            mech_scram_init(sclient, error_r) < 0)
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
 
-       return auth_scram_client_input(&sclient->scram_client,
-                                      input, input_len, error_r);
+       if (auth_scram_client_input(&sclient->scram_client,
+                                   input, input_len, error_r) < 0)
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
+       return 0;
 }
 
-static int
+static enum dsasl_client_result
 mech_scram_output(struct dsasl_client *client,
                  const unsigned char **output_r, size_t *output_len_r,
                  const char **error_r)
@@ -116,20 +118,20 @@ mech_scram_output(struct dsasl_client *client,
 
        if (client->set.authid == NULL) {
                *error_r = "authid not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
        if (client->password == NULL) {
                *error_r = "password not set";
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
        }
 
        if (sclient->scram_client.state == AUTH_SCRAM_CLIENT_STATE_INIT &&
            mech_scram_init(sclient, error_r) < 0)
-               return -1;
+               return DSASL_CLIENT_RESULT_ERR_PROTOCOL;
 
        auth_scram_client_output(&sclient->scram_client,
                                 output_r, output_len_r);
-       return 0;
+       return DSASL_CLIENT_RESULT_OK;
 }
 
 static void mech_scram_free(struct dsasl_client *client)
index 05b65f22547f49f1e340c9f9b83c1415879ab5b4..8fec4ebd6ed774587f8af0ec5c935ed48b580824 100644 (file)
@@ -42,8 +42,8 @@ static void test_sasl_client_login(void)
 
        /* Any input is valid */
        str_append(input, "Username:");
-       test_assert(dsasl_client_input(client, input->data, input->used, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
+       test_assert(dsasl_client_input(client, input->data, input->used, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
        /* see what we got */
        str_append_data(output_s, output, olen);
        test_assert_strcmp(str_c(output_s), "testuser");
@@ -52,8 +52,8 @@ static void test_sasl_client_login(void)
        str_truncate(output_s, 0);
 
        str_append(input, "Password:");
-       test_assert(dsasl_client_input(client, input->data, input->used, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
+       test_assert(dsasl_client_input(client, input->data, input->used, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
        str_append_data(output_s, output, olen);
        test_assert_strcmp(str_c(output_s), "testpassword");
 
@@ -66,11 +66,11 @@ static void test_sasl_client_login(void)
        /* server sends input after password */
        client = dsasl_client_new(mech, &sasl_set);
        i_assert(client != NULL);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Server didn't finish authentication");
 
        dsasl_client_free(&client);
@@ -79,8 +79,8 @@ static void test_sasl_client_login(void)
        client = dsasl_client_new(mech, &sasl_empty_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "authid not set");
        dsasl_client_free(&client);
 
@@ -88,8 +88,8 @@ static void test_sasl_client_login(void)
        client = dsasl_client_new(mech, &sasl_no_password_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "password not set");
        dsasl_client_free(&client);
 
@@ -99,7 +99,7 @@ static void test_sasl_client_login(void)
 
        str_truncate(input, 0);
        str_append_data(input, "unexpected\0", 11);
-       test_assert(dsasl_client_input(client, input->data, input->used, &error) == -1);
+       test_assert(dsasl_client_input(client, input->data, input->used, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Unexpected NUL in input data");
        dsasl_client_free(&client);
 
@@ -118,8 +118,8 @@ static void test_sasl_client_plain(void)
        const unsigned char *output;
        size_t olen;
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
        const unsigned char expected[] = "\0testuser\0testpassword";
        /* there is no NUL byte at the end */
        test_assert(olen == sizeof(expected) - 1);
@@ -131,8 +131,8 @@ static void test_sasl_client_plain(void)
        client = dsasl_client_new(mech, &sasl_master_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
        const unsigned char expected_master[] =
                "testuser\0masteruser\0masterpassword";
        /* there is no NUL byte at the end */
@@ -146,7 +146,7 @@ static void test_sasl_client_plain(void)
        const unsigned char input[] = "ir";
        client = dsasl_client_new(mech, &sasl_set);
        i_assert(client != NULL);
-       test_assert(dsasl_client_input(client, input, sizeof(input)-1, &error) == -1);
+       test_assert(dsasl_client_input(client, input, sizeof(input)-1, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Server sent non-empty initial response");
 
        dsasl_client_free(&client);
@@ -154,9 +154,9 @@ static void test_sasl_client_plain(void)
        /* server sends input after response */
        client = dsasl_client_new(mech, &sasl_set);
        i_assert(client != NULL);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Server didn't finish authentication");
 
        dsasl_client_free(&client);
@@ -165,8 +165,8 @@ static void test_sasl_client_plain(void)
        client = dsasl_client_new(mech, &sasl_empty_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "authid not set");
        dsasl_client_free(&client);
 
@@ -174,8 +174,8 @@ static void test_sasl_client_plain(void)
        client = dsasl_client_new(mech, &sasl_no_password_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "password not set");
        dsasl_client_free(&client);
 
@@ -184,7 +184,7 @@ static void test_sasl_client_plain(void)
        i_assert(client != NULL);
 
        const unsigned char input2[] = "unexpected\0";
-       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == -1);
+       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Unexpected NUL in input data");
        dsasl_client_free(&client);
 
@@ -203,8 +203,8 @@ static void test_sasl_client_external(void)
        const unsigned char *output;
        size_t olen;
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
        const unsigned char expected[] = "testuser";
        /* there is no NUL byte at the end */
        test_assert(olen == sizeof(expected) - 1);
@@ -216,8 +216,8 @@ static void test_sasl_client_external(void)
        client = dsasl_client_new(mech, &sasl_master_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
        const unsigned char expected_master[] = "testuser";
        /* there is no NUL byte at the end */
        test_assert(olen == sizeof(expected_master) - 1);
@@ -231,7 +231,7 @@ static void test_sasl_client_external(void)
        i_assert(client != NULL);
 
        const unsigned char input2[] = "unexpected\0";
-       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == -1);
+       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Unexpected NUL in input data");
        dsasl_client_free(&client);
 
@@ -252,9 +252,9 @@ static void test_sasl_client_oauthbearer(void)
        const unsigned char *output;
        size_t olen;
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
 
        const unsigned char expected[] = "n,a=testuser,\1"
                "auth=Bearer testpassword\1\1";
@@ -277,9 +277,9 @@ static void test_sasl_client_oauthbearer(void)
        test_assert(dsasl_client_set_parameter(client, "port", "143", &error) == 1);
        test_assert(dsasl_client_set_parameter(client, "unknown", "value", &error) == 0);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
 
        const unsigned char expected_h_p[] = "n,a=testuser,\1"
                "host=example.com\1"
@@ -295,11 +295,11 @@ static void test_sasl_client_oauthbearer(void)
 
        client = dsasl_client_new(mech, &sasl_set);
        /* test error response */
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
        str_append(input, "{\"status\":\"401\",\"schemes\":\"bearer\",\"scope\":\"mail\"}");
-       test_assert(dsasl_client_input(client, input->data, input->used, &error) == -1);
+       test_assert(dsasl_client_input(client, input->data, input->used, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Failed to authenticate: 401");
        test_assert(dsasl_client_get_result(client, "status", &value, &error) == 1);
        test_assert_strcmp(value, "401");
@@ -310,8 +310,8 @@ static void test_sasl_client_oauthbearer(void)
        client = dsasl_client_new(mech, &sasl_empty_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "authid not set");
        dsasl_client_free(&client);
 
@@ -319,8 +319,8 @@ static void test_sasl_client_oauthbearer(void)
        client = dsasl_client_new(mech, &sasl_no_password_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "password not set");
        dsasl_client_free(&client);
 
@@ -329,7 +329,7 @@ static void test_sasl_client_oauthbearer(void)
        i_assert(client != NULL);
 
        const unsigned char input2[] = "unexpected\0";
-       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == -1);
+       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Unexpected NUL in input data");
        dsasl_client_free(&client);
 
@@ -349,9 +349,9 @@ static void test_sasl_client_xoauth2(void)
        const unsigned char *output;
        size_t olen;
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
 
        const unsigned char expected[] = "user=testuser\1auth=Bearer testpassword\1\1";
        /* there is no NUL byte at the end */
@@ -363,11 +363,11 @@ static void test_sasl_client_xoauth2(void)
 
        client = dsasl_client_new(mech, &sasl_set);
        /* test error response */
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == 0);
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
        str_append(input, "{\"status\":\"401\",\"schemes\":\"bearer\",\"scope\":\"mail\"}");
-       test_assert(dsasl_client_input(client, input->data, input->used, &error) == -1);
+       test_assert(dsasl_client_input(client, input->data, input->used, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Failed to authenticate: 401");
 
        dsasl_client_free(&client);
@@ -376,8 +376,8 @@ static void test_sasl_client_xoauth2(void)
        client = dsasl_client_new(mech, &sasl_empty_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "authid not set");
        dsasl_client_free(&client);
 
@@ -385,8 +385,8 @@ static void test_sasl_client_xoauth2(void)
        client = dsasl_client_new(mech, &sasl_no_password_set);
        i_assert(client != NULL);
 
-       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == 0);
-       test_assert(dsasl_client_output(client, &output, &olen, &error) == -1);
+       test_assert(dsasl_client_input(client, uchar_empty_ptr, 0, &error) == DSASL_CLIENT_RESULT_OK);
+       test_assert(dsasl_client_output(client, &output, &olen, &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "password not set");
        dsasl_client_free(&client);
 
@@ -395,7 +395,7 @@ static void test_sasl_client_xoauth2(void)
        i_assert(client != NULL);
 
        const unsigned char input2[] = "unexpected\0";
-       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == -1);
+       test_assert(dsasl_client_input(client, input2, sizeof(input2), &error) == DSASL_CLIENT_RESULT_ERR_PROTOCOL);
        test_assert_strcmp(error, "Unexpected NUL in input data");
        dsasl_client_free(&client);
 
index 5d0abe24e400fa91fb2aa2bd4af08f5fb29fdbe1..87694357562024255d40375674e800bdcfad744f 100644 (file)
@@ -798,11 +798,11 @@ smtp_client_connection_auth_cb(const struct smtp_reply *reply,
                                reply->text_lines[0]);
                } else if (dsasl_client_input(conn->sasl_client,
                                              buf->data, buf->used,
-                                             &error) < 0) {
+                                             &error) != DSASL_CLIENT_RESULT_OK) {
                        error = t_strdup_printf("Authentication failed: %s",
                                                error);
                } else if (dsasl_client_output(conn->sasl_client, &sasl_output,
-                                              &sasl_output_len, &error) < 0) {
+                                              &sasl_output_len, &error) != DSASL_CLIENT_RESULT_OK) {
                        error = t_strdup_printf("Authentication failed: %s",
                                                error);
                } else {
@@ -951,7 +951,7 @@ smtp_client_connection_authenticate(struct smtp_client_connection *conn)
        conn->sasl_client = dsasl_client_new(sasl_mech, &sasl_set);
 
        if (dsasl_client_output(conn->sasl_client, &sasl_output,
-                               &sasl_output_len, &error) < 0) {
+                               &sasl_output_len, &error) != DSASL_CLIENT_RESULT_OK) {
                error = t_strdup_printf(
                        "Failed to create initial %s SASL reply: %s",
                        dsasl_client_mech_get_name(sasl_mech), error);
index befd897d6bf4b9e5714147bd332128d27e9cb631..07e0e7e39a71c0f7d5ab0c053db0d5d0ada8ad70 100644 (file)
@@ -91,7 +91,7 @@ static int proxy_send_login(struct pop3_client *client, struct ostream *output)
 
        str_printfa(str, "AUTH %s ", mech_name);
        if (dsasl_client_output(client->common.proxy_sasl_client,
-                               &sasl_output, &len, &error) < 0) {
+                               &sasl_output, &len, &error) != DSASL_CLIENT_RESULT_OK) {
                const char *reason = t_strdup_printf(
                        "SASL mechanism %s init failed: %s",
                        mech_name, error);
@@ -120,7 +120,6 @@ pop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
        const unsigned char *data;
        size_t data_len;
        const char *error;
-       int ret;
 
        str = t_str_new(128);
        if (base64_decode(line, strlen(line), str) < 0) {
@@ -131,13 +130,14 @@ pop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
                        LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason);
                return -1;
        }
-       ret = dsasl_client_input(client->proxy_sasl_client,
-                                str_data(str), str_len(str), &error);
-       if (ret == 0) {
-               ret = dsasl_client_output(client->proxy_sasl_client,
-                                         &data, &data_len, &error);
+       enum dsasl_client_result sasl_res =
+               dsasl_client_input(client->proxy_sasl_client,
+                                  str_data(str), str_len(str), &error);
+       if (sasl_res == DSASL_CLIENT_RESULT_OK) {
+               sasl_res = dsasl_client_output(client->proxy_sasl_client,
+                                              &data, &data_len, &error);
        }
-       if (ret < 0) {
+       if (sasl_res != DSASL_CLIENT_RESULT_OK) {
                const char *reason = t_strdup_printf(
                        "Invalid authentication data: %s", error);
                login_proxy_failed(client->login_proxy,
@@ -145,7 +145,6 @@ pop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
                                   LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason);
                return -1;
        }
-       i_assert(ret == 0);
 
        str_truncate(str, 0);
        base64_encode(data, data_len, str);
index 7fc77bfc8081de6afe5569ebb03f33a228e142e5..5f711f4a3a51e4ca7e68b1e475391b44b077c444 100644 (file)
@@ -250,7 +250,8 @@ proxy_send_login(struct submission_client *client, struct ostream *output)
 
        str_printfa(str, "AUTH %s", mech_name);
        if (dsasl_client_output(client->common.proxy_sasl_client,
-                               &sasl_output, &sasl_output_len, &error) < 0) {
+                               &sasl_output, &sasl_output_len,
+                               &error) != DSASL_CLIENT_RESULT_OK) {
                const char *reason = t_strdup_printf(
                        "SASL mechanism %s init failed: %s",
                        mech_name, error);
@@ -355,7 +356,6 @@ submission_proxy_continue_sasl_auth(struct client *client,
        const unsigned char *data;
        size_t data_len;
        const char *error;
-       int ret;
 
        if (!last_line) {
                const char *reason = t_strdup_printf(
@@ -392,13 +392,15 @@ submission_proxy_continue_sasl_auth(struct client *client,
                        "Invalid base64 data in AUTH response");
                return -1;
        }
-       ret = dsasl_client_input(client->proxy_sasl_client,
-                                str_data(str), str_len(str), &error);
-       if (ret == 0) {
-               ret = dsasl_client_output(client->proxy_sasl_client,
-                                         &data, &data_len, &error);
+
+       enum dsasl_client_result sasl_res =
+               dsasl_client_input(client->proxy_sasl_client,
+                                  str_data(str), str_len(str), &error);
+       if (sasl_res == DSASL_CLIENT_RESULT_OK) {
+               sasl_res = dsasl_client_output(client->proxy_sasl_client,
+                                              &data, &data_len, &error);
        }
-       if (ret < 0) {
+       if (sasl_res != DSASL_CLIENT_RESULT_OK) {
                const char *reason = t_strdup_printf(
                        "Invalid authentication data: %s", error);
                login_proxy_failed(client->login_proxy,
@@ -406,7 +408,6 @@ submission_proxy_continue_sasl_auth(struct client *client,
                        LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason);
                return -1;
        }
-       i_assert(ret == 0);
 
        str_truncate(str, 0);
        base64_encode(data, data_len, str);