res_http_websocket: ensure control frames do not interfere with data
authorJeremy Lainé <jeremy.laine@m4x.org>
Wed, 23 Jan 2019 10:45:56 +0000 (11:45 +0100)
committerJeremy Lainé <jeremy.laine@m4x.org>
Wed, 23 Jan 2019 15:02:38 +0000 (09:02 -0600)
Control frames (PING / PONG / CLOSE) can be received in the middle of a
fragmented message. In order to ensure they do not interfere with the
reassembly buffer, we exit early and do not return the payload to the
caller.

ASTERISK-28257 #close

Change-Id: Ia5367144fe08ac6141bba3309517a48ec7f013bc

res/res_http_websocket.c

index a44f601..e79066b 100644 (file)
@@ -632,9 +632,17 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
                }
 
                /* Per the RFC for PING we need to send back an opcode with the application data as received */
-               if ((*opcode == AST_WEBSOCKET_OPCODE_PING) && (ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len))) {
+               if (*opcode == AST_WEBSOCKET_OPCODE_PING) {
+                       if (ast_websocket_write(session, AST_WEBSOCKET_OPCODE_PONG, *payload, *payload_len)) {
+                               ast_websocket_close(session, 1009);
+                       }
+                       *payload_len = 0;
+                       return 0;
+               }
+
+               /* Stop PONG processing here */
+               if (*opcode == AST_WEBSOCKET_OPCODE_PONG) {
                        *payload_len = 0;
-                       ast_websocket_close(session, 1009);
                        return 0;
                }
 
@@ -648,6 +656,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
                        return 0;
                }
 
+               /* Below this point we are handling TEXT, BINARY or CONTINUATION opcodes */
                if (*payload_len) {
                        if (!(new_payload = ast_realloc(session->payload, (session->payload_len + *payload_len)))) {
                                ast_log(LOG_WARNING, "Failed allocation: %p, %zu, %"PRIu64"\n",