1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-01 15:26:37 +02:00

relay: accept hash of password in init command with option "password_hash"

Allowed algorithms are:

* PBKDF2 (SHA256 or SHA512, salt, iterations)
* SHA256
* SHA512
This commit is contained in:
Sébastien Helleu
2020-03-02 00:46:10 +01:00
parent 1882686f8a
commit 2d2b49bfaa
11 changed files with 633 additions and 139 deletions
@@ -158,13 +158,172 @@ relay_weechat_protocol_is_sync (struct t_relay_client *ptr_client,
return 0;
}
/*
* Parses PBKDF2 parameters from string with format:
*
* algorithm:salt:iterations:hash
*
* where:
*
* algorithm is "sha256" or "sha512"
* salt is the salt in hexadecimal
* iterations it the number of iterations (≥ 1)
* hash is the hashed password with the parameters above, in hexadecimal
*/
void
relay_weechat_protocol_parse_pbkdf2 (const char *parameters,
char **algorithm,
char **salt,
int *salt_size,
int *iterations,
char **hash_pbkdf2)
{
char **argv, *error;
int argc;
*algorithm = NULL;
*salt = NULL;
*salt_size = 0;
*iterations = 0;
*hash_pbkdf2 = NULL;
if (!parameters)
return;
argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc);
if (!argv || (argc < 4))
{
/* not enough parameters */
if (argv)
weechat_string_free_split (argv);
return;
}
/* parameter 1: algorithm */
if ((strcmp (argv[0], "sha256") == 0)
|| (strcmp (argv[0], "sha512") == 0))
{
*algorithm = strdup (argv[0]);
}
/* parameter 2: salt */
*salt = malloc (strlen (argv[1]) + 1);
if (*salt)
*salt_size = weechat_string_base_decode (16, argv[1], *salt);
/* parameter 3: iterations */
*iterations = (int)strtol (argv[2], &error, 10);
if (!error || error[0])
*iterations = 0;
/* parameter 4: the PBKDF2 hash */
*hash_pbkdf2 = strdup (argv[3]);
weechat_string_free_split (argv);
}
/*
* Checks if hashed password received is valid.
*
* Format of hash_password is: algorithm:hash
*
* Returns 1 if the hashed password is valid, otherwise 0.
*/
int
relay_weechat_protocol_check_hash (const char *hashed_password,
const char *password)
{
const char *pos_hash;
char *hash_algo, hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1];
char *hash_pbkdf2_algo, *salt, *hash_pbkdf2;
int rc, hash_size, salt_size, iterations;
rc = 0;
if (!hashed_password || !password)
goto end;
pos_hash = strchr (hashed_password, ':');
if (!pos_hash)
goto end;
hash_algo = weechat_strndup (hashed_password, pos_hash - hashed_password);
if (!hash_algo)
goto end;
pos_hash++;
if ((strcmp (hash_algo, "sha256") == 0)
|| (strcmp (hash_algo, "sha512") == 0))
{
if (weechat_crypto_hash (password, strlen (password), hash_algo,
hash, &hash_size))
{
weechat_string_base_encode (16, hash, hash_size, hash_hexa);
if (weechat_strcasecmp (hash_hexa, pos_hash) == 0)
rc = 1;
}
}
else if (strcmp (hash_algo, "pbkdf2") == 0)
{
relay_weechat_protocol_parse_pbkdf2 (pos_hash,
&hash_pbkdf2_algo,
&salt,
&salt_size,
&iterations,
&hash_pbkdf2);
if (hash_pbkdf2_algo && salt && (salt_size > 0) && (iterations > 0)
&& hash_pbkdf2)
{
if (weechat_crypto_hash_pbkdf2 (password, strlen (password),
hash_pbkdf2_algo,
salt, salt_size,
iterations,
hash, &hash_size))
{
weechat_string_base_encode (16, hash, hash_size, hash_hexa);
if (weechat_strcasecmp (hash_hexa, hash_pbkdf2) == 0)
rc = 1;
}
}
if (hash_pbkdf2_algo)
free (hash_pbkdf2_algo);
if (salt)
free (salt);
if (hash_pbkdf2)
free (hash_pbkdf2);
}
free (hash_algo);
end:
return rc;
}
/*
* Callback for command "init" (from client).
*
* Format is: init arg1=value1,arg2=value2
*
* Allowed arguments:
* password plain text password (recommended with SSL only)
* password_hash hashed password, value is: algorithm:[parameters:]hash
* supported algorithms: sha256, sha512 and pbkdf2
* for pbkdf2, parameters are: algorithm, salt, iterations
* hash is given in hexadecimal
* totp time-based one time password used as secondary
* authentication factor
* compression zlib (default) or off
*
* Message looks like:
* init password=mypass
* init password=mypass,compression=zlib
* init password=mypass,compression=off
* init password_hash=sha256:71c480df93d6ae2f1efad1447c66c9…,totp=123456
* init password_hash=pbkdf2:sha256:414232…:100000:01757d53157c…,totp=123456
*/
RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
@@ -201,6 +360,15 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
if (password && (strcmp (password, pos) == 0))
RELAY_WEECHAT_DATA(client, password_ok) = 1;
}
else if (strcmp (options[i], "password_hash") == 0)
{
password_received = 1;
if (password
&& relay_weechat_protocol_check_hash (pos, password))
{
RELAY_WEECHAT_DATA(client, password_ok) = 1;
}
}
else if (strcmp (options[i], "totp") == 0)
{
totp_received = 1;