[dovecot-cvs] dovecot/src/auth passdb.c, 1.18,
1.19 password-scheme.c, 1.9, 1.10 password-scheme.h, 1.3, 1.4
cras at dovecot.org
cras at dovecot.org
Mon Jul 26 19:21:32 EEST 2004
Update of /home/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv19895/src/auth
Modified Files:
passdb.c password-scheme.c password-scheme.h
Log Message:
Added dovecotpw utility. Patch by Joshua Goodall
Index: passdb.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/passdb.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- passdb.c 23 Jun 2004 17:47:06 -0000 1.18
+++ passdb.c 26 Jul 2004 16:21:30 -0000 1.19
@@ -52,7 +52,8 @@
if (password != NULL) {
wanted_scheme = passdb_credentials_to_str(credentials);
if (strcasecmp(scheme, wanted_scheme) != 0) {
- if (strcasecmp(scheme, "PLAIN") == 0) {
+ if (strcasecmp(scheme, "PLAIN") == 0 ||
+ strcasecmp(scheme, "CLEARTEXT") == 0) {
/* we can generate anything out of plaintext
passwords */
password = password_generate(password, user,
Index: password-scheme.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/password-scheme.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- password-scheme.c 23 Jul 2004 18:07:14 -0000 1.9
+++ password-scheme.c 26 Jul 2004 16:21:30 -0000 1.10
@@ -8,13 +8,10 @@
#include "module-dir.h"
#include "mycrypt.h"
#include "randgen.h"
+#include "sha1.h"
#include "str.h"
#include "password-scheme.h"
-#ifdef HAVE_OPENSSL_SHA1
-# include <openssl/sha.h>
-#endif
-
static const char salt_chars[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@@ -40,6 +37,19 @@
return -1;
}
+const char *password_list_schemes(const struct password_scheme **listptr)
+{
+ if (*listptr == NULL)
+ *listptr = schemes;
+
+ if ((*listptr)->name == NULL) {
+ *listptr = NULL;
+ return NULL;
+ }
+
+ return (*listptr)++->name;
+}
+
const char *password_get_scheme(const char **password)
{
const char *p, *scheme;
@@ -68,6 +78,14 @@
scheme = t_strdup_until(*password + 1, p);
*password = p + 1;
+
+ /* LDAP's RFC2307 specifies the MD5 scheme for what we call PLAIN-MD5,
+ only base64-encoded rather than hex-encoded.
+ We can detect this case - base64 doesn't use '$'. */
+ if (strncasecmp(scheme, "MD5", 3) == 0 &&
+ strncmp(*password, "$1$", 3) != 0) {
+ scheme = "LDAP-MD5";
+ }
return scheme;
}
@@ -124,20 +142,146 @@
return password_generate_md5_crypt(plaintext, salt);
}
-#ifdef HAVE_OPENSSL_SHA1
-static int sha_verify(const char *plaintext, const char *password,
+static const char *sha1_generate(const char *plaintext,
+ const char *user __attr_unused__)
+{
+ unsigned char digest[SHA1_RESULTLEN];
+ string_t *str;
+
+ sha1_get_digest(plaintext, strlen(plaintext), digest);
+ str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(digest)+1));
+ base64_encode(digest, sizeof(digest), str);
+ return str_c(str);
+}
+
+static int sha1_verify(const char *plaintext, const char *password,
const char *user __attr_unused__)
{
- unsigned char digest[SHA_DIGEST_LENGTH];
+ unsigned char sha1_digest[SHA1_RESULTLEN];
+ const char *data;
+ buffer_t *buf;
+ size_t size;
+
+ sha1_get_digest(plaintext, strlen(plaintext), sha1_digest);
+
+ buf = buffer_create_static(pool_datastack_create(),
+ MAX_BASE64_DECODED_SIZE(strlen(password)+1));
+
+ if (base64_decode(password, strlen(password), NULL, buf) <= 0) {
+ i_error("sha1_verify(%s): failed decoding SHA base64", user);
+ return 0;
+ }
+
+ data = buffer_get_data(buf, &size);
+ if (size < SHA1_RESULTLEN) {
+ i_error("sha1_verify(%s): invalid SHA base64 decode", user);
+ return 0;
+ }
+
+ return memcmp(sha1_digest, data, SHA1_RESULTLEN) == 0;
+}
+
+static const char *ssha_generate(const char *plaintext,
+ const char *user __attr_unused__)
+{
+ unsigned char ssha_digest[SHA1_RESULTLEN+4];
+ unsigned char *salt = &ssha_digest[SHA1_RESULTLEN];
+ struct sha1_ctxt ctx;
string_t *str;
- SHA1(plaintext, strlen(plaintext), digest);
+ random_fill(salt, 4);
- str = t_str_new(64);
- base64_encode(digest, sizeof(digest), str);
- return strcasecmp(str_c(str), password) == 0;
+ sha1_init(&ctx);
+ sha1_loop(&ctx, plaintext, strlen(plaintext));
+ sha1_loop(&ctx, salt, 4);
+ sha1_result(&ctx, ssha_digest);
+
+ str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(ssha_digest))+1);
+ base64_encode(ssha_digest, sizeof(ssha_digest), str);
+ return str_c(str);
+}
+
+static int ssha_verify(const char *plaintext, const char *password,
+ const char *user __attr_unused__)
+{
+ unsigned char sha1_digest[SHA1_RESULTLEN];
+ buffer_t *buf;
+ const char *data;
+ size_t size;
+ struct sha1_ctxt ctx;
+
+ /* format: base64-encoded MD5 hash and salt */
+ buf = buffer_create_static(pool_datastack_create(),
+ MAX_BASE64_DECODED_SIZE(strlen(password)+1));
+
+ if (base64_decode(password, strlen(password), NULL, buf) <= 0) {
+ i_error("ssha_verify(%s): failed decoding SSHA base64", user);
+ return 0;
+ }
+
+ data = buffer_get_data(buf, &size);
+ if (size <= SHA1_RESULTLEN) {
+ i_error("ssha_verify(%s): invalid SSHA base64 decode", user);
+ return 0;
+ }
+
+ sha1_init(&ctx);
+ sha1_loop(&ctx, plaintext, strlen(plaintext));
+ sha1_loop(&ctx, &data[SHA1_RESULTLEN], size-SHA1_RESULTLEN);
+ sha1_result(&ctx, sha1_digest);
+ return memcmp(sha1_digest, data, SHA1_RESULTLEN) == 0;
+}
+
+static const char *smd5_generate(const char *plaintext,
+ const char *user __attr_unused__)
+{
+ unsigned char smd5_digest[20];
+ unsigned char *salt = &smd5_digest[16];
+ struct md5_context ctx;
+ string_t *str;
+
+ random_fill(salt, 4);
+
+ md5_init(&ctx);
+ md5_update(&ctx, plaintext, strlen(plaintext));
+ md5_update(&ctx, salt, 4);
+ md5_final(&ctx, smd5_digest);
+
+ str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(smd5_digest))+1);
+ base64_encode(smd5_digest, sizeof(smd5_digest), str);
+ return str_c(str);
+}
+
+static int smd5_verify(const char *plaintext, const char *password,
+ const char *user __attr_unused__)
+{
+ unsigned char md5_digest[16];
+ buffer_t *buf;
+ const char *data;
+ size_t size;
+ struct md5_context ctx;
+
+ /* format: base64-encoded MD5 hash and salt */
+ buf = buffer_create_static(pool_datastack_create(),
+ MAX_BASE64_DECODED_SIZE(strlen(password)+1));
+
+ if (base64_decode(password, strlen(password), NULL, buf) <= 0) {
+ i_error("smd5_verify(%s): failed decoding SMD5 base64", user);
+ return 0;
+ }
+
+ data = buffer_get_data(buf, &size);
+ if (size <= 16) {
+ i_error("smd5_verify(%s): invalid SMD5 base64 decode", user);
+ return 0;
+ }
+
+ md5_init(&ctx);
+ md5_update(&ctx, plaintext, strlen(plaintext));
+ md5_update(&ctx, &data[16], size-16);
+ md5_final(&ctx, md5_digest);
+ return memcmp(md5_digest, data, 16) == 0;
}
-#endif
static int plain_verify(const char *plaintext, const char *password,
const char *user __attr_unused__)
@@ -216,17 +360,59 @@
return binary_to_hex(digest, sizeof(digest));
}
+static const char *ldap_md5_generate(const char *plaintext,
+ const char *user __attr_unused__)
+{
+ unsigned char digest[16];
+ string_t *str;
+
+ md5_get_digest(plaintext, strlen(plaintext), digest);
+ str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(digest)+1));
+ base64_encode(digest, sizeof(digest), str);
+ return str_c(str);
+}
+
+static int ldap_md5_verify(const char *plaintext, const char *password,
+ const char *user __attr_unused__)
+{
+ unsigned char md5_digest[16];
+ buffer_t *buf;
+ const char *data;
+ size_t size;
+
+ md5_get_digest(plaintext, strlen(plaintext), md5_digest);
+
+ buf = buffer_create_static(pool_datastack_create(),
+ MAX_BASE64_DECODED_SIZE(strlen(password)+1));
+
+ if (base64_decode(password, strlen(password), NULL, buf) <= 0) {
+ i_error("ldap_md5_verify(%s): failed decoding MD5 base64",
+ user);
+ return 0;
+ }
+
+ data = buffer_get_data(buf, &size);
+ if (size != 16) {
+ i_error("ldap_md5_verify(%s): invalid MD5 base64 decode", user);
+ return 0;
+ }
+
+ return memcmp(md5_digest, data, 16) == 0;
+}
+
static const struct password_scheme default_schemes[] = {
{ "CRYPT", crypt_verify, crypt_generate },
{ "MD5", md5_verify, md5_generate },
-#ifdef HAVE_OPENSSL_SHA1
- { "SHA", sha_verify, NULL },
- { "SHA1", sha_verify, NULL },
-#endif
+ { "SHA", sha1_verify, sha1_generate },
+ { "SHA1", sha1_verify, sha1_generate },
+ { "SMD5", smd5_verify, smd5_generate },
+ { "SSHA", ssha_verify, ssha_generate },
{ "PLAIN", plain_verify, plain_generate },
+ { "CLEARTEXT", plain_verify, plain_generate },
{ "HMAC-MD5", hmac_md5_verify, hmac_md5_generate },
{ "DIGEST-MD5", digest_md5_verify, digest_md5_generate },
{ "PLAIN-MD5", plain_md5_verify, plain_md5_generate },
+ { "LDAP-MD5", ldap_md5_verify, ldap_md5_generate },
{ NULL, NULL, NULL }
};
Index: password-scheme.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/password-scheme.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- password-scheme.h 30 May 2004 03:57:15 -0000 1.3
+++ password-scheme.h 26 Jul 2004 16:21:30 -0000 1.4
@@ -21,6 +21,9 @@
const char *password_generate(const char *plaintext, const char *user,
const char *scheme);
+/* Iterate through the list of password schemes, returning names */
+const char *password_list_schemes(const struct password_scheme **listptr);
+
void password_schemes_init(void);
void password_schemes_deinit(void);
More information about the dovecot-cvs
mailing list