diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/relay/api/relay-api-protocol.c | 57 | ||||
-rw-r--r-- | src/plugins/relay/api/relay-api.c | 2 | ||||
-rw-r--r-- | src/plugins/relay/relay-auth.c | 234 | ||||
-rw-r--r-- | src/plugins/relay/relay-auth.h | 8 | ||||
-rw-r--r-- | src/plugins/relay/relay-client.c | 11 | ||||
-rw-r--r-- | src/plugins/relay/relay-client.h | 1 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.c | 8 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.h | 1 | ||||
-rw-r--r-- | src/plugins/relay/relay-http.c | 172 | ||||
-rw-r--r-- | src/plugins/relay/relay-http.h | 17 | ||||
-rw-r--r-- | src/plugins/relay/weechat/relay-weechat-protocol.c | 11 |
11 files changed, 325 insertions, 197 deletions
diff --git a/src/plugins/relay/api/relay-api-protocol.c b/src/plugins/relay/api/relay-api-protocol.c index f04264125..b850194f7 100644 --- a/src/plugins/relay/api/relay-api-protocol.c +++ b/src/plugins/relay/api/relay-api-protocol.c @@ -39,60 +39,6 @@ /* - * Checks authentication from client. - * - * Returns: - * 1: OK, client authenticated - * 0: client NOT authenticated - */ - -int -relay_api_protocol_check_auth (struct t_relay_client *client, - struct t_relay_http_request *request) -{ - if (client->status == RELAY_STATUS_CONNECTED) - return 1; - - switch (relay_http_check_auth (request)) - { - case 0: /* OK */ - return 1; - case -1: /* missing password */ - relay_api_msg_send_error_json (client, - RELAY_HTTP_401_UNAUTHORIZED, - "WWW-Authenticate: Basic realm=Password", - RELAY_HTTP_ERROR_MISSING_PASSWORD); - break; - case -2: /* invalid password */ - relay_api_msg_send_error_json (client, - RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_INVALID_PASSWORD); - break; - case -3: /* missing TOTP */ - relay_api_msg_send_error_json (client, - RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_MISSING_TOTP); - break; - case -4: /* invalid TOTP */ - relay_api_msg_send_error_json (client, - RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_INVALID_TOTP); - break; - case -5: /* out of memory */ - relay_api_msg_send_error_json (client, - RELAY_HTTP_503_SERVICE_UNAVAILABLE, - NULL, - RELAY_HTTP_ERROR_OUT_OF_MEMORY); - break; - } - - return 0; -} - -/* * Returns value of an URL parameter as boolean (0 or 1), using a default value * if the parameter is not set or if it's not a valid boolean. */ @@ -677,7 +623,8 @@ relay_api_protocol_recv_http (struct t_relay_client *client, if (!request || RELAY_CLIENT_HAS_ENDED(client)) return; - if (!relay_api_protocol_check_auth (client, request)) + if ((client->status != RELAY_STATUS_CONNECTED) + && !relay_http_check_auth (client, request)) { relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); return; diff --git a/src/plugins/relay/api/relay-api.c b/src/plugins/relay/api/relay-api.c index a82c72e0b..158305367 100644 --- a/src/plugins/relay/api/relay-api.c +++ b/src/plugins/relay/api/relay-api.c @@ -134,7 +134,7 @@ relay_api_unhook_signals (struct t_relay_client *client) void relay_api_recv_http (struct t_relay_client *client, - struct t_relay_http_request *request) + struct t_relay_http_request *request) { relay_api_protocol_recv_http (client, request); } diff --git a/src/plugins/relay/relay-auth.c b/src/plugins/relay/relay-auth.c index 76bdf35a7..a03dc0559 100644 --- a/src/plugins/relay/relay-auth.c +++ b/src/plugins/relay/relay-auth.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <time.h> #include <gcrypt.h> #include "../weechat-plugin.h" @@ -103,37 +104,28 @@ relay_auth_generate_nonce (int size) * Checks if password received as plain text is valid. * * Returns: - * 1: password is valid - * 0: password is not valid + * 0: password is valid + * -1: (plain-text password ("plain") is not allowed + * -2: password is not valid */ int -relay_auth_check_password_plain (const char *password, +relay_auth_check_password_plain (struct t_relay_client *client, + const char *password, const char *relay_password) { - if (!password || !relay_password) - return 0; - - return (strcmp (password, relay_password) == 0) ? 1 : 0; -} + if (!client || !password || !relay_password) + return -2; -/* - * Authenticates with password (plain text). - * - * Returns: - * 1: authentication OK - * 0: authentication failed - */ - -int -relay_auth_password (struct t_relay_client *client, - const char *password, const char *relay_password) -{ - if (client->password_hash_algo != RELAY_AUTH_PASSWORD_HASH_PLAIN) - return 0; - - return relay_auth_check_password_plain (password, relay_password); + if (!weechat_string_match_list ( + "plain", + (const char **)relay_config_network_password_hash_algo_list, + 1)) + { + return -1; + } + return (strcmp (password, relay_password) == 0) ? 0 : -2; } /* @@ -145,6 +137,11 @@ relay_auth_password (struct t_relay_client *client, * * salt is the salt in hexadecimal * hash is the hashed password with the parameters above, in hexadecimal + * + * If salt_hexa is not NULL, it is set with salt as hexadecimal, and the parsed + * salt is decoded and put in salt. + * If salt_hexa is NULL, parsed salt is considered not encoded and is put + * directly in salt. */ void @@ -155,7 +152,8 @@ relay_auth_parse_sha (const char *parameters, char **argv; int argc; - *salt_hexa = NULL; + if (salt_hexa) + *salt_hexa = NULL; *salt = NULL; *salt_size = 0; *hash = NULL; @@ -174,18 +172,27 @@ relay_auth_parse_sha (const char *parameters, } /* parameter 1: salt */ - *salt = malloc (strlen (argv[0]) + 1); - if (*salt) + if (salt_hexa) { - *salt_size = weechat_string_base_decode ("16", argv[0], *salt); - if (*salt_size > 0) - *salt_hexa = strdup (argv[0]); - else + *salt = malloc (strlen (argv[0]) + 1); + if (*salt) { - free (*salt); - *salt = NULL; + *salt_size = weechat_string_base_decode ("16", argv[0], *salt); + if (*salt_size > 0) + *salt_hexa = strdup (argv[0]); + else + { + free (*salt); + *salt = NULL; + } } } + else + { + *salt = strdup (argv[0]); + if (*salt) + *salt_size = strlen (*salt); + } /* parameter 2: the SHA256 or SHA512 hash */ *hash = strdup (argv[1]); @@ -203,6 +210,11 @@ relay_auth_parse_sha (const char *parameters, * salt is the salt in hexadecimal * iterations it the number of iterations (≥ 1) * hash is the hashed password with the parameters above, in hexadecimal + * + * If salt_hexa is not NULL, it is set with salt as hexadecimal, and the parsed + * salt is decoded and put in salt. + * If salt_hexa is NULL, parsed salt is considered not encoded and is put + * directly in salt. */ void @@ -213,7 +225,8 @@ relay_auth_parse_pbkdf2 (const char *parameters, char **argv, *error; int argc; - *salt_hexa = NULL; + if (salt_hexa) + *salt_hexa = NULL; *salt = NULL; *salt_size = 0; *iterations = 0; @@ -233,18 +246,27 @@ relay_auth_parse_pbkdf2 (const char *parameters, } /* parameter 1: salt */ - *salt = malloc (strlen (argv[0]) + 1); - if (*salt) + if (salt_hexa) { - *salt_size = weechat_string_base_decode ("16", argv[0], *salt); - if (*salt_size > 0) - *salt_hexa = strdup (argv[0]); - else + *salt = malloc (strlen (argv[0]) + 1); + if (*salt) { - free (*salt); - *salt = NULL; + *salt_size = weechat_string_base_decode ("16", argv[0], *salt); + if (*salt_size > 0) + *salt_hexa = strdup (argv[0]); + else + { + free (*salt); + *salt = NULL; + } } } + else + { + *salt = strdup (argv[0]); + if (*salt) + *salt_size = strlen (*salt); + } /* parameter 2: iterations */ error = NULL; @@ -261,7 +283,12 @@ relay_auth_parse_pbkdf2 (const char *parameters, /* * Checks if the salt received from the client is valid. * - * It is valid if both conditions are true: + * For "api" protocol, it is valid if both conditions are true: + * 1. the salt is a valid integer (unix timestamp) + * 2. the timestamp value is current timestamp (or +/- seconds, according to + * the option relay.network.time_window) + * + * For other protocols, it is valid if both conditions are true: * 1. the salt is longer than the server nonce, so it means it includes a * client nonce * 2. the salt begins with the server nonce (client->nonce) @@ -272,8 +299,31 @@ relay_auth_parse_pbkdf2 (const char *parameters, */ int -relay_auth_check_salt (struct t_relay_client *client, const char *salt_hexa) +relay_auth_check_salt (struct t_relay_client *client, + const char *salt_hexa, const char *salt, int salt_size) { + long number; + int time_window; + char *error; + time_t time_now; + + if (!client) + return 0; + + if (client->protocol == RELAY_PROTOCOL_API) + { + if (!salt || (salt_size < 1)) + return 0; + error = NULL; + number = strtol (salt, &error, 10); + if (!error || error[0]) + return 0; + time_now = time (NULL); + time_window = weechat_config_integer (relay_config_network_time_window); + return ((number >= time_now - time_window) + && (number <= time_now + time_window)) ? 1 : 0; + } + return (salt_hexa && client->nonce && (strlen (salt_hexa) > strlen (client->nonce)) @@ -370,8 +420,11 @@ relay_auth_check_hash_pbkdf2 (const char *hash_pbkdf2_algo, * Authenticates with password hash. * * Returns: - * 1: authentication OK - * 0: authentication failed + * 0: authentication OK + * -1: invalid hash algorithm + * -2: invalid salt + * -3: invalid number of iterations + * -4: invalid password (hash) */ int @@ -387,40 +440,83 @@ relay_auth_password_hash (struct t_relay_client *client, str_hash_algo = NULL; - /* no authentication supported at all? */ - if (client->password_hash_algo < 0) + /* no authentication supported at all with weechat protocol? */ + if ((client->protocol == RELAY_PROTOCOL_WEECHAT) + && (client->password_hash_algo < 0)) + { + rc = -1; goto end; + } if (!hashed_password || !relay_password) + { + rc = -4; goto end; + } pos_hash = strchr (hashed_password, ':'); if (!pos_hash) + { + rc = -4; goto end; + } str_hash_algo = weechat_strndup (hashed_password, pos_hash - hashed_password); if (!str_hash_algo) + { + rc = -1; goto end; + } pos_hash++; hash_algo = relay_auth_password_hash_algo_search (str_hash_algo); + if (hash_algo < 0) + { + rc = -1; + goto end; + } - if (hash_algo != client->password_hash_algo) + /* only algo negotiated in handshake is allowed for protocol "weechat" */ + if ((client->protocol == RELAY_PROTOCOL_WEECHAT) + && (hash_algo != client->password_hash_algo)) + { + rc = -1; + goto end; + } + + /* only algos matching allowed algos are allowed for protocol "api" */ + if ((client->protocol == RELAY_PROTOCOL_API) + && (!weechat_string_match_list ( + relay_auth_password_hash_algo_name[hash_algo], + (const char **)relay_config_network_password_hash_algo_list, + 1))) + { + rc = -1; goto end; + } + + salt_hexa = NULL; switch (hash_algo) { case RELAY_AUTH_PASSWORD_HASH_SHA256: case RELAY_AUTH_PASSWORD_HASH_SHA512: - relay_auth_parse_sha (pos_hash, &salt_hexa, &salt, &salt_size, - &hash_sha); - if (relay_auth_check_salt (client, salt_hexa) - && relay_auth_check_hash_sha (str_hash_algo, salt, salt_size, - hash_sha, relay_password)) + relay_auth_parse_sha ( + pos_hash, + (client->protocol == RELAY_PROTOCOL_API) ? NULL : &salt_hexa, + &salt, + &salt_size, + &hash_sha); + if (!relay_auth_check_salt (client, salt_hexa, salt, salt_size)) { - rc = 1; + rc = -2; + } + else if (!relay_auth_check_hash_sha (str_hash_algo, salt, salt_size, + hash_sha, relay_password)) + { + rc = -4;; } if (salt_hexa) free (salt_hexa); @@ -432,15 +528,26 @@ relay_auth_password_hash (struct t_relay_client *client, case RELAY_AUTH_PASSWORD_HASH_PBKDF2_SHA256: case RELAY_AUTH_PASSWORD_HASH_PBKDF2_SHA512: hash_pbkdf2_algo = strdup (str_hash_algo + 7); - relay_auth_parse_pbkdf2 (pos_hash, &salt_hexa, &salt, &salt_size, - &iterations, &hash_pbkdf2); - if ((iterations == client->password_hash_iterations) - && relay_auth_check_salt (client, salt_hexa) - && relay_auth_check_hash_pbkdf2 (hash_pbkdf2_algo, salt, - salt_size, iterations, - hash_pbkdf2, relay_password)) + relay_auth_parse_pbkdf2 ( + pos_hash, + (client->protocol == RELAY_PROTOCOL_API) ? NULL : &salt_hexa, + &salt, + &salt_size, + &iterations, + &hash_pbkdf2); + if (iterations != weechat_config_integer (relay_config_network_password_hash_iterations)) { - rc = 1; + rc = -3; + } + else if (!relay_auth_check_salt (client, salt_hexa, salt, salt_size)) + { + rc = -2; + } + else if (!relay_auth_check_hash_pbkdf2 (hash_pbkdf2_algo, salt, + salt_size, iterations, + hash_pbkdf2, relay_password)) + { + rc = -4; } if (hash_pbkdf2_algo) free (hash_pbkdf2_algo); @@ -452,6 +559,7 @@ relay_auth_password_hash (struct t_relay_client *client, free (hash_pbkdf2); break; case RELAY_NUM_PASSWORD_HASH_ALGOS: + rc = -4; break; } diff --git a/src/plugins/relay/relay-auth.h b/src/plugins/relay/relay-auth.h index 9d1158c45..dcb7801fc 100644 --- a/src/plugins/relay/relay-auth.h +++ b/src/plugins/relay/relay-auth.h @@ -37,11 +37,9 @@ extern char *relay_auth_password_hash_algo_name[]; extern int relay_auth_password_hash_algo_search (const char *name); extern char *relay_auth_generate_nonce (int size); -extern int relay_auth_check_password_plain (const char *password, +extern int relay_auth_check_password_plain (struct t_relay_client *client, + const char *password, const char *relay_password); -extern int relay_auth_password (struct t_relay_client *client, - const char *password, - const char *relay_password); extern void relay_auth_parse_sha (const char *parameters, char **salt_hexa, char **salt, @@ -53,8 +51,6 @@ extern void relay_auth_parse_pbkdf2 (const char *parameters, int *salt_size, int *iterations, char **hash); -extern int relay_auth_check_salt (struct t_relay_client *client, - const char *salt_hexa); extern int relay_auth_check_hash_sha (const char *hash_algo, const char *salt, int salt_size, diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c index fa62d8f20..b5260700d 100644 --- a/src/plugins/relay/relay-client.c +++ b/src/plugins/relay/relay-client.c @@ -1391,8 +1391,6 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server) (const char **)relay_config_network_password_hash_algo_list, 1); new_client->password_hash_algo = (plain_text_password) ? 0 : -1; - new_client->password_hash_iterations = weechat_config_integer ( - relay_config_network_password_hash_iterations); new_client->listen_start_time = server->start_time; new_client->start_time = time (NULL); new_client->end_time = 0; @@ -1665,12 +1663,6 @@ relay_client_new_with_infolist (struct t_infolist *infolist) new_client->password_hash_algo = weechat_infolist_integer (infolist, "password_hash_algo"); else new_client->password_hash_algo = RELAY_AUTH_PASSWORD_HASH_PLAIN; - /* "password_hash_iterations" is new in WeeChat 2.9 */ - if (weechat_infolist_search_var (infolist, "password_hash_iterations")) - new_client->password_hash_iterations = weechat_infolist_integer (infolist, "password_hash_iterations"); - else - new_client->password_hash_iterations = weechat_config_integer ( - relay_config_network_password_hash_iterations); new_client->listen_start_time = weechat_infolist_time (infolist, "listen_start_time"); new_client->start_time = weechat_infolist_time (infolist, "start_time"); new_client->end_time = weechat_infolist_time (infolist, "end_time"); @@ -2102,8 +2094,6 @@ relay_client_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_integer (ptr_item, "password_hash_algo", client->password_hash_algo)) return 0; - if (!weechat_infolist_new_var_integer (ptr_item, "password_hash_iterations", client->password_hash_iterations)) - return 0; if (!weechat_infolist_new_var_time (ptr_item, "listen_start_time", client->listen_start_time)) return 0; if (!weechat_infolist_new_var_time (ptr_item, "start_time", client->start_time)) @@ -2188,7 +2178,6 @@ relay_client_print_log () ptr_client->password_hash_algo, (ptr_client->password_hash_algo >= 0) ? relay_auth_password_hash_algo_name[ptr_client->password_hash_algo] : ""); - weechat_log_printf (" password_hash_iterations. : %d", ptr_client->password_hash_iterations); weechat_log_printf (" listen_start_time . . . . : %lld", (long long)ptr_client->listen_start_time); weechat_log_printf (" start_time. . . . . . . . : %lld", (long long)ptr_client->start_time); weechat_log_printf (" end_time. . . . . . . . . : %lld", (long long)ptr_client->end_time); diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h index 0afec9387..9d22f629f 100644 --- a/src/plugins/relay/relay-client.h +++ b/src/plugins/relay/relay-client.h @@ -119,7 +119,6 @@ struct t_relay_client /* example: server for irc protocol */ char *nonce; /* nonce used in salt of hashed pwd */ int password_hash_algo; /* password hash algo (negotiated) */ - int password_hash_iterations; /* password hash iterations */ time_t listen_start_time; /* when listening started */ time_t start_time; /* time of client connection */ time_t end_time; /* time of client disconnection */ diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c index b9c4422ec..148e693d6 100644 --- a/src/plugins/relay/relay-config.c +++ b/src/plugins/relay/relay-config.c @@ -81,6 +81,7 @@ struct t_config_option *relay_config_network_nonce_size = NULL; struct t_config_option *relay_config_network_password = NULL; struct t_config_option *relay_config_network_password_hash_algo = NULL; struct t_config_option *relay_config_network_password_hash_iterations = NULL; +struct t_config_option *relay_config_network_time_window = NULL; struct t_config_option *relay_config_network_tls_cert_key = NULL; struct t_config_option *relay_config_network_tls_priorities = NULL; struct t_config_option *relay_config_network_totp_secret = NULL; @@ -1370,6 +1371,13 @@ relay_config_init () "if your CPU is slow"), NULL, 1, 1000000, "100000", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + relay_config_network_time_window = weechat_config_new_option ( + relay_config_file, relay_config_section_network, + "time_window", "integer", + N_("number of seconds to allow before and after the current time " + "for salted password in api protocol"), + NULL, 0, 256, "5", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); relay_config_network_tls_cert_key = weechat_config_new_option ( relay_config_file, relay_config_section_network, "tls_cert_key", "string", diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h index de5697341..e454ba97e 100644 --- a/src/plugins/relay/relay-config.h +++ b/src/plugins/relay/relay-config.h @@ -53,6 +53,7 @@ extern struct t_config_option *relay_config_network_nonce_size; extern struct t_config_option *relay_config_network_password; extern struct t_config_option *relay_config_network_password_hash_algo; extern struct t_config_option *relay_config_network_password_hash_iterations; +extern struct t_config_option *relay_config_network_time_window; extern struct t_config_option *relay_config_network_tls_cert_key; extern struct t_config_option *relay_config_network_tls_priorities; extern struct t_config_option *relay_config_network_totp_secret; diff --git a/src/plugins/relay/relay-http.c b/src/plugins/relay/relay-http.c index a59552599..51ce00174 100644 --- a/src/plugins/relay/relay-http.c +++ b/src/plugins/relay/relay-http.c @@ -31,6 +31,7 @@ #include "../weechat-plugin.h" #include "relay.h" +#include "relay-auth.h" #include "relay-client.h" #include "relay-config.h" #include "relay-http.h" @@ -514,7 +515,7 @@ relay_http_add_to_body (struct t_relay_http_request *request, } /* - * Checks if authentication is OK. + * Gets authentication status according to headers in the request. * * Returns: * 0: authentication OK (password + TOTP if enabled) @@ -522,11 +523,15 @@ relay_http_add_to_body (struct t_relay_http_request *request, * -2: invalid password * -3: missing TOTP * -4: invalid TOTP - * -5: out of memory + * -5: invalid hash algorithm + * -6: invalid salt + * -7: invalid number of iterations (PBKDF2) + * -8: out of memory */ int -relay_http_check_auth (struct t_relay_http_request *request) +relay_http_get_auth_status (struct t_relay_client *client, + struct t_relay_http_request *request) { const char *auth, *client_totp, *pos; char *relay_password, *totp_secret, *info_totp_args, *info_totp; @@ -538,6 +543,15 @@ relay_http_check_auth (struct t_relay_http_request *request) totp_secret = NULL; user_pass = NULL; + relay_password = weechat_string_eval_expression ( + weechat_config_string (relay_config_network_password), + NULL, NULL, NULL); + if (!relay_password) + { + rc = -8; + goto end; + } + auth = weechat_hashtable_get (request->headers, "authorization"); if (!auth || (weechat_strncasecmp (auth, "basic ", 6) != 0)) { @@ -555,7 +569,7 @@ relay_http_check_auth (struct t_relay_http_request *request) user_pass = malloc (length + 1); if (!user_pass) { - rc = -5; + rc = -8; goto end; } length = weechat_string_base_decode ("64", pos, user_pass); @@ -564,23 +578,43 @@ relay_http_check_auth (struct t_relay_http_request *request) rc = -2; goto end; } - if (strncmp (user_pass, "weechat:", 8) != 0) + if (strncmp (user_pass, "plain:", 6) == 0) { - rc = -2; - goto end; + switch (relay_auth_check_password_plain (client, user_pass + 6, relay_password)) + { + case 0: /* password OK */ + break; + case -1: /* "plain" is not allowed */ + rc = -5; + goto end; + case -2: /* invalid password */ + default: + rc = -2; + goto end; + } } - - relay_password = weechat_string_eval_expression ( - weechat_config_string (relay_config_network_password), - NULL, NULL, NULL); - - if (!relay_password) + else if (strncmp (user_pass, "hash:", 5) == 0) { - rc = -5; - goto end; + switch (relay_auth_password_hash (client, user_pass + 5, relay_password)) + { + case 0: /* password OK */ + break; + case -1: /* invalid hash algorithm */ + rc = -5; + goto end; + case -2: /* invalid salt */ + rc = -6; + goto end; + case -3: /* invalid iterations */ + rc = -7; + goto end; + case -4: /* invalid password */ + default: + rc = -2; + goto end; + } } - - if (strcmp (user_pass + 8, relay_password) != 0) + else { rc = -2; goto end; @@ -632,6 +666,69 @@ end: } /* + * Checks authentication in HTTP request. + * + * Returns: + * 1: authentication OK + * 0: authentication failed + */ + +int +relay_http_check_auth (struct t_relay_client *client, + struct t_relay_http_request *request) +{ + int rc; + + rc = relay_http_get_auth_status (client, request); + switch (rc) + { + case 0: /* authentication OK */ + break; + case -1: /* missing password */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_MISSING_PASSWORD); + break; + case -2: /* invalid password */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_INVALID_PASSWORD); + break; + case -3: /* missing TOTP */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_MISSING_TOTP); + break; + case -4: /* invalid TOTP */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_INVALID_TOTP); + break; + case -5: /* invalid hash algorithm */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_INVALID_HASH_ALGO); + break; + case -6: /* invalid salt */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_INVALID_SALT); + break; + case -7: /* invalid iterations */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_INVALID_ITERATIONS); + break; + case -8: /* out of memory */ + relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, + NULL, + RELAY_HTTP_ERROR_OUT_OF_MEMORY); + break; + } + return (rc == 0) ? 1 : 0; +} + +/* * Processes HTTP websocket request. */ @@ -681,41 +778,14 @@ relay_http_process_websocket (struct t_relay_client *client) /* handshake from client is valid, auth is mandatory for "api" protocol */ if (client->protocol == RELAY_PROTOCOL_API) { - switch (relay_http_check_auth (client->http_req)) + if (relay_http_check_auth (client, client->http_req)) { - case 0: /* authentication OK */ - relay_client_set_status (client, RELAY_STATUS_CONNECTED); - break; - case -1: /* missing password */ - relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_MISSING_PASSWORD); - relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); - return; - case -2: /* invalid password */ - relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_INVALID_PASSWORD); - relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); - return; - case -3: /* missing TOTP */ - relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_MISSING_TOTP); - relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); - return; - case -4: /* invalid TOTP */ - relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_INVALID_TOTP); - relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); - return; - case -5: /* out of memory */ - relay_http_send_error_json (client, RELAY_HTTP_401_UNAUTHORIZED, - NULL, - RELAY_HTTP_ERROR_OUT_OF_MEMORY); - relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); - return; + relay_client_set_status (client, RELAY_STATUS_CONNECTED); + } + else + { + relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); + return; } } diff --git a/src/plugins/relay/relay-http.h b/src/plugins/relay/relay-http.h index 8ed0bcd88..5716cb98d 100644 --- a/src/plugins/relay/relay-http.h +++ b/src/plugins/relay/relay-http.h @@ -41,11 +41,15 @@ enum t_relay_client_http_status #define RELAY_HTTP_500_INTERNAL_SERVER_ERROR 500, "Internal Server Error" #define RELAY_HTTP_503_SERVICE_UNAVAILABLE 503, "Service Unvavailable" -#define RELAY_HTTP_ERROR_MISSING_PASSWORD "Missing password" -#define RELAY_HTTP_ERROR_INVALID_PASSWORD "Invalid password" -#define RELAY_HTTP_ERROR_MISSING_TOTP "Missing TOTP" -#define RELAY_HTTP_ERROR_INVALID_TOTP "Invalid TOTP" -#define RELAY_HTTP_ERROR_OUT_OF_MEMORY "Out of memory" +#define RELAY_HTTP_ERROR_MISSING_PASSWORD "Missing password" +#define RELAY_HTTP_ERROR_INVALID_PASSWORD "Invalid password" +#define RELAY_HTTP_ERROR_MISSING_TOTP "Missing TOTP" +#define RELAY_HTTP_ERROR_INVALID_TOTP "Invalid TOTP" +#define RELAY_HTTP_ERROR_INVALID_HASH_ALGO "Invalid hash algorithm " \ + "(not found or not supported)" +#define RELAY_HTTP_ERROR_INVALID_SALT "Invalid salt" +#define RELAY_HTTP_ERROR_INVALID_ITERATIONS "Invalid number of iterations" +#define RELAY_HTTP_ERROR_OUT_OF_MEMORY "Out of memory" struct t_relay_http_request { @@ -71,7 +75,8 @@ extern void relay_http_request_reinit (struct t_relay_http_request *request); extern struct t_relay_http_request *relay_http_request_alloc (); extern int relay_http_parse_method_path (struct t_relay_http_request *request, const char *method_path); -extern int relay_http_check_auth (struct t_relay_http_request *request); +extern int relay_http_check_auth (struct t_relay_client *client, + struct t_relay_http_request *request); extern void relay_http_recv (struct t_relay_client *client, const char *data); extern int relay_http_send (struct t_relay_client *client, int return_code, const char *message, diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.c b/src/plugins/relay/weechat/relay-weechat-protocol.c index a7d47e3af..948ecd38f 100644 --- a/src/plugins/relay/weechat/relay-weechat-protocol.c +++ b/src/plugins/relay/weechat/relay-weechat-protocol.c @@ -170,7 +170,9 @@ relay_weechat_protocol_handshake_reply (struct t_relay_client *client, "password_hash_algo", (client->password_hash_algo >= 0) ? relay_auth_password_hash_algo_name[client->password_hash_algo] : ""); - snprintf (string, sizeof (string), "%d", client->password_hash_iterations); + snprintf (string, sizeof (string), + "%d", + weechat_config_integer (relay_config_network_password_hash_iterations)); weechat_hashtable_set ( hashtable, "password_hash_iterations", @@ -388,13 +390,16 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init) if (strcmp (options[i], "password") == 0) { password_received = 1; - if (relay_auth_password (client, pos, relay_password)) + if ((client->password_hash_algo == RELAY_AUTH_PASSWORD_HASH_PLAIN) + && (relay_auth_check_password_plain (client, pos, relay_password) == 0)) + { RELAY_WEECHAT_DATA(client, password_ok) = 1; + } } else if (strcmp (options[i], "password_hash") == 0) { password_received = 1; - if (relay_auth_password_hash (client, pos, relay_password)) + if (relay_auth_password_hash (client, pos, relay_password) == 0) RELAY_WEECHAT_DATA(client, password_ok) = 1; } else if (strcmp (options[i], "totp") == 0) |