password-scheme.c revision 9c4d433f42e4d04aca2375c112a57826cd85dfed
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainenstatic const char salt_chars[] =
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
25757faf029c369a8318349dafe952e2358df1d8Timo SirainenARRAY_TYPE(password_scheme_p) password_schemes;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstatic const struct password_scheme *
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen unsigned int i, count;
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen schemes = array_get(&password_schemes, &count);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen for (i = 0; i < count; i++) {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Lookup scheme and encoding by given name. The encoding is taken from
d9b73f3eb3d5f608dfd438cee89ce2b27547173fTimo Sirainen ".base64", ".b64" or ".hex" suffix if it exists, otherwise the default
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen encoding is used. */
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainenstatic const struct password_scheme *
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainenpassword_scheme_lookup(const char *name, enum password_encoding *encoding_r)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen for (scheme_len = 0; name[scheme_len] != '\0'; scheme_len++) {
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen /* unknown encoding. treat as invalid scheme. */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenint password_verify(const char *plaintext, const char *user, const char *scheme,
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen const unsigned char *raw_password, size_t size)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen const struct password_scheme *s;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen const unsigned char *generated;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen s = password_scheme_lookup(scheme, &encoding);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen return s->password_verify(plaintext, user, raw_password, size);
356303df200c991580bd24041996a070ad08c05eTimo Sirainen /* generic verification handler: generate the password and compare it
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen to the one in database */
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen s->password_generate(plaintext, user, &generated, &generated_size);
e15f1d736c225c7ce6f3d08a37c1b2ae66b57c50Timo Sirainenconst char *password_get_scheme(const char **password)
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen const char *p, *scheme;
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen /* $1$<salt>$<password>[$<ignored>] */
356303df200c991580bd24041996a070ad08c05eTimo Sirainen /* stop at next '$' after password */
22535a9e685e29214082878e37a267157044618eTimo Sirainen return "MD5-CRYPT";
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainenint password_decode(const char *password, const char *scheme,
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen const unsigned char **raw_password_r, size_t *size_r)
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen const struct password_scheme *s;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen unsigned int len;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen s = password_scheme_lookup(scheme, &encoding);
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen if (encoding != PW_ENCODING_NONE && s->raw_password_len != 0 &&
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen /* encoding not specified. we can autodetect between
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen base64 and hex encodings. */
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen encoding = len == s->raw_password_len * 2 ? PW_ENCODING_HEX :
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen *raw_password_r = (const unsigned char *)password;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen if (base64_decode(password, len, NULL, buf) < 0)
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (s->raw_password_len != *size_r && s->raw_password_len != 0) {
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen /* password has invalid length */
const char *scheme,
const struct password_scheme *s;
if (s == NULL)
return FALSE;
return TRUE;
const struct password_scheme *s;
const unsigned char *raw_password;
if (s == NULL)
return FALSE;
switch (encoding) {
case PW_ENCODING_NONE:
case PW_ENCODING_BASE64:
case PW_ENCODING_HEX:
return TRUE;
unsigned int i, count;
return TRUE;
for (i = 0; i < count; i++) {
const char *password;
if (size == 0) {
return FALSE;
const char *password;
const char *password;
unsigned char *digest;
unsigned char *digest;
return FALSE;
return FALSE;
unsigned char *context_digest;
unsigned char *digest;
unsigned char *digest;
unsigned char *digest;
unsigned char *digest;
unsigned char *digest;
const char *password;
const char *password;
const char *password;
unsigned char *digest;
unsigned int i, count;
for (i = 0; i < count; i++) {
void password_schemes_init(void)
void password_schemes_deinit(void)