websockets: Properly parse Hixie-76 handshake.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
pull/1/head
Joel Martin 13 years ago committed by Johannes Schindelin
parent 430b8f2449
commit 7a77cc32b2

@ -41,11 +41,11 @@ Upgrade: WebSocket\r\n\
Connection: Upgrade\r\n\ Connection: Upgrade\r\n\
%sWebSocket-Origin: %s\r\n\ %sWebSocket-Origin: %s\r\n\
%sWebSocket-Location: %s://%s%s\r\n\ %sWebSocket-Location: %s://%s%s\r\n\
%sWebSocket-Protocol: sample\r\n\ %sWebSocket-Protocol: %s\r\n\
\r\n%s" \r\n%s"
#define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 100 #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 #define WEBSOCKETS_MAX_HANDSHAKE_LEN 4096
#if defined(__linux__) && defined(NEED_TIMEVAL) #if defined(__linux__) && defined(NEED_TIMEVAL)
@ -123,7 +123,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
char *buf, *response, *line; char *buf, *response, *line;
int n, linestart = 0, len = 0, llen; int n, linestart = 0, len = 0, llen;
char prefix[5], trailer[17]; 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; char *key1 = NULL, *key2 = NULL, *key3 = NULL;
buf = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN); buf = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN);
@ -155,7 +155,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
llen = len - linestart; llen = len - linestart;
if (((llen >= 2)) && (buf[len-1] == '\n')) { if (((llen >= 2)) && (buf[len-1] == '\n')) {
line = buf+linestart; 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 (key1 && key2) {
if ((n = rfbReadExact(cl, buf+len, 8)) <= 0) { if ((n = rfbReadExact(cl, buf+len, 8)) <= 0) {
if ((n < 0) && (errno == ETIMEDOUT)) { if ((n < 0) && (errno == ETIMEDOUT)) {
@ -176,32 +176,30 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
break; break;
} else if ((llen >= 16) && ((strncmp("GET ", line, min(llen,4))) == 0)) { } else if ((llen >= 16) && ((strncmp("GET ", line, min(llen,4))) == 0)) {
/* 16 = 4 ("GET ") + 1 ("/.*") + 11 (" HTTP/1.1\r\n") */ /* 16 = 4 ("GET ") + 1 ("/.*") + 11 (" HTTP/1.1\r\n") */
/* rfbLog("Got path\n"); */
path = line+4; path = line+4;
buf[len-11] = '\0'; /* Trim trailing " HTTP/1.1\r\n" */ buf[len-11] = '\0'; /* Trim trailing " HTTP/1.1\r\n" */
if (strstr(path, "b64encode")) { cl->webSocketsBase64 = TRUE;
rfbLog(" - using base64 encoding\n"); /* rfbLog("Got path: %s\n", path); */
cl->webSocketsBase64 = TRUE; } else if ((strncasecmp("host: ", line, min(llen,6))) == 0) {
} else {
rfbLog(" - using UTF-8 encoding\n");
cl->webSocketsBase64 = FALSE;
}
} else if ((strncmp("Host: ", line, min(llen,6))) == 0) {
/* rfbLog("Got host\n"); */
host = line+6; host = line+6;
buf[len-2] = '\0'; buf[len-2] = '\0';
} else if ((strncmp("Origin: ", line, min(llen,8))) == 0) { /* rfbLog("Got host: %s\n", host); */
/* rfbLog("Got origin\n"); */ } else if ((strncasecmp("origin: ", line, min(llen,8))) == 0) {
origin = line+8; origin = line+8;
buf[len-2] = '\0'; buf[len-2] = '\0';
} else if ((strncmp("Sec-Websocket-Key1: ", line, min(llen,20))) == 0) { /* rfbLog("Got origin: %s\n", origin); */
/* rfbLog("Got key1\n"); */ } else if ((strncasecmp("sec-websocket-key1: ", line, min(llen,20))) == 0) {
key1 = line+20; key1 = line+20;
buf[len-2] = '\0'; buf[len-2] = '\0';
} else if ((strncmp("Sec-Websocket-Key2: ", line, min(llen,20))) == 0) { /* rfbLog("Got key1: %s\n", key1); */
/* rfbLog("Got key2\n"); */ } else if ((strncasecmp("sec-websocket-key2: ", line, min(llen,20))) == 0) {
key2 = line+20; key2 = line+20;
buf[len-2] = '\0'; 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; linestart = len;
} }
@ -214,6 +212,15 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
return FALSE; 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 * Generate the WebSockets server response based on the the headers sent
* by the client. * by the client.
@ -231,7 +238,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
snprintf(response, WEBSOCKETS_MAX_HANDSHAKE_LEN, snprintf(response, WEBSOCKETS_MAX_HANDSHAKE_LEN,
WEBSOCKETS_HANDSHAKE_RESPONSE, prefix, origin, prefix, scheme, WEBSOCKETS_HANDSHAKE_RESPONSE, prefix, origin, prefix, scheme,
host, path, prefix, trailer); host, path, prefix, protocol, trailer);
if (rfbWriteExact(cl, response, strlen(response)) < 0) { if (rfbWriteExact(cl, response, strlen(response)) < 0) {
rfbErr("webSocketsHandshake: failed sending WebSockets response\n"); rfbErr("webSocketsHandshake: failed sending WebSockets response\n");

Loading…
Cancel
Save