diff options
Diffstat (limited to 'src/lib-mail/mail-user-hash.c')
-rw-r--r-- | src/lib-mail/mail-user-hash.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/lib-mail/mail-user-hash.c b/src/lib-mail/mail-user-hash.c new file mode 100644 index 0000000..88724a6 --- /dev/null +++ b/src/lib-mail/mail-user-hash.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "md5.h" +#include "str.h" +#include "var-expand.h" +#include "mail-user-hash.h" + +bool mail_user_hash(const char *username, const char *format, + unsigned int *hash_r, const char **error_r) +{ + unsigned char md5[MD5_RESULTLEN]; + unsigned int i, hash = 0; + int ret = 1; + + if (strcmp(format, "%u") == 0) { + /* fast path */ + md5_get_digest(username, strlen(username), md5); + } else if (strcmp(format, "%Lu") == 0) { + /* almost as fast path */ + T_BEGIN { + md5_get_digest(t_str_lcase(username), + strlen(username), md5); + } T_END; + } else T_BEGIN { + const struct var_expand_table tab[] = { + { 'u', username, "user" }, + { 'n', t_strcut(username, '@'), "username" }, + { 'd', i_strchr_to_next(username, '@'), "domain" }, + { '\0', NULL, NULL } + }; + string_t *str = t_str_new(128); + + ret = var_expand(str, format, tab, error_r); + i_assert(ret >= 0); + md5_get_digest(str_data(str), str_len(str), md5); + } T_END_PASS_STR_IF(ret == 0, error_r); + for (i = 0; i < sizeof(hash); i++) + hash = (hash << CHAR_BIT) | md5[i]; + if (hash == 0) { + /* Make sure we don't return the hash as 0, since it's often + treated in a special way that won't work well. For example + trying to insert it into a hash table will assert-crash. */ + hash = 1; + } + *hash_r = hash; + return ret > 0; +} |