password-scheme.c revision b193066823000095cae0781445fe9234c7c01366
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2003 Timo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "buffer.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "base64.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "hex-binary.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "md4.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "md5.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "module-dir.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "mycrypt.h"
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen#include "randgen.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "sha1.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "password-scheme.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char salt_chars[] =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic buffer_t *schemes_buf;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic const struct password_scheme *schemes;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#ifdef HAVE_MODULES
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic struct module *scheme_modules;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#endif
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint password_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *scheme, const char *user)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct password_scheme *s;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (password == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (s = schemes; s->name != NULL; s++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (strcasecmp(s->name, scheme) == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return s->password_verify(plaintext, password, user);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenconst char *password_list_schemes(const struct password_scheme **listptr)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (*listptr == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *listptr = schemes;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((*listptr)->name == NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *listptr = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return (*listptr)++->name;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenconst char *password_get_scheme(const char **password)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *p, *scheme;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*password == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (strncmp(*password, "$1$", 3) == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* skip the salt */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen p = strchr(*password + 3, '$');
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (p != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* stop at next '$' */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen p = strchr(p+1, '$');
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (p != NULL)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen *password = t_strdup_until(*password, p);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "MD5";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (**password != '{')
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen p = strchr(*password, '}');
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (p == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen scheme = t_strdup_until(*password + 1, p);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *password = p + 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* LDAP's RFC2307 specifies the MD5 scheme for what we call LDAP-MD5.
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen We can detect this case - base64 doesn't use '$'. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (strncasecmp(scheme, "MD5", 3) == 0 &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen strncmp(*password, "$1$", 3) != 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen scheme = "LDAP-MD5";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return scheme;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenconst char *password_generate(const char *plaintext, const char *user,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *scheme)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct password_scheme *s;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (s = schemes; s->name != NULL; s++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (strcasecmp(s->name, scheme) == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return s->password_generate(plaintext, user);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic bool crypt_verify(const char *plaintext, const char *password,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *user __attr_unused__)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return strcmp(mycrypt(plaintext, password), password) == 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic const char *crypt_generate(const char *plaintext,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *user __attr_unused__)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen char salt[9];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen random_fill(salt, 2);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen salt[0] = salt_chars[salt[0] % (sizeof(salt_chars)-1)];
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen salt[1] = salt_chars[salt[1] % (sizeof(salt_chars)-1)];
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen salt[2] = '\0';
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return t_strdup(mycrypt(plaintext, salt));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenstatic bool md5_verify(const char *plaintext, const char *password,
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen const char *str;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen str = password_generate_md5_crypt(plaintext, password);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return strcmp(str, password) == 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const char *md5_generate(const char *plaintext,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen char salt[9];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen int i;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen random_fill(salt, 8);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < 8; i++)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen salt[i] = salt_chars[salt[i] % (sizeof(salt_chars)-1)];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen salt[8] = '\0';
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return password_generate_md5_crypt(plaintext, salt);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const char *sha1_generate(const char *plaintext,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char digest[SHA1_RESULTLEN];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen string_t *str;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_get_digest(plaintext, strlen(plaintext), digest);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(digest)+1));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen base64_encode(digest, sizeof(digest), str);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return str_c(str);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const void *
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenpassword_decode(const char *password, unsigned int result_len)
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen{
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen buffer_t *buf;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t len;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen len = strlen(password);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (len == result_len*2) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* hex-encoded */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen result_len);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (hex_to_binary(password, buf) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return NULL;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen } else {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* base64-encoded */
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen MAX_BASE64_DECODED_SIZE(len));
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (base64_decode(password, len, NULL, buf) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return buf->used != result_len ? NULL : buf->data;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool sha1_verify(const char *plaintext, const char *password,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen unsigned char sha1_digest[SHA1_RESULTLEN];
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *data;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_get_digest(plaintext, strlen(plaintext), sha1_digest);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen data = password_decode(password, SHA1_RESULTLEN);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (data == NULL) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen i_error("sha1_verify(%s): Invalid password encoding", user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen return memcmp(sha1_digest, data, SHA1_RESULTLEN) == 0;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const char *ssha_generate(const char *plaintext,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char ssha_digest[SHA1_RESULTLEN+4];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char *salt = &ssha_digest[SHA1_RESULTLEN];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct sha1_ctxt ctx;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen string_t *str;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen random_fill(salt, 4);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_init(&ctx);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_loop(&ctx, plaintext, strlen(plaintext));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_loop(&ctx, salt, 4);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_result(&ctx, ssha_digest);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(ssha_digest))+1);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen base64_encode(ssha_digest, sizeof(ssha_digest), str);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return str_c(str);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool ssha_verify(const char *plaintext, const char *password,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen{
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen unsigned char sha1_digest[SHA1_RESULTLEN];
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen buffer_t *buf;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *data;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen size_t size, password_len;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen struct sha1_ctxt ctx;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* format: base64-encoded MD5 hash and salt */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen password_len = strlen(password);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen MAX_BASE64_DECODED_SIZE(password_len));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (base64_decode(password, password_len, NULL, buf) < 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_error("ssha_verify(%s): failed decoding SSHA base64", user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen data = buffer_get_data(buf, &size);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (size <= SHA1_RESULTLEN) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_error("ssha_verify(%s): invalid SSHA base64 decode", user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_init(&ctx);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_loop(&ctx, plaintext, strlen(plaintext));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_loop(&ctx, &data[SHA1_RESULTLEN], size-SHA1_RESULTLEN);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sha1_result(&ctx, sha1_digest);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return memcmp(sha1_digest, data, SHA1_RESULTLEN) == 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const char *smd5_generate(const char *plaintext,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char smd5_digest[20];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char *salt = &smd5_digest[MD5_RESULTLEN];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct md5_context ctx;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen string_t *str;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen random_fill(salt, 4);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen md5_init(&ctx);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_update(&ctx, plaintext, strlen(plaintext));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_update(&ctx, salt, 4);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_final(&ctx, smd5_digest);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(smd5_digest))+1);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen base64_encode(smd5_digest, sizeof(smd5_digest), str);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return str_c(str);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool smd5_verify(const char *plaintext, const char *password,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char md5_digest[MD5_RESULTLEN];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_t *buf;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *data;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t size, password_len;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct md5_context ctx;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* format: base64-encoded MD5 hash and salt */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen password_len = strlen(password);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen MAX_BASE64_DECODED_SIZE(password_len));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (base64_decode(password, password_len, NULL, buf) < 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_error("smd5_verify(%s): failed decoding SMD5 base64", user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen data = buffer_get_data(buf, &size);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (size <= MD5_RESULTLEN) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_error("smd5_verify(%s): invalid SMD5 base64 decode", user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_init(&ctx);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_update(&ctx, plaintext, strlen(plaintext));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_update(&ctx, &data[MD5_RESULTLEN], size-MD5_RESULTLEN);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_final(&ctx, md5_digest);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return memcmp(md5_digest, data, MD5_RESULTLEN) == 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool plain_verify(const char *plaintext, const char *password,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return strcmp(password, plaintext) == 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const char *plain_generate(const char *plaintext,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return plaintext;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool hmac_md5_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return strcmp(password_generate_cram_md5(plaintext), password) == 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *hmac_md5_generate(const char *plaintext,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return password_generate_cram_md5(plaintext);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool digest_md5_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned char digest[MD5_RESULTLEN];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *realm, *str;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* user:realm:passwd */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen realm = strchr(user, '@');
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (realm != NULL) realm++; else realm = "";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str = t_strconcat(t_strcut(user, '@'), ":", realm, ":",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen plaintext, NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen md5_get_digest(str, strlen(str), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str = binary_to_hex(digest, sizeof(digest));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return strcasecmp(str, password) == 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *digest_md5_generate(const char *plaintext, const char *user)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *realm, *str;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned char digest[MD5_RESULTLEN];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (user == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_fatal("digest_md5_generate(): username not given");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* user:realm:passwd */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen realm = strchr(user, '@');
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (realm != NULL) realm++; else realm = "";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str = t_strconcat(t_strcut(user, '@'), ":", realm, ":",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen plaintext, NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen md5_get_digest(str, strlen(str), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return binary_to_hex(digest, sizeof(digest));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool plain_md4_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned char digest[MD4_RESULTLEN];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const void *data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen md4_get_digest(plaintext, strlen(plaintext), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data = password_decode(password, MD4_RESULTLEN);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (data == NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("plain_md4_verify(%s): Invalid password encoding",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return memcmp(digest, data, MD4_RESULTLEN) == 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *plain_md4_generate(const char *plaintext,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen unsigned char digest[MD4_RESULTLEN];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen md4_get_digest(plaintext, strlen(plaintext), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return binary_to_hex(digest, sizeof(digest));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool plain_md5_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned char digest[MD5_RESULTLEN];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const void *data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen md5_get_digest(plaintext, strlen(plaintext), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data = password_decode(password, MD5_RESULTLEN);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (data == NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_error("plain_md5_verify(%s): Invalid password encoding",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen user);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return memcmp(digest, data, MD5_RESULTLEN) == 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic const char *plain_md5_generate(const char *plaintext,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *user __attr_unused__)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned char digest[MD5_RESULTLEN];
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen md5_get_digest(plaintext, strlen(plaintext), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return binary_to_hex(digest, sizeof(digest));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *ldap_md5_generate(const char *plaintext,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned char digest[MD5_RESULTLEN];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen string_t *str;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen md5_get_digest(plaintext, strlen(plaintext), digest);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(digest)+1));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen base64_encode(digest, sizeof(digest), str);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return str_c(str);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool lm_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return strcasecmp(password, password_generate_lm(plaintext)) == 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic const char *lm_generate(const char *plaintext,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *user __attr_unused__)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return password_generate_lm(plaintext);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool ntlm_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return strcasecmp(password, password_generate_ntlm(plaintext)) == 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *ntlm_generate(const char *plaintext,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *user __attr_unused__)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return password_generate_ntlm(plaintext);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool rpa_verify(const char *plaintext, const char *password,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user __attr_unused__)
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return strcasecmp(password, password_generate_rpa(plaintext)) == 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic const char *rpa_generate(const char *plaintext,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *user __attr_unused__)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return password_generate_rpa(plaintext);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const struct password_scheme default_schemes[] = {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "CRYPT", crypt_verify, crypt_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "MD5", md5_verify, md5_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "SHA", sha1_verify, sha1_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "SHA1", sha1_verify, sha1_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "SMD5", smd5_verify, smd5_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "SSHA", ssha_verify, ssha_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "PLAIN", plain_verify, plain_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "CLEARTEXT", plain_verify, plain_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "HMAC-MD5", hmac_md5_verify, hmac_md5_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "DIGEST-MD5", digest_md5_verify, digest_md5_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "PLAIN-MD4", plain_md4_verify, plain_md4_generate },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { "PLAIN-MD5", plain_md5_verify, plain_md5_generate },
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen { "LDAP-MD5", plain_md5_verify, ldap_md5_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "LANMAN", lm_verify, lm_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "NTLM", ntlm_verify, ntlm_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { "RPA", rpa_verify, rpa_generate },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { NULL, NULL, NULL }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen};
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid password_schemes_init(void)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen static const struct password_scheme null_scheme = { NULL, NULL, NULL };
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct password_scheme *s;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#ifdef HAVE_MODULES
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct module *mod;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *symbol;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#endif
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen schemes_buf = buffer_create_dynamic(default_pool, 128);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (s = default_schemes; s->name != NULL; s++)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen buffer_append(schemes_buf, s, sizeof(*s));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#ifdef HAVE_MODULES
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen scheme_modules = module_dir_load(AUTH_MODULE_DIR"/password",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen NULL, FALSE);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (mod = scheme_modules; mod != NULL; mod = mod->next) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_push();
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen symbol = t_strconcat(mod->name, "_scheme", NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen s = module_get_symbol(mod, symbol);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (s != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen buffer_append(schemes_buf, s, sizeof(*s));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_pop();
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#endif
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen buffer_append(schemes_buf, &null_scheme, sizeof(null_scheme));
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen schemes = buffer_get_data(schemes_buf, NULL);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid password_schemes_deinit(void)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#ifdef HAVE_MODULES
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen module_dir_unload(&scheme_modules);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#endif
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen buffer_free(schemes_buf);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen schemes = NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen