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 = {
"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}
};
"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 {
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)
{
gchar *encoded_salt, *encoded_key;
gsize plen;
- pbkdf = &pbkdf_list[0];
+ pbkdf = rspamadm_get_pbkdf ();
g_assert (pbkdf != NULL);
if (password == NULL) {
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);
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);
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",
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);
}
}
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);
}
}
exit (1);
}
+ if (list) {
+ rspamadm_alg_list ();
+ exit (EXIT_SUCCESS);
+ }
if (!do_encrypt && !do_check) {
do_encrypt = TRUE;