]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Skip authentication with noauthenticate
authorAki Tuomi <aki.tuomi@dovecot.fi>
Sat, 9 Jul 2016 17:11:45 +0000 (20:11 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 11 Jul 2016 14:39:03 +0000 (17:39 +0300)
src/auth/auth-master-connection.c
src/auth/auth-request-handler.c
src/auth/auth-request.c
src/auth/auth-worker-client.c
src/auth/passdb-blocking.c
src/auth/passdb-sql.c
src/auth/passdb.h

index 1b0bedafa149ca9bbdbd0b3abf47eb0b24575103..73e368285bf5ea07c0659d8dac49b4da95f30c78 100644 (file)
@@ -341,6 +341,7 @@ static void pass_callback_finish(struct auth_request *auth_request,
        case PASSDB_RESULT_PASS_EXPIRED:
                str_printfa(str, "NOTFOUND\t%u", auth_request->id);
                break;
+       case PASSDB_RESULT_NEXT:
        case PASSDB_RESULT_PASSWORD_MISMATCH:
        case PASSDB_RESULT_INTERNAL_FAILURE:
                str_printfa(str, "FAIL\t%u", auth_request->id);
index 17d52c655e9781541c27d77ca84528ac3c16b2ba..415b06d68b2c9d0a9401d21275da5632ed9c5cfa 100644 (file)
@@ -305,6 +305,7 @@ auth_request_handler_reply_failure_finish(struct auth_request *request)
        auth_str_append_extra_fields(request, str);
 
        switch (request->passdb_result) {
+       case PASSDB_RESULT_NEXT:
        case PASSDB_RESULT_INTERNAL_FAILURE:
        case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
        case PASSDB_RESULT_USER_UNKNOWN:
index 89ec55d869bb1c35cfb05fcf399d1bf2a87aaf6a..7040fad7f66d1e89038c9da384963c0f3cb0add1 100644 (file)
@@ -485,6 +485,7 @@ static void auth_request_save_cache(struct auth_request *request,
        case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
                /* can be cached */
                break;
+       case PASSDB_RESULT_NEXT:
        case PASSDB_RESULT_USER_DISABLED:
        case PASSDB_RESULT_PASS_EXPIRED:
                /* FIXME: we can't cache this now, or cache lookup would
@@ -652,6 +653,11 @@ auth_request_handle_passdb_callback(enum passdb_result *result,
        case PASSDB_RESULT_INTERNAL_FAILURE:
                result_rule = request->passdb->result_internalfail;
                break;
+       case PASSDB_RESULT_NEXT:
+               auth_request_log_debug(request, AUTH_SUBSYS_DB,
+                       "Not performing authentication (noauthenticate set)");
+               result_rule = AUTH_DB_RULE_CONTINUE;
+               break;
        case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
        case PASSDB_RESULT_USER_UNKNOWN:
        case PASSDB_RESULT_PASSWORD_MISMATCH:
@@ -692,6 +698,7 @@ auth_request_handle_passdb_callback(enum passdb_result *result,
        /* nopassword check is specific to a single passdb and shouldn't leak
           to the next one. we already added it to cache. */
        auth_fields_remove(request->extra_fields, "nopassword");
+       auth_fields_remove(request->extra_fields, "noauthenticate");
 
        if (request->requested_login_user != NULL &&
            *result == PASSDB_RESULT_OK) {
@@ -706,7 +713,7 @@ auth_request_handle_passdb_callback(enum passdb_result *result,
                auth_request_want_skip_passdb(request, next_passdb))
                next_passdb = next_passdb->next;
 
-       if (*result == PASSDB_RESULT_OK) {
+       if (*result == PASSDB_RESULT_OK || *result == PASSDB_RESULT_NEXT) {
                /* this passdb lookup succeeded, preserve its extra fields */
                auth_fields_snapshot(request->extra_fields);
                request->snapshot_have_userdb_prefetch_set =
@@ -777,6 +784,10 @@ void auth_request_verify_plain_callback(enum passdb_result result,
 
        auth_request_set_state(request, AUTH_REQUEST_STATE_MECH_CONTINUE);
 
+       if (result == PASSDB_RESULT_OK &&
+           auth_fields_exists(request->extra_fields, "noauthenticate"))
+               result = PASSDB_RESULT_NEXT;
+
        if (result != PASSDB_RESULT_INTERNAL_FAILURE)
                auth_request_save_cache(request, result);
        else {
@@ -1009,6 +1020,10 @@ void auth_request_lookup_credentials_callback(enum passdb_result result,
 
        auth_request_set_state(request, AUTH_REQUEST_STATE_MECH_CONTINUE);
 
+       if (result == PASSDB_RESULT_OK &&
+           auth_fields_exists(request->extra_fields, "noauthenticate"))
+               result = PASSDB_RESULT_NEXT;
+
        if (result != PASSDB_RESULT_INTERNAL_FAILURE)
                auth_request_save_cache(request, result);
        else {
@@ -2254,7 +2269,8 @@ int auth_request_password_verify(struct auth_request *request,
                return 0;
        }
 
-       if (auth_fields_exists(request->extra_fields, "nopassword")) {
+       if (auth_fields_exists(request->extra_fields, "nopassword") ||
+           auth_fields_exists(request->extra_fields, "noauthenticate")) {
                auth_request_log_debug(request, subsystem,
                                        "Allowing any password");
                return 1;
index fdf72bc4c95b90c7de818a71ebc099251c091fbb..da0bed715d92319a9a1d98a768966286b3d5735e 100644 (file)
@@ -152,7 +152,10 @@ static void verify_plain_callback(enum passdb_result result,
        str_printfa(str, "%u\t", request->id);
 
        if (result == PASSDB_RESULT_OK)
-               str_append(str, "OK");
+               if (auth_fields_exists(request->extra_fields, "noauthenticate"))
+                       str_append(str, "NEXT");
+               else
+                       str_append(str, "OK");
        else
                str_printfa(str, "FAIL\t%d", result);
        if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
@@ -235,10 +238,13 @@ lookup_credentials_callback(enum passdb_result result,
        str = t_str_new(128);
        str_printfa(str, "%u\t", request->id);
 
-       if (result != PASSDB_RESULT_OK)
+       if (result != PASSDB_RESULT_OK && result != PASSDB_RESULT_NEXT)
                str_printfa(str, "FAIL\t%d", result);
        else {
-               str_append(str, "OK\t");
+               if (result == PASSDB_RESULT_NEXT)
+                       str_append(str, "NEXT\t");
+               else
+                       str_append(str, "OK\t");
                str_append_tabescaped(str, request->user);
                str_append_c(str, '\t');
                if (request->credentials_scheme[0] != '\0') {
index 7bf6c6b390971bdafcdc51349811e0ebf1b94a0b..fe8de403c534be86f5e36a9ee64bfeba7cf03741 100644 (file)
@@ -36,6 +36,13 @@ auth_worker_reply_parse(struct auth_request *request, const char *reply)
                return PASSDB_RESULT_OK;
        }
 
+       if (strcmp(*args, "NEXT") == 0 && args[1] != NULL) {
+               /* NEXT \t user [\t extra] */
+               auth_request_set_field(request, "user", args[1], NULL);
+               auth_worker_reply_parse_args(request, args + 1);
+               return PASSDB_RESULT_NEXT;
+       }
+
        if (strcmp(*args, "FAIL") == 0 && args[1] != NULL) {
                int result;
                /* FAIL \t result [\t user \t password [\t extra]] */
index 81a3ba61dc439b0467e341777812cbc04bcd9369..d3f391211a3b8ffc41fe64ab20843cd4334bf2d0 100644 (file)
@@ -99,7 +99,8 @@ static void sql_query_callback(struct sql_result *result,
                        auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
                                "Password query returned multiple matches");
                } else if (auth_request->passdb_password == NULL &&
-                          !auth_fields_exists(auth_request->extra_fields, "nopassword")) {
+                          !auth_fields_exists(auth_request->extra_fields, "nopassword") &&
+                          !auth_fields_exists(auth_request->extra_fields, "noauthenticate")) {
                        auth_request_log_info(auth_request, AUTH_SUBSYS_DB,
                                "Empty password returned without nopassword");
                        passdb_result = PASSDB_RESULT_PASSWORD_MISMATCH;
index 57b25391e1e18ea0b49931322132aa99b464b062..922ec00912f008ee3c88d22a36a72b98db1dc447 100644 (file)
@@ -16,6 +16,7 @@ enum passdb_result {
        PASSDB_RESULT_USER_UNKNOWN = -3,
        PASSDB_RESULT_USER_DISABLED = -4,
        PASSDB_RESULT_PASS_EXPIRED = -5,
+       PASSDB_RESULT_NEXT = -6,
 
        PASSDB_RESULT_PASSWORD_MISMATCH = 0,
        PASSDB_RESULT_OK = 1