From b212e765ad521f685bb6817e9b65b19a51d9a933 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 21 Apr 2016 12:10:59 +0100 Subject: [PATCH] [Feature] Allow catena encrypted passwords in controller --- src/controller.c | 21 +++++++++++++++------ src/libcryptobox/catena/catena.c | 9 +++++---- src/libcryptobox/catena/catena.h | 4 ++-- src/libcryptobox/cryptobox.c | 27 +++++++++++++++++++++++++-- src/libcryptobox/cryptobox.h | 19 ++++++++++++++----- src/libutil/util.c | 10 +++++++++- src/rspamadm/pw.c | 4 ++-- src/rspamd.h | 11 +++++++++-- 8 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/controller.c b/src/controller.c index f3e21730e..542f197c3 100644 --- a/src/controller.c +++ b/src/controller.c @@ -174,8 +174,9 @@ rspamd_is_encrypted_password (const gchar *password, { const gchar *start, *end; gint64 id; - gsize size; + gsize size, i; gboolean ret = FALSE; + const struct rspamd_controller_pbkdf *p; if (password[0] == '$') { /* Parse id */ @@ -192,11 +193,18 @@ rspamd_is_encrypted_password (const gchar *password, gchar *endptr; id = strtoul (start, &endptr, 10); - if ((endptr == NULL || *endptr == *end) && id == RSPAMD_PBKDF_ID_V1) { - ret = TRUE; + if ((endptr == NULL || *endptr == *end)) { + for (i = 0; i < RSPAMD_PBKDF_ID_MAX - 1; i ++) { + p = &pbkdf_list[i]; + + if (p->id == id) { + ret = TRUE; + if (pbkdf != NULL) { + *pbkdf = &pbkdf_list[0]; + } - if (pbkdf != NULL) { - *pbkdf = &pbkdf_list[0]; + break; + } } } } @@ -298,7 +306,8 @@ rspamd_check_encrypted_password (struct rspamd_controller_worker_ctx *ctx, local_key = g_alloca (pbkdf->key_len); rspamd_cryptobox_pbkdf (password->begin, password->len, salt_decoded, salt_len, - local_key, pbkdf->key_len, pbkdf->rounds); + local_key, pbkdf->key_len, pbkdf->complexity, + pbkdf->type); if (!rspamd_constant_memcmp (key_decoded, local_key, pbkdf->key_len)) { msg_info_ctx ("incorrect or absent password has been specified"); diff --git a/src/libcryptobox/catena/catena.c b/src/libcryptobox/catena/catena.c index c7f21637f..29950dd6e 100644 --- a/src/libcryptobox/catena/catena.c +++ b/src/libcryptobox/catena/catena.c @@ -346,7 +346,8 @@ Flap (const uint8_t x[H_LEN], const uint8_t lambda, const uint8_t garlic, g_free (tmp); } -static int __Catena(const uint8_t *pwd, const uint32_t pwdlen, +static int +__Catena (const uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, const uint8_t saltlen, const uint8_t *data, const uint32_t datalen, const uint8_t lambda, const uint8_t min_garlic, const uint8_t garlic, const uint8_t hashlen, const uint8_t client, @@ -402,7 +403,7 @@ static int __Catena(const uint8_t *pwd, const uint32_t pwdlen, /***************************************************/ int -catena (uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, +catena (const uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, const uint8_t saltlen, const uint8_t *data, const uint32_t datalen, const uint8_t lambda, const uint8_t min_garlic, const uint8_t garlic, const uint8_t hashlen, uint8_t *hash) @@ -413,12 +414,12 @@ catena (uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, } int -simple_catena (uint8_t *pwd, const uint32_t pwdlen, +simple_catena (const uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, const uint8_t saltlen, const uint8_t *data, const uint32_t datalen, uint8_t hash[H_LEN]) { - return __Catena(pwd, pwdlen, salt, saltlen, data, datalen, + return __Catena (pwd, pwdlen, salt, saltlen, data, datalen, LAMBDA, MIN_GARLIC, GARLIC, H_LEN, REGULAR, PASSWORD_HASHING_MODE, hash); } diff --git a/src/libcryptobox/catena/catena.h b/src/libcryptobox/catena/catena.h index 6624a54ec..56da560ea 100644 --- a/src/libcryptobox/catena/catena.h +++ b/src/libcryptobox/catena/catena.h @@ -25,7 +25,7 @@ #define CATENA_HLEN 64 int -catena (uint8_t *pwd, const uint32_t pwdlen, +catena (const uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, const uint8_t saltlen, const uint8_t *data, const uint32_t datalen, const uint8_t lambda, const uint8_t min_garlic, @@ -42,7 +42,7 @@ catena (uint8_t *pwd, const uint32_t pwdlen, * @param hash output hash * @return 0 if hash is generated, -1 in case of error */ -int simple_catena(uint8_t *pwd, const uint32_t pwdlen, +int simple_catena (const uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt, const uint8_t saltlen, const uint8_t *data, const uint32_t datalen, uint8_t hash[CATENA_HLEN]); diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index 22860695a..1680f1848 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -1200,8 +1200,8 @@ rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in, * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). * Code based on IEEE Std 802.11-2007, Annex H.4.2. */ -gboolean -rspamd_cryptobox_pbkdf (const char *pass, gsize pass_len, +static gboolean +rspamd_cryptobox_pbkdf2 (const char *pass, gsize pass_len, const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len, unsigned int rounds) { @@ -1253,6 +1253,29 @@ rspamd_cryptobox_pbkdf (const char *pass, gsize pass_len, return TRUE; } +gboolean +rspamd_cryptobox_pbkdf (const char *pass, gsize pass_len, + const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len, + unsigned int complexity, enum rspamd_cryptobox_pbkdf_type type) +{ + gboolean ret = FALSE; + + switch (type) { + case RSPAMD_CRYPTOBOX_CATENA: + if (catena (pass, pass_len, salt, salt_len, "rspamd", 6, + 4, complexity, complexity, key_len, key) == 0) { + ret = TRUE; + } + break; + case RSPAMD_CRYPTOBOX_PBKDF2: + default: + ret = rspamd_cryptobox_pbkdf2 (pass, pass_len, salt, salt_len, key, + key_len, complexity); + break; + } + + return ret; +} guint rspamd_cryptobox_pk_bytes (enum rspamd_cryptobox_mode mode) diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index fffbc098b..9631bd8d0 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -229,20 +229,29 @@ void rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in, unsigned long long inlen, const rspamd_sipkey_t k); +enum rspamd_cryptobox_pbkdf_type { + RSPAMD_CRYPTOBOX_PBKDF2 = 0, + RSPAMD_CRYPTOBOX_CATENA +}; + + /** - * Derive key from password using PKCS#5 and HMAC-blake2 + * Derive key from password using the specified algorithm * @param pass input password * @param pass_len length of the password * @param salt input salt * @param salt_len length of salt * @param key output key * @param key_len size of the key - * @param rounds number of rounds (should be reasonably high) + * @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena) * @return TRUE in case of success and FALSE if failed */ -gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len, - const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len, - unsigned int rounds); +gboolean rspamd_cryptobox_pbkdf (const char *pass, gsize pass_len, + const guint8 *salt, gsize salt_len, + guint8 *key, gsize key_len, + unsigned int complexity, + enum rspamd_cryptobox_pbkdf_type type); + /** * Real size of rspamd cryptobox public key diff --git a/src/libutil/util.c b/src/libutil/util.c index 7a649508e..4120849a3 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -77,8 +77,16 @@ const struct rspamd_controller_pbkdf pbkdf_list[] = { { + .type = RSPAMD_CRYPTOBOX_PBKDF2, .id = RSPAMD_PBKDF_ID_V1, - .rounds = 16000, + .complexity = 16000, + .salt_len = 20, + .key_len = rspamd_cryptobox_HASHBYTES / 2 + }, + { + .type = RSPAMD_CRYPTOBOX_CATENA, + .id = RSPAMD_PBKDF_ID_V2, + .complexity = 10, .salt_len = 20, .key_len = rspamd_cryptobox_HASHBYTES / 2 } diff --git a/src/rspamadm/pw.c b/src/rspamadm/pw.c index b11b671f7..ff0185024 100644 --- a/src/rspamadm/pw.c +++ b/src/rspamadm/pw.c @@ -98,7 +98,7 @@ rspamadm_pw_encrypt (void) ottery_rand_bytes (salt, pbkdf->salt_len); /* Derive key */ rspamd_cryptobox_pbkdf (password, strlen (password), - salt, pbkdf->salt_len, key, pbkdf->key_len, pbkdf->rounds); + salt, pbkdf->salt_len, key, pbkdf->key_len, pbkdf->complexity); encoded_salt = rspamd_encode_base32 (salt, pbkdf->salt_len); encoded_key = rspamd_encode_base32 (key, pbkdf->key_len); @@ -213,7 +213,7 @@ rspamadm_pw_check (void) local_key = g_alloca (pbkdf->key_len); rspamd_cryptobox_pbkdf (test_password, plen, salt_decoded, salt_len, - local_key, pbkdf->key_len, pbkdf->rounds); + local_key, pbkdf->key_len, pbkdf->complexity); rspamd_explicit_memzero (test_password, plen); if (!rspamd_constant_memcmp (key_decoded, local_key, pbkdf->key_len)) { diff --git a/src/rspamd.h b/src/rspamd.h index a677f02c7..52838a950 100644 --- a/src/rspamd.h +++ b/src/rspamd.h @@ -85,8 +85,9 @@ struct rspamd_worker_signal_handler { }; struct rspamd_controller_pbkdf { + enum rspamd_cryptobox_pbkdf_type type; gint id; - guint rounds; + guint complexity; gsize salt_len; gsize key_len; }; @@ -291,9 +292,15 @@ void register_custom_controller_command (const gchar *name, gboolean privilleged, gboolean require_message); -#define RSPAMD_PBKDF_ID_V1 1 +enum rspamd_pbkdf_version_id { + RSPAMD_PBKDF_ID_V1 = 1, + RSPAMD_PBKDF_ID_V2= 2, + RSPAMD_PBKDF_ID_MAX +}; + extern const struct rspamd_controller_pbkdf pbkdf_list[]; + #endif /* -- 2.39.5