summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2016-08-29 18:08:22 -0500
committerRichard Mudgett <rmudgett@digium.com>2016-09-09 17:09:54 -0500
commit30af92e78d36523f8012da5eb9aee16687d8fe61 (patch)
tree1f84280f76613282c8a81dc9b7aaf2b738201dfa /res
parent7580a736bb30577d7557aac9165894dc9f9583e6 (diff)
res_pjsip: Add ignore_uri_user_options option.
This implements the chan_sip legacy_useroption_parsing option but with a better name. * Made the caller-id number and redirecting number strings obtained from incoming SIP URI user fields always truncated at the first semicolon. People don't care about anything after the semicolon showing up on their displays even though the RFC allows the semicolon. ASTERISK-26316 #close Reported by: Kevin Harwell Change-Id: Ib42b0e940dd34d84c7b14bc2e90d1ba392624f62
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip.c24
-rw-r--r--res/res_pjsip/config_global.c20
-rw-r--r--res/res_pjsip/pjsip_options.c12
-rw-r--r--res/res_pjsip_caller_id.c18
-rw-r--r--res/res_pjsip_diversion.c25
-rw-r--r--res/res_pjsip_endpoint_identifier_user.c12
-rw-r--r--res/res_pjsip_messaging.c25
-rw-r--r--res/res_pjsip_path.c22
-rw-r--r--res/res_pjsip_pubsub.c18
-rw-r--r--res/res_pjsip_refer.c7
-rw-r--r--res/res_pjsip_registrar.c6
-rw-r--r--res/res_pjsip_session.c13
12 files changed, 185 insertions, 17 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 96c07d501..039495d55 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -1544,6 +1544,30 @@
</para>
</description>
</configOption>
+ <configOption name="ignore_uri_user_options">
+ <synopsis>Enable/Disable ignoring SIP URI user field options.</synopsis>
+ <description>
+ <para>If you have this option enabled and there are semicolons
+ in the user field of a SIP URI then the field is truncated
+ at the first semicolon. This effectively makes the semicolon
+ a non-usable character for PJSIP endpoint names, extensions,
+ and AORs. This can be useful for improving compatability with
+ an ITSP that likes to use user options for whatever reason.
+ </para>
+ <example title="Sample SIP URI">
+ sip:1235557890;phone-context=national@x.x.x.x;user=phone
+ </example>
+ <example title="Sample SIP URI user field">
+ 1235557890;phone-context=national
+ </example>
+ <example title="Sample SIP URI user field truncated">
+ 1235557890
+ </example>
+ <note><para>The caller-id and redirecting number strings
+ obtained from incoming SIP URI user fields are always truncated
+ at the first semicolon.</para></note>
+ </description>
+ </configOption>
</configObject>
</configFile>
</configInfo>
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index 281630ae4..fc1227d25 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -47,6 +47,7 @@
#define DEFAULT_MWI_TPS_QUEUE_HIGH AST_TASKPROCESSOR_HIGH_WATER_LEVEL
#define DEFAULT_MWI_TPS_QUEUE_LOW -1
#define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0
+#define DEFAULT_IGNORE_URI_USER_OPTIONS 0
/*!
* \brief Cached global config object
@@ -100,6 +101,8 @@ struct global_config {
/*! Nonzero to disable sending unsolicited mwi to all endpoints on startup */
unsigned int disable_initial_unsolicited;
} mwi;
+ /*! Nonzero if URI user field options are ignored. */
+ unsigned int ignore_uri_user_options;
};
static void global_destructor(void *obj)
@@ -384,6 +387,20 @@ unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
return disable_initial_unsolicited;
}
+unsigned int ast_sip_get_ignore_uri_user_options(void)
+{
+ unsigned int ignore_uri_user_options;
+ struct global_config *cfg;
+
+ cfg = get_global_cfg();
+ if (!cfg) {
+ return DEFAULT_IGNORE_URI_USER_OPTIONS;
+ }
+
+ ignore_uri_user_options = cfg->ignore_uri_user_options;
+ ao2_ref(cfg, -1);
+ return ignore_uri_user_options;
+}
/*!
* \internal
@@ -533,6 +550,9 @@ int ast_sip_initialize_sorcery_global(void)
ast_sorcery_object_field_register(sorcery, "global", "mwi_disable_initial_unsolicited",
DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED ? "yes" : "no",
OPT_BOOL_T, 1, FLDSET(struct global_config, mwi.disable_initial_unsolicited));
+ ast_sorcery_object_field_register(sorcery, "global", "ignore_uri_user_options",
+ DEFAULT_IGNORE_URI_USER_OPTIONS ? "yes" : "no",
+ OPT_BOOL_T, 1, FLDSET(struct global_config, ignore_uri_user_options));
if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
return -1;
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index d87188363..8c8836fd9 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -760,8 +760,7 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
pjsip_sip_uri *sip_ruri;
char exten[AST_MAX_EXTENSION];
- if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
- &pjsip_options_method)) {
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
return PJ_FALSE;
}
@@ -778,13 +777,20 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
sip_ruri = pjsip_uri_get_uri(ruri);
ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten));
+ /*
+ * We may want to match in the dialplan without any user
+ * options getting in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
if (ast_shutting_down()) {
/*
* Not taking any new calls at this time.
* Likely a server availability OPTIONS poll.
*/
send_options_response(rdata, 503);
- } else if (!ast_strlen_zero(exten) && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
+ } else if (!ast_strlen_zero(exten)
+ && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
send_options_response(rdata, 404);
} else {
send_options_response(rdata, 200);
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index 4d9f09237..c3aa338ae 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -46,11 +46,29 @@ static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id)
char cid_num[AST_CHANNEL_NAME];
pjsip_sip_uri *uri;
pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri;
+ char *semi;
uri = pjsip_uri_get_uri(id_name_addr);
ast_copy_pj_str(cid_name, &id_name_addr->display, sizeof(cid_name));
ast_copy_pj_str(cid_num, &uri->user, sizeof(cid_num));
+ /* Always truncate caller-id number at a semicolon. */
+ semi = strchr(cid_num, ';');
+ if (semi) {
+ /*
+ * We need to be able to handle URI's looking like
+ * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+ *
+ * Where the uri->user field will result in:
+ * "1235557890;phone-context=national"
+ *
+ * People don't care about anything after the semicolon
+ * showing up on their displays even though the RFC
+ * allows the semicolon.
+ */
+ *semi = '\0';
+ }
+
ast_free(id->name.str);
id->name.str = ast_strdup(cid_name);
if (!ast_strlen_zero(cid_name)) {
diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c
index 99d18da44..b9225de9c 100644
--- a/res/res_pjsip_diversion.c
+++ b/res/res_pjsip_diversion.c
@@ -148,11 +148,32 @@ static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *
struct ast_set_party_id *update)
{
pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri);
+ char *semi;
+ pj_str_t uri_user;
+
+ uri_user = uri->user;
+
+ /* Always truncate redirecting number at a semicolon. */
+ semi = pj_strchr(&uri_user, ';');
+ if (semi) {
+ /*
+ * We need to be able to handle URI's looking like
+ * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+ *
+ * Where the uri->user field will result in:
+ * "1235557890;phone-context=national"
+ *
+ * People don't care about anything after the semicolon
+ * showing up on their displays even though the RFC
+ * allows the semicolon.
+ */
+ pj_strset(&uri_user, (char *) pj_strbuf(&uri_user), semi - pj_strbuf(&uri_user));
+ }
- if (pj_strlen(&uri->user)) {
+ if (pj_strlen(&uri_user)) {
update->number = 1;
data->number.valid = 1;
- set_redirecting_value(&data->number.str, &uri->user);
+ set_redirecting_value(&data->number.str, &uri_user);
}
if (pj_strlen(&name_addr->display)) {
diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c
index e018abd61..30da062ed 100644
--- a/res/res_pjsip_endpoint_identifier_user.c
+++ b/res/res_pjsip_endpoint_identifier_user.c
@@ -33,6 +33,7 @@ static int get_from_header(pjsip_rx_data *rdata, char *username, size_t username
{
pjsip_uri *from = rdata->msg_info.from->uri;
pjsip_sip_uri *sip_from;
+
if (!PJSIP_URI_SCHEME_IS_SIP(from) && !PJSIP_URI_SCHEME_IS_SIPS(from)) {
return -1;
}
@@ -115,18 +116,25 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi
static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata)
{
- char username[64], domain[64];
+ char username[64];
+ char domain[64];
struct ast_sip_endpoint *endpoint;
if (get_from_header(rdata, username, sizeof(username), domain, sizeof(domain))) {
return NULL;
}
+
+ /*
+ * We may want to be matched without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
+
ast_debug(3, "Attempting identify by From username '%s' domain '%s'\n", username, domain);
endpoint = find_endpoint(rdata, username, domain);
if (!endpoint) {
ast_debug(3, "Endpoint not found for From username '%s' domain '%s'\n", username, domain);
- ao2_cleanup(endpoint);
return NULL;
}
if (!(endpoint->ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME)) {
diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c
index 4e5ad2652..07869052d 100644
--- a/res/res_pjsip_messaging.c
+++ b/res/res_pjsip_messaging.c
@@ -133,6 +133,12 @@ static struct ast_sip_endpoint* get_outbound_endpoint(
} else if ((aor_uri = strchr(name, '@'))) {
/* format was 'endpoint@' - don't use the rest */
*aor_uri = '\0';
+
+ /*
+ * We may want to match without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(name);
}
/* at this point, if name is not empty then it
@@ -448,6 +454,12 @@ static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct as
sip_ruri = pjsip_uri_get_uri(ruri);
ast_copy_pj_str(exten, &sip_ruri->user, AST_MAX_EXTENSION);
+ /*
+ * We may want to match in the dialplan without any user
+ * options getting in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
endpt = ast_pjsip_rdata_get_endpoint(rdata);
ast_assert(endpt != NULL);
@@ -528,7 +540,7 @@ static void msg_data_destroy(void *obj)
static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *to, const char *from)
{
- char *tag;
+ char *uri_params;
struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy);
if (!mdata) {
@@ -553,9 +565,14 @@ static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *t
return NULL;
}
- /* sometimes from can still contain the tag at this point, so remove it */
- if ((tag = strchr(mdata->from, ';'))) {
- *tag = '\0';
+ /*
+ * Sometimes from URI can contain URI parameters, so remove them.
+ *
+ * sip:user;user-options@domain;uri-parameters
+ */
+ uri_params = strchr(mdata->from, '@');
+ if (uri_params && (uri_params = strchr(mdata->from, ';'))) {
+ *uri_params = '\0';
}
return mdata;
}
diff --git a/res/res_pjsip_path.c b/res/res_pjsip_path.c
index 47d6a7906..20c9d4366 100644
--- a/res/res_pjsip_path.c
+++ b/res/res_pjsip_path.c
@@ -40,7 +40,8 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
char *configured_aors, *aor_name;
pjsip_sip_uri *sip_uri;
char *domain_name;
- RAII_VAR(struct ast_str *, id, NULL, ast_free);
+ char *username;
+ struct ast_str *id = NULL;
if (ast_strlen_zero(endpoint->aors)) {
return NULL;
@@ -49,6 +50,14 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
sip_uri = pjsip_uri_get_uri(uri);
domain_name = ast_alloca(sip_uri->host.slen + 1);
ast_copy_pj_str(domain_name, &sip_uri->host, sip_uri->host.slen + 1);
+ username = ast_alloca(sip_uri->user.slen + 1);
+ ast_copy_pj_str(username, &sip_uri->user, sip_uri->user.slen + 1);
+
+ /*
+ * We may want to match without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
configured_aors = ast_strdupa(endpoint->aors);
@@ -60,15 +69,16 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
continue;
}
- if (!pj_strcmp2(&sip_uri->user, aor_name)) {
+ if (!strcmp(username, aor_name)) {
break;
}
- if (!id && !(id = ast_str_create(sip_uri->user.slen + sip_uri->host.slen + 2))) {
- return NULL;
+ if (!id && !(id = ast_str_create(strlen(username) + sip_uri->host.slen + 2))) {
+ aor_name = NULL;
+ break;
}
- ast_str_set(&id, 0, "%.*s@", (int)sip_uri->user.slen, sip_uri->user.ptr);
+ ast_str_set(&id, 0, "%s@", username);
if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
ast_str_append(&id, 0, "%s", alias->domain);
ao2_cleanup(alias);
@@ -77,10 +87,10 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
}
if (!strcmp(aor_name, ast_str_buffer(id))) {
- ast_free(id);
break;
}
}
+ ast_free(id);
if (ast_strlen_zero(aor_name)) {
return NULL;
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 3ac3f342f..2fa7f34e3 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -1400,6 +1400,12 @@ static int sub_persistence_recreate(void *obj)
resource = ast_alloca(resource_size);
ast_copy_pj_str(resource, &request_uri->user, resource_size);
+ /*
+ * We may want to match without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource);
+
handler = subscription_get_handler_from_rdata(rdata);
if (!handler || !handler->notifier) {
ast_log(LOG_WARNING, "Failed recreating '%s' subscription: Could not get subscription handler.\n",
@@ -2815,6 +2821,12 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
resource = ast_alloca(resource_size);
ast_copy_pj_str(resource, &request_uri_sip->user, resource_size);
+ /*
+ * We may want to match without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource);
+
expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
if (expires_header) {
@@ -3028,6 +3040,12 @@ static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoi
resource_name = ast_alloca(resource_size);
ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size);
+ /*
+ * We may want to match without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource_name);
+
resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name);
if (!resource) {
ast_debug(1, "No 'inbound-publication' defined for resource '%s'\n", resource_name);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index 8fe4e8477..99295d5f3 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -814,6 +814,13 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
/* Using the user portion of the target URI see if it exists as a valid extension in their context */
ast_copy_pj_str(exten, &target->user, sizeof(exten));
+
+ /*
+ * We may want to match in the dialplan without any user
+ * options getting in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
if (!ast_exists_extension(NULL, context, exten, 1, NULL)) {
ast_log(LOG_ERROR, "Channel '%s' from endpoint '%s' attempted blind transfer to '%s@%s' but target does not exist\n",
ast_channel_name(session->channel), ast_sorcery_object_get_id(session->endpoint), exten, context);
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index 1e0f5ab72..a13f8f86b 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -634,6 +634,12 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc
username = ast_alloca(uri->user.slen + 1);
ast_copy_pj_str(username, &uri->user, uri->user.slen + 1);
+ /*
+ * We may want to match without any user options getting
+ * in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
+
aor_name = find_aor_name(username, domain_name, endpoint->aors);
if (aor_name) {
ast_debug(3, "Matched aor '%s' by To username\n", aor_name);
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 050970998..8b8e9d114 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1980,6 +1980,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s
sip_ruri = pjsip_uri_get_uri(ruri);
ast_copy_pj_str(session->exten, &sip_ruri->user, sizeof(session->exten));
+ /*
+ * We may want to match in the dialplan without any user
+ * options getting in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(session->exten);
+
pickup_cfg = ast_get_chan_features_pickup_config(session->channel);
if (!pickup_cfg) {
ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
@@ -3059,6 +3065,13 @@ static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const
char exten[AST_MAX_EXTENSION];
ast_copy_pj_str(exten, &uri->user, sizeof(exten));
+
+ /*
+ * We may want to match in the dialplan without any user
+ * options getting in the way.
+ */
+ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
ast_channel_call_forward_set(session->channel, exten);
} else if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_CORE) {
char target_uri[PJSIP_MAX_URL_SIZE];