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
This commit is contained in:
Walter Doekes
2012-10-16 21:46:09 +00:00
parent 8a65f47e88
commit 1a0646aec1

View File

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