# HG changeset patch # User Timo Sirainen # Date 1068496562 -7200 # Node ID ed5e808d934ffb31ad74aa732535e0529960a6ed # Parent f83bf8214723ad2a03bfb11233317c6466e2c34a CRAM-MD5 mechanism by Joshua Goodall, plus some cleanups. diff -r f83bf8214723 -r ed5e808d934f src/auth/Makefile.am --- a/src/auth/Makefile.am Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/Makefile.am Mon Nov 10 22:36:02 2003 +0200 @@ -23,11 +23,11 @@ db-pgsql.c \ db-passwd-file.c \ main.c \ - md5crypt.c \ mech.c \ mech-anonymous.c \ mech-cyrus-sasl2.c \ mech-plain.c \ + mech-cram-md5.c \ mech-digest-md5.c \ mycrypt.c \ passdb.c \ @@ -40,6 +40,8 @@ passdb-vpopmail.c \ passdb-pgsql.c \ password-scheme.c \ + password-scheme-md5crypt.c \ + password-scheme-cram-md5.c \ userdb.c \ userdb-ldap.c \ userdb-passwd.c \ @@ -59,7 +61,6 @@ db-pgsql.h \ db-passwd-file.h \ common.h \ - md5crypt.h \ mech.h \ mycrypt.h \ passdb.h \ diff -r f83bf8214723 -r ed5e808d934f src/auth/auth-client-interface.h --- a/src/auth/auth-client-interface.h Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/auth-client-interface.h Mon Nov 10 22:36:02 2003 +0200 @@ -12,6 +12,7 @@ AUTH_MECH_PLAIN = 0x01, AUTH_MECH_DIGEST_MD5 = 0x02, AUTH_MECH_ANONYMOUS = 0x04, + AUTH_MECH_CRAM_MD5 = 0x08, AUTH_MECH_COUNT }; diff -r f83bf8214723 -r ed5e808d934f src/auth/auth-mech-desc.h --- a/src/auth/auth-mech-desc.h Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/auth-mech-desc.h Mon Nov 10 22:36:02 2003 +0200 @@ -10,6 +10,7 @@ static struct auth_mech_desc auth_mech_desc[AUTH_MECH_COUNT] = { { AUTH_MECH_PLAIN, "PLAIN", TRUE, FALSE }, + { AUTH_MECH_CRAM_MD5, "CRAM-MD5", FALSE, TRUE }, { AUTH_MECH_DIGEST_MD5, "DIGEST-MD5", FALSE, TRUE }, { AUTH_MECH_ANONYMOUS, "ANONYMOUS", FALSE, TRUE } }; diff -r f83bf8214723 -r ed5e808d934f src/auth/md5crypt.c --- a/src/auth/md5crypt.c Mon Nov 10 20:53:40 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - */ - -/* - * Ported from FreeBSD to Linux, only minimal changes. --marekm - */ - -/* - * Adapted from shadow-19990607 by Tudor Bosman, tudorb@jm.nu - */ - -#include "lib.h" -#include "safe-memset.h" -#include "str.h" -#include "md5.h" -#include "md5crypt.h" - -static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -static char *magic = "$1$"; /* - * This string is magic for - * this algorithm. Having - * it this way, we can get - * get better later on - */ - -static void -to64(string_t *str, unsigned long v, int n) -{ - while (--n >= 0) { - str_append_c(str, itoa64[v&0x3f]); - v >>= 6; - } -} - -/* - * UNIX password - * - * Use MD5 for what it is best at... - */ - -const char * -md5_crypt(const char *pw, const char *salt) -{ - const char *sp,*ep; - unsigned char final[16]; - int sl,pl,i,j; - struct md5_context ctx,ctx1; - unsigned long l; - string_t *passwd; - size_t pw_len = strlen(pw); - - /* Refine the Salt first */ - sp = salt; - - /* If it starts with the magic string, then skip that */ - if (strncmp(sp, magic, sizeof(magic)-1) == 0) - sp += sizeof(magic)-1; - - /* It stops at the first '$', max 8 chars */ - for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) - continue; - - /* get the length of the true salt */ - sl = ep - sp; - - md5_init(&ctx); - - /* The password first, since that is what is most unknown */ - md5_update(&ctx,pw,pw_len); - - /* Then our magic string */ - md5_update(&ctx,magic,sizeof(magic)-1); - - /* Then the raw salt */ - md5_update(&ctx,sp,sl); - - /* Then just as many characters of the MD5(pw,salt,pw) */ - md5_init(&ctx1); - md5_update(&ctx1,pw,pw_len); - md5_update(&ctx1,sp,sl); - md5_update(&ctx1,pw,pw_len); - md5_final(&ctx1,final); - for(pl = pw_len; pl > 0; pl -= 16) - md5_update(&ctx,final,pl>16 ? 16 : pl); - - /* Don't leave anything around in vm they could use. */ - safe_memset(final, 0, sizeof(final)); - - /* Then something really weird... */ - for (j=0,i = pw_len; i ; i >>= 1) - if(i&1) - md5_update(&ctx, final+j, 1); - else - md5_update(&ctx, pw+j, 1); - - /* Now make the output string */ - passwd = t_str_new(sl + 64); - str_append(passwd, magic); - str_append_n(passwd, sp, sl); - str_append_c(passwd, '$'); - - md5_final(&ctx,final); - - /* - * and now, just to make sure things don't run too fast - * On a 60 Mhz Pentium this takes 34 msec, so you would - * need 30 seconds to build a 1000 entry dictionary... - */ - for(i=0;i<1000;i++) { - md5_init(&ctx1); - if(i & 1) - md5_update(&ctx1,pw,pw_len); - else - md5_update(&ctx1,final,16); - - if(i % 3) - md5_update(&ctx1,sp,sl); - - if(i % 7) - md5_update(&ctx1,pw,pw_len); - - if(i & 1) - md5_update(&ctx1,final,16); - else - md5_update(&ctx1,pw,pw_len); - md5_final(&ctx1,final); - } - - l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(passwd,l,4); - l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(passwd,l,4); - l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(passwd,l,4); - l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(passwd,l,4); - l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(passwd,l,4); - l = final[11] ; to64(passwd,l,2); - - /* Don't leave anything around in vm they could use. */ - safe_memset(final, 0, sizeof(final)); - - return str_c(passwd); -} diff -r f83bf8214723 -r ed5e808d934f src/auth/md5crypt.h --- a/src/auth/md5crypt.h Mon Nov 10 20:53:40 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#ifndef __MD5CRYPT_H -#define __MD5CRYPT_H - -const char *md5_crypt(const char *pw, const char *salt); - -#endif diff -r f83bf8214723 -r ed5e808d934f src/auth/mech-cram-md5.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/mech-cram-md5.c Mon Nov 10 22:36:02 2003 +0200 @@ -0,0 +1,230 @@ +/* Copyright (C) 2002,2003 Timo Sirainen / Joshua Goodall */ + +/* CRAM-MD5 SASL authentication, see RFC-2195 + Joshua Goodall */ + +#include "common.h" +#include "ioloop.h" +#include "buffer.h" +#include "hex-binary.h" +#include "md5.h" +#include "randgen.h" +#include "mech.h" +#include "passdb.h" +#include "hostpid.h" + +#include +#include + +struct cram_auth_request { + struct auth_request auth_request; + + pool_t pool; + + /* requested: */ + char *challenge; + + /* received: */ + char *username; + char *response; + unsigned long maxbuf; +}; + +static const char *get_cram_challenge(void) +{ + char buf[17]; + size_t i; + + hostpid_init(); + random_fill(buf, sizeof(buf)-1); + + for (i = 0; i < sizeof(buf)-1; i++) + buf[i] = (buf[i] % 10) + '0'; + buf[sizeof(buf)-1] = '\0'; + + return t_strdup_printf("%s.%s@%s", buf, dec2str(ioloop_time), + my_hostname); +} + +static int verify_credentials(struct cram_auth_request *auth, + const char *credentials) +{ + + unsigned char digest[16], context_digest[32], *cdp; + struct md5_context ctxo, ctxi; + buffer_t *context_digest_buf; + const char *response_hex; + + if (credentials == NULL) + return FALSE; + + context_digest_buf = + buffer_create_data(pool_datastack_create(), + context_digest, sizeof(context_digest)); + + if (hex_to_binary(credentials, context_digest_buf) <= 0) + return FALSE; + +#define CDGET(p, c) STMT_START { \ + (c) = (*p++); \ + (c) += (*p++ << 8); \ + (c) += (*p++ << 16); \ + (c) += (*p++ << 24); \ +} STMT_END + + cdp = context_digest; + CDGET(cdp, ctxo.a); + CDGET(cdp, ctxo.b); + CDGET(cdp, ctxo.c); + CDGET(cdp, ctxo.d); + CDGET(cdp, ctxi.a); + CDGET(cdp, ctxi.b); + CDGET(cdp, ctxi.c); + CDGET(cdp, ctxi.d); + + ctxo.lo = ctxi.lo = 64; + ctxo.hi = ctxi.hi = 0; + + md5_update(&ctxi, auth->challenge, strlen(auth->challenge)); + md5_final(&ctxi, digest); + md5_update(&ctxo, digest, 16); + md5_final(&ctxo, digest); + response_hex = binary_to_hex(digest, 16); + + if (memcmp(response_hex, auth->response, 32) != 0) { + if (verbose) { + i_info("cram-md5(%s): password mismatch", + auth->username); + } + return FALSE; + } + + return TRUE; +} + +static int parse_cram_response(struct cram_auth_request *auth, + const char *data, const char **error) +{ + char *digest; + int failed; + + *error = NULL; + failed = FALSE; + + digest = strchr(data, ' '); + if (digest != NULL) { + auth->username = p_strdup_until(auth->pool, data, digest); + digest++; + auth->response = p_strdup(auth->pool, digest); + } else { + *error = "missing digest"; + failed = TRUE; + } + + return !failed; +} + +static void credentials_callback(const char *result, + struct auth_request *request) +{ + struct cram_auth_request *auth = + (struct cram_auth_request *) request; + + if (verify_credentials(auth, result)) { + if (verbose) { + i_info("cram-md5(%s): authenticated", + auth->username == NULL ? "" : auth->username); + } + mech_auth_finish(request, NULL, 0, TRUE); + } else { + if (verbose) { + i_info("cram-md5(%s): authentication failed", + auth->username == NULL ? "" : auth->username); + } + mech_auth_finish(request, NULL, 0, FALSE); + } +} + +static int +mech_cram_md5_auth_continue(struct auth_request *auth_request, + struct auth_client_request_continue *request, + const unsigned char *data, + mech_callback_t *callback) +{ + struct cram_auth_request *auth = + (struct cram_auth_request *)auth_request; + const char *error; + + /* unused */ + (void)request; + + if (parse_cram_response(auth, (const char *) data, &error)) { + auth_request->callback = callback; + + auth_request->user = + p_strdup(auth_request->pool, auth->username); + + if (mech_is_valid_username(auth_request->user)) { + passdb->lookup_credentials(&auth->auth_request, + PASSDB_CREDENTIALS_CRAM_MD5, + credentials_callback); + return TRUE; + } + + error = "invalid username"; + } + + if (error == NULL) + error = "authentication failed"; + + if (verbose) { + i_info("cram-md5(%s): %s", + auth->username == NULL ? "" : auth->username, error); + } + + /* failed */ + mech_auth_finish(auth_request, NULL, 0, FALSE); + return FALSE; +} + +static void mech_cram_md5_auth_free(struct auth_request *auth_request) +{ + pool_unref(auth_request->pool); +} + +static struct auth_request * +mech_cram_md5_auth_new(struct auth_client_connection *conn, + unsigned int id, mech_callback_t *callback) +{ + struct auth_client_request_reply reply; + struct cram_auth_request *auth; + pool_t pool; + + pool = pool_alloconly_create("cram_md5_auth_request", 2048); + auth = p_new(pool, struct cram_auth_request, 1); + auth->pool = pool; + + auth->auth_request.refcount = 1; + auth->auth_request.pool = pool; + auth->auth_request.auth_continue = mech_cram_md5_auth_continue; + auth->auth_request.auth_free = mech_cram_md5_auth_free; + + auth->challenge = p_strdup(auth->pool, get_cram_challenge()); + + /* initialize reply */ + mech_init_auth_client_reply(&reply); + reply.id = id; + reply.result = AUTH_CLIENT_RESULT_CONTINUE; + + /* send the initial challenge */ + reply.reply_idx = 0; + reply.data_size = strlen(auth->challenge); + callback(&reply, auth->challenge, conn); + + return &auth->auth_request; +} + +struct mech_module mech_cram_md5 = { + AUTH_MECH_CRAM_MD5, + mech_cram_md5_auth_new +}; diff -r f83bf8214723 -r ed5e808d934f src/auth/mech-digest-md5.c --- a/src/auth/mech-digest-md5.c Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/mech-digest-md5.c Mon Nov 10 22:36:02 2003 +0200 @@ -464,7 +464,7 @@ } static int parse_digest_response(struct digest_auth_request *auth, - const char *data, size_t size, + const unsigned char *data, size_t size, const char **error) { char *copy, *key, *value; @@ -569,8 +569,7 @@ return TRUE; } - if (parse_digest_response(auth, (const char *) data, - request->data_size, &error)) { + if (parse_digest_response(auth, data, request->data_size, &error)) { auth_request->callback = callback; realm = auth->realm != NULL ? auth->realm : default_realm; diff -r f83bf8214723 -r ed5e808d934f src/auth/mech.c --- a/src/auth/mech.c Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/mech.c Mon Nov 10 22:36:02 2003 +0200 @@ -215,6 +215,7 @@ } extern struct mech_module mech_plain; +extern struct mech_module mech_cram_md5; extern struct mech_module mech_digest_md5; extern struct mech_module mech_anonymous; @@ -242,6 +243,8 @@ while (*mechanisms != NULL) { if (strcasecmp(*mechanisms, "PLAIN") == 0) mech_register_module(&mech_plain); + else if (strcasecmp(*mechanisms, "CRAM-MD5") == 0) + mech_register_module(&mech_cram_md5); else if (strcasecmp(*mechanisms, "DIGEST-MD5") == 0) mech_register_module(&mech_digest_md5); else if (strcasecmp(*mechanisms, "ANONYMOUS") == 0) { @@ -293,6 +296,7 @@ void mech_deinit(void) { mech_unregister_module(&mech_plain); + mech_unregister_module(&mech_cram_md5); mech_unregister_module(&mech_digest_md5); mech_unregister_module(&mech_anonymous); } diff -r f83bf8214723 -r ed5e808d934f src/auth/passdb.c --- a/src/auth/passdb.c Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/passdb.c Mon Nov 10 22:36:02 2003 +0200 @@ -24,6 +24,8 @@ return "PLAIN"; case PASSDB_CREDENTIALS_CRYPT: return "CRYPT"; + case PASSDB_CREDENTIALS_CRAM_MD5: + return "CRAM-MD5"; case PASSDB_CREDENTIALS_DIGEST_MD5: return "DIGEST-MD5"; } @@ -133,6 +135,10 @@ passdb->verify_plain == NULL) i_fatal("Passdb %s doesn't support PLAIN method", name); + if ((auth_mechanisms & AUTH_MECH_CRAM_MD5) && + passdb->lookup_credentials == NULL) + i_fatal("Passdb %s doesn't support CRAM-MD5 method", name); + if ((auth_mechanisms & AUTH_MECH_DIGEST_MD5) && passdb->lookup_credentials == NULL) i_fatal("Passdb %s doesn't support DIGEST-MD5 method", name); diff -r f83bf8214723 -r ed5e808d934f src/auth/passdb.h --- a/src/auth/passdb.h Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/passdb.h Mon Nov 10 22:36:02 2003 +0200 @@ -11,6 +11,7 @@ PASSDB_CREDENTIALS_PLAINTEXT, PASSDB_CREDENTIALS_CRYPT, + PASSDB_CREDENTIALS_CRAM_MD5, PASSDB_CREDENTIALS_DIGEST_MD5 }; diff -r f83bf8214723 -r ed5e808d934f src/auth/password-scheme-cram-md5.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/password-scheme-cram-md5.c Mon Nov 10 22:36:02 2003 +0200 @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 Timo Sirainen */ + +#include "lib.h" +#include "md5.h" +#include "hex-binary.h" +#include "password-scheme.h" + +const char *password_generate_cram_md5(const char *plaintext) +{ + unsigned char digest[16], ipad[64], opad[64], context_digest[32], *cdp; + struct md5_context ctxo, ctxi; + size_t len; + int i; + + memset(ipad, 0, sizeof(ipad)); + memset(opad, 0, sizeof(opad)); + + /* Hash excessively long passwords */ + len = strlen(plaintext); + if (len > 64) { + md5_get_digest(plaintext, len, digest); + memcpy(ipad, digest, 16); + memcpy(opad, digest, 16); + } else { + memcpy(ipad, plaintext, len); + memcpy(opad, plaintext, len); + } + + /* ipad/opad operation */ + for (i = 0; i < 64; i++) { + ipad[i] ^= 0x36; + opad[i] ^= 0x5c; + } + + md5_init(&ctxi); + md5_init(&ctxo); + md5_update(&ctxi, ipad, 64); + md5_update(&ctxo, opad, 64); + + /* Make HMAC-MD5 hex digest */ +#define CDPUT(p, c) STMT_START { \ + *(p)++ = (c) & 0xff; \ + *(p)++ = (c) >> 8 & 0xff; \ + *(p)++ = (c) >> 16 & 0xff; \ + *(p)++ = (c) >> 24 & 0xff; \ +} STMT_END + cdp = context_digest; + CDPUT(cdp, ctxo.a); + CDPUT(cdp, ctxo.b); + CDPUT(cdp, ctxo.c); + CDPUT(cdp, ctxo.d); + CDPUT(cdp, ctxi.a); + CDPUT(cdp, ctxi.b); + CDPUT(cdp, ctxi.c); + CDPUT(cdp, ctxi.d); + + return binary_to_hex(context_digest, sizeof(context_digest)); +} diff -r f83bf8214723 -r ed5e808d934f src/auth/password-scheme-md5crypt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/password-scheme-md5crypt.c Mon Nov 10 22:36:02 2003 +0200 @@ -0,0 +1,147 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +/* + * Ported from FreeBSD to Linux, only minimal changes. --marekm + */ + +/* + * Adapted from shadow-19990607 by Tudor Bosman, tudorb@jm.nu + */ + +#include "lib.h" +#include "safe-memset.h" +#include "str.h" +#include "md5.h" +#include "password-scheme.h" + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static char *magic = "$1$"; /* + * This string is magic for + * this algorithm. Having + * it this way, we can get + * get better later on + */ + +static void +to64(string_t *str, unsigned long v, int n) +{ + while (--n >= 0) { + str_append_c(str, itoa64[v&0x3f]); + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +const char *password_generate_md5_crypt(const char *pw, const char *salt) +{ + const char *sp,*ep; + unsigned char final[16]; + int sl,pl,i,j; + struct md5_context ctx,ctx1; + unsigned long l; + string_t *passwd; + size_t pw_len = strlen(pw); + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if (strncmp(sp, magic, sizeof(magic)-1) == 0) + sp += sizeof(magic)-1; + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + md5_init(&ctx); + + /* The password first, since that is what is most unknown */ + md5_update(&ctx,pw,pw_len); + + /* Then our magic string */ + md5_update(&ctx,magic,sizeof(magic)-1); + + /* Then the raw salt */ + md5_update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + md5_init(&ctx1); + md5_update(&ctx1,pw,pw_len); + md5_update(&ctx1,sp,sl); + md5_update(&ctx1,pw,pw_len); + md5_final(&ctx1,final); + for(pl = pw_len; pl > 0; pl -= 16) + md5_update(&ctx,final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + safe_memset(final, 0, sizeof(final)); + + /* Then something really weird... */ + for (j=0,i = pw_len; i ; i >>= 1) + if(i&1) + md5_update(&ctx, final+j, 1); + else + md5_update(&ctx, pw+j, 1); + + /* Now make the output string */ + passwd = t_str_new(sl + 64); + str_append(passwd, magic); + str_append_n(passwd, sp, sl); + str_append_c(passwd, '$'); + + md5_final(&ctx,final); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + md5_init(&ctx1); + if(i & 1) + md5_update(&ctx1,pw,pw_len); + else + md5_update(&ctx1,final,16); + + if(i % 3) + md5_update(&ctx1,sp,sl); + + if(i % 7) + md5_update(&ctx1,pw,pw_len); + + if(i & 1) + md5_update(&ctx1,final,16); + else + md5_update(&ctx1,pw,pw_len); + md5_final(&ctx1,final); + } + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(passwd,l,4); + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(passwd,l,4); + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(passwd,l,4); + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(passwd,l,4); + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(passwd,l,4); + l = final[11] ; to64(passwd,l,2); + + /* Don't leave anything around in vm they could use. */ + safe_memset(final, 0, sizeof(final)); + + return str_c(passwd); +} diff -r f83bf8214723 -r ed5e808d934f src/auth/password-scheme.c --- a/src/auth/password-scheme.c Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/password-scheme.c Mon Nov 10 22:36:02 2003 +0200 @@ -3,7 +3,6 @@ #include "lib.h" #include "hex-binary.h" #include "md5.h" -#include "md5crypt.h" #include "mycrypt.h" #include "randgen.h" #include "password-scheme.h" @@ -23,8 +22,10 @@ if (strcasecmp(scheme, "CRYPT") == 0) return strcmp(mycrypt(plaintext, password), password) == 0; - if (strcasecmp(scheme, "MD5") == 0) - return strcmp(md5_crypt(plaintext, password), password) == 0; + if (strcasecmp(scheme, "MD5") == 0) { + str = password_generate_md5_crypt(plaintext, password); + return strcmp(str, password) == 0; + } if (strcasecmp(scheme, "PLAIN") == 0) return strcmp(password, plaintext) == 0; @@ -103,12 +104,15 @@ for (i = 0; i < 8; i++) salt[i] = salt_chars[salt[i] % (sizeof(salt_chars)-1)]; salt[8] = '\0'; - return t_strdup(md5_crypt(plaintext, salt)); + return password_generate_md5_crypt(plaintext, salt); } if (strcasecmp(scheme, "PLAIN") == 0) return plaintext; + if (strcasecmp(scheme, "CRAM-MD5") == 0) + return password_generate_cram_md5(plaintext); + if (strcasecmp(scheme, "DIGEST-MD5") == 0) { /* user:realm:passwd */ realm = strchr(user, '@'); diff -r f83bf8214723 -r ed5e808d934f src/auth/password-scheme.h --- a/src/auth/password-scheme.h Mon Nov 10 20:53:40 2003 +0200 +++ b/src/auth/password-scheme.h Mon Nov 10 22:36:02 2003 +0200 @@ -12,4 +12,8 @@ const char *password_generate(const char *plaintext, const char *user, const char *scheme); +/* INTERNAL: */ +const char *password_generate_md5_crypt(const char *pw, const char *salt); +const char *password_generate_cram_md5(const char *pw); + #endif