struct auth_passdb *passdb = request->passdb;
const char *encoded_password;
string_t *str;
+ struct password_generate_params gen_params = {.user = request->user,
+ .rounds = 0 };
switch (result) {
case PASSDB_RESULT_USER_UNKNOWN:
strdup() it so that mech_password doesn't get
cleared too early. */
if (!password_generate_encoded(request->mech_password,
- request->user,
- CACHED_PASSWORD_SCHEME,
- &encoded_password))
+ &gen_params,
+ CACHED_PASSWORD_SCHEME,
+ &encoded_password))
i_unreached();
request->passdb_password =
p_strconcat(request->pool, "{"CACHED_PASSWORD_SCHEME"}",
static void log_password_failure(struct auth_request *request,
const char *plain_password,
const char *crypted_password,
- const char *scheme, const char *user,
+ const char *scheme,
+ const struct password_generate_params *params,
const char *subsystem)
{
static bool scheme_ok = FALSE;
/* perhaps the scheme is wrong - see if we can find
a working one */
working_scheme = password_scheme_detect(plain_password,
- crypted_password, user);
+ crypted_password, params);
if (working_scheme != NULL) {
str_printfa(str, ", try %s scheme instead",
working_scheme);
size_t raw_password_size;
const char *error;
int ret;
+ struct password_generate_params gen_params = {.user = request->original_username,
+ .rounds = 0};
if (request->skip_password_check) {
/* passdb continue* rule after a successful authentication */
/* Use original_username since it may be important for some
password schemes (eg. digest-md5). Otherwise the username is used
only for logging purposes. */
- ret = password_verify(plain_password, request->original_username,
+ ret = password_verify(plain_password, &gen_params,
scheme, raw_password, raw_password_size, &error);
if (ret < 0) {
const char *password_str = request->set->debug_passwords ?
if (ret <= 0 && request->set->debug_passwords) T_BEGIN {
log_password_failure(request, plain_password,
crypted_password, scheme,
- request->original_username,
+ &gen_params,
subsystem);
} T_END;
return ret;
const unsigned char **credentials_r, size_t *size_r)
{
const char *wanted_scheme = auth_request->credentials_scheme;
- const char *plaintext, *username, *error;
+ const char *plaintext, *error;
int ret;
+ struct password_generate_params pwd_gen_params;
if (auth_request->prefer_plain_credentials &&
password_scheme_is_alias(input_scheme, "PLAIN")) {
/* we can generate anything out of plaintext passwords */
plaintext = t_strndup(*credentials_r, *size_r);
- username = auth_request->original_username;
+ i_zero(&pwd_gen_params);
+ pwd_gen_params.user = auth_request->original_username;
if (!auth_request->domain_is_realm &&
- strchr(username, '@') != NULL) {
+ strchr(pwd_gen_params.user, '@') != NULL) {
/* domain must not be used as realm. add the @realm. */
- username = t_strconcat(username, "@",
+ pwd_gen_params.user = t_strconcat(pwd_gen_params.user, "@",
auth_request->realm, NULL);
}
if (auth_request->set->debug_passwords) {
auth_request_log_debug(auth_request, AUTH_SUBSYS_DB,
"Generating %s from user '%s', password '%s'",
- wanted_scheme, username, plaintext);
+ wanted_scheme, pwd_gen_params.user, plaintext);
}
- if (!password_generate(plaintext, username,
+ if (!password_generate(plaintext, &pwd_gen_params,
wanted_scheme, credentials_r, size_r)) {
auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
"Requested unknown scheme %s", wanted_scheme);
#define CRYPT_SHA2_ROUNDS_MAX 999999999
#define CRYPT_SHA2_SALT_LEN 16
-unsigned int password_scheme_encryption_rounds = 0;
-
-void password_set_encryption_rounds(unsigned int rounds)
-{
- /* just take the new value. crypt_generate_*() will enforce their
- limits. */
- password_scheme_encryption_rounds = rounds;
-}
-
static void
-crypt_generate_des(const char *plaintext, const char *user ATTR_UNUSED,
+crypt_generate_des(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
#define CRYPT_SALT_LEN 2
}
static void
-crypt_generate_blowfisch(const char *plaintext, const char *user ATTR_UNUSED,
+crypt_generate_blowfisch(const char *plaintext, const struct password_generate_params *params,
const unsigned char **raw_password_r, size_t *size_r)
{
const char *password, *salt, *magic_salt;
- unsigned int rounds = password_scheme_encryption_rounds;
+ unsigned int rounds = params->rounds;
if (rounds == 0)
rounds = CRYPT_BLF_ROUNDS_DEFAULT;
}
static void
-crypt_generate_sha256(const char *plaintext, const char *user ATTR_UNUSED,
+crypt_generate_sha256(const char *plaintext, const struct password_generate_params *params,
const unsigned char **raw_password_r, size_t *size_r)
{
const char *password, *salt, *magic_salt;
- unsigned int rounds = password_scheme_encryption_rounds;
+ unsigned int rounds = params->rounds;
if (rounds == 0)
rounds = CRYPT_SHA2_ROUNDS_DEFAULT;
}
static void
-crypt_generate_sha512(const char *plaintext, const char *user ATTR_UNUSED,
+crypt_generate_sha512(const char *plaintext, const struct password_generate_params *params,
const unsigned char **raw_password_r, size_t *size_r)
{
const char *password, *salt, *magic_salt;
- unsigned int rounds = password_scheme_encryption_rounds;
+ unsigned int rounds = params->rounds;
if (rounds == 0)
rounds = CRYPT_SHA2_ROUNDS_DEFAULT;
rounds, PBKDF2_KEY_SIZE_SHA1, &buf);
}
-void pbkdf2_generate(const char *plaintext, const char *user ATTR_UNUSED,
+void pbkdf2_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char key[PBKDF2_KEY_SIZE_SHA1];
const char *salt;
string_t *str = t_str_new(64);
- unsigned int rounds = password_scheme_encryption_rounds;
+ unsigned int rounds = params->rounds;
if (rounds == 0)
rounds = PBKDF2_ROUNDS_DEFAULT;
*size_r = str_len(str);
}
-int pbkdf2_verify(const char *plaintext, const char *user ATTR_UNUSED,
+int pbkdf2_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
return 0;
}
-int scram_sha1_verify(const char *plaintext, const char *user ATTR_UNUSED,
+int scram_sha1_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
return ret;
}
-void scram_sha1_generate(const char *plaintext, const char *user ATTR_UNUSED,
+void scram_sha1_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
string_t *str;
return scheme;
}
-int password_verify(const char *plaintext, const char *user, const char *scheme,
- const unsigned char *raw_password, size_t size,
- const char **error_r)
+int password_verify(const char *plaintext,
+ const struct password_generate_params *params,
+ const char *scheme, const unsigned char *raw_password,
+ size_t size, const char **error_r)
{
const struct password_scheme *s;
enum password_encoding encoding;
}
if (s->password_verify != NULL) {
- ret = s->password_verify(plaintext, user, raw_password, size,
+ ret = s->password_verify(plaintext, params, raw_password, size,
error_r);
} else {
/* generic verification handler: generate the password and
compare it to the one in database */
- s->password_generate(plaintext, user,
+ s->password_generate(plaintext, params,
&generated, &generated_size);
ret = size != generated_size ? 0 :
mem_equals_timing_safe(generated, raw_password, size) ? 1 : 0;
return 1;
}
-bool password_generate(const char *plaintext, const char *user,
+bool password_generate(const char *plaintext, const struct password_generate_params *params,
const char *scheme,
const unsigned char **raw_password_r, size_t *size_r)
{
if (s == NULL)
return FALSE;
- s->password_generate(plaintext, user, raw_password_r, size_r);
+ s->password_generate(plaintext, params, raw_password_r, size_r);
return TRUE;
}
-bool password_generate_encoded(const char *plaintext, const char *user,
+bool password_generate_encoded(const char *plaintext, const struct password_generate_params *params,
const char *scheme, const char **password_r)
{
const struct password_scheme *s;
if (s == NULL)
return FALSE;
- s->password_generate(plaintext, user, &raw_password, &size);
+ s->password_generate(plaintext, params, &raw_password, &size);
switch (encoding) {
case PW_ENCODING_NONE:
*password_r = t_strndup(raw_password, size);
const char *
password_scheme_detect(const char *plain_password, const char *crypted_password,
- const char *user)
+ const struct password_generate_params *params)
{
struct hash_iterate_context *ctx;
const char *key;
&error) <= 0)
continue;
- if (password_verify(plain_password, user, scheme->name,
+ if (password_verify(plain_password, params, scheme->name,
raw_password, raw_password_size,
&error) > 0)
break;
return key;
}
-int crypt_verify(const char *plaintext, const char *user ATTR_UNUSED,
+int crypt_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static int
-md5_verify(const char *plaintext, const char *user,
+md5_verify(const char *plaintext, const struct password_generate_params *params,
const unsigned char *raw_password, size_t size, const char **error_r)
{
const char *password, *str, *error;
*error_r = "Not a valid MD5-CRYPT or PLAIN-MD5 password";
return -1;
} else {
- return password_verify(plaintext, user, "PLAIN-MD5",
+ return password_verify(plaintext, params, "PLAIN-MD5",
md5_password, md5_size, error_r);
}
}
static int
-md5_crypt_verify(const char *plaintext, const char *user ATTR_UNUSED,
+md5_crypt_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r ATTR_UNUSED)
{
}
static void
-md5_crypt_generate(const char *plaintext, const char *user ATTR_UNUSED,
+md5_crypt_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
const char *password;
}
static void
-sha1_generate(const char *plaintext, const char *user ATTR_UNUSED,
+sha1_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
}
static void
-sha256_generate(const char *plaintext, const char *user ATTR_UNUSED,
+sha256_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
}
static void
-sha512_generate(const char *plaintext, const char *user ATTR_UNUSED,
+sha512_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
}
static void
-ssha_generate(const char *plaintext, const char *user ATTR_UNUSED,
+ssha_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
#define SSHA_SALT_LEN 4
*size_r = SHA1_RESULTLEN + SSHA_SALT_LEN;
}
-static int ssha_verify(const char *plaintext, const char *user ATTR_UNUSED,
+static int ssha_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static void
-ssha256_generate(const char *plaintext, const char *user ATTR_UNUSED,
+ssha256_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
#define SSHA256_SALT_LEN 4
*size_r = SHA256_RESULTLEN + SSHA256_SALT_LEN;
}
-static int ssha256_verify(const char *plaintext, const char *user ATTR_UNUSED,
+static int ssha256_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static void
-ssha512_generate(const char *plaintext, const char *user ATTR_UNUSED,
+ssha512_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
#define SSHA512_SALT_LEN 4
*size_r = SHA512_RESULTLEN + SSHA512_SALT_LEN;
}
-static int ssha512_verify(const char *plaintext, const char *user ATTR_UNUSED,
+static int ssha512_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static void
-smd5_generate(const char *plaintext, const char *user ATTR_UNUSED,
+smd5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
#define SMD5_SALT_LEN 4
*size_r = MD5_RESULTLEN + SMD5_SALT_LEN;
}
-static int smd5_verify(const char *plaintext, const char *user ATTR_UNUSED,
+static int smd5_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static void
-plain_generate(const char *plaintext, const char *user ATTR_UNUSED,
+plain_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
*raw_password_r = (const unsigned char *)plaintext,
}
static int
-plain_verify(const char *plaintext, const char *user ATTR_UNUSED,
+plain_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r ATTR_UNUSED)
{
}
static int
-plain_trunc_verify(const char *plaintext, const char *user ATTR_UNUSED,
+plain_trunc_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static void
-cram_md5_generate(const char *plaintext, const char *user ATTR_UNUSED,
+cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
struct hmac_context ctx;
}
static void
-digest_md5_generate(const char *plaintext, const char *user,
+digest_md5_generate(const char *plaintext, const struct password_generate_params *params,
const unsigned char **raw_password_r, size_t *size_r)
{
- const char *realm, *str;
+ const char *realm, *str, *user;
unsigned char *digest;
- if (user == NULL)
+ if (params->user == NULL)
i_fatal("digest_md5_generate(): username not given");
+ user = params->user;
+
/* assume user@realm format for username. If user@domain is wanted
in the username, allow also user@domain@realm. */
}
static void
-plain_md4_generate(const char *plaintext, const char *user ATTR_UNUSED,
+plain_md4_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
}
static void
-plain_md5_generate(const char *plaintext, const char *user ATTR_UNUSED,
+plain_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
}
static void
-lm_generate(const char *plaintext, const char *user ATTR_UNUSED,
+lm_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
}
static void
-ntlm_generate(const char *plaintext, const char *user ATTR_UNUSED,
+ntlm_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
*size_r = NTLMSSP_HASH_SIZE;
}
-static int otp_verify(const char *plaintext, const char *user ATTR_UNUSED,
+static int otp_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r)
{
}
static void
-otp_generate(const char *plaintext, const char *user ATTR_UNUSED,
+otp_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
const char *password;
}
static void
-skey_generate(const char *plaintext, const char *user ATTR_UNUSED,
+skey_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
const char *password;
}
static void
-rpa_generate(const char *plaintext, const char *user ATTR_UNUSED,
+rpa_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
unsigned char *digest;
PW_ENCODING_HEX
};
+struct password_generate_params {
+ const char *user;
+ unsigned int rounds;
+};
+
struct password_scheme {
const char *name;
enum password_encoding default_encoding;
hex and base64 encoded passwords. */
unsigned int raw_password_len;
- int (*password_verify)(const char *plaintext, const char *user,
+ int (*password_verify)(const char *plaintext, const struct password_generate_params *params,
const unsigned char *raw_password, size_t size,
const char **error_r);
- void (*password_generate)(const char *plaintext, const char *user,
+ void (*password_generate)(const char *plaintext, const struct password_generate_params *params,
const unsigned char **raw_password_r,
size_t *size_r);
};
/* Returns 1 = matched, 0 = didn't match, -1 = unknown scheme or invalid
raw_password */
-int password_verify(const char *plaintext, const char *user, const char *scheme,
- const unsigned char *raw_password, size_t size,
+int password_verify(const char *plaintext, const struct password_generate_params *params,
+ const char *scheme, const unsigned char *raw_password, size_t size,
const char **error_r);
/* Extracts scheme from password, or returns NULL if it isn't found.
/* Create password with wanted scheme out of plaintext password and username.
Potential base64/hex directives are ignored in scheme. Returns FALSE if
the scheme is unknown. */
-bool password_generate(const char *plaintext, const char *user,
+bool password_generate(const char *plaintext, const struct password_generate_params *params,
const char *scheme,
const unsigned char **raw_password_r, size_t *size_r);
/* Like above, but generate encoded passwords. If hex/base64 directive isn't
specified in the scheme, the default encoding for the scheme is used.
Returns FALSE if the scheme is unknown. */
-bool password_generate_encoded(const char *plaintext, const char *user,
+bool password_generate_encoded(const char *plaintext, const struct password_generate_params *params,
const char *scheme, const char **password_r);
/* Returns TRUE if schemes are equivalent. */
or NULL if nothing was found. */
const char *
password_scheme_detect(const char *plain_password, const char *crypted_password,
- const char *user);
+ const struct password_generate_params *params);
void password_scheme_register(const struct password_scheme *scheme);
void password_scheme_unregister(const struct password_scheme *scheme);
ATTR_NULL(2);
void password_generate_rpa(const char *pw, unsigned char result[]);
-int crypt_verify(const char *plaintext, const char *user,
+int crypt_verify(const char *plaintext, const struct password_generate_params *params,
const unsigned char *raw_password, size_t size,
const char **error_r);
unsigned int *iter_count_r, const char **salt_r,
unsigned char stored_key_r[],
unsigned char server_key_r[], const char **error_r);
-int scram_sha1_verify(const char *plaintext, const char *user ATTR_UNUSED,
+int scram_sha1_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r ATTR_UNUSED);
-void scram_sha1_generate(const char *plaintext, const char *user ATTR_UNUSED,
+void scram_sha1_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r);
-void pbkdf2_generate(const char *plaintext, const char *user ATTR_UNUSED,
+void pbkdf2_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r);
-int pbkdf2_verify(const char *plaintext, const char *user ATTR_UNUSED,
+int pbkdf2_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char *raw_password, size_t size,
const char **error_r);
static void cmd_pw(int argc, char *argv[])
{
const char *hash = NULL;
- const char *user = NULL;
const char *scheme = NULL;
const char *plaintext = NULL;
const char *test_hash = NULL;
bool list_schemes = FALSE, reverse_verify = FALSE;
- unsigned int rounds = 0;
int c;
struct module_dir_load_settings mod_set;
+ struct password_generate_params gen_params;
+ i_zero(&gen_params);
password_schemes_init();
plaintext = optarg;
break;
case 'r':
- if (str_to_uint(optarg, &rounds) < 0)
+ if (str_to_uint(optarg, &gen_params.rounds) < 0)
i_fatal("Invalid number of rounds: %s", optarg);
break;
case 's':
reverse_verify = TRUE;
break;
case 'u':
- user = optarg;
+ gen_params.user = optarg;
break;
case 'V':
reverse_verify = TRUE;
help(&doveadm_cmd_pw);
scheme = scheme == NULL ? DEFAULT_SCHEME : t_str_ucase(scheme);
- if (rounds > 0)
- password_set_encryption_rounds(rounds);
if (test_hash != NULL && plaintext == NULL)
plaintext = t_askpass("Enter password to verify: ");
}
}
- if (!password_generate_encoded(plaintext, user, scheme, &hash))
+ if (!password_generate_encoded(plaintext, &gen_params, scheme, &hash))
i_fatal("Unknown scheme: %s", scheme);
if (reverse_verify) {
const unsigned char *raw_password;
&error) <= 0)
i_fatal("reverse decode check failed: %s", error);
- if (password_verify(plaintext, user, scheme,
+ if (password_verify(plaintext, &gen_params, scheme,
raw_password, size, &error) <= 0) {
i_fatal("reverse password verification check failed: %s",
error);