]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix segfault for certain invalid WebSocket input.
authorDavid M. Lee <dlee@digium.com>
Wed, 12 Jun 2013 21:00:38 +0000 (21:00 +0000)
committerDavid M. Lee <dlee@digium.com>
Wed, 12 Jun 2013 21:00:38 +0000 (21:00 +0000)
The WebSocket code would allocate, on the stack, a string large enough
to hold a key provided by the client, and the WEBSOCKET_GUID. If the key
is NULL, this causes a segfault. If the key is too large, it could
overflow the stack.

This patch checks the key for NULL and checks the length of the key to
avoid stack smashing nastiness.

(closes issue ASTERISK-21825)
Reported by: Alfred Farrugia
Tested by: Alfred Farrugia, David M. Lee
Patches:
    issueA21825_check_if_key_is_sent.patch uploaded by Walter Doekes (license 5674)

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@391560 65c4cc65-6c06-0410-ace0-fbb531ad65f3

res/res_http_websocket.c

index cfc6d16f5d78a8889649b44d151c65daa1078403..c7ac232c5ad492f4d2618ff3f317bc4cf5b98be0 100644 (file)
@@ -544,9 +544,18 @@ static int websocket_callback(struct ast_tcptls_session_instance *ser, const str
                /* Version 7 defined in specification http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07 */
                /* Version 8 defined in specification http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10 */
                /* Version 13 defined in specification http://tools.ietf.org/html/rfc6455 */
-               char combined[strlen(key) + strlen(WEBSOCKET_GUID) + 1], base64[64];
+               char *combined, base64[64];
+               unsigned combined_length;
                uint8_t sha[20];
 
+               combined_length = (key ? strlen(key) : 0) + strlen(WEBSOCKET_GUID) + 1;
+               if (!key || combined_length > 8192) { /* no stack overflows please */
+                       fputs("HTTP/1.1 400 Bad Request\r\n"
+                             "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+                       ao2_ref(protocol_handler, -1);
+                       return 0;
+               }
+
                if (!(session = ao2_alloc(sizeof(*session), session_destroy_fn))) {
                        ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted\n",
                                ast_sockaddr_stringify(&ser->remote_address));
@@ -556,7 +565,8 @@ static int websocket_callback(struct ast_tcptls_session_instance *ser, const str
                        return 0;
                }
 
-               snprintf(combined, sizeof(combined), "%s%s", key, WEBSOCKET_GUID);
+               combined = ast_alloca(combined_length);
+               snprintf(combined, combined_length, "%s%s", key, WEBSOCKET_GUID);
                ast_sha1_hash_uint(sha, combined);
                ast_base64encode(base64, (const unsigned char*)sha, 20, sizeof(base64));