[asterisk-bugs] [JIRA] (ASTERISK-24915) Missing Contact: header in 200 OK

Etienne Lessard (JIRA) noreply at issues.asterisk.org
Mon Apr 20 14:47:33 CDT 2015


    [ https://issues.asterisk.org/jira/browse/ASTERISK-24915?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=225945#comment-225945 ] 

Etienne Lessard commented on ASTERISK-24915:
--------------------------------------------

I've taken a look at the bug in asterisk 11, and the problem comes from the handle_incoming function:

{code}
	...
	p->method = req->method;	/* Find out which SIP method they are using */
	ast_debug(4, "**** Received %s (%u) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd);

	if (p->icseq && (p->icseq > seqno) ) {
		if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) {
			ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n");
		} else {
			ast_debug(1, "Ignoring too old SIP packet packet %u (expecting >= %u)\n", seqno, p->icseq);
			if (req->method == SIP_INVITE) {
				unsigned int ran = (ast_random() % 10) + 1;
				char seconds[4];
				snprintf(seconds, sizeof(seconds), "%u", ran);
				transmit_response_with_retry_after(p, "500 Server error", req, seconds);	/* respond according to RFC 3261 14.2 with Retry-After betwewn 0 and 10 */
			} else if (req->method != SIP_ACK) {
				transmit_response(p, "500 Server error", req);	/* We must respond according to RFC 3261 sec 12.2 */
			}
			return -1;
		}
	} ...
{code}

The problem occurs because the handle_incoming function updates p->method to req->method (p being a struct sip_pvt *) before checking if the CSeq makes sense, and if the CSeq is unexpected, it does not reset p->method to its old value before returning. Then, when asterisk sends the 200 OK response for the original INVITE, since p->method is now equal to SIP_ACK (instead of SIP_INVITE), the resp_need_contact function (called from respprep) says "its a SIP ACK, no need to add a Contact header for the response", which is wrong, since it's not a SIP ACK but a SIP INVITE dialog.

I've attached a "quick and dirty" patch that fix the scenario described in this ticket. That said, I would not be surprised if a more "complete" patch would be required to fix a more global problem; the problem being that p->method might not always be in the right state after the handle_incoming function returns.

Note that I'm not a chan_sip expert.

> Missing Contact: header in 200 OK
> ---------------------------------
>
>                 Key: ASTERISK-24915
>                 URL: https://issues.asterisk.org/jira/browse/ASTERISK-24915
>             Project: Asterisk
>          Issue Type: Bug
>      Security Level: None
>          Components: Channels/chan_sip/General
>    Affects Versions: 1.8.32.2, 11.16.0
>            Reporter: Etienne Allovon
>         Attachments: AST-24915.diff, ASTERISK-24915-asterisk-extensions.conf, ASTERISK-24915-asterisk-full.log, ASTERISK-24915-asterisk-sip.conf, ASTERISK-24915.pcapng, REGISTER_INVITE_client.csv, REGISTER_INVITE_client.xml
>
>
> *Summary*
> In some cases asterisk answers a call (SIP 200 OK) without the {{Contact:}} header.
> It results, for the receiving peer, to terminate the call (SIP BYE) because he can't answer.
> For example, if the receiving peer is an asterisk, you get the following WARNING in the CLI :
> {code}
> WARNING[32089] chan_sip.c: Invalid contact uri  (missing sip: or sips:), attempting to use anyway
> {code}
> More precisely this happens when asterisk receives a SIP message with a bad CSeq (for example with CSeq-1). Then the next 200 OK doesn't contain the Contact: header.
> *When does it happen in real life ?*
> In real life I saw it with two asterisk interconnected with a SIP trunk via a WAN.
> When there is some asymetric latency it results in retransmissions.
> {code}
> < INVITE            (CSeq 1)
> > 401 Unauthorized  (CSeq 1)
> > 401 Unauthorized  (CSeq 1) .... retransmission because ACK is not received on time
> < ACK               (CSeq 1) .... ACK of the first 401 Unauthorized
> < INVITE            (CSeq 2)
> > 100 Trying        (CSeq 2)  
> > 180 Ringing       (CSeq 2)
> < ACK               (Cseq *1*) .. ACK of the retransmitted 401 Unauthorized
> > 200 OK            (Cseq 2) .... /!\ which does not contain the Contact: header
> {code}
> *How to reproduce*
> Below is a SIP exchange forged with SIPp which reproduce the problem :
> {code}
> < INVITE            (CSeq 1)
> > 401 Unauthorized  (CSeq 1)
> < ACK               (CSeq 1)
> < INVITE            (CSeq 2)
> > 100 Trying        (CSeq 2) ..... contains Contact: header
> > 180 Ringing       (CSeq 2) ..... contains Contact: header
> < ACK               (Cseq *1*)
> > 200 OK            (Cseq 2) ..... /!\ does not contain Contact: header
> {code}
> The bug appears at step #7.
> Asterisk seems to handle the spurious ACK correctly since you find the following DEBUG message :
> {code}
> DEBUG[26739] chan_sip.c: **** Received ACK (6) - Command in SIP ACK
> DEBUG[26739] chan_sip.c: Ignoring too old SIP packet packet 1 (expecting >= 2)
> DEBUG[26739] chan_sip.c: SIP message could not be handled, bad request: 261113e445fb3f8777068f5513a8d61f at 10.14.12.1:5060
> {code}
> Here's the SIPp command to launch the scenario :
> {code}
> /usr/src/sipp-3.3/sipp 192.168.18.55 -sf REGISTER_INVITE_client.xml -inf REGISTER_INVITE_client.csv -i 192.168.18.11 -m 1 -l 1 -r 1
> {code}
> You need to :
> * replace 192.168.18.65 asterisk IP,
> * replace 192.168.18.11 with SIPp client IP
> * get the REGISTER_INVITE_client.xml file,
> * get the REGISTER_INVITE_client.csv file and change the authentication information
> *References*
> SIPp scenarios based on examples found here : http://tomeko.net/other/sipp/sipp_cheatsheet.php?lang



--
This message was sent by Atlassian JIRA
(v6.2#6252)



More information about the asterisk-bugs mailing list