diff options
Diffstat (limited to 'pjsip')
-rw-r--r-- | pjsip/include/pjsip/sip_parser.h | 3 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_parser.c | 36 | ||||
-rw-r--r-- | pjsip/src/test-pjsip/msg_test.c | 136 |
3 files changed, 167 insertions, 8 deletions
diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h index b3e6a671..34e049ab 100644 --- a/pjsip/include/pjsip/sip_parser.h +++ b/pjsip/include/pjsip/sip_parser.h @@ -336,6 +336,9 @@ typedef struct pjsip_parser_const_t pj_cis_t pjsip_ALNUM_SPEC; /**< Decimal + Alpha. */ pj_cis_t pjsip_TOKEN_SPEC; /**< Token. */ pj_cis_t pjsip_TOKEN_SPEC_ESC; /**< Token without '%' character */ + pj_cis_t pjsip_VIA_PARAM_SPEC; /**< Via param is token + ":" for + IPv6. */ + pj_cis_t pjsip_VIA_PARAM_SPEC_ESC; /**< .. as above without '%' */ pj_cis_t pjsip_HEX_SPEC; /**< Hexadecimal digits. */ pj_cis_t pjsip_PARAM_CHAR_SPEC; /**< For scanning pname (or pvalue when it's not quoted.) in URI */ diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index bb470c72..e86cf601 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -325,6 +325,14 @@ static pj_status_t init_parser() PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); pj_cis_del_str(&pconst.pjsip_TOKEN_SPEC_ESC, "%"); + status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC, &pconst.pjsip_TOKEN_SPEC); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":"); + + status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":"); + status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); pj_cis_add_str( &pconst.pjsip_HOST_SPEC, HOST); @@ -770,6 +778,8 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, const char *pos; const char *line; int content_length = -1; + pj_str_t cur_msg; + const pj_str_t end_hdr = { "\n\r\n", 3}; *msg_size = size; @@ -779,8 +789,12 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, } - /* Find the end of header area by finding an empty line. */ - pos = pj_ansi_strstr(buf, "\n\r\n"); + /* Find the end of header area by finding an empty line. + * Don't use plain strstr() since we want to be able to handle + * NULL character in the message + */ + cur_msg.ptr = (char*)buf; cur_msg.slen = size; + pos = pj_strstr(&cur_msg, &end_hdr); if (pos == NULL) { return PJSIP_EPARTIALMSG; } @@ -789,7 +803,7 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, body_start = pos+3; /* Find "Content-Length" header the hard way. */ - line = pj_ansi_strchr(buf, '\n'); + line = pj_strchr(&cur_msg, '\n'); while (line && line < hdr_end) { ++line; if ( ((*line=='C' || *line=='c') && @@ -840,7 +854,9 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, break; /* Go to next line. */ - line = pj_ansi_strchr(line, '\n'); + cur_msg.slen -= (line - cur_msg.ptr); + cur_msg.ptr = (char*)line; + line = pj_strchr(&cur_msg, '\n'); } /* Found Content-Length? */ @@ -1652,7 +1668,7 @@ static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr, pj_str_t next, tmp; pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue); - if (IS_NEWLINE(*scanner->curptr)) + if (pj_scan_is_eof(scanner) || IS_NEWLINE(*scanner->curptr)) break; /* mangled, get next fraction */ pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next); @@ -1982,7 +1998,15 @@ static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner, //parse_param_imp(scanner, pool, &pname, &pvalue, // &pconst.pjsip_TOKEN_SPEC, // &pconst.pjsip_TOKEN_SPEC_ESC, 0); - int_parse_param(scanner, pool, &pname, &pvalue, 0); + //int_parse_param(scanner, pool, &pname, &pvalue, 0); + // This should be the correct one: + // added special spec for Via parameter, basically token plus + // ":" to allow IPv6 address in the received param. + pj_scan_get_char(scanner); + parse_param_imp(scanner, pool, &pname, &pvalue, + &pconst.pjsip_VIA_PARAM_SPEC, + &pconst.pjsip_VIA_PARAM_SPEC_ESC, + 0); if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) { hdr->branch_param = pvalue; diff --git a/pjsip/src/test-pjsip/msg_test.c b/pjsip/src/test-pjsip/msg_test.c index f825a98f..840c40ff 100644 --- a/pjsip/src/test-pjsip/msg_test.c +++ b/pjsip/src/test-pjsip/msg_test.c @@ -73,6 +73,7 @@ struct test_msg "P-Associated-URI:\r\n" /* empty header without space */ "\r\n", &create_msg0, + 0, PJ_SUCCESS }, { @@ -100,6 +101,136 @@ struct test_msg "m=audio 3456 RTP/AVP 0 1 3 99\r\n" "a=rtpmap:0 PCMU/8000\r\n", &create_msg1, + 0, + PJ_SUCCESS +}, +{ + /* Torture message from RFC 4475 + * 3.1.1.1 A short tortuous INVITE + */ + "INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0\n" + "TO :\n" + " sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n\n" + "from : \"J Rosenberg \\\\\\\"\" <sip:jdrosen@example.com>\n" + " ;\n" + " tag = 98asjd8\n" + "MaX-fOrWaRdS: 0068\n" + "Call-ID: wsinv.ndaksdj@192.0.2.1\n" + "Content-Length : 150\n" + "cseq: 0009\n" + " INVITE\n" + "Via : SIP / 2.0\n" + " /UDP\n" + " 192.0.2.2;rport;branch=390skdjuw\n" + "s :\n" + "NewFangledHeader: newfangled value\n" + " continued newfangled value\n" + "UnknownHeaderWithUnusualValue: ;;,,;;,;\n" + "Content-Type: application/sdp\n" + "Route:\n" + " <sip:services.example.com;lr;unknownwith=value;unknown-no-value>\n" + "v: SIP / 2.0 / TCP spindle.example.com ;\n" + " branch = z9hG4bK9ikj8 ,\n" + " SIP / 2.0 / UDP 192.168.255.111 ; branch=\n" + " z9hG4bK30239\n" + "m:\"Quoted string \\\"\\\"\" <sip:jdrosen@example.com> ; newparam =\n" + " newvalue ;\n" + " secondparam ; q = 0.33\r\n" + "\r\n" + "v=0\r\n" + "o=mhandley 29739 7272939 IN IP4 192.0.2.3\r\n" + "s=-\r\n" + "c=IN IP4 192.0.2.4\r\n" + "t=0 0\r\n" + "m=audio 49217 RTP/AVP 0 12\r\n" + "m=video 3227 RTP/AVP 31\r\n" + "a=rtpmap:31 LPC\r\n", + NULL, + 0, + PJ_SUCCESS +}, +{ + /* Torture message from RFC 4475 + * 3.1.1.2 Wide Range of Valid Characters + */ + "!interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0\n" + "Via: SIP/2.0/UDP host1.example.com;rport;branch=z9hG4bK-.!%66*_+`'~\n" + "To: \"BEL:\\\x07 NUL:\\\x00 DEL:\\\x7F\" <sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*@example.com>\n" + "From: token1~` token2'+_ token3*%!.- <sip:mundane@example.com> ;fromParam''~+*_!.-%=\"\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9\";tag=_token~1'+`*%!-.\n" + "Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\\/\"][?}{\n" + "CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~\n" + "Max-Forwards: 255\n" + "extensionHeader-!.%*+_`'~: \xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB\n" + "Content-Length: 0\r\n\r\n", + NULL, + 641, + PJ_SUCCESS +}, +{ + /* Torture message from RFC 4475 + * 3.1.1.3 Valid Use of the % Escaping Mechanism + */ + "INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0\n" + "To: sip:%75se%72@example.com\n" + "From: <sip:I%20have%20spaces@example.net>;tag=1234\n" + "Max-Forwards: 87\n" + "i: esc01.239409asdfakjkn23onasd0-3234\n" + "CSeq: 234234 INVITE\n" + "Via: SIP/2.0/UDP host5.example.net;rport;branch=z9hG4bKkdjuw\n" + "C: application/sdp\n" + "Contact:\n" + " <sip:cal%6Cer@192.168.0.2:5060;%6C%72;n%61me=v%61lue%25%34%31>\n" + "Content-Length: 150\r\n" + "\r\n" + "v=0\r\n" + "o=mhandley 29739 7272939 IN IP4 192.0.2.1\r\n" + "s=-\r\n" + "c=IN IP4 192.0.2.1\r\n" + "t=0 0\r\n" + "m=audio 49217 RTP/AVP 0 12\r\n" + "m=video 3227 RTP/AVP 31\r\n" + "a=rtpmap:31 LPC\r\n", + NULL, + 0, + PJ_SUCCESS +}, +{ + /* Torture message from RFC 4475 + * 3.1.1.4 Escaped Nulls in URIs + */ + "REGISTER sip:example.com SIP/2.0\r\n" + "To: sip:null-%00-null@example.com\r\n" + "From: sip:null-%00-null@example.com;tag=839923423\r\n" + "Max-Forwards: 70\r\n" + "Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd\r\n" + "CSeq: 14398234 REGISTER\r\n" + "Via: SIP/2.0/UDP host5.example.com;rport;branch=z9hG4bKkdjuw\r\n" + "Contact: <sip:%00@host5.example.com>\r\n" + "Contact: <sip:%00%00@host5.example.com>\r\n" + "L:0\r\n" + "\r\n", + NULL, + 0, + PJ_SUCCESS +}, +{ + /* Torture message from RFC 4475 + * 3.1.1.5 Use of % When It Is Not an Escape + */ + "RE%47IST%45R sip:registrar.example.com SIP/2.0\r\n" + "To: \"%Z%45\" <sip:resource@example.com>\r\n" + "From: \"%Z%45\" <sip:resource@example.com>;tag=f232jadfj23\r\n" + "Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf\r\n" + "Via: SIP/2.0/TCP host.example.com;rport;branch=z9hG4bK209%fzsnel234\r\n" + "CSeq: 29344 RE%47IST%45R\r\n" + "Max-Forwards: 70\r\n" + "Contact: <sip:alias1@host1.example.com>\r\n" + "C%6Fntact: <sip:alias2@host2.example.com>\r\n" + "Contact: <sip:alias3@host3.example.com>\r\n" + "l: 0\r\n" + "\r\n", + NULL, + 0, PJ_SUCCESS } }; @@ -126,7 +257,8 @@ static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry ) char msgbuf2[PJSIP_MAX_PKT_LEN]; enum { BUFLEN = 512 }; - entry->len = pj_ansi_strlen(entry->msg); + if (entry->len==0) + entry->len = pj_ansi_strlen(entry->msg); if (var.flag & FLAG_PARSE_ONLY) goto parse_msg; @@ -180,7 +312,7 @@ parse_msg: pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&var.parse_time, &t2); - if (var.flag & FLAG_PARSE_ONLY) + if ((var.flag & FLAG_PARSE_ONLY) || entry->creator==NULL) return PJ_SUCCESS; /* Create reference message. */ |