]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow catena encrypted passwords in controller
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 21 Apr 2016 11:10:59 +0000 (12:10 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 21 Apr 2016 11:10:59 +0000 (12:10 +0100)
src/controller.c
src/libcryptobox/catena/catena.c
src/libcryptobox/catena/catena.h
src/libcryptobox/cryptobox.c
src/libcryptobox/cryptobox.h
src/libutil/util.c
src/rspamadm/pw.c
src/rspamd.h

index f3e21730e355abc60261a5662ce83dbf90208a91..542f197c3644508421d4496e36d254c0b32a14ae 100644 (file)
@@ -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");
index c7f21637f1290208e1029bd46c0328ca0a41e6f4..29950dd6e3bebcbb3d1c8498757a17f599385b53 100644 (file)
@@ -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);
 }
index 6624a54ec0819c50e86fe48196d6b8b82e0241b4..56da560ea31a97195d813a2d02b34acf1fd23b10 100644 (file)
@@ -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]);
index 22860695ae519ba3701269e1af7199a06be46137..1680f1848fdbd26807de6fda99e72b84467ef546 100644 (file)
@@ -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)
index fffbc098b86394f11e3cee9ff2d46bd9912182ac..9631bd8d06dd2c32cb49d84078a4e3adca43aa2f 100644 (file)
@@ -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
index 7a649508e96c39c41d401d277341f0a63ea20bb4..4120849a3fcbbf1b6be9903f2c249cfb9587d467 100644 (file)
 
 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
                }
index b11b671f7ba9a62ef92eb312d5ed41bda3df2937..ff0185024f95de1c60bb49486420e2ece015aefc 100644 (file)
@@ -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)) {
index a677f02c79468fa136a89c5f0b2876e7093e3b04..52838a9504535ff97aa23f6d02d4b260dd905988 100644 (file)
@@ -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
 
 /*