]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added dovecotpw utility. Patch by Joshua Goodall
authorTimo Sirainen <tss@iki.fi>
Mon, 26 Jul 2004 16:21:29 +0000 (19:21 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 26 Jul 2004 16:21:29 +0000 (19:21 +0300)
--HG--
branch : HEAD

configure.in
src/auth/passdb.c
src/auth/password-scheme.c
src/auth/password-scheme.h
src/lib/Makefile.am
src/util/Makefile.am

index eb5207cfb21a695d89f8e40b267a7e28d21dde13..cc85ea4831ff0498a26efd7ae0ddd32f8bbbfe7a 100644 (file)
@@ -1,7 +1,7 @@
 AC_INIT(src)
 
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(dovecot, 1.0-test29)
+AM_INIT_AUTOMAKE(dovecot, 1.0-test30)
 
 AM_MAINTAINER_MODE
 
@@ -588,13 +588,6 @@ else
 fi
 AC_SUBST(RAND_LIBS)
 
-AC_CHECK_LIB(crypto, SHA1_Init, [
-  AC_CHECK_HEADER(openssl/sha.h, [
-    AC_DEFINE(HAVE_OPENSSL_SHA1,, Define if you have SHA1 in OpenSSL)
-    AUTH_LIBS=-lcrypto
-  ])
-])
-
 dnl * do we have tm_gmtoff
 AC_MSG_CHECKING([for tm_gmtoff])
 AC_CACHE_VAL(i_cv_field_tm_gmtoff,
index af95276cae3868d386a3864a52b2a15f9de97083..78c46edb2bc3b7ad966247ebc58f8cd06d461941 100644 (file)
@@ -52,7 +52,8 @@ void passdb_handle_credentials(enum passdb_credentials credentials,
        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 90420fdbea471402d61d0d061c33f1e93b71dffb..a6cb26283ed9e3381f6dc2b0584f28fb16b891fb 100644 (file)
@@ -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 @@ int password_verify(const char *plaintext, const char *password,
        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 @@ const char *password_get_scheme(const char **password)
 
        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 @@ static const char *md5_generate(const char *plaintext,
        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 @@ static const char *plain_md5_generate(const char *plaintext,
        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 e24c4fcbf42acb4554d77a6ccdb26b6aecc832e4..1eda2e8df146f74c6e8604b836a5802e49ee4f31 100644 (file)
@@ -21,6 +21,9 @@ const char *password_get_scheme(const char **password);
 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);
 
index 5410dc6694ba8237cbf8aafc758b006a520db748..8dd15532f25d0549f601ce0c6342047e04f9242d 100644 (file)
@@ -54,6 +54,7 @@ liblib_a_SOURCES = \
        safe-memset.c \
        safe-mkdir.c \
        sendfile-util.c \
+       sha1.c \
        str.c \
        strescape.c \
        strfuncs.c \
@@ -109,6 +110,7 @@ noinst_HEADERS = \
        safe-memset.h \
        safe-mkdir.h \
        sendfile-util.h \
+       sha1.h \
        str.h \
        strescape.h \
        strfuncs.h \
index 025ad27cf945febc9498e7fbcd74b7c96b78b491..8c9e8e9bf8acad534ef6ba2162887d9f6deb816b 100644 (file)
@@ -1,12 +1,28 @@
 pkglibexecdir = $(libexecdir)/dovecot
 
 pkglibexec_PROGRAMS = rawlog
+sbin_PROGRAMS = dovecotpw
 
 INCLUDES = \
-       -I$(top_srcdir)/src/lib
+       -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/auth
 
 rawlog_LDADD = \
        ../lib/liblib.a
 
 rawlog_SOURCES = \
        rawlog.c
+
+dovecotpw_INCLUDES = \
+       -DAUTH_MODULE_DIR=\""$(moduledir)/auth"\"
+
+dovecotpw_LDADD = \
+       ../lib/liblib.a \
+       ../auth/password-scheme.o \
+       ../auth/password-scheme-cram-md5.o \
+       ../auth/password-scheme-md5crypt.o \
+       ../auth/mycrypt.o \
+       $(AUTH_LIBS)
+
+dovecotpw_SOURCES = \
+       dovecotpw.c