]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Adds legacy_useroption_parsing to address interoperability concerns.
authorJonathan Rose <jrose@digium.com>
Fri, 20 May 2011 13:28:24 +0000 (13:28 +0000)
committerJonathan Rose <jrose@digium.com>
Fri, 20 May 2011 13:28:24 +0000 (13:28 +0000)
With the new option engaged, Asterisk should interpret user fields with useroptions
contained within the userfield of the uri by stripping them out of the original message
whenever a semicolon is encountered in the userfield string.

(closes issue #18344)
Reported by: danimal
Tested by: jrose

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

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

channels/chan_sip.c
channels/sip/include/sip.h
configs/sip.conf.sample

index 001c3b5db3d766c6f5bf02e7b35e8f63cc82763f..fcc559b8a61cd1d7ce3713c9d8e2f28f50919c6e 100644 (file)
@@ -13261,6 +13261,18 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
        return TRUE;            
 }
 
+/*! \brief parse uri in a way that allows semicolon stripping if legacy mode is enabled */
+static int parse_uri_legacy_check(char *uri, const char *scheme, char **user, char **pass, char **domain, char **transport) {
+       int ret = parse_uri(uri, scheme, user, pass, domain, transport);
+       if (sip_cfg.legacy_useroption_parsing) { /* if legacy mode is active, strip semis from the user field */
+               char *p;
+               if ((p = strchr(uri, (int)';'))) {
+                       *p = '\0';
+               }
+       }
+       return ret;
+}
+
 static int __set_address_from_contact(const char *fullcontact, struct ast_sockaddr *addr, int tcp)
 {
        char *domain, *transport;
@@ -13278,7 +13290,7 @@ static int __set_address_from_contact(const char *fullcontact, struct ast_sockad
         * We still need to be able to send to the remote agent through the proxy.
         */
 
-       if (parse_uri(contact, "sip:,sips:", &contact, NULL, &domain,
+       if (parse_uri_legacy_check(contact, "sip:,sips:", &contact, NULL, &domain,
                      &transport)) {
                ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact);
        }
@@ -13407,7 +13419,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
        ast_string_field_build(pvt, our_contact, "<%s>", curi);
 
        /* Make sure it's a SIP URL */
-       if (parse_uri(curi, "sip:,sips:", &curi, NULL, &domain, &transport)) {
+       if (parse_uri_legacy_check(curi, "sip:,sips:", &curi, NULL, &domain, &transport)) {
                ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:/sips:) trying to use anyway\n");
        }
 
@@ -14108,7 +14120,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
        c = get_in_brackets(tmp);
        c = remove_uri_parameters(c);
 
-       if (parse_uri(c, "sip:,sips:", &name, &dummy, &domain, NULL)) {
+       if (parse_uri_legacy_check(c, "sip:,sips:", &name, &dummy, &domain, NULL)) {
                ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_sockaddr_stringify_addr(addr));
                return -1;
        }
@@ -14689,7 +14701,7 @@ static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_re
        
        uri = ast_strdupa(get_in_brackets(tmp));
 
-       if (parse_uri(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) {
+       if (parse_uri_legacy_check(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) {
                ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri);
                return SIP_GET_DEST_INVALID_URI;
        }
@@ -14714,7 +14726,7 @@ static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_re
        ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf));
        if (!ast_strlen_zero(tmpf)) {
                from = get_in_brackets(tmpf);
-               if (parse_uri(from, "sip:,sips:", &from, NULL, &domain, NULL)) {
+               if (parse_uri_legacy_check(from, "sip:,sips:", &from, NULL, &domain, NULL)) {
                        ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from);
                        return SIP_GET_DEST_INVALID_URI;
                }
@@ -15125,7 +15137,7 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
        ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp));
        c = get_in_brackets(tmp);
 
-       if (parse_uri(c, "sip:,sips:", &c, NULL, &a, NULL)) {
+       if (parse_uri_legacy_check(c, "sip:,sips:", &c, NULL, &a, NULL)) {
                ast_log(LOG_WARNING, "Huh?  Not a SIP header in Also: transfer (%s)?\n", c);
                return -1;
        }
@@ -15494,7 +15506,7 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
        ast_string_field_set(p, from, of);
 
        /* ignore all fields but name */
-       if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, NULL)) {
+       if (parse_uri_legacy_check(of, "sip:,sips:", &of, &dummy, &domain, NULL)) {
                ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
        }
 
@@ -17333,6 +17345,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
        ast_cli(a->fd, "  SDP Owner Name:         %s\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner);
        ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(sip_cfg.regcontext, "(not set)"));
        ast_cli(a->fd, "  Regexten on Qualify:    %s\n", AST_CLI_YESNO(sip_cfg.regextenonqualify));
+       ast_cli(a->fd, "  Legacy userfield parse: %s\n", AST_CLI_YESNO(sip_cfg.legacy_useroption_parsing));
        ast_cli(a->fd, "  Caller ID:              %s\n", default_callerid);
        if ((default_fromdomainport) && (default_fromdomainport != STANDARD_SIP_PORT)) {
                ast_cli(a->fd, "  From: Domain:           %s:%d\n", default_fromdomain, default_fromdomainport);
@@ -26938,6 +26951,7 @@ static int reload_config(enum channelreloadreason reason)
        sip_cfg.regcontext[0] = '\0';
        sip_cfg.capability = DEFAULT_CAPABILITY;
        sip_cfg.regextenonqualify = DEFAULT_REGEXTENONQUALIFY;
+       sip_cfg.legacy_useroption_parsing = DEFAULT_LEGACY_USEROPTION_PARSING;
        sip_cfg.notifyringing = DEFAULT_NOTIFYRINGING;
        sip_cfg.notifycid = DEFAULT_NOTIFYCID;
        sip_cfg.notifyhold = FALSE;             /*!< Keep track of hold status for a peer */
@@ -27210,6 +27224,8 @@ static int reload_config(enum channelreloadreason reason)
                        ast_copy_string(sip_cfg.regcontext, v->value, sizeof(sip_cfg.regcontext));
                } else if (!strcasecmp(v->name, "regextenonqualify")) {
                        sip_cfg.regextenonqualify = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "legacy_useroption_parsing")) {
+                       sip_cfg.legacy_useroption_parsing = ast_true(v->value);
                } else if (!strcasecmp(v->name, "callerid")) {
                        ast_copy_string(default_callerid, v->value, sizeof(default_callerid));
                } else if (!strcasecmp(v->name, "mwi_from")) {
index a6e69be04dca79657196a10c4e9c8915f2ed17a1..932504487e36ce5935b06ef1dba2603aa03ab96d 100644 (file)
 #define DEFAULT_ALWAYSAUTHREJECT  TRUE  /*!< Don't reject authentication requests always */
 #define DEFAULT_AUTH_OPTIONS  FALSE
 #define DEFAULT_REGEXTENONQUALIFY FALSE
+#define DEFAULT_LEGACY_USEROPTION_PARSING FALSE
 #define DEFAULT_T1MIN             100   /*!< 100 MS for minimal roundtrip time */
 #define DEFAULT_MAX_CALL_BITRATE (384)  /*!< Max bitrate for video */
 #ifndef DEFAULT_USERAGENT
@@ -683,6 +684,7 @@ struct sip_settings {
        int allow_external_domains; /*!< Accept calls to external SIP domains? */
        int callevents;             /*!< Whether we send manager events or not */
        int regextenonqualify;      /*!< Whether to add/remove regexten when qualifying peers */
+       int legacy_useroption_parsing; /*!< Whether to strip useroptions in URI via semicolons */
        int matchexternaddrlocally;   /*!< Match externaddr/externhost setting against localnet setting */
        char regcontext[AST_MAX_CONTEXT];  /*!< Context for auto-extensions */
        unsigned int disallowed_methods;   /*!< methods that we should never try to use */
index b0f507e0b634849f1e2fd4f10333530ac6cf635d..333f978e677c7f1d362b3d38dcae0eb85e774977 100644 (file)
@@ -432,6 +432,14 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
                                 ; If you have qualify on and the peer becomes unreachable
                                 ; this setting will enforce inactivation of the regexten
                                 ; extension for the peer
+;legacy_useroption_parsing=yes ; Default "no"      ; If you have this option enabled and there are semicolons
+                                                    ; in the user field of a sip URI, the field be truncated
+                                                    ; at the first semicolon seen. This effectively makes
+                                                    ; semicolon a non-usable character for peer names, extensions,
+                                                    ; and maybe other, less tested things.  This can be useful
+                                                    ; for improving compatability with devices that like to use
+                                                    ; user options for whatever reason.  The behavior is similar to
+                                                    ; how SIP URI's were typically handled in 1.6.2, hence the name.
 
 ; The shrinkcallerid function removes '(', ' ', ')', non-trailing '.', and '-' not
 ; in square brackets.  For example, the caller id value 555.5555 becomes 5555555