Review Board 1.7.16


Yet Another Whack at the SIP user options issue.

Review Request #1223 - Created May 19, 2011 and submitted

Jonathan Rose
1.8
18344
Reviewers
asterisk-dev
dvossel, lmadsen, russell
Asterisk
A quick recap:
As of Asterisk 1.8, semicolons in user fields are accepted as just part of the user field in compliance with RFC 3261.  This makes devices that employ those options unable to register and also unable to match intended extensions without dialplan workarounds.

This approach involves a global sip option (if it were done per channel, we couldn't match on registers unfortunately) to strip the semicolons in the same general way as it was done in 1.6.2.  For that reason I chose to call it legacyuseroptionparsing
Made sure matches while the option were on would happen with the following using sipp:


        REGISTER sip:localhost SIP/2.0
        Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
		To: "Jonathan" <sip:evilhost;garbage@[local_ip]:[local_port]>
        From: "Jonathan" <sip:evilhost;garbage@[local_ip]:[local_port]>;tag=[call_number]

        Call-ID: [call_id]
        CSeq: 1 REGISTER
        Contact: sip:evilhost@[local_ip]:[local_port];expires=3600
        ALLOW: INVITE,ACK,BYE,CANCEL,OPTIONS,PRACK,REFER,NOTIFY,SUBSCRIBE,INFO,MESSAGE
		User-Agent: Sipp
        Content-Length: [len]

And


        INVITE sip:2005;5002;phone-context=+1;npdi=yes@[remote_ip]:[remote_port] SIP/2.0
        Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
        From: "Lrrrr Schmrrr" <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
        To: Asterisk <sip:2005;5002;phone-context=+1;npdi=yes@[remote_ip]:[remote_port]>
        Call-ID: [call_id]
        CSeq: 1 OPTIONS
        Contact: sip:sipp@[local_ip]:[local_port]
        Max-Forwards: 70
        Subject: Asterisk Testsuite
        Content-Length: [len]


Also that they also acted the same as the way they acted before with the option off.
/branches/1.8/channels/chan_sip.c
Revision 319526 New Change
[20] 13258 lines
[+20] [+] static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
13259
	/* We should return false for URI:s we can't handle,
13259
	/* We should return false for URI:s we can't handle,
13260
		like tel:, mailto:,ldap: etc */
13260
		like tel:, mailto:,ldap: etc */
13261
	return TRUE;		
13261
	return TRUE;		
13262
}
13262
}
13263

    
   
13263

   

    
   
13264
/*! \brief parse uri in a way that allows semicolon stripping if legacy mode is enabled */

    
   
13265
static int parse_uri_legacy_check(char *uri, const char *scheme, char **user, char **pass, char **domain, char **transport) {

    
   
13266
	int ret = parse_uri(uri, scheme, user, pass, domain, transport);

    
   
13267
	if (sip_cfg.legacyuseroptionparsing) { /* if legacy mode is active, strip semis from the user field */

    
   
13268
		char *p;

    
   
13269
		if ((p = strchr(uri, (int)';'))) {

    
   
13270
			*p = '\0';

    
   
13271
		}

    
   
13272
	}

    
   
13273
	return ret;

    
   
13274
}

    
   
13275

   
13264
static int __set_address_from_contact(const char *fullcontact, struct ast_sockaddr *addr, int tcp)
13276
static int __set_address_from_contact(const char *fullcontact, struct ast_sockaddr *addr, int tcp)
13265
{
13277
{
13266
	char *domain, *transport;
13278
	char *domain, *transport;
13267
	char contact_buf[256];
13279
	char contact_buf[256];
13268
	char *contact;
13280
	char *contact;
[+20] [20] 7 lines
[+20] static int __set_address_from_contact(const char *fullcontact, struct ast_sockaddr *addr, int tcp)
13276
	 *
13288
	 *
13277
	 * Note: The outbound proxy could be using UDP between the proxy and Asterisk.
13289
	 * Note: The outbound proxy could be using UDP between the proxy and Asterisk.
13278
	 * We still need to be able to send to the remote agent through the proxy.
13290
	 * We still need to be able to send to the remote agent through the proxy.
13279
	 */
13291
	 */
13280

    
   
13292

   
13281
	if (parse_uri(contact, "sip:,sips:", &contact, NULL, &domain,
13293
	if (parse_uri_legacy_check(contact, "sip:,sips:", &contact, NULL, &domain,
13282
		      &transport)) {
13294
		      &transport)) {
13283
		ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact);
13295
		ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact);
13284
	}
13296
	}
13285

    
   
13297

   
13286
	/* XXX This could block for a long time XXX */
13298
	/* XXX This could block for a long time XXX */
[+20] [20] 118 lines
[+20] [+] static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *peer, struct sip_request *req)
13405

    
   
13417

   
13406
	/* For the 200 OK, we should use the received contact */
13418
	/* For the 200 OK, we should use the received contact */
13407
	ast_string_field_build(pvt, our_contact, "<%s>", curi);
13419
	ast_string_field_build(pvt, our_contact, "<%s>", curi);
13408

    
   
13420

   
13409
	/* Make sure it's a SIP URL */
13421
	/* Make sure it's a SIP URL */
13410
	if (parse_uri(curi, "sip:,sips:", &curi, NULL, &domain, &transport)) {
13422
	if (parse_uri_legacy_check(curi, "sip:,sips:", &curi, NULL, &domain, &transport)) {
13411
		ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:/sips:) trying to use anyway\n");
13423
		ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:/sips:) trying to use anyway\n");
13412
	}
13424
	}
13413

    
   
13425

   
13414
	/* handle the transport type specified in Contact header. */
13426
	/* handle the transport type specified in Contact header. */
13415
	if (!(transport_type = get_transport_str2enum(transport))) {
13427
	if (!(transport_type = get_transport_str2enum(transport))) {
[+20] [20] 690 lines
[+20] [+] static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr,
14106
	ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp));
14118
	ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp));
14107

    
   
14119

   
14108
	c = get_in_brackets(tmp);
14120
	c = get_in_brackets(tmp);
14109
	c = remove_uri_parameters(c);
14121
	c = remove_uri_parameters(c);
14110

    
   
14122

   
14111
	if (parse_uri(c, "sip:,sips:", &name, &dummy, &domain, NULL)) {
14123
	if (parse_uri_legacy_check(c, "sip:,sips:", &name, &dummy, &domain, NULL)) {
14112
		ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_sockaddr_stringify_addr(addr));
14124
		ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_sockaddr_stringify_addr(addr));
14113
		return -1;
14125
		return -1;
14114
	}
14126
	}
14115

    
   
14127

   
14116
	SIP_PEDANTIC_DECODE(name);
14128
	SIP_PEDANTIC_DECODE(name);
[+20] [20] 570 lines
[+20] [+] static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
14687
	if (req->rlPart2)
14699
	if (req->rlPart2)
14688
		ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp));
14700
		ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp));
14689
	
14701
	
14690
	uri = ast_strdupa(get_in_brackets(tmp));
14702
	uri = ast_strdupa(get_in_brackets(tmp));
14691

    
   
14703

   
14692
	if (parse_uri(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) {
14704
	if (parse_uri_legacy_check(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) {
14693
		ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri);
14705
		ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri);
14694
		return SIP_GET_DEST_INVALID_URI;
14706
		return SIP_GET_DEST_INVALID_URI;
14695
	}
14707
	}
14696

    
   
14708

   
14697
	SIP_PEDANTIC_DECODE(domain);
14709
	SIP_PEDANTIC_DECODE(domain);
[+20] [20] 14 lines
[+20] static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
14712
	   Needs to be checked
14724
	   Needs to be checked
14713
        */
14725
        */
14714
	ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf));
14726
	ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf));
14715
	if (!ast_strlen_zero(tmpf)) {
14727
	if (!ast_strlen_zero(tmpf)) {
14716
		from = get_in_brackets(tmpf);
14728
		from = get_in_brackets(tmpf);
14717
		if (parse_uri(from, "sip:,sips:", &from, NULL, &domain, NULL)) {
14729
		if (parse_uri_legacy_check(from, "sip:,sips:", &from, NULL, &domain, NULL)) {
14718
			ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from);
14730
			ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from);
14719
			return SIP_GET_DEST_INVALID_URI;
14731
			return SIP_GET_DEST_INVALID_URI;
14720
		}
14732
		}
14721

    
   
14733

   
14722
		SIP_PEDANTIC_DECODE(from);
14734
		SIP_PEDANTIC_DECODE(from);
[+20] [20] 400 lines
[+20] [+] static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
15123
	referdata = p->refer;
15135
	referdata = p->refer;
15124

    
   
15136

   
15125
	ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp));
15137
	ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp));
15126
	c = get_in_brackets(tmp);
15138
	c = get_in_brackets(tmp);
15127

    
   
15139

   
15128
	if (parse_uri(c, "sip:,sips:", &c, NULL, &a, NULL)) {
15140
	if (parse_uri_legacy_check(c, "sip:,sips:", &c, NULL, &a, NULL)) {
15129
		ast_log(LOG_WARNING, "Huh?  Not a SIP header in Also: transfer (%s)?\n", c);
15141
		ast_log(LOG_WARNING, "Huh?  Not a SIP header in Also: transfer (%s)?\n", c);
15130
		return -1;
15142
		return -1;
15131
	}
15143
	}
15132
	
15144
	
15133
	SIP_PEDANTIC_DECODE(c);
15145
	SIP_PEDANTIC_DECODE(c);
[+20] [20] 358 lines
[+20] [+] static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
15492

    
   
15504

   
15493
	/* save the URI part of the From header */
15505
	/* save the URI part of the From header */
15494
	ast_string_field_set(p, from, of);
15506
	ast_string_field_set(p, from, of);
15495

    
   
15507

   
15496
	/* ignore all fields but name */
15508
	/* ignore all fields but name */
15497
	if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, NULL)) {
15509
	if (parse_uri_legacy_check(of, "sip:,sips:", &of, &dummy, &domain, NULL)) {
15498
		ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
15510
		ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
15499
	}
15511
	}
15500

    
   
15512

   
15501
	SIP_PEDANTIC_DECODE(of);
15513
	SIP_PEDANTIC_DECODE(of);
15502
	SIP_PEDANTIC_DECODE(domain);
15514
	SIP_PEDANTIC_DECODE(domain);
[+20] [20] 1828 lines
[+20] [+] static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17331
	ast_cli(a->fd, "  User Agent:             %s\n", global_useragent);
17343
	ast_cli(a->fd, "  User Agent:             %s\n", global_useragent);
17332
	ast_cli(a->fd, "  SDP Session Name:       %s\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
17344
	ast_cli(a->fd, "  SDP Session Name:       %s\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
17333
	ast_cli(a->fd, "  SDP Owner Name:         %s\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner);
17345
	ast_cli(a->fd, "  SDP Owner Name:         %s\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner);
17334
	ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(sip_cfg.regcontext, "(not set)"));
17346
	ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(sip_cfg.regcontext, "(not set)"));
17335
	ast_cli(a->fd, "  Regexten on Qualify:    %s\n", AST_CLI_YESNO(sip_cfg.regextenonqualify));
17347
	ast_cli(a->fd, "  Regexten on Qualify:    %s\n", AST_CLI_YESNO(sip_cfg.regextenonqualify));

    
   
17348
	ast_cli(a->fd, "  Legacy userfield parse: %s\n", AST_CLI_YESNO(sip_cfg.legacyuseroptionparsing));
17336
	ast_cli(a->fd, "  Caller ID:              %s\n", default_callerid);
17349
	ast_cli(a->fd, "  Caller ID:              %s\n", default_callerid);
17337
	if ((default_fromdomainport) && (default_fromdomainport != STANDARD_SIP_PORT)) {
17350
	if ((default_fromdomainport) && (default_fromdomainport != STANDARD_SIP_PORT)) {
17338
		ast_cli(a->fd, "  From: Domain:           %s:%d\n", default_fromdomain, default_fromdomainport);
17351
		ast_cli(a->fd, "  From: Domain:           %s:%d\n", default_fromdomain, default_fromdomainport);
17339
	} else {
17352
	} else {
17340
		ast_cli(a->fd, "  From: Domain:           %s\n", default_fromdomain);
17353
		ast_cli(a->fd, "  From: Domain:           %s\n", default_fromdomain);
[+20] [20] 9592 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
26933
	/* Reset channel settings to default before re-configuring */
26946
	/* Reset channel settings to default before re-configuring */
26934
	sip_cfg.allow_external_domains = DEFAULT_ALLOW_EXT_DOM;				/* Allow external invites */
26947
	sip_cfg.allow_external_domains = DEFAULT_ALLOW_EXT_DOM;				/* Allow external invites */
26935
	sip_cfg.regcontext[0] = '\0';
26948
	sip_cfg.regcontext[0] = '\0';
26936
	sip_cfg.capability = DEFAULT_CAPABILITY;
26949
	sip_cfg.capability = DEFAULT_CAPABILITY;
26937
	sip_cfg.regextenonqualify = DEFAULT_REGEXTENONQUALIFY;
26950
	sip_cfg.regextenonqualify = DEFAULT_REGEXTENONQUALIFY;

    
   
26951
	sip_cfg.legacyuseroptionparsing = DEFAULT_LEGACYUSEROPTIONPARSING;
26938
	sip_cfg.notifyringing = DEFAULT_NOTIFYRINGING;
26952
	sip_cfg.notifyringing = DEFAULT_NOTIFYRINGING;
26939
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26953
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26940
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26954
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26941
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26955
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26942
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26956
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
[+20] [20] 262 lines
[+20] static int reload_config(enum channelreloadreason reason)
27205
				ast_context_find_or_create(NULL, NULL, context, "SIP");
27219
				ast_context_find_or_create(NULL, NULL, context, "SIP");
27206
			}
27220
			}
27207
			ast_copy_string(sip_cfg.regcontext, v->value, sizeof(sip_cfg.regcontext));
27221
			ast_copy_string(sip_cfg.regcontext, v->value, sizeof(sip_cfg.regcontext));
27208
		} else if (!strcasecmp(v->name, "regextenonqualify")) {
27222
		} else if (!strcasecmp(v->name, "regextenonqualify")) {
27209
			sip_cfg.regextenonqualify = ast_true(v->value);
27223
			sip_cfg.regextenonqualify = ast_true(v->value);

    
   
27224
		} else if (!strcasecmp(v->name, "legacyuseroptionparsing")) {

    
   
27225
			sip_cfg.legacyuseroptionparsing = ast_true(v->value);
27210
		} else if (!strcasecmp(v->name, "callerid")) {
27226
		} else if (!strcasecmp(v->name, "callerid")) {
27211
			ast_copy_string(default_callerid, v->value, sizeof(default_callerid));
27227
			ast_copy_string(default_callerid, v->value, sizeof(default_callerid));
27212
		} else if (!strcasecmp(v->name, "mwi_from")) {
27228
		} else if (!strcasecmp(v->name, "mwi_from")) {
27213
			ast_copy_string(default_mwi_from, v->value, sizeof(default_mwi_from));
27229
			ast_copy_string(default_mwi_from, v->value, sizeof(default_mwi_from));
27214
		} else if (!strcasecmp(v->name, "fromdomain")) {
27230
		} else if (!strcasecmp(v->name, "fromdomain")) {
[+20] [20] 2176 lines
/branches/1.8/channels/sip/include/sip.h
Revision 319526 New Change
 
/branches/1.8/configs/sip.conf.sample
Revision 319526 New Change
 
  1. /branches/1.8/channels/chan_sip.c: Loading...
  2. /branches/1.8/channels/sip/include/sip.h: Loading...
  3. /branches/1.8/configs/sip.conf.sample: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.