summaryrefslogtreecommitdiff
path: root/res/res_pjsip_registrar.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip_registrar.c')
-rw-r--r--res/res_pjsip_registrar.c129
1 files changed, 98 insertions, 31 deletions
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index 8edd6ee43..ae8440aab 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -657,6 +657,65 @@ static int rx_task(void *data)
return res;
}
+static int match_aor(const char *aor_name, const char *id)
+{
+ if (ast_strlen_zero(aor_name)) {
+ return 0;
+ }
+
+ if (!strcmp(aor_name, id)) {
+ ast_debug(3, "Matched id '%s' to aor '%s'\n", id, aor_name);
+ return 1;
+ }
+
+ return 0;
+}
+
+static char *find_aor_name(const char *username, const char *domain, const char *aors)
+{
+ char *configured_aors;
+ char *aor_name;
+ char *id_domain;
+ struct ast_sip_domain_alias *alias;
+
+ id_domain = ast_alloca(strlen(username) + strlen(domain) + 2);
+ sprintf(id_domain, "%s@%s", username, domain);
+
+ /* Look for exact match on username@domain */
+ configured_aors = ast_strdupa(aors);
+ while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
+ if (match_aor(aor_name, id_domain)) {
+ return ast_strdup(aor_name);
+ }
+ }
+
+ /* If there's a domain alias, look for exact match on username@domain_alias */
+ alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain);
+ if (alias) {
+ char *id_domain_alias = ast_alloca(strlen(username) + strlen(alias->domain) + 2);
+
+ sprintf(id_domain, "%s@%s", username, alias->domain);
+ ao2_cleanup(alias);
+
+ configured_aors = ast_strdupa(aors);
+ while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
+ if (match_aor(aor_name, id_domain_alias)) {
+ return ast_strdup(aor_name);
+ }
+ }
+ }
+
+ /* Look for exact match on username only */
+ configured_aors = ast_strdupa(aors);
+ while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
+ if (match_aor(aor_name, username)) {
+ return ast_strdup(aor_name);
+ }
+ }
+
+ return NULL;
+}
+
static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
{
RAII_VAR(struct serializer *, ser, NULL, ao2_cleanup);
@@ -665,10 +724,10 @@ static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
RAII_VAR(struct ast_sip_endpoint *, endpoint,
ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
- pjsip_sip_uri *uri;
- char *domain_name;
- char *configured_aors, *aor_name;
- RAII_VAR(struct ast_str *, id, NULL, ast_free);
+ char *domain_name = NULL;
+ char *username = NULL;
+ RAII_VAR(char *, aor_name, NULL, ast_free);
+ int i;
if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) || !endpoint) {
return PJ_FALSE;
@@ -689,38 +748,46 @@ static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
return PJ_TRUE;
}
- 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);
+ for (i = 0; i < AST_VECTOR_SIZE(&endpoint->ident_method_order); i++) {
+ pjsip_sip_uri *uri;
+ pjsip_authorization_hdr *header = NULL;
- configured_aors = ast_strdupa(endpoint->aors);
+ switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) {
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME :
+ uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
- /* Iterate the configured AORs to see if the user or the user+domain match */
- while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
- struct ast_sip_domain_alias *alias = NULL;
+ 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);
- if (ast_strlen_zero(aor_name)) {
- continue;
- }
-
- if (!pj_strcmp2(&uri->user, aor_name)) {
+ 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);
+ }
break;
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME :
+ while ((header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION,
+ header ? header->next : NULL))) {
+ if (header && !pj_stricmp2(&header->scheme, "digest")) {
+ username = ast_alloca(header->credential.digest.username.slen + 1);
+ ast_copy_pj_str(username, &header->credential.digest.username, header->credential.digest.username.slen + 1);
+ domain_name = ast_alloca(header->credential.digest.realm.slen + 1);
+ ast_copy_pj_str(domain_name, &header->credential.digest.realm, header->credential.digest.realm.slen + 1);
+
+ aor_name = find_aor_name(username, domain_name, endpoint->aors);
+ if (aor_name) {
+ ast_debug(3, "Matched aor '%s' by Authentication username\n", aor_name);
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ continue;
}
- if (!id && !(id = ast_str_create(uri->user.slen + uri->host.slen + 2))) {
- return PJ_TRUE;
- }
-
- ast_str_set(&id, 0, "%.*s@", (int)uri->user.slen, uri->user.ptr);
- 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);
- } else {
- ast_str_append(&id, 0, "%s", domain_name);
- }
-
- if (!strcmp(aor_name, ast_str_buffer(id))) {
- ast_free(id);
+ if (aor_name) {
break;
}
}
@@ -729,7 +796,7 @@ static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
/* The provided AOR name was not found (be it within the configuration or sorcery itself) */
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
ast_sip_report_req_no_support(endpoint, rdata, "registrar_requested_aor_not_found");
- ast_log(LOG_WARNING, "AOR '%.*s' not found for endpoint '%s'\n", (int)uri->user.slen, uri->user.ptr, ast_sorcery_object_get_id(endpoint));
+ ast_log(LOG_WARNING, "AOR '%s' not found for endpoint '%s'\n", username, ast_sorcery_object_get_id(endpoint));
return PJ_TRUE;
}