diff options
Diffstat (limited to 'res/res_pjsip_registrar.c')
-rw-r--r-- | res/res_pjsip_registrar.c | 129 |
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; } |