]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Use hash table for schemes
authorAki Tuomi <aki.tuomi@dovecot.fi>
Fri, 28 Jul 2017 07:09:06 +0000 (10:09 +0300)
committerAki Tuomi <aki.tuomi@dovecot.fi>
Mon, 14 Aug 2017 11:52:01 +0000 (14:52 +0300)
src/auth/password-scheme.c
src/auth/password-scheme.h
src/doveadm/doveadm-pw.c

index 2362e285b23982f12f117edbd603612fd7127a16..8b6956f73c50c0c765277f8fc7573a3884dfe646 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "hash.h"
 #include "base64.h"
 #include "hex-binary.h"
 #include "md4.h"
 static const char salt_chars[] =
        "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
-ARRAY_TYPE(password_scheme_p) password_schemes;
+static HASH_TABLE(const char*, const struct password_scheme *) password_schemes;
 
 static const struct password_scheme *
 password_scheme_lookup_name(const char *name)
 {
-       const struct password_scheme *const *schemes;
-
-       array_foreach(&password_schemes, schemes) {
-               const struct password_scheme *scheme = *schemes;
-
-               if (strcasecmp(scheme->name, name) == 0)
-                       return scheme;
-       }
-       return NULL;
+       return hash_table_lookup(password_schemes, name);
 }
 
 /* Lookup scheme and encoding by given name. The encoding is taken from
@@ -272,7 +265,7 @@ const char *password_generate_salt(size_t len)
 
 bool password_scheme_is_alias(const char *scheme1, const char *scheme2)
 {
-       const struct password_scheme *const *schemes, *s1 = NULL, *s2 = NULL;
+       const struct password_scheme *s1 = NULL, *s2 = NULL;
 
        scheme1 = t_strcut(scheme1, '.');
        scheme2 = t_strcut(scheme2, '.');
@@ -280,14 +273,8 @@ bool password_scheme_is_alias(const char *scheme1, const char *scheme2)
        if (strcasecmp(scheme1, scheme2) == 0)
                return TRUE;
 
-       array_foreach(&password_schemes, schemes) {
-               const struct password_scheme *scheme = *schemes;
-
-               if (strcasecmp(scheme->name, scheme1) == 0)
-                       s1 = scheme;
-               else if (strcasecmp(scheme->name, scheme2) == 0)
-                       s2 = scheme;
-       }
+       s1 = hash_table_lookup(password_schemes, scheme1);
+       s2 = hash_table_lookup(password_schemes, scheme2);
 
        /* if they've the same generate function, they're equivalent */
        return s1 != NULL && s2 != NULL &&
@@ -298,25 +285,27 @@ const char *
 password_scheme_detect(const char *plain_password, const char *crypted_password,
                       const char *user)
 {
-       const struct password_scheme *const *schemes;
-       unsigned int i, count;
+       struct hash_iterate_context *ctx;
+       const char *key;
+       const struct password_scheme *scheme;
        const unsigned char *raw_password;
        size_t raw_password_size;
        const char *error;
 
-       schemes = array_get(&password_schemes, &count);
-       for (i = 0; i < count; i++) {
-               if (password_decode(crypted_password, schemes[i]->name,
+       ctx = hash_table_iterate_init(password_schemes);
+       while (hash_table_iterate(ctx, password_schemes, &key, &scheme)) {
+               if (password_decode(crypted_password, scheme->name,
                                    &raw_password, &raw_password_size,
                                    &error) <= 0)
                        continue;
 
-               if (password_verify(plain_password, user, schemes[i]->name,
+               if (password_verify(plain_password, user, scheme->name,
                                    raw_password, raw_password_size,
                                    &error) > 0)
-                       return schemes[i]->name;
+                       break;
+               key = NULL;
        }
-       return NULL;
+       return key;
 }
 
 int crypt_verify(const char *plaintext, const char *user ATTR_UNUSED,
@@ -847,29 +836,34 @@ void password_scheme_register(const struct password_scheme *scheme)
                i_panic("password_scheme_register(%s): Already registered",
                        scheme->name);
        }
-       array_append(&password_schemes, &scheme, 1);
+       hash_table_insert(password_schemes, scheme->name, scheme);
 }
 
 void password_scheme_unregister(const struct password_scheme *scheme)
 {
-       const struct password_scheme *const *schemes;
-       unsigned int idx;
+       if (!hash_table_try_remove(password_schemes, scheme->name))
+               i_panic("password_scheme_unregister(%s): Not registered", scheme->name);
+}
 
-       array_foreach(&password_schemes, schemes) {
-               if (strcasecmp((*schemes)->name, scheme->name) == 0) {
-                       idx = array_foreach_idx(&password_schemes, schemes);
-                       array_delete(&password_schemes, idx, 1);
-                       return;
-               }
-       }
-       i_panic("password_scheme_unregister(%s): Not registered", scheme->name);
+void password_schemes_get(ARRAY_TYPE(password_scheme_p) *schemes_r)
+{
+        struct hash_iterate_context *ctx;
+        const char *key;
+        const struct password_scheme *scheme;
+        ctx = hash_table_iterate_init(password_schemes);
+        while(hash_table_iterate(ctx, password_schemes, &key, &scheme)) {
+               array_append(schemes_r, &scheme, 1);
+        }
+       hash_table_iterate_deinit(&ctx);
 }
 
 void password_schemes_init(void)
 {
        unsigned int i;
 
-       i_array_init(&password_schemes, N_ELEMENTS(builtin_schemes) + 4);
+       hash_table_create(&password_schemes, default_pool,
+                         N_ELEMENTS(builtin_schemes)*2, strfastcase_hash,
+                         strcasecmp);
        for (i = 0; i < N_ELEMENTS(builtin_schemes); i++)
                password_scheme_register(&builtin_schemes[i]);
        password_scheme_register_crypt();
@@ -877,5 +871,5 @@ void password_schemes_init(void)
 
 void password_schemes_deinit(void)
 {
-       array_free(&password_schemes);
+       hash_table_destroy(&password_schemes);
 }
index 35feee9d249c5e424bee4f46689015b2e998e0de..0f1a8cc4855f182d2a988f1b031b5996b9da6861 100644 (file)
@@ -23,8 +23,8 @@ struct password_scheme {
                                  size_t *size_r);
 };
 ARRAY_DEFINE_TYPE(password_scheme_p, const struct password_scheme *);
+void password_schemes_get(ARRAY_TYPE(password_scheme_p) *schemes_r);
 
-extern ARRAY_TYPE(password_scheme_p) password_schemes;
 extern unsigned int password_scheme_encryption_rounds;
 
 /* Returns 1 = matched, 0 = didn't match, -1 = unknown scheme or invalid
index 1706f564f1c773d267a62d1a8acc4caad3457c18..ec24f9b9ea9e4364f32736bef7cb025f8b17597e 100644 (file)
@@ -73,10 +73,12 @@ static void cmd_pw(int argc, char *argv[])
        }
 
        if (list_schemes) {
+               ARRAY_TYPE(password_scheme_p) arr;
                const struct password_scheme *const *schemes;
                unsigned int i, count;
-
-               schemes = array_get(&password_schemes, &count);
+               t_array_init(&arr, 30);
+               password_schemes_get(&arr);
+               schemes = array_get(&arr, &count);
                for (i = 0; i < count; i++)
                        printf("%s ", schemes[i]->name);
                printf("\n");