From 1a0646aec17422b5d5071714fa8f1992a097c367 Mon Sep 17 00:00:00 2001 From: Walter Doekes Date: Tue, 16 Oct 2012 21:46:09 +0000 Subject: [PATCH] Fixes to the fd-oriented SIP TCP reads. 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 | 70 +++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 03f0de6e68..b372d8c5b4 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -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; - } - if (content_length_str) { - content_length_str += sizeof("\nContent-Length:"); - } else if (l_str) { - content_length_str = l_str + sizeof("\nl:"); - } else { - return -1; + goto done; } - 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"