]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: mech-oauth2 - Always fail with protocol specific error
authorAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 15 May 2023 10:49:58 +0000 (13:49 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 29 Aug 2023 07:08:45 +0000 (07:08 +0000)
src/auth/mech-oauth2.c

index c51d16f73f81a8ee2a9d65b9e5c73d3c0491ff02..dae563291d73c82ed2ab450fe8462d938c4f8167 100644 (file)
@@ -65,8 +65,6 @@ static void oauth2_verify_callback(enum passdb_result result,
                                   const char *const *error_fields,
                                   struct auth_request *request)
 {
-       struct oauth2_auth_request *oauth2_req =
-                       (struct oauth2_auth_request*)request;
        const char *oidc_url;
 
        i_assert(result == PASSDB_RESULT_OK || error_fields != NULL);
@@ -75,8 +73,8 @@ static void oauth2_verify_callback(enum passdb_result result,
                auth_request_success(request, "", 0);
                break;
        case PASSDB_RESULT_INTERNAL_FAILURE:
-               auth_request_internal_failure(request);
-               break;
+               request->internal_failure = TRUE;
+               /* fall through */
        default:
                /* we could get new token after this */
                if (request->mech_password != NULL)
@@ -108,13 +106,24 @@ static void oauth2_verify_callback(enum passdb_result result,
                        str_append_c(error, '"');
                }
                str_append_c(error, '}');
-               auth_request_handler_reply_continue(request, str_data(error),
-                                                   str_len(error));
-               oauth2_req->failed = TRUE;
+               auth_request_fail_with_reply(request, str_data(error), str_len(error));
                break;
        }
 }
 
+static void mech_oauth2_verify_token(struct auth_request *request,
+                                    const char *token,
+                                    enum passdb_result result,
+                                    verify_plain_callback_t callback)
+{
+       i_assert(token != NULL);
+       if (result != PASSDB_RESULT_OK) {
+               request->passdb_result = result;
+               request->failed = TRUE;
+       }
+       auth_request_verify_plain(request, token, callback);
+}
+
 static void
 xoauth2_verify_callback(enum passdb_result result, struct auth_request *request)
 {
@@ -145,16 +154,6 @@ mech_xoauth2_auth_continue(struct auth_request *request,
                           const unsigned char *data,
                           size_t data_size)
 {
-       struct oauth2_auth_request *oauth2_req =
-                       (struct oauth2_auth_request*)request;
-
-       /* Specification says that client is sent "invalid token" challenge
-          which the client is supposed to ack with empty response */
-       if (oauth2_req->failed) {
-               auth_request_fail(request);
-               return;
-       }
-
        /* split the data from ^A */
        bool user_given = FALSE;
        const char *error;
@@ -177,7 +176,8 @@ mech_xoauth2_auth_continue(struct auth_request *request,
                        } else {
                                e_info(request->mech_event,
                                       "Invalid continued data");
-                               auth_request_fail(request);
+                               xoauth2_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                                       request);
                                return;
                        }
                }
@@ -187,16 +187,16 @@ mech_xoauth2_auth_continue(struct auth_request *request,
        if (user_given && !auth_request_set_username(request, username, &error)) {
                e_info(request->mech_event,
                       "%s", error);
-               auth_request_fail(request);
+               xoauth2_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
                return;
        }
 
        if (user_given && token != NULL)
-               auth_request_verify_plain(request, token,
-                                         xoauth2_verify_callback);
+               mech_oauth2_verify_token(request, token, PASSDB_RESULT_OK,
+                                        xoauth2_verify_callback);
        else {
                e_info(request->mech_event, "Username or token missing");
-               auth_request_fail(request);
+               xoauth2_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
        }
 }
 
@@ -208,14 +208,6 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
                               const unsigned char *data,
                               size_t data_size)
 {
-       struct oauth2_auth_request *oauth2_req =
-                       (struct oauth2_auth_request*)request;
-
-       if (oauth2_req->failed) {
-               auth_request_fail(request);
-               return;
-       }
-
        bool user_given = FALSE;
        const char *error;
        const char *username;
@@ -228,7 +220,8 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
        if (*fields == NULL || *(fields[0]) == '\0') {
                e_info(request->mech_event,
                       "Invalid continued data");
-               auth_request_fail(request);
+               oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                           request);
                return;
        }
 
@@ -238,13 +231,15 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
                case 'f':
                        e_info(request->mech_event,
                               "Client requested non-standard mechanism");
-                       auth_request_fail(request);
+                       oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                                   request);
                        return;
                case 'p':
                        /* channel binding is not supported */
                        e_info(request->mech_event,
                               "Client requested and used channel-binding");
-                       auth_request_fail(request);
+                       oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                                   request);
                        return;
                case 'n':
                case 'y':
@@ -255,8 +250,9 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
                            !oauth2_unescape_username((*ptr)+2, &username)) {
                                 e_info(request->mech_event,
                                        "Invalid username escaping");
-                                auth_request_fail(request);
-                                return;
+                               oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                                           request);
+                               return;
                        } else {
                                user_given = TRUE;
                        }
@@ -264,7 +260,8 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
                default:
                        e_info(request->mech_event,
                               "Invalid gs2-header in request");
-                       auth_request_fail(request);
+                       oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                                   request);
                        return;
                }
        }
@@ -278,7 +275,8 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
                        } else {
                                e_info(request->mech_event,
                                       "Invalid continued data");
-                               auth_request_fail(request);
+                               oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                                           request);
                                return;
                        }
                }
@@ -287,15 +285,17 @@ mech_oauthbearer_auth_continue(struct auth_request *request,
        if (user_given && !auth_request_set_username(request, username, &error)) {
                e_info(request->mech_event,
                       "%s", error);
-               auth_request_fail(request);
+               oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                           request);
                return;
        }
        if (user_given && token != NULL)
-               auth_request_verify_plain(request, token,
-                                         oauthbearer_verify_callback);
+               mech_oauth2_verify_token(request, token, PASSDB_RESULT_OK,
+                                        oauthbearer_verify_callback);
        else {
                e_info(request->mech_event, "Missing username or token");
-               auth_request_fail(request);
+               oauthbearer_verify_callback(PASSDB_RESULT_PASSWORD_MISMATCH,
+                                           request);
        }
 }