]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: mech-scram: Make implementation generic to support other hash algorithms.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 6 Jan 2019 22:08:38 +0000 (23:08 +0100)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Wed, 4 Dec 2019 14:33:31 +0000 (14:33 +0000)
src/auth/Makefile.am
src/auth/mech-scram.c
src/auth/mech-scram.h [new file with mode: 0644]

index bb196e4067d71f953f700f46eb51fe05604df444..a6d75a28bbdc4f13d8f84d2d14d9fc6f9b896bfc 100644 (file)
@@ -164,6 +164,7 @@ headers = \
        auth-master-connection.h \
        mech-otp-skey-common.h \
        mech-plain-common.h \
+       mech-scram.h \
        auth-penalty.h \
        auth-policy.h \
        auth-request.h \
index 252ca15a62aa3ec914c25c0a63ec8e147749f304..b10eac7e5e8a532d4427e15649834d04444348f9 100644 (file)
@@ -21,6 +21,7 @@
 #include "strnum.h"
 #include "password-scheme.h"
 #include "mech.h"
+#include "mech-scram.h"
 
 /* s-nonce length */
 #define SCRAM_SERVER_NONCE_LEN 64
@@ -30,6 +31,9 @@ struct scram_auth_request {
 
        pool_t pool;
 
+       const struct hash_method *hash_method;
+       const char *password_scheme;
+
        /* sent: */
        const char *server_first_message;
        const char *snonce;
@@ -42,8 +46,8 @@ struct scram_auth_request {
        buffer_t *proof;
 
        /* stored */
-       unsigned char stored_key[SHA1_RESULTLEN];
-       unsigned char server_key[SHA1_RESULTLEN];
+       unsigned char *stored_key;
+       unsigned char *server_key;
 };
 
 static const char *get_scram_server_first(struct scram_auth_request *request,
@@ -72,17 +76,17 @@ static const char *get_scram_server_first(struct scram_auth_request *request,
 
 static const char *get_scram_server_final(struct scram_auth_request *request)
 {
+       const struct hash_method *hmethod = request->hash_method;
        struct hmac_context ctx;
        const char *auth_message;
-       unsigned char server_signature[SHA1_RESULTLEN];
+       unsigned char server_signature[hmethod->digest_size];
        string_t *str;
 
        auth_message = t_strconcat(request->client_first_message_bare, ",",
                        request->server_first_message, ",",
                        request->client_final_message_without_proof, NULL);
 
-       hmac_init(&ctx, request->server_key, sizeof(request->server_key),
-                 &hash_method_sha1);
+       hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod);
        hmac_update(&ctx, auth_message, strlen(auth_message));
        hmac_final(&ctx, server_signature);
 
@@ -222,19 +226,19 @@ static bool parse_scram_client_first(struct scram_auth_request *request,
 
 static bool verify_credentials(struct scram_auth_request *request)
 {
+       const struct hash_method *hmethod = request->hash_method;
        struct hmac_context ctx;
        const char *auth_message;
-       unsigned char client_key[SHA1_RESULTLEN];
-       unsigned char client_signature[SHA1_RESULTLEN];
-       unsigned char stored_key[SHA1_RESULTLEN];
+       unsigned char client_key[hmethod->digest_size];
+       unsigned char client_signature[hmethod->digest_size];
+       unsigned char stored_key[hmethod->digest_size];
        size_t i;
 
        auth_message = t_strconcat(request->client_first_message_bare, ",",
                        request->server_first_message, ",",
                        request->client_final_message_without_proof, NULL);
 
-       hmac_init(&ctx, request->stored_key, sizeof(request->stored_key),
-                 &hash_method_sha1);
+       hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod);
        hmac_update(&ctx, auth_message, strlen(auth_message));
        hmac_final(&ctx, client_signature);
 
@@ -242,7 +246,8 @@ static bool verify_credentials(struct scram_auth_request *request)
                client_key[i] =
                        ((char*)request->proof->data)[i] ^ client_signature[i];
 
-       sha1_get_digest(client_key, sizeof(client_key), stored_key);
+       hash_method_get_digest(hmethod, client_key, sizeof(client_key),
+                              stored_key);
 
        safe_memset(client_key, 0, sizeof(client_key));
        safe_memset(client_signature, 0, sizeof(client_signature));
@@ -261,7 +266,8 @@ static void credentials_callback(enum passdb_result result,
 
        switch (result) {
        case PASSDB_RESULT_OK:
-               if (scram_scheme_parse(&hash_method_sha1, "SCRAM-SHA-1",
+               if (scram_scheme_parse(request->hash_method,
+                                      request->password_scheme,
                                       credentials, size, &iter_count, &salt,
                                       request->stored_key, request->server_key,
                                       &error) < 0) {
@@ -291,6 +297,7 @@ static bool parse_scram_client_final(struct scram_auth_request *request,
                                     const unsigned char *data, size_t size,
                                     const char **error_r)
 {
+       const struct hash_method *hmethod = request->hash_method;
        const char **fields, *cbind_input, *nonce_str;
        unsigned int field_count;
        string_t *str;
@@ -328,7 +335,7 @@ static bool parse_scram_client_final(struct scram_auth_request *request,
                        *error_r = "Invalid base64 encoding";
                        return FALSE;
                }
-               if (request->proof->used != SHA1_RESULTLEN) {
+               if (request->proof->used != hmethod->digest_size) {
                        *error_r = "Invalid ClientProof length";
                        return FALSE;
                }
@@ -344,9 +351,8 @@ static bool parse_scram_client_final(struct scram_auth_request *request,
        return TRUE;
 }
 
-static void mech_scram_sha1_auth_continue(struct auth_request *auth_request,
-                                         const unsigned char *data,
-                                         size_t data_size)
+void mech_scram_auth_continue(struct auth_request *auth_request,
+                             const unsigned char *data, size_t data_size)
 {
        struct scram_auth_request *request =
                (struct scram_auth_request *)auth_request;
@@ -358,9 +364,10 @@ static void mech_scram_sha1_auth_continue(struct auth_request *auth_request,
                /* Received client-first-message */
                if (parse_scram_client_first(request, data,
                                             data_size, &error)) {
-                       auth_request_lookup_credentials(&request->auth_request,
-                                                       "SCRAM-SHA-1",
-                                                       credentials_callback);
+                       auth_request_lookup_credentials(
+                               &request->auth_request,
+                               request->password_scheme,
+                               credentials_callback);
                        return;
                }
        } else {
@@ -386,19 +393,32 @@ static void mech_scram_sha1_auth_continue(struct auth_request *auth_request,
        auth_request_fail(auth_request);
 }
 
-static struct auth_request *mech_scram_sha1_auth_new(void)
+struct auth_request *
+mech_scram_auth_new(const struct hash_method *hash_method,
+                   const char *password_scheme)
 {
        struct scram_auth_request *request;
        pool_t pool;
 
-       pool = pool_alloconly_create(MEMPOOL_GROWING"scram_sha1_auth_request", 2048);
+       pool = pool_alloconly_create(MEMPOOL_GROWING"scram_auth_request", 2048);
        request = p_new(pool, struct scram_auth_request, 1);
        request->pool = pool;
 
+       request->hash_method = hash_method;
+       request->password_scheme = password_scheme;
+
+       request->stored_key = p_malloc(pool, hash_method->digest_size);
+       request->server_key = p_malloc(pool, hash_method->digest_size);
+
        request->auth_request.pool = pool;
        return &request->auth_request;
 }
 
+static struct auth_request *mech_scram_sha1_auth_new(void)
+{
+       return mech_scram_auth_new(&hash_method_sha1, "SCRAM-SHA-1");
+}
+
 const struct mech_module mech_scram_sha1 = {
        "SCRAM-SHA-1",
 
@@ -407,6 +427,6 @@ const struct mech_module mech_scram_sha1 = {
 
        mech_scram_sha1_auth_new,
        mech_generic_auth_initial,
-       mech_scram_sha1_auth_continue,
+       mech_scram_auth_continue,
        mech_generic_auth_free
 };
diff --git a/src/auth/mech-scram.h b/src/auth/mech-scram.h
new file mode 100644 (file)
index 0000000..0275aa7
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef MECH_SCRAM_H
+#define MECH_SCRAM_H
+
+struct auth_request *
+mech_scram_auth_new(const struct hash_method *hash_method,
+                   const char *password_scheme);
+void mech_scram_auth_continue(struct auth_request *auth_request,
+                             const unsigned char *data, size_t data_size);
+
+#endif