]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
login-common: Added result codes for mechanism-related failures.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Wed, 2 Nov 2016 00:31:40 +0000 (01:31 +0100)
committerGitLab <gitlab@git.dovecot.net>
Wed, 2 Nov 2016 12:01:45 +0000 (14:01 +0200)
src/imap-login/client-authenticate.c
src/lib-auth/auth-client-interface.h
src/login-common/client-common-auth.c
src/login-common/client-common.c
src/login-common/client-common.h
src/login-common/sasl-server.c
src/login-common/sasl-server.h
src/pop3-login/client-authenticate.c

index 8dc689aae8590b3a85cbbfbb28aebb39d061eaae..add783ac6ae696816d89a38d22dcb5da8a75bf80 100644 (file)
@@ -78,6 +78,7 @@ void imap_client_auth_result(struct client *client,
                client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
                break;
        case CLIENT_AUTH_RESULT_AUTHFAILED_REASON:
+       case CLIENT_AUTH_RESULT_MECH_INVALID:
                if (text[0] == '[')
                        client_send_reply(client, IMAP_CMD_REPLY_NO, text);
                else {
@@ -94,6 +95,7 @@ void imap_client_auth_result(struct client *client,
                                       IMAP_RESP_CODE_UNAVAILABLE, text);
                break;
        case CLIENT_AUTH_RESULT_SSL_REQUIRED:
+       case CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED:
                client_send_reply_code(client, IMAP_CMD_REPLY_NO,
                                       IMAP_RESP_CODE_PRIVACYREQUIRED, text);
                break;
index 493f6ec120d65b69ddfb6debafc844dd2109536d..c58c7bc1d9087e5aff230701c1275fc4b5038e60 100644 (file)
@@ -32,4 +32,8 @@ enum mech_security_flags {
 #define AUTH_CLIENT_FAIL_CODE_USER_DISABLED     "user_disabled"
 #define AUTH_CLIENT_FAIL_CODE_PASS_EXPIRED      "pass_expired"
 
+/* not actually returned from auth service */
+#define AUTH_CLIENT_FAIL_CODE_MECH_INVALID      "auth_mech_invalid"
+#define AUTH_CLIENT_FAIL_CODE_MECH_SSL_REQUIRED "auth_mech_ssl_required"
+
 #endif
index a18f5419cdf94c966af0257a22b2001e761f5302..8bc59e4fce31a7fd22c272d0d5402ac8c37aa98e 100644 (file)
@@ -37,6 +37,10 @@ static const struct client_auth_fail_code_id client_auth_fail_codes[] = {
                CLIENT_AUTH_FAIL_CODE_USER_DISABLED },
        { AUTH_CLIENT_FAIL_CODE_PASS_EXPIRED,
                CLIENT_AUTH_FAIL_CODE_PASS_EXPIRED },
+       { AUTH_CLIENT_FAIL_CODE_MECH_INVALID,
+               CLIENT_AUTH_FAIL_CODE_MECH_INVALID },
+       { AUTH_CLIENT_FAIL_CODE_MECH_SSL_REQUIRED,
+               CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED },
        { NULL, CLIENT_AUTH_FAIL_CODE_NONE }
 };
 
@@ -527,6 +531,12 @@ client_auth_handle_reply(struct client *client,
                case CLIENT_AUTH_FAIL_CODE_PASS_EXPIRED:
                        result = CLIENT_AUTH_RESULT_PASS_EXPIRED;
                        break;
+               case CLIENT_AUTH_FAIL_CODE_MECH_INVALID:
+                       result = CLIENT_AUTH_RESULT_MECH_INVALID;
+                       break;
+               case CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED:
+                       result = CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED;
+                       break;
                case CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED:
                        result = CLIENT_AUTH_RESULT_LOGIN_DISABLED;
                        if (reason == NULL)
@@ -570,7 +580,7 @@ void client_auth_abort(struct client *client)
 
 void client_auth_fail(struct client *client, const char *text)
 {
-       sasl_server_auth_failed(client, text);
+       sasl_server_auth_failed(client, text, NULL);
 }
 
 int client_auth_read_line(struct client *client)
@@ -768,8 +778,10 @@ int client_auth_begin(struct client *client, const char *mech_name,
 
 bool client_check_plaintext_auth(struct client *client, bool pass_sent)
 {
+       bool ssl_required = (strcmp(client->ssl_set->ssl, "required") == 0);
+
        if (client->secured || (!client->set->disable_plaintext_auth &&
-                               strcmp(client->ssl_set->ssl, "required") != 0))
+                               !ssl_required))
                return TRUE;
 
        if (client->set->auth_verbose) {
@@ -782,9 +794,14 @@ bool client_check_plaintext_auth(struct client *client, bool pass_sent)
                         "without SSL/TLS, but your client did it anyway. "
                         "If anyone was listening, the password was exposed.");
        }
-       client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
+
+       if (ssl_required) {
+               client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
+                          AUTH_PLAINTEXT_DISABLED_MSG);
+       } else {
+               client_auth_result(client, CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED, NULL,
                           AUTH_PLAINTEXT_DISABLED_MSG);
-       client->auth_tried_disabled_plaintext = TRUE;
+       }
        client->auth_attempts++;
        return FALSE;
 }
index c8bbca801fa02280ecaa637b04c4195fa80cfeab..ecadbd24ad90532bbddaa22878a829e109578b7d 100644 (file)
@@ -720,13 +720,10 @@ const char *client_get_extra_disconnect_reason(struct client *client)
        }
 
        /* some auth attempts without SSL/TLS */
-       if (client->auth_tried_disabled_plaintext)
-               return "(tried to use disallowed plaintext auth)";
        if (client->set->auth_ssl_require_client_cert &&
            client->ssl_proxy == NULL)
                return "(cert required, client didn't start TLS)";
-       if (client->auth_tried_unsupported_mech)
-               return "(tried to use unsupported auth mechanism)";
+
        if (client->auth_waiting && client->auth_attempts == 1) {
                return t_strdup_printf("(client didn't finish SASL auth, "
                                       "waited %u secs)", auth_secs);
@@ -764,6 +761,10 @@ const char *client_get_extra_disconnect_reason(struct client *client)
                return "(password expired)";
        case CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED:
                return "(login disabled)";
+       case CLIENT_AUTH_FAIL_CODE_MECH_INVALID:
+               return "(tried to use unsupported auth mechanism)";
+       case CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED:
+               return "(tried to use disallowed plaintext auth)";
        default:
                break;
        }
index e6ec6f60a7cd0ef33d2dada4e5dac943e8ca272f..da0a7b298c82e20fe74fed69a1daff9400d2f6fb 100644 (file)
@@ -50,6 +50,8 @@ enum client_auth_fail_code {
        CLIENT_AUTH_FAIL_CODE_USER_DISABLED,
        CLIENT_AUTH_FAIL_CODE_PASS_EXPIRED,
        CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED,
+       CLIENT_AUTH_FAIL_CODE_MECH_INVALID,
+       CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED,
 };
 
 enum client_auth_result {
@@ -64,6 +66,8 @@ enum client_auth_result {
        CLIENT_AUTH_RESULT_PASS_EXPIRED,
        CLIENT_AUTH_RESULT_SSL_REQUIRED,
        CLIENT_AUTH_RESULT_LOGIN_DISABLED,
+       CLIENT_AUTH_RESULT_MECH_INVALID,
+       CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED
 };
 
 struct client_auth_reply {
@@ -182,8 +186,6 @@ struct client {
        bool trusted:1;
        bool ssl_servername_settings_read:1;
        bool authenticating:1;
-       bool auth_tried_disabled_plaintext:1;
-       bool auth_tried_unsupported_mech:1;
        bool auth_try_aborted:1;
        bool auth_initializing:1;
        bool auth_process_comm_fail:1;
index 097b83db93313c25e50ed6cea9b9d8ad48ab1177..d01d62abb0e19ae995145686d52344ee62b9e7e9 100644 (file)
@@ -336,17 +336,17 @@ void sasl_server_auth_begin(struct client *client,
 
        mech = auth_client_find_mech(auth_client, mech_name);
        if (mech == NULL) {
-               client->auth_tried_unsupported_mech = TRUE;
                sasl_server_auth_failed(client,
-                       "Unsupported authentication mechanism.");
+                       "Unsupported authentication mechanism.",
+                       AUTH_CLIENT_FAIL_CODE_MECH_INVALID);
                return;
        }
 
        if (!client->secured && client->set->disable_plaintext_auth &&
            (mech->flags & MECH_SEC_PLAINTEXT) != 0) {
-               client->auth_tried_disabled_plaintext = TRUE;
                sasl_server_auth_failed(client,
-                       "Plaintext authentication disabled.");
+                       "Plaintext authentication disabled.",
+                        AUTH_CLIENT_FAIL_CODE_MECH_SSL_REQUIRED);
                return;
        }
 
@@ -373,9 +373,9 @@ void sasl_server_auth_begin(struct client *client,
                                        authenticate_callback, client);
 }
 
-static void ATTR_NULL(2)
+static void ATTR_NULL(2, 3)
 sasl_server_auth_cancel(struct client *client, const char *reason,
-                       enum sasl_server_reply reply)
+                       const char *code, enum sasl_server_reply reply)
 {
        i_assert(client->authenticating);
 
@@ -390,16 +390,26 @@ sasl_server_auth_cancel(struct client *client, const char *reason,
        if (client->auth_request != NULL)
                auth_client_request_abort(&client->auth_request);
 
+       if (code != NULL) {
+               const char *args[2];
+
+               args[0] = t_strconcat("code=", code, NULL);
+               args[1] = NULL;
+               call_client_callback(client, reply, reason, args);
+               return;
+       }
+
        call_client_callback(client, reply, reason, NULL);
 }
 
-void sasl_server_auth_failed(struct client *client, const char *reason)
+void sasl_server_auth_failed(struct client *client, const char *reason,
+       const char *code)
 {
-       sasl_server_auth_cancel(client, reason, SASL_SERVER_REPLY_AUTH_FAILED);
+       sasl_server_auth_cancel(client, reason, code, SASL_SERVER_REPLY_AUTH_FAILED);
 }
 
 void sasl_server_auth_abort(struct client *client)
 {
        client->auth_try_aborted = TRUE;
-       sasl_server_auth_cancel(client, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
+       sasl_server_auth_cancel(client, NULL, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
 }
index 7c8940ba18912f311c07460a39cc2873838251b3..bd5103ac00f0b9560443c1e10fdc5d3044fda9b3 100644 (file)
@@ -22,7 +22,8 @@ void sasl_server_auth_begin(struct client *client,
                            const char *service, const char *mech_name,
                            const char *initial_resp_base64,
                            sasl_server_callback_t *callback);
-void sasl_server_auth_failed(struct client *client, const char *reason);
+void sasl_server_auth_failed(struct client *client, const char *reason,
+       const char *code) ATTR_NULL(3);
 void sasl_server_auth_abort(struct client *client);
 
 #endif
index b3e1e236211a309605a5a02c4fa899d6ea8ab16a..6d90e5cc2bc4e563b2f1863048c8cc3078b0767c 100644 (file)
@@ -66,6 +66,8 @@ void pop3_client_auth_result(struct client *client,
        case CLIENT_AUTH_RESULT_PASS_EXPIRED:
        case CLIENT_AUTH_RESULT_SSL_REQUIRED:
        case CLIENT_AUTH_RESULT_LOGIN_DISABLED:
+       case CLIENT_AUTH_RESULT_MECH_INVALID:
+       case CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED:
                client_send_reply(client, POP3_CMD_REPLY_AUTH_ERROR, text);
                break;
        default: