diff --git a/src/plugins/relay/relay-http.c b/src/plugins/relay/relay-http.c index 6a522e534..8cde856b9 100644 --- a/src/plugins/relay/relay-http.c +++ b/src/plugins/relay/relay-http.c @@ -560,15 +560,18 @@ relay_http_add_to_body (struct t_relay_http_request *request, int relay_http_get_auth_status (struct t_relay_client *client) { - const char *auth, *client_totp, *pos; + const char *auth, *sec_websocket_protocol, *client_totp, *pos; char *relay_password, *totp_secret, *info_totp_args, *info_totp; char *user_pass; - int rc, length, totp_ok; + char **protocol_array; + int rc, i, length, protocol_count, use_base64url, totp_ok; rc = 0; relay_password = NULL; + protocol_array = NULL; totp_secret = NULL; user_pass = NULL; + use_base64url = 0; relay_password = weechat_string_eval_expression ( weechat_config_string (relay_config_network_password), @@ -589,13 +592,43 @@ relay_http_get_auth_status (struct t_relay_client *client) if (relay_password[0]) { auth = weechat_hashtable_get (client->http_req->headers, "authorization"); - if (!auth || (weechat_strncasecmp (auth, "basic ", 6) != 0)) + + if (auth) { - rc = -1; - goto end; + if (weechat_strncasecmp (auth, "basic ", 6) != 0) + { + rc = -1; + goto end; + } + + pos = auth + 6; + } + else + { + sec_websocket_protocol = weechat_hashtable_get ( + client->http_req->headers, "sec-websocket-protocol"); + protocol_array = weechat_string_split (sec_websocket_protocol, + ",", " ", 0, 0, &protocol_count); + + pos = NULL; + for (i = 0; i < protocol_count; i++) + { + if (strncmp (protocol_array[i], + "base64url.bearer.authorization.weechat.", 39) == 0) + { + pos = protocol_array[i] + 39; + use_base64url = 1; + break; + } + } + + if (!pos) + { + rc = -1; + goto end; + } } - pos = auth + 6; while (pos[0] == ' ') { pos++; @@ -608,7 +641,8 @@ relay_http_get_auth_status (struct t_relay_client *client) rc = -8; goto end; } - length = weechat_string_base_decode ("64", pos, user_pass); + length = weechat_string_base_decode ((use_base64url) ? "64url" : "64", + pos, user_pass); if (length < 0) { rc = -2; @@ -616,7 +650,9 @@ relay_http_get_auth_status (struct t_relay_client *client) } if (strncmp (user_pass, "plain:", 6) == 0) { - switch (relay_auth_check_password_plain (client, user_pass + 6, relay_password)) + switch (relay_auth_check_password_plain (client, + user_pass + 6, + relay_password)) { case 0: /* password OK */ break; @@ -631,7 +667,8 @@ relay_http_get_auth_status (struct t_relay_client *client) } else if (strncmp (user_pass, "hash:", 5) == 0) { - switch (relay_auth_password_hash (client, user_pass + 5, relay_password)) + switch (relay_auth_password_hash (client, user_pass + 5, + relay_password)) { case 0: /* password OK */ break; @@ -692,6 +729,7 @@ relay_http_get_auth_status (struct t_relay_client *client) } end: + weechat_string_free_split (protocol_array); free (relay_password); free (totp_secret); free (user_pass); diff --git a/src/plugins/relay/relay-websocket.c b/src/plugins/relay/relay-websocket.c index 330aac959..2bc023889 100644 --- a/src/plugins/relay/relay-websocket.c +++ b/src/plugins/relay/relay-websocket.c @@ -400,10 +400,12 @@ relay_websocket_parse_extensions (const char *extensions, char * relay_websocket_build_handshake (struct t_relay_http_request *request) { - const char *sec_websocket_key; + const char *sec_websocket_key, *sec_websocket_protocol_request; char *key, sec_websocket_accept[128], handshake[4096], hash[160 / 8]; - char **extensions, str_window_bits[128], sec_websocket_extensions[1024]; - int length, hash_size; + char **extensions, **protocol_array, str_window_bits[128]; + char sec_websocket_extensions[1024]; + char sec_websocket_protocol[1024]; + int i, length, hash_size, protocol_count; if (!request) return NULL; @@ -481,6 +483,24 @@ relay_websocket_build_handshake (struct t_relay_http_request *request) sec_websocket_extensions[0] = '\0'; } + sec_websocket_protocol_request = weechat_hashtable_get ( + request->headers, "sec-websocket-protocol"); + protocol_array = weechat_string_split (sec_websocket_protocol_request, + ",", " ", 0, 0, &protocol_count); + + sec_websocket_protocol[0] = '\0'; + for (i = 0; i < protocol_count; i++) + { + if (strcmp (protocol_array[i], WEBSOCKET_SUB_PROTOCOL_API_WEECHAT) == 0) + { + snprintf ( + sec_websocket_protocol, sizeof (sec_websocket_protocol), + "Sec-WebSocket-Protocol: %s\r\n", + WEBSOCKET_SUB_PROTOCOL_API_WEECHAT); + break; + } + } + /* build the handshake (it will be sent as-is to client) */ snprintf (handshake, sizeof (handshake), "HTTP/1.1 101 Switching Protocols\r\n" @@ -488,9 +508,11 @@ relay_websocket_build_handshake (struct t_relay_http_request *request) "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %s\r\n" "%s" + "%s" "\r\n", sec_websocket_accept, - sec_websocket_extensions); + sec_websocket_extensions, + sec_websocket_protocol); return strdup (handshake); } diff --git a/src/plugins/relay/relay-websocket.h b/src/plugins/relay/relay-websocket.h index 5845a4e8f..e1d4071b8 100644 --- a/src/plugins/relay/relay-websocket.h +++ b/src/plugins/relay/relay-websocket.h @@ -37,6 +37,8 @@ #define WEBSOCKET_FRAME_OPCODE_PING 0x09 #define WEBSOCKET_FRAME_OPCODE_PONG 0x0A +#define WEBSOCKET_SUB_PROTOCOL_API_WEECHAT "api.weechat" + struct t_relay_client; struct t_relay_http_request;