summaryrefslogtreecommitdiff
path: root/tests/unit
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2024-01-30 18:32:21 +0100
committerSébastien Helleu <flashcode@flashtux.org>2024-02-01 21:39:23 +0100
commit83567fd8714a65785c09e08622d0e157fcf001f9 (patch)
tree9d94babd344f60e1ccdeb7b1ce98973ad764b716 /tests/unit
parent70907fc16938a21113b45c6e826a245da01955a2 (diff)
downloadweechat-83567fd8714a65785c09e08622d0e157fcf001f9.zip
relay: allow password hash authentication in api relay, add option relay.network.time_window (issue #2066)
Diffstat (limited to 'tests/unit')
-rw-r--r--tests/unit/plugins/relay/test-relay-auth.cpp109
-rw-r--r--tests/unit/plugins/relay/test-relay-http.cpp234
2 files changed, 312 insertions, 31 deletions
diff --git a/tests/unit/plugins/relay/test-relay-auth.cpp b/tests/unit/plugins/relay/test-relay-auth.cpp
index af7738093..32574b6aa 100644
--- a/tests/unit/plugins/relay/test-relay-auth.cpp
+++ b/tests/unit/plugins/relay/test-relay-auth.cpp
@@ -26,7 +26,16 @@ extern "C"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <time.h>
+#include "src/core/wee-config-file.h"
+#include "src/plugins/relay/relay.h"
#include "src/plugins/relay/relay-auth.h"
+#include "src/plugins/relay/relay-client.h"
+#include "src/plugins/relay/relay-config.h"
+
+extern int relay_auth_check_salt (struct t_relay_client *client,
+ const char *salt_hexa,
+ const char *salt, int salt_size);
}
#define WEE_CHECK_PARSE_SHA(__parameters) \
@@ -100,6 +109,38 @@ TEST(RelayAuth, GenerateNonce)
/*
* Tests functions:
+ * relay_auth_check_password_plain
+ */
+
+TEST(RelayAuth, CheckPasswordPlain)
+{
+ struct t_relay_client *client;
+
+ client = (struct t_relay_client *)calloc (1, sizeof (*client));
+ CHECK(client);
+ client->protocol = RELAY_PROTOCOL_API;
+
+ /* invalid arguments */
+ LONGS_EQUAL(-2, relay_auth_check_password_plain (client, NULL, NULL));
+ LONGS_EQUAL(-2, relay_auth_check_password_plain (client, "abcd", NULL));
+ LONGS_EQUAL(-2, relay_auth_check_password_plain (client, NULL, "password"));
+
+ /* wrong password */
+ LONGS_EQUAL(-2, relay_auth_check_password_plain (client, "test", "password"));
+ LONGS_EQUAL(-2, relay_auth_check_password_plain (client, "Password", "password"));
+
+ /* good password */
+ LONGS_EQUAL(0, relay_auth_check_password_plain (client, "", ""));
+ LONGS_EQUAL(0, relay_auth_check_password_plain (client, "password", "password"));
+
+ /* test with "plain" disabled */
+ config_file_option_set (relay_config_network_password_hash_algo, "*,!plain", 1);
+ LONGS_EQUAL(-1, relay_auth_check_password_plain (client, "password", "password"));
+ config_file_option_reset (relay_config_network_password_hash_algo, 1);
+}
+
+/*
+ * Tests functions:
* relay_auth_parse_sha
*/
@@ -241,23 +282,53 @@ TEST(RelayAuth, ParsePbkdf2)
/*
* Tests functions:
- * relay_auth_check_password_plain
+ * relay_auth_check_salt
*/
-TEST(RelayAuth, CheckPasswordPlain)
+TEST(RelayAuth, CheckSalt)
{
- /* invalid arguments */
- LONGS_EQUAL(0, relay_auth_check_password_plain (NULL, NULL));
- LONGS_EQUAL(0, relay_auth_check_password_plain ("abcd", NULL));
- LONGS_EQUAL(0, relay_auth_check_password_plain (NULL, "password"));
-
- /* wrong password */
- LONGS_EQUAL(0, relay_auth_check_password_plain ("test", "password"));
- LONGS_EQUAL(0, relay_auth_check_password_plain ("Password", "password"));
-
- /* good password */
- LONGS_EQUAL(1, relay_auth_check_password_plain ("", ""));
- LONGS_EQUAL(1, relay_auth_check_password_plain ("password", "password"));
+ struct t_relay_client *client;
+ time_t time_now;
+ char salt[128];
+
+ client = (struct t_relay_client *)calloc (1, sizeof (*client));
+ CHECK(client);
+ client->nonce = strdup ("01aa03bb");
+
+ client->protocol = RELAY_PROTOCOL_API;
+
+ LONGS_EQUAL(0, relay_auth_check_salt (NULL, NULL, NULL, 0));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, NULL, 0));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, "test", 4));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, "1234", 4));
+
+ time_now = time (NULL);
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, relay_auth_check_salt (client, NULL, salt, strlen (salt)));
+ time_now = time (NULL) - 2;
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, relay_auth_check_salt (client, NULL, salt, strlen (salt)));
+ time_now = time (NULL) + 2;
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, relay_auth_check_salt (client, NULL, salt, strlen (salt)));
+ time_now = time (NULL) - 10;
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, salt, strlen (salt)));
+
+ client->protocol = RELAY_PROTOCOL_WEECHAT;
+
+ LONGS_EQUAL(0, relay_auth_check_salt (NULL, NULL, NULL, 0));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, NULL, 0));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, "test", 4));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, NULL, "1234", 4));
+
+ LONGS_EQUAL(0, relay_auth_check_salt (client, "01aa", "\x01\xaa", 2));
+ LONGS_EQUAL(0, relay_auth_check_salt (client, "01aa03bb", "\x01\xaa\x03\xbb", 4));
+ LONGS_EQUAL(1, relay_auth_check_salt (client, "01aa03bbcc", "\x01\xaa\x03\xbb\xcc", 5));
+ LONGS_EQUAL(1, relay_auth_check_salt (client, "01AA03BBCC", "\x01\xaa\x03\xbb\xcc", 5));
+
+ free (client->nonce);
+ free (client);
}
/*
@@ -403,3 +474,13 @@ TEST(RelayAuth, CheckHashPbkdf2)
"f53326c3729ffd12",
"password"));
}
+
+/*
+ * Tests functions:
+ * relay_auth_password_hash
+ */
+
+TEST(RelayAuth, PasswordHash)
+{
+ /* TODO: write tests */
+}
diff --git a/tests/unit/plugins/relay/test-relay-http.cpp b/tests/unit/plugins/relay/test-relay-http.cpp
index 64bb7b752..075e286d8 100644
--- a/tests/unit/plugins/relay/test-relay-http.cpp
+++ b/tests/unit/plugins/relay/test-relay-http.cpp
@@ -28,10 +28,15 @@ extern "C"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <time.h>
+#include <gcrypt.h>
#include "src/core/wee-config-file.h"
+#include "src/core/wee-crypto.h"
#include "src/core/wee-hashtable.h"
#include "src/core/wee-hook.h"
#include "src/core/wee-string.h"
+#include "src/plugins/relay/relay.h"
+#include "src/plugins/relay/relay-client.h"
#include "src/plugins/relay/relay-config.h"
#include "src/plugins/relay/relay-http.h"
#include "src/plugins/relay/relay-websocket.h"
@@ -45,6 +50,8 @@ extern int relay_http_parse_header (struct t_relay_http_request *request,
const char *header);
extern void relay_http_add_to_body (struct t_relay_http_request *request,
char **partial_message);
+extern int relay_http_get_auth_status (struct t_relay_client *client,
+ struct t_relay_http_request *request);
extern char *relay_http_compress (struct t_relay_http_request *request,
const char *data, int data_size,
int *compressed_size,
@@ -589,51 +596,244 @@ TEST(RelayHttp, AddToBody)
/*
* Tests functions:
- * relay_http_check_auth
+ * relay_http_get_auth_status
*/
-TEST(RelayHttp, CheckAuth)
+TEST(RelayHttp, GetAuthStatus)
{
+ struct t_relay_client *client;
struct t_relay_http_request *request;
- char *totp, *totp2;
+ const char *good_pwd = "secret_password";
+ const char *bad_pwd = "test";
+ char *totp, *totp2, salt[1024], salt_pass[1024], hash[1024], hash_hexa[2048];
+ char auth[4096], auth_base64[4096], auth_header[8192];
+ time_t time_now;
+ int hash_size;
+
+ config_file_option_set (relay_config_network_password, good_pwd, 1);
- config_file_option_set (relay_config_network_password, "secret_password", 1);
+ client = (struct t_relay_client *)calloc (1, sizeof (*client));
+ CHECK(client);
+ client->protocol = RELAY_PROTOCOL_API;
request = relay_http_request_alloc ();
CHECK(request);
- /* test password */
- LONGS_EQUAL(-1, relay_http_check_auth (request));
+ LONGS_EQUAL(-1, relay_http_get_auth_status (client, request));
hashtable_set (request->headers, "authorization", "Basic ");
- LONGS_EQUAL(-2, relay_http_check_auth (request));
+ LONGS_EQUAL(-2, relay_http_get_auth_status (client, request));
hashtable_set (request->headers, "authorization", "Basic \u26c4");
- LONGS_EQUAL(-2, relay_http_check_auth (request));
- /* set invalid user/password: "weechat:test" */
- hashtable_set (request->headers, "authorization", "Basic d2VlY2hhdDp0ZXN0");
- LONGS_EQUAL(-2, relay_http_check_auth (request));
- /* set valid user/password: "weechat:secret_password" */
+ LONGS_EQUAL(-2, relay_http_get_auth_status (client, request));
+
+ /* test invalid plain-text password ("test") */
+ hashtable_set (request->headers, "authorization", "Basic cGxhaW46dGVzdA==");
+ LONGS_EQUAL(-2, relay_http_get_auth_status (client, request));
+
+ /* test valid plain-text password ("secret_password") */
hashtable_set (request->headers,
- "authorization", "Basic d2VlY2hhdDpzZWNyZXRfcGFzc3dvcmQ");
- LONGS_EQUAL(0, relay_http_check_auth (request));
+ "authorization",
+ "Basic cGxhaW46c2VjcmV0X3Bhc3N3b3Jk");
+ LONGS_EQUAL(0, relay_http_get_auth_status (client, request));
+
+ /* test invalid hash: "SHA128" */
+ time_now = time (NULL);
+ snprintf (salt_pass, sizeof (salt_pass),
+ "%ld%s", time_now, bad_pwd);
+ LONGS_EQUAL(1, weecrypto_hash (salt_pass, strlen (salt_pass),
+ GCRY_MD_SHA256, hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:sha128:%ld:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(-5, relay_http_get_auth_status (client, request));
+
+ /* test invalid password hashed with SHA256: "test" */
+ time_now = time (NULL);
+ snprintf (salt_pass, sizeof (salt_pass),
+ "%ld%s", time_now, bad_pwd);
+ LONGS_EQUAL(1, weecrypto_hash (salt_pass, strlen (salt_pass),
+ GCRY_MD_SHA256, hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:sha256:%ld:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(-2, relay_http_get_auth_status (client, request));
+
+ /* test invalid password hashed with SHA512: "test" */
+ time_now = time (NULL);
+ snprintf (salt_pass, sizeof (salt_pass),
+ "%ld%s", time_now, bad_pwd);
+ LONGS_EQUAL(1, weecrypto_hash (salt_pass, strlen (salt_pass),
+ GCRY_MD_SHA512, hash, &hash_size));
+ LONGS_EQUAL(128, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:sha512:%ld:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(-2, relay_http_get_auth_status (client, request));
+
+ /* test valid password hashed with SHA256: "secret_password" but too old time (salt) */
+ time_now = time (NULL) - 10;
+ snprintf (salt_pass, sizeof (salt_pass),
+ "%ld%s", time_now, good_pwd);
+ LONGS_EQUAL(1, weecrypto_hash (salt_pass, strlen (salt_pass),
+ GCRY_MD_SHA256, hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:sha256:%ld:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(-6, relay_http_get_auth_status (client, request));
+
+ /* test valid password hashed with SHA256: "secret_password" */
+ time_now = time (NULL);
+ snprintf (salt_pass, sizeof (salt_pass),
+ "%ld%s", time_now, good_pwd);
+ LONGS_EQUAL(1, weecrypto_hash (salt_pass, strlen (salt_pass),
+ GCRY_MD_SHA256, hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:sha256:%ld:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(0, relay_http_get_auth_status (client, request));
+
+ /* test valid password hashed with SHA512: "secret_password" */
+ time_now = time (NULL);
+ snprintf (salt_pass, sizeof (salt_pass),
+ "%ld%s", time_now, good_pwd);
+ LONGS_EQUAL(1, weecrypto_hash (salt_pass, strlen (salt_pass),
+ GCRY_MD_SHA512, hash, &hash_size));
+ LONGS_EQUAL(128, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:sha512:%ld:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(0, relay_http_get_auth_status (client, request));
+
+ /* test invalid number of iterations */
+ time_now = time (NULL);
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, weecrypto_hash_pbkdf2 (good_pwd, strlen (good_pwd),
+ GCRY_MD_SHA256,
+ salt, strlen (salt),
+ 123,
+ hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:pbkdf2+sha256:%ld:123:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(-7, relay_http_get_auth_status (client, request));
+
+ /* test invalid password hashed with PBKDF2+SHA256: "test" */
+ time_now = time (NULL);
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, weecrypto_hash_pbkdf2 (bad_pwd, strlen (bad_pwd),
+ GCRY_MD_SHA256,
+ salt, strlen (salt),
+ 100000,
+ hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:pbkdf2+sha256:%ld:100000:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(-2, relay_http_get_auth_status (client, request));
+
+ /* test valid password hashed with PBKDF2+SHA256: "secret_password" */
+ time_now = time (NULL);
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, weecrypto_hash_pbkdf2 (good_pwd, strlen (good_pwd),
+ GCRY_MD_SHA256,
+ salt, strlen (salt),
+ 100000,
+ hash, &hash_size));
+ LONGS_EQUAL(64, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:pbkdf2+sha256:%ld:100000:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(0, relay_http_get_auth_status (client, request));
+
+ /* test valid password hashed with PBKDF2+SHA512: "secret_password" */
+ time_now = time (NULL);
+ snprintf (salt, sizeof (salt), "%ld", time_now);
+ LONGS_EQUAL(1, weecrypto_hash_pbkdf2 (good_pwd, strlen (good_pwd),
+ GCRY_MD_SHA512,
+ salt, strlen (salt),
+ 100000,
+ hash, &hash_size));
+ LONGS_EQUAL(128, string_base_encode ("16", hash, hash_size, hash_hexa));
+ snprintf (auth, sizeof (auth),
+ "hash:pbkdf2+sha512:%ld:100000:%s",
+ time_now,
+ hash_hexa);
+ string_base_encode ("64", auth, strlen (auth), auth_base64);
+ snprintf (auth_header, sizeof (auth_header), "Basic %s", auth_base64);
+ hashtable_set (request->headers, "authorization", auth_header);
+ LONGS_EQUAL(0, relay_http_get_auth_status (client, request));
/* test missing/invalid TOTP */
config_file_option_set (relay_config_network_totp_secret, "secretbase32", 1);
config_file_option_set (relay_config_network_totp_window, "1", 1);
- LONGS_EQUAL(-3, relay_http_check_auth (request));
+ LONGS_EQUAL(-3, relay_http_get_auth_status (client, request));
totp = hook_info_get (NULL, "totp_generate", "secretbase32");
CHECK(totp);
totp2 = strdup (totp);
totp2[0] = (totp2[0] == '1') ? '2' : '1';
hashtable_set (request->headers, "x-weechat-totp", totp2);
- LONGS_EQUAL(-4, relay_http_check_auth (request));
+ LONGS_EQUAL(-4, relay_http_get_auth_status (client, request));
hashtable_set (request->headers, "x-weechat-totp", totp);
- LONGS_EQUAL(0, relay_http_check_auth (request));
+ LONGS_EQUAL(0, relay_http_get_auth_status (client, request));
free (totp);
free (totp2);
config_file_option_reset (relay_config_network_totp_secret, 1);
config_file_option_reset (relay_config_network_totp_window, 1);
config_file_option_reset (relay_config_network_password, 1);
+
+ relay_http_request_free (request);
+ free (client);
+}
+
+/*
+ * Tests functions:
+ * relay_http_check_auth
+ */
+
+TEST(RelayHttp, CheckAuth)
+{
+ /* TODO: write tests */
}
/*