Fixes to the fd-oriented SIP TCP reads.
authorWalter Doekes <walter+asterisk@wjd.nu>
Tue, 16 Oct 2012 21:46:09 +0000 (21:46 +0000)
committerWalter Doekes <walter+asterisk@wjd.nu>
Tue, 16 Oct 2012 21:46:09 +0000 (21:46 +0000)
Don't crash on large user input. Allow SIP headers without space.
Optimize code a bit.

Review: https://reviewboard.asterisk.org/r/2162
........

Merged revisions 375111 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 375112 from http://svn.asterisk.org/svn/asterisk/branches/10
........

Merged revisions 375113 from http://svn.asterisk.org/svn/asterisk/branches/11

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

channels/chan_sip.c

index 03f0de6..b372d8c 100644 (file)
@@ -2853,54 +2853,50 @@ enum message_integrity {
  */
 static int read_raw_content_length(const char *message)
 {
-       char *end_of_line;
        char *content_length_str;
-       char *l_str;
-       int content_length;
+       int content_length = -1;
+
+       struct ast_str *msg_copy;
        char *msg;
 
+       /* Using a ast_str because lws2sws takes one of those */
+       if (!(msg_copy = ast_str_create(strlen(message) + 1))) {
+               return -1;
+       }
+       ast_str_set(&msg_copy, 0, "%s", message);
+
        if (sip_cfg.pedanticsipchecking) {
-               struct ast_str *msg_copy = ast_str_create(strlen(message));
-               if (!msg_copy) {
-                       return -1;
-               }
-               ast_str_set(&msg_copy, 0, "%s", message);
                lws2sws(msg_copy);
-               msg = ast_strdupa(ast_str_buffer(msg_copy));
-               ast_free(msg_copy);
-       } else {
-               msg = ast_strdupa(message);
        }
 
+       msg = ast_str_buffer(msg_copy);
+
        /* Let's find a Content-Length header */
-       content_length_str = strcasestr(msg, "\nContent-Length:");
-       if (!content_length_str && !(l_str = strcasestr(msg, "\nl:"))) {
+       if ((content_length_str = strcasestr(msg, "\nContent-Length:"))) {
+               content_length_str += sizeof("\nContent-Length:") - 1;
+       } else if ((content_length_str = strcasestr(msg, "\nl:"))) {
+               content_length_str += sizeof("\nl:") - 1;
+       } else {
                /* RFC 3261 18.3
                 * "In the case of stream-oriented transports such as TCP, the Content-
                 *  Length header field indicates the size of the body.  The Content-
                 *  Length header field MUST be used with stream oriented transports."
                 */
-               return -1;
+               goto done;
        }
-       if (content_length_str) {
-               content_length_str += sizeof("\nContent-Length:");
-       } else if (l_str) {
-               content_length_str = l_str + sizeof("\nl:");
-       } else {
-               return -1;
-       }
-
-       end_of_line = strchr(content_length_str, '\n');
 
-       if (!end_of_line) {
-               return -1;
+       /* Double-check that this is a complete header */
+       if (!strchr(content_length_str, '\n')) {
+               goto done;
        }
 
-       if (sscanf(content_length_str, "%30d", &content_length) == 1) {
-               return content_length;
+       if (sscanf(content_length_str, "%30d", &content_length) != 1) {
+               content_length = -1;
        }
 
-       return -1;
+done:
+       ast_free(msg_copy);
+       return content_length;
 }
 
 /*!
@@ -2917,11 +2913,11 @@ static int read_raw_content_length(const char *message)
  */
 static enum message_integrity check_message_integrity(struct ast_str **request, struct ast_str **overflow)
 {
-       char *message = ast_strdupa(ast_str_buffer(*request));
+       char *message = ast_str_buffer(*request);
        char *body;
        int content_length;
+       int message_len = ast_str_strlen(*request);
        int body_len;
-       int message_len = strlen(message);
 
        /* Important pieces to search for in a SIP request are \r\n\r\n. This
         * marks either
@@ -2936,7 +2932,7 @@ static enum message_integrity check_message_integrity(struct ast_str **request,
                return MESSAGE_FRAGMENT;
        }
        body += sizeof("\r\n\r\n") - 1;
-       body_len = strlen(body);
+       body_len = message_len - (body - message);
 
        body[-1] = '\0';
        content_length = read_raw_content_length(message);
@@ -2952,8 +2948,8 @@ static enum message_integrity check_message_integrity(struct ast_str **request,
                if (body_len == 0) {
                        return MESSAGE_COMPLETE;
                } else {
-                       ast_str_truncate(*request, message_len - body_len);
                        ast_str_append(overflow, 0, "%s", body);
+                       ast_str_truncate(*request, message_len - body_len);
                        return MESSAGE_FRAGMENT_COMPLETE;
                }
        }
@@ -2967,8 +2963,8 @@ static enum message_integrity check_message_integrity(struct ast_str **request,
                /* We have the full message plus a fragment of a further
                 * message
                 */
-               ast_str_truncate(*request, message_len - (body_len - content_length));
                ast_str_append(overflow, 0, "%s", body + content_length);
+               ast_str_truncate(*request, message_len - (body_len - content_length));
                return MESSAGE_FRAGMENT_COMPLETE;
        } else {
                /* Yay! Full message with no extra content */
@@ -33725,7 +33721,7 @@ AST_TEST_DEFINE(test_tcp_message_fragmentation)
                "Contact: sip:127.0.0.1:5061\r\n"
                "Max-Forwards: 70\r\n"
                "Content-Type: application/sdp\r\n"
-               "l: 130\r\n"
+               "l:130\r\n" /* intentionally no space */
                "\r\n"
                "v=0\r\n"
                "o=user1 53655765 2353687637 IN IP4 127.0.0.1\r\n"
@@ -33751,7 +33747,7 @@ AST_TEST_DEFINE(test_tcp_message_fragmentation)
                "Content-Type: application/sdp\r\n"
                "DisContent-Length: 0\r\n"
                "MalContent-Length: 60\r\n"
-               "Content-Length: 130\r\n"
+               "Content-Length:130\r\n" /* intentionally no space */
                "\r\n"
                "v=0\r\n"
                "o=user1 53655765 2353687637 IN IP4 127.0.0.1\r\n"
@@ -33841,7 +33837,7 @@ AST_TEST_DEFINE(test_tcp_message_fragmentation)
        switch (cmd) {
                case TEST_INIT:
                        info->name = "sip_tcp_message_fragmentation";
-                       info->category = "/main/sip/transport";
+                       info->category = "/main/sip/transport/";
                        info->summary = "SIP TCP message fragmentation test";
                        info->description =
                                "Tests reception of different TCP messages that have been fragmented or"