From 7a77cc32b25477026886b6c3ddccacc1b4293e54 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Tue, 16 Aug 2011 14:02:34 +0200 Subject: [PATCH] websockets: Properly parse Hixie-76 handshake. Signed-off-by: Johannes Schindelin --- libvncserver/websockets.c | 49 ++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index 9ea0eab..e0d3cc9 100755 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -41,11 +41,11 @@ Upgrade: WebSocket\r\n\ Connection: Upgrade\r\n\ %sWebSocket-Origin: %s\r\n\ %sWebSocket-Location: %s://%s%s\r\n\ -%sWebSocket-Protocol: sample\r\n\ +%sWebSocket-Protocol: %s\r\n\ \r\n%s" #define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 100 -#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 20 +#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 100 #define WEBSOCKETS_MAX_HANDSHAKE_LEN 4096 #if defined(__linux__) && defined(NEED_TIMEVAL) @@ -123,7 +123,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) char *buf, *response, *line; int n, linestart = 0, len = 0, llen; char prefix[5], trailer[17]; - char *path, *host, *origin; + char *path = NULL, *host = NULL, *origin = NULL, *protocol = NULL; char *key1 = NULL, *key2 = NULL, *key3 = NULL; buf = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN); @@ -155,7 +155,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) llen = len - linestart; if (((llen >= 2)) && (buf[len-1] == '\n')) { line = buf+linestart; - if ((llen == 2) && ((strncmp("\r\n\r\n", buf+len-4, 4)) == 0)) { + if ((llen == 2) && (strncmp("\r\n", line, 2) == 0)) { if (key1 && key2) { if ((n = rfbReadExact(cl, buf+len, 8)) <= 0) { if ((n < 0) && (errno == ETIMEDOUT)) { @@ -176,32 +176,30 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) break; } else if ((llen >= 16) && ((strncmp("GET ", line, min(llen,4))) == 0)) { /* 16 = 4 ("GET ") + 1 ("/.*") + 11 (" HTTP/1.1\r\n") */ - /* rfbLog("Got path\n"); */ path = line+4; buf[len-11] = '\0'; /* Trim trailing " HTTP/1.1\r\n" */ - if (strstr(path, "b64encode")) { - rfbLog(" - using base64 encoding\n"); - cl->webSocketsBase64 = TRUE; - } else { - rfbLog(" - using UTF-8 encoding\n"); - cl->webSocketsBase64 = FALSE; - } - } else if ((strncmp("Host: ", line, min(llen,6))) == 0) { - /* rfbLog("Got host\n"); */ + cl->webSocketsBase64 = TRUE; + /* rfbLog("Got path: %s\n", path); */ + } else if ((strncasecmp("host: ", line, min(llen,6))) == 0) { host = line+6; buf[len-2] = '\0'; - } else if ((strncmp("Origin: ", line, min(llen,8))) == 0) { - /* rfbLog("Got origin\n"); */ + /* rfbLog("Got host: %s\n", host); */ + } else if ((strncasecmp("origin: ", line, min(llen,8))) == 0) { origin = line+8; buf[len-2] = '\0'; - } else if ((strncmp("Sec-Websocket-Key1: ", line, min(llen,20))) == 0) { - /* rfbLog("Got key1\n"); */ + /* rfbLog("Got origin: %s\n", origin); */ + } else if ((strncasecmp("sec-websocket-key1: ", line, min(llen,20))) == 0) { key1 = line+20; buf[len-2] = '\0'; - } else if ((strncmp("Sec-Websocket-Key2: ", line, min(llen,20))) == 0) { - /* rfbLog("Got key2\n"); */ + /* rfbLog("Got key1: %s\n", key1); */ + } else if ((strncasecmp("sec-websocket-key2: ", line, min(llen,20))) == 0) { key2 = line+20; buf[len-2] = '\0'; + /* rfbLog("Got key2: %s\n", key2); */ + } else if ((strncasecmp("sec-websocket-protocol: ", line, min(llen,24))) == 0) { + protocol = line+24; + buf[len-2] = '\0'; + /* rfbLog("Got protocol: %s\n", protocol); */ } linestart = len; } @@ -214,6 +212,15 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) return FALSE; } + /* + if ((!protocol) || (!strcasestr(protocol, "base64"))) { + rfbErr("webSocketsHandshake: base64 subprotocol not supported by client\n"); + free(response); + free(buf); + return FALSE; + } + */ + /* * Generate the WebSockets server response based on the the headers sent * by the client. @@ -231,7 +238,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) snprintf(response, WEBSOCKETS_MAX_HANDSHAKE_LEN, WEBSOCKETS_HANDSHAKE_RESPONSE, prefix, origin, prefix, scheme, - host, path, prefix, trailer); + host, path, prefix, protocol, trailer); if (rfbWriteExact(cl, response, strlen(response)) < 0) { rfbErr("webSocketsHandshake: failed sending WebSockets response\n");