]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add ignore_uri_user_options option. 60/3860/2
authorRichard Mudgett <rmudgett@digium.com>
Mon, 29 Aug 2016 23:08:22 +0000 (18:08 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 9 Sep 2016 22:08:25 +0000 (17:08 -0500)
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

16 files changed:
CHANGES
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/config_global.c
res/res_pjsip/pjsip_options.c
res/res_pjsip_caller_id.c
res/res_pjsip_diversion.c
res/res_pjsip_endpoint_identifier_user.c
res/res_pjsip_messaging.c
res/res_pjsip_path.c
res/res_pjsip_pubsub.c
res/res_pjsip_refer.c
res/res_pjsip_registrar.c
res/res_pjsip_session.c

diff --git a/CHANGES b/CHANGES
index fed0d40d717d0e21f3bd3c6cf8d7fd79962fe766..0fac84e42c9ca24ff89d31143b109af33a4454b7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,23 @@
 ===
 ==============================================================================
 
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 13.8-cert3 to Asterisk 13.8-cert4 ----
+------------------------------------------------------------------------------
+
+res_pjsip
+------------------
+ * Added "ignore_uri_user_options" global configuration option for
+   compatibility with an ITSP that sends URI user field options.  When enabled
+   the user field is truncated at the first semicolon.
+   Example:
+   URI: "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+   The user field is "1235557890;phone-context=national"
+   Which is truncated to this: "1235557890"
+
+   Note: The caller-id and redirecting number strings obtained from incoming
+   SIP URI user fields are now always truncated at the first semicolon.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.8-cert2 to Asterisk 13.8-cert3 ----
 ------------------------------------------------------------------------------
index 0fa1a9d78f20412b13ac328ecb7098839fec2086..4b8f385c393be1f4c34f9564810511aab40a7b4e 100644 (file)
 ; with us. The extension added is the name of the endpoint.
 ;regcontext=sipregistrations
 
+;ignore_uri_user_options=no ; Enable/Disable ignoring SIP URI user field options.
+                    ; 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.
+                    ; Example:
+                    ; URI: "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+                    ; The user field is "1235557890;phone-context=national"
+                    ; Which becomes this: "1235557890"
+                    ;
+                    ; Note: The caller-id and redirecting number strings obtained
+                    ; from incoming SIP URI user fields are always truncated at the
+                    ; first semicolon.
+
 ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
 ;==========================ACL SECTION OPTIONS=========================
 ;[acl]
diff --git a/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py b/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py
new file mode 100644 (file)
index 0000000..2ce40a0
--- /dev/null
@@ -0,0 +1,32 @@
+"""ps_globals add ignore_uri_user_options
+
+Revision ID: a6ef36f1309
+Revises: 4e2493ef32e6
+Create Date: 2016-08-31 12:24:22.368956
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a6ef36f1309'
+down_revision = '4e2493ef32e6'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_globals', sa.Column('ignore_uri_user_options', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_globals', 'ignore_uri_user_options')
+
index 4475f8d4cefeb56b9e1b9c9a41798dd3c9d153d4..68f9544dcfcd75c1c27fb412a0749feb3852efa6 100644 (file)
@@ -2192,6 +2192,38 @@ int ast_sip_register_supplement(struct ast_sip_supplement *supplement);
  */
 void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement);
 
+/*!
+ * \brief Retrieve the global setting 'ignore_uri_user_options'.
+ * \since 13.12.0
+ *
+ * \retval non zero if ignore the user field options.
+ */
+unsigned int ast_sip_get_ignore_uri_user_options(void);
+
+/*!
+ * \brief Truncate the URI user field options string if enabled.
+ * \since 13.12.0
+ *
+ * \param str URI user field string to truncate if enabled
+ *
+ * \details
+ * 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 is:
+ * "1235557890;phone-context=national"
+ *
+ * When truncated the string will become:
+ * "1235557890"
+ */
+#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)                               \
+       do {                                                                                                            \
+               char *__semi = strchr((str), ';');                                              \
+               if (__semi && ast_sip_get_ignore_uri_user_options()) {  \
+                       *__semi = '\0';                                                                         \
+               }                                                                                                               \
+       } while (0)
+
 /*!
  * \brief Retrieve the system debug setting (yes|no|host).
  *
index 5fda9312d39fdf9b3204815715e039b5cd071c55..269bfe3a0082319aca0e3b70608a238feae20e3a 100644 (file)
                                         set to this value if there is no better option (such as CallerID) to be
                                         used.</synopsis>
                                </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>
index ca608dca6e81e7a2c290e17ffe4c5d5a9156e9dd..7a34876cf8913c5e9a2848219f524299cbb82f78 100644 (file)
@@ -37,6 +37,7 @@
 #define DEFAULT_FROM_USER "asterisk"
 #define DEFAULT_REGCONTEXT ""
 #define DEFAULT_DISABLE_MULTI_DOMAIN 0
+#define DEFAULT_IGNORE_URI_USER_OPTIONS 0
 
 static char default_useragent[256];
 
@@ -61,6 +62,8 @@ struct global_config {
        unsigned int max_initial_qualify_time;
        /*! Nonzero to disable multi domain support */
        unsigned int disable_multi_domain;
+       /*! Nonzero if URI user field options are ignored. */
+       unsigned int ignore_uri_user_options;
 };
 
 static void global_destructor(void *obj)
@@ -232,6 +235,21 @@ void ast_sip_get_default_from_user(char *from_user, size_t size)
        }
 }
 
+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
  * \brief Observer to set default global object if none exist.
@@ -351,6 +369,9 @@ int ast_sip_initialize_sorcery_global(void)
                OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, regcontext));
        ast_sorcery_object_field_register(sorcery, "global", "disable_multi_domain", "no",
                OPT_BOOL_T, 1, FLDSET(struct global_config, disable_multi_domain));
+       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;
index 80fa1c2dd8dff0e02768644b5208cfc3f0686faf..15158bcd789306e1e0f84acc4d22fac18aee54dd 100644 (file)
@@ -701,8 +701,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;
        }
 
@@ -719,13 +718,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);
index efa1b89a816977a90c23282802fe1206646d6118..4a5fc8dfcad85ad51ede64b773599adcf23ce0aa 100644 (file)
@@ -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)) {
index 41e6c821a793985cb13cc7567783c5855746e909..c32884253a6ec87329b4e6d18519aae855728895 100644 (file)
@@ -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)) {
index 10b08afb0acb88085508eb3ca958987411e013c9..4ad10bd17b286736e0cb4d78118af061aa494dd9 100644 (file)
@@ -33,6 +33,7 @@ static int get_endpoint_details(pjsip_rx_data *rdata, char *endpoint, size_t end
 {
        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;
        }
@@ -69,6 +70,12 @@ static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata)
                return NULL;
        }
 
+       /*
+        * We may want to be matched without any user options getting
+        * in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(endpoint_name);
+
        if (!ast_sip_get_disable_multi_domain()) {
                /* Attempt to find the endpoint given the name and domain provided */
                snprintf(id, sizeof(id), "%s@%s", endpoint_name, domain_name);
index 594c0fdac38c9bb70e76e82138d77115525ad21f..edc66bf43773b98642e4279c86f3d059bbf61ac2 100644 (file)
@@ -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;
 }
index 47d6a790661f441583194d890f784cde7d6cf4dd..20c9d436670ba656aa9f0c4047ee72b60ca106cd 100644 (file)
@@ -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;
index ae75ce7b8c751a1d6684ae5b51fd6137324008e5..c24ac0176ca4f46e06c3eab38a7a0093d2f696bf 100644 (file)
@@ -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",
@@ -2796,6 +2802,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) {
@@ -3009,6 +3021,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) {
                pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
index f3af65c3cf304f0474ef0dfe1fa975bbf27acfd2..f586718b27582dd310b093ccb176d0dc6a5feb8d 100644 (file)
@@ -809,6 +809,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);
index 29ee0771c0dfed0b20eab8f00ff5a9d03e26142b..099ccc03b856cd28614db24b74192a1ff18c14e4 100644 (file)
@@ -519,6 +519,7 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc
        struct ast_sip_aor *aor = NULL;
        pjsip_sip_uri *uri;
        char *domain_name;
+       char *username;
        char *configured_aors;
        char *aor_name;
        struct ast_str *id = NULL;
@@ -526,6 +527,14 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc
        uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
        domain_name = ast_alloca(uri->host.slen + 1);
        ast_copy_pj_str(domain_name, &uri->host, uri->host.slen + 1);
+       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);
 
        configured_aors = ast_strdupa(endpoint->aors);
 
@@ -537,16 +546,16 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc
                        continue;
                }
 
-               if (!pj_strcmp2(&uri->user, aor_name)) {
+               if (!strcmp(username, aor_name)) {
                        break;
                }
 
-               if (!id && !(id = ast_str_create(uri->user.slen + uri->host.slen + 2))) {
+               if (!id && !(id = ast_str_create(strlen(username) + uri->host.slen + 2))) {
                        aor_name = NULL;
                        break;
                }
 
-               ast_str_set(&id, 0, "%.*s@", (int)uri->user.slen, 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);
index a4108d566f9e3d8f9d3d99872e33c79ee85c013e..c04d019939a04d4d419be3d9659d5a2615b5452a 100644 (file)
@@ -1952,6 +1952,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");
@@ -2903,6 +2909,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];