aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-21 12:34:03 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-21 12:34:03 +0100
commitb5391a29c27486a6c50636952e7e92a77e5ac18a (patch)
treec87a9d488d1193d7bd23e20b71f5e8d86e962d3c
parentb212e765ad521f685bb6817e9b65b19a51d9a933 (diff)
downloadrspamd-b5391a29c27486a6c50636952e7e92a77e5ac18a.tar.gz
rspamd-b5391a29c27486a6c50636952e7e92a77e5ac18a.zip
[Feature] Allow multiple PBKDF types in `rspamadm pw`
-rw-r--r--src/libutil/util.c6
-rw-r--r--src/rspamadm/pw.c104
-rw-r--r--src/rspamd.h3
3 files changed, 102 insertions, 11 deletions
diff --git a/src/libutil/util.c b/src/libutil/util.c
index 4120849a3..87395c568 100644
--- a/src/libutil/util.c
+++ b/src/libutil/util.c
@@ -77,6 +77,9 @@
const struct rspamd_controller_pbkdf pbkdf_list[] = {
{
+ .name = "PBKDF2-blake2b",
+ .alias = "pbkdf2",
+ .description = "standard CPU intensive \"slow\" KDF using blake2b hash function",
.type = RSPAMD_CRYPTOBOX_PBKDF2,
.id = RSPAMD_PBKDF_ID_V1,
.complexity = 16000,
@@ -84,6 +87,9 @@ const struct rspamd_controller_pbkdf pbkdf_list[] = {
.key_len = rspamd_cryptobox_HASHBYTES / 2
},
{
+ .name = "Catena-Butterfly",
+ .alias = "catena",
+ .description = "modern CPU and memory intensive KDF",
.type = RSPAMD_CRYPTOBOX_CATENA,
.id = RSPAMD_PBKDF_ID_V2,
.complexity = 10,
diff --git a/src/rspamadm/pw.c b/src/rspamadm/pw.c
index ff0185024..47c111335 100644
--- a/src/rspamadm/pw.c
+++ b/src/rspamadm/pw.c
@@ -27,6 +27,8 @@ static const char *rspamadm_pw_help (gboolean full_help);
static gboolean do_encrypt = FALSE;
static gboolean do_check = FALSE;
static gboolean quiet = FALSE;
+static gboolean list = FALSE;
+static gchar *type = "catena";
static gchar *password = NULL;
struct rspamadm_command pw_command = {
@@ -45,6 +47,10 @@ static GOptionEntry entries[] = {
"Supress output", NULL},
{"password", 'p', 0, G_OPTION_ARG_STRING, &password,
"Input password", NULL},
+ {"type", 't', 0, G_OPTION_ARG_STRING, &type,
+ "PBKDF type", NULL},
+ {"list", 'l', 0, G_OPTION_ARG_NONE, &list,
+ "List available algorithms", NULL},
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
};
@@ -59,6 +65,8 @@ rspamadm_pw_help (gboolean full_help)
"Where commands are:\n\n"
"--encrypt: encrypt password (this is a default command)\n"
"--check: check encrypted password using encrypted password\n"
+ "--list: list available pbkdf algorithms\n"
+ "--type: select the specified pbkdf type\n"
"--help: shows available options and commands";
}
else {
@@ -68,6 +76,26 @@ rspamadm_pw_help (gboolean full_help)
return help_str;
}
+static const struct rspamd_controller_pbkdf *
+rspamadm_get_pbkdf (void)
+{
+ const struct rspamd_controller_pbkdf *pbkdf;
+ guint i;
+
+ for (i = 0; i < RSPAMD_PBKDF_ID_MAX - 1; i ++) {
+ pbkdf = &pbkdf_list[i];
+
+ if (strcmp (type, pbkdf->alias) == 0) {
+ return pbkdf;
+ }
+ }
+
+ rspamd_fprintf (stderr, "Unknown PKDF type: %s\n", type);
+ exit (EXIT_FAILURE);
+
+ return NULL;
+}
+
static void
rspamadm_pw_encrypt (void)
{
@@ -76,7 +104,7 @@ rspamadm_pw_encrypt (void)
gchar *encoded_salt, *encoded_key;
gsize plen;
- pbkdf = &pbkdf_list[0];
+ pbkdf = rspamadm_get_pbkdf ();
g_assert (pbkdf != NULL);
if (password == NULL) {
@@ -98,7 +126,8 @@ 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->complexity);
+ salt, pbkdf->salt_len, key, pbkdf->key_len, pbkdf->complexity,
+ pbkdf->type);
encoded_salt = rspamd_encode_base32 (salt, pbkdf->salt_len);
encoded_key = rspamd_encode_base32 (key, pbkdf->key_len);
@@ -142,19 +171,22 @@ rspamd_encrypted_password_get_str (const gchar *password, gsize skip,
static void
rspamadm_pw_check (void)
{
- const struct rspamd_controller_pbkdf *pbkdf;
+ const struct rspamd_controller_pbkdf *pbkdf = NULL;
GIOChannel *in;
GString *encrypted_pwd;
const gchar *salt, *hash;
+ const gchar *start, *end;
guchar *salt_decoded, *key_decoded, *local_key;
- gsize salt_len, key_len;
+ gsize salt_len, key_len, size;
gchar test_password[8192];
- gsize plen, term = 0;
+ gsize plen, term = 0, i;
+ gint id;
+ gboolean ret = FALSE;
if (password == NULL) {
encrypted_pwd = g_string_new ("");
in = g_io_channel_unix_new (STDIN_FILENO);
- printf ("Enter encrypted password: ");
+ rspamd_printf ("Enter encrypted password: ");
fflush (stdout);
g_io_channel_read_line_string (in, encrypted_pwd, &term, NULL);
@@ -167,8 +199,38 @@ rspamadm_pw_check (void)
encrypted_pwd = g_string_new (password);
}
- pbkdf = &pbkdf_list[0];
- g_assert (pbkdf != NULL);
+ if (encrypted_pwd->str[0] == '$') {
+ /* Parse id */
+ start = encrypted_pwd->str + 1;
+ end = start;
+ size = 0;
+
+ while (*end != '\0' && g_ascii_isdigit (*end)) {
+ size++;
+ end++;
+ }
+
+ if (size > 0) {
+ gchar *endptr;
+ id = strtoul (start, &endptr, 10);
+
+ if ((endptr == NULL || *endptr == *end)) {
+ for (i = 0; i < RSPAMD_PBKDF_ID_MAX - 1; i ++) {
+ pbkdf = &pbkdf_list[i];
+
+ if (pbkdf->id == id) {
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!ret) {
+ rspamd_fprintf (stderr, "Invalid password format\n");
+ exit (EXIT_FAILURE);
+ }
if (encrypted_pwd->len < pbkdf->salt_len + pbkdf->key_len + 3) {
msg_err ("incorrect salt: password length: %z, must be at least %z characters",
@@ -213,12 +275,14 @@ 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->complexity);
+ local_key, pbkdf->key_len,
+ pbkdf->complexity,
+ pbkdf->type);
rspamd_explicit_memzero (test_password, plen);
if (!rspamd_constant_memcmp (key_decoded, local_key, pbkdf->key_len)) {
if (!quiet) {
- printf ("password incorrect\n");
+ rspamd_printf ("password incorrect\n");
}
exit (EXIT_FAILURE);
}
@@ -233,7 +297,21 @@ rspamadm_pw_check (void)
}
if (!quiet) {
- printf ("password correct\n");
+ rspamd_printf ("password correct\n");
+ }
+}
+
+static void
+rspamadm_alg_list (void)
+{
+ const struct rspamd_controller_pbkdf *pbkdf;
+ guint i;
+
+ for (i = 0; i < RSPAMD_PBKDF_ID_MAX - 1; i ++) {
+ pbkdf = &pbkdf_list[i];
+
+ rspamd_printf ("%s: %s - %s\n", pbkdf->alias, pbkdf->name,
+ pbkdf->description);
}
}
@@ -257,6 +335,10 @@ rspamadm_pw (gint argc, gchar **argv)
exit (1);
}
+ if (list) {
+ rspamadm_alg_list ();
+ exit (EXIT_SUCCESS);
+ }
if (!do_encrypt && !do_check) {
do_encrypt = TRUE;
diff --git a/src/rspamd.h b/src/rspamd.h
index 52838a950..bd4ca9684 100644
--- a/src/rspamd.h
+++ b/src/rspamd.h
@@ -85,6 +85,9 @@ struct rspamd_worker_signal_handler {
};
struct rspamd_controller_pbkdf {
+ const char *name;
+ const char *alias;
+ const char *description;
enum rspamd_cryptobox_pbkdf_type type;
gint id;
guint complexity;