diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2024-01-30 18:32:21 +0100 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2024-02-01 21:39:23 +0100 |
commit | 83567fd8714a65785c09e08622d0e157fcf001f9 (patch) | |
tree | 9d94babd344f60e1ccdeb7b1ce98973ad764b716 /tests/unit | |
parent | 70907fc16938a21113b45c6e826a245da01955a2 (diff) | |
download | weechat-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.cpp | 109 | ||||
-rw-r--r-- | tests/unit/plugins/relay/test-relay-http.cpp | 234 |
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 */ } /* |