password-scheme.c revision 0afc67e19d59d5f8f4eca73903047a970b5f6016
/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "base64.h"
#include "hex-binary.h"
#include "md4.h"
#include "md5.h"
#include "hmac-md5.h"
#include "ntlm.h"
#include "mycrypt.h"
#include "randgen.h"
#include "sha1.h"
#include "sha2.h"
#include "otp.h"
#include "str.h"
#include "password-scheme.h"
static const char salt_chars[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static const struct password_scheme *
password_scheme_lookup_name(const char *name)
{
const struct password_scheme *const *schemes;
unsigned int i, count;
for (i = 0; i < count; i++) {
return schemes[i];
}
return NULL;
}
/* Lookup scheme and encoding by given name. The encoding is taken from
".base64", ".b64" or ".hex" suffix if it exists, otherwise the default
encoding is used. */
static const struct password_scheme *
{
const struct password_scheme *scheme;
unsigned int scheme_len;
break;
}
}
return NULL;
else {
/* unknown encoding. treat as invalid scheme. */
return NULL;
}
return scheme;
}
{
const struct password_scheme *s;
enum password_encoding encoding;
const unsigned char *generated;
if (s == NULL)
return -1;
if (s->password_verify != NULL)
/* generic verification handler: generate the password and compare it
to the one in database */
return size != generated_size ? 0 :
}
const char *password_get_scheme(const char **password)
{
const char *p, *scheme;
return NULL;
/* $1$<salt>$<password>[$<ignored>] */
if (p != NULL) {
/* stop at next '$' after password */
if (p != NULL)
return "MD5-CRYPT";
}
}
if (**password != '{')
return NULL;
if (p == NULL)
return NULL;
*password = p + 1;
return scheme;
}
{
const struct password_scheme *s;
enum password_encoding encoding;
unsigned int len;
if (s == NULL)
return 0;
/* encoding not specified. we can guess quite well between
base64 and hex encodings. the only problem is distinguishing
2 character strings, but there shouldn't be any that short
raw_password_lens. */
}
switch (encoding) {
case PW_ENCODING_NONE:
*raw_password_r = (const unsigned char *)password;
break;
case PW_ENCODING_HEX:
break;
}
/* fall through, just in case it was base64-encoded after
all. some input lengths produce matching hex and base64
encoded lengths. */
case PW_ENCODING_BASE64:
return -1;
break;
}
/* password has invalid length */
return -1;
}
return 1;
}
const char *scheme,
{
const struct password_scheme *s;
enum password_encoding encoding;
if (s == NULL)
return FALSE;
return TRUE;
}
const char *scheme, const char **password_r)
{
const struct password_scheme *s;
const unsigned char *raw_password;
enum password_encoding encoding;
if (s == NULL)
return FALSE;
switch (encoding) {
case PW_ENCODING_NONE:
break;
case PW_ENCODING_BASE64:
break;
case PW_ENCODING_HEX:
break;
}
return TRUE;
}
{
unsigned int i, count;
return TRUE;
for (i = 0; i < count; i++) {
}
/* if they've the same generate function, they're equivalent */
}
static bool
{
if (size == 0) {
/* the default mycrypt() handler would return match */
return FALSE;
}
/* really shouldn't happen unless the system is broken */
i_error("crypt() failed: %m");
return FALSE;
}
}
static void
{
char salt[3];
const char *password;
*raw_password_r = (const unsigned char *)password;
}
static bool
{
const unsigned char *md5_password;
/* MD5-CRYPT */
&md5_password, &md5_size) < 0) {
i_error("md5_verify(%s): Not a valid MD5-CRYPT or "
"PLAIN-MD5 password", user);
return FALSE;
} else {
md5_password, md5_size) > 0;
}
}
static bool
{
}
static void
{
const char *password;
char salt[9];
unsigned int i;
for (i = 0; i < sizeof(salt)-1; i++)
*raw_password_r = (const unsigned char *)password;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
*size_r = SHA1_RESULTLEN;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
}
static void
{
#define SSHA_SALT_LEN 4
*raw_password_r = digest;
}
{
unsigned char sha1_digest[SHA1_RESULTLEN];
/* format: <SHA1 hash><salt> */
if (size <= SHA1_RESULTLEN) {
return FALSE;
}
}
static void
{
#define SSHA256_SALT_LEN 4
struct sha256_ctx ctx;
sha256_init(&ctx);
*raw_password_r = digest;
}
{
unsigned char sha256_digest[SHA256_RESULTLEN];
struct sha256_ctx ctx;
/* format: <SHA256 hash><salt> */
if (size <= SHA256_RESULTLEN) {
return FALSE;
}
sha256_init(&ctx);
size - SHA256_RESULTLEN);
}
static void
{
#define SMD5_SALT_LEN 4
struct md5_context ctx;
*raw_password_r = digest;
}
{
unsigned char md5_digest[MD5_RESULTLEN];
struct md5_context ctx;
/* format: <MD5 hash><salt> */
if (size <= MD5_RESULTLEN) {
return FALSE;
}
}
static void
{
*raw_password_r = (const unsigned char *)plaintext,
}
static void
{
struct hmac_md5_context ctx;
unsigned char *context_digest;
}
static void
{
unsigned char *digest;
i_fatal("digest_md5_generate(): username not given");
/* assume user@realm format for username. If user@domain is wanted
in the username, allow also user@domain@realm. */
realm++;
} else {
realm = "";
}
/* user:realm:passwd */
*raw_password_r = digest;
*size_r = MD5_RESULTLEN;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
*size_r = MD4_RESULTLEN;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
*size_r = MD5_RESULTLEN;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
*size_r = LM_HASH_SIZE;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
}
{
const char *password;
return strcasecmp(password,
}
static void
{
const char *password;
*raw_password_r = (const unsigned char *)password;
}
static void
{
const char *password;
*raw_password_r = (const unsigned char *)password;
}
static void
{
unsigned char *digest;
*raw_password_r = digest;
*size_r = MD5_RESULTLEN;
}
static const struct password_scheme builtin_schemes[] = {
{ "MD5-CRYPT", PW_ENCODING_NONE, 0,
NULL, sha256_generate },
};
{
i_panic("password_scheme_register(%s): Already registered",
}
}
{
const struct password_scheme *const *schemes;
unsigned int i, count;
for (i = 0; i < count; i++) {
return;
}
}
}
void password_schemes_init(void)
{
unsigned int i;
for (i = 0; i < N_ELEMENTS(builtin_schemes); i++)
}
void password_schemes_deinit(void)
{
}