From 6fb023d6647f8cc89dbb2305b0215b494d41f045 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 1 Apr 2018 00:38:48 -0400 Subject: [PATCH] [mod_wstunnel] better Sec-WebSocket-Protocol parse Improve handling of Sec-WebSocket-Protocol: binary, base64 for RFC6455. When client sends Sec-WebSocket-Protocol in request header, client may expect Sec-WebSocket-Protocol response. mod_wstunnel is basic tunnel endpoint and supports "binary" and "text" modes for RFC6455, conventionally requested by client browsers as "binary" or "base64" --- src/mod_wstunnel.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/mod_wstunnel.c b/src/mod_wstunnel.c index e80f4c51..1e49499f 100644 --- a/src/mod_wstunnel.c +++ b/src/mod_wstunnel.c @@ -164,6 +164,7 @@ typedef struct { int hybivers; time_t ping_ts; + int subproto; server *srv; /*(for mod_wstunnel module-specific DEBUG_LOG() macro)*/ plugin_config conf; @@ -535,9 +536,30 @@ static handler_t wstunnel_handler_setup (server *srv, connection *con, plugin_da if (!binary) { data_string *ds = (data_string *) array_get_element(con->request.headers, "Sec-WebSocket-Protocol"); - binary = (NULL != ds - && buffer_is_equal_caseless_string(ds->value, - CONST_STR_LEN("binary"))); + if (NULL != ds) { + for (const char *s = ds->value->ptr; *s; ++s) { + while (*s==' '||*s=='\t'||*s=='\r'||*s=='\n') ++s; + if (0 == strncasecmp(s, "binary", sizeof("binary")-1)) { + s += sizeof("binary")-1; + while (*s==' '||*s=='\t'||*s=='\r'||*s=='\n') ++s; + if (*s==','||*s=='\0') { + hctx->subproto = 1; + binary = 1; + break; + } + } + else if (0 == strncasecmp(s, "base64", sizeof("base64")-1)) { + s += sizeof("base64")-1; + while (*s==' '||*s=='\t'||*s=='\r'||*s=='\n') ++s; + if (*s==','||*s=='\0') { + hctx->subproto = -1; + break; + } + } + s = strchr(s, ','); + if (NULL == s) break; + } + } } if (binary) { @@ -843,6 +865,9 @@ static int create_response_rfc_6455(handler_ctx *hctx) { if (hctx->frame.type == MOD_WEBSOCKET_FRAME_TYPE_BIN) array_set_key_value(hdrs, CONST_STR_LEN("Sec-WebSocket-Protocol"), CONST_STR_LEN("binary")); + else if (-1 == hctx->subproto) + array_set_key_value(hdrs, CONST_STR_LEN("Sec-WebSocket-Protocol"), + CONST_STR_LEN("base64")); return 0; }