--- dovecot-0.99.10.4/src/auth/passdb-ldap.c.orig Fri Mar 21 02:55:57 2003 +++ dovecot-0.99.10.4/src/auth/passdb-ldap.c Tue Feb 3 12:19:17 2004 @@ -11,6 +11,9 @@ #include "password-scheme.h" #include "db-ldap.h" #include "passdb.h" +#include "base64.h" +#include "buffer.h" +#include "hex-binary.h" #include #include @@ -54,6 +57,7 @@ struct auth_request *auth_request = request->context; LDAPMessage *entry; BerElement *ber; + buffer_t *buf; char *attr, **vals; const char *user, *password, *scheme; int ret; @@ -102,6 +106,16 @@ if (scheme == NULL) { scheme = conn->set.default_pass_scheme; i_assert(scheme != NULL); + } + + /* Special case for OpenLDAP's MD5 type */ + if (strcasecmp(scheme, "MD5") == 0) { + buf = buffer_create_static(data_stack_pool, 16); + if (base64_decode(password, strlen(password), NULL, buf) == 1 + && buffer_get_used_size(buf) == 16) { + password = binary_to_hex(buffer_get_data(buf, NULL), 16); + scheme = "PLAIN-MD5"; + } } if (ldap_request->credentials != -1) { --- dovecot-0.99.10.4/src/auth/password-scheme.c.orig Sun May 4 04:32:59 2003 +++ dovecot-0.99.10.4/src/auth/password-scheme.c Tue Feb 3 12:20:57 2004 @@ -2,6 +2,8 @@ #include "lib.h" #include "hex-binary.h" +#include "base64.h" +#include "buffer.h" #include "md5.h" #include "md5crypt.h" #include "mycrypt.h" @@ -16,6 +18,10 @@ { unsigned char digest[16]; const char *realm, *str; + buffer_t *buf; + size_t size; + const void *data; + struct md5_context ctx; if (password == NULL) return 0; @@ -48,6 +54,29 @@ return strcasecmp(str, password) == 0; } + /* format: base64-encoded MD5 hash and salt */ + if (strcasecmp(scheme, "SMD5") == 0) { + buf = buffer_create_static(data_stack_pool, + MAX_BASE64_DECODED_SIZE(strlen(password)+1)); + + if (base64_decode(password, strlen(password), NULL, buf) == 1) { + data = buffer_get_data(buf, &size); + if (size <= 16) { + i_error("password-verify(%s): invalid SMD5", user); + return -1; + } + + md5_init(&ctx); + md5_update(&ctx, plaintext, strlen(plaintext)); + md5_update(&ctx, &data[16], size-16); + md5_final(&ctx, digest); + return memcmp(digest, data, 16) == 0; + } else { + i_error("password-verify(%s): couldn't decode SMD5", user); + return -1; + } + } + return -1; } @@ -79,6 +108,14 @@ scheme = t_strdup_until(*password + 1, p); *password = p + 1; + + /* LDAP's RFC2307 specifies the MD5 scheme for what we call PLAIN-MD5. + * Implementations use base64 encoding for the hash, so we can + * detect the genuine {MD5}'s MCF format - base64 doesn't use '$'. */ + if (strncasecmp(scheme, "MD5", 3) == 0 && + strncmp(*password, "$1$", 3) != 0) { + scheme = "PLAIN-MD5"; + } return scheme; }