summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_sip.c30
-rw-r--r--channels/sip/include/sip.h2
-rw-r--r--configs/sip.conf.sample8
3 files changed, 33 insertions, 7 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4a01cd434..75e902e5c 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -13524,6 +13524,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;
@@ -13541,7 +13553,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);
}
@@ -13670,7 +13682,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");
}
@@ -14371,7 +14383,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;
}
@@ -14952,7 +14964,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;
}
@@ -14977,7 +14989,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;
}
@@ -15388,7 +15400,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;
}
@@ -15764,7 +15776,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");
}
@@ -17619,6 +17631,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, " Regexten on Qualify: %s\n", AST_CLI_YESNO(sip_cfg.regextenonqualify));
ast_cli(a->fd, " Trust RPID: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_TRUSTRPID)));
ast_cli(a->fd, " Send RPID: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_SENDRPID)));
+ 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);
@@ -27303,6 +27316,7 @@ static int reload_config(enum channelreloadreason reason)
sip_cfg.regcontext[0] = '\0';
sip_set_default_format_capabilities(sip_cfg.caps);
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 */
@@ -27576,6 +27590,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")) {
diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h
index b856a7f3e..4b69010b3 100644
--- a/channels/sip/include/sip.h
+++ b/channels/sip/include/sip.h
@@ -212,6 +212,7 @@
#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 */
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 1726299d3..179678a39 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -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