]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Discard responses with more than one Via
authorTerry Wilson <twilson@digium.com>
Fri, 19 Nov 2010 20:53:36 +0000 (20:53 +0000)
committerTerry Wilson <twilson@digium.com>
Fri, 19 Nov 2010 20:53:36 +0000 (20:53 +0000)
This is not a perfect solution as headers that are joined via commas are not
detected. This is a parsing issue that to fix "correctly" would necessitate
a new SIP parser.

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

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

channels/chan_sip.c

index e5a97ae3d1cdf7b0c6f933293c0468117f4d0dd5..a06726bd6b08bf7bb1ea317b8cd0b8ca27a1cdc1 100644 (file)
@@ -16788,6 +16788,9 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
        const char *cmd;
        const char *cseq;
        const char *useragent;
+       const char *via;
+       const char *callid;
+       int via_pos = 0;
        int seqno;
        int len;
        int ignore = FALSE;
@@ -16799,13 +16802,19 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
        int oldmethod = p->method;
        int acked = 0;
 
-       /* Get Method and Cseq */
+       /* RFC 3261 - 8.1.1 A valid SIP request must contain To, From, CSeq, Call-ID and Via.
+        * 8.2.6.2 Response must have To, From, Call-ID CSeq, and Via related to the request,
+        * so we can check to make sure these fields exist for all requests and responses */
        cseq = get_header(req, "Cseq");
        cmd = req->header[0];
+       /* Save the via_pos so we can check later that responses only have 1 Via header */
+       via = __get_header(req, "Via", &via_pos);
+       /* This must exist already because we've called find_call by now */
+       callid = get_header(req, "Call-ID");
 
        /* Must have Cseq */
-       if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) {
-               ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n");
+       if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq) || ast_strlen_zero(via)) {
+               ast_log(LOG_ERROR, "Dropping this SIP message with Call-ID '%s', it's incomplete.\n", callid);
                error = 1;
        }
        if (!error && sscanf(cseq, "%30d%n", &seqno, &len) != 1) {
@@ -16841,6 +16850,13 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
                        ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid);
                        return 0;
                }
+               /* RFC 3261 - 8.1.3.3 If more than one Via header field value is present in a reponse
+                * the UAC SHOULD discard the message. This is not perfect, as it will not catch multiple
+                * headers joined with a comma. Fixing that would pretty much involve writing a new parser */
+               if (!ast_strlen_zero(__get_header(req, "via", &via_pos))) {
+                       ast_log(LOG_WARNING, "Misrouted SIP response '%s' with Call-ID '%s', too many vias\n", e, callid);
+                       return 0;
+               }
                if (!p->initreq.headers) {
                        if (option_debug)
                                ast_log(LOG_DEBUG, "That's odd...  Got a response on a call we don't know about. Cseq %d Cmd %s\n", seqno, cmd);