29 #include "asterisk/res_pjsip.h"
32 static int get_from_header(pjsip_rx_data *rdata,
char *username,
size_t username_size,
char *domain,
size_t domain_size)
34 pjsip_uri *from = rdata->msg_info.from->uri;
36 if (!ast_sip_is_uri_sip_sips(from)) {
40 ast_copy_pj_str(username, ast_sip_pjsip_uri_get_username(from), username_size);
41 ast_copy_pj_str(domain, ast_sip_pjsip_uri_get_hostname(from), domain_size);
46 static pjsip_authorization_hdr *get_auth_header(pjsip_rx_data *rdata,
char *username,
47 size_t username_size,
char *realm,
size_t realm_size, pjsip_authorization_hdr *start)
49 pjsip_authorization_hdr *
header;
51 header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, start);
53 if (!header || pj_stricmp2(&header->scheme,
"digest")) {
57 ast_copy_pj_str(username, &header->credential.digest.username, username_size);
58 ast_copy_pj_str(realm, &header->credential.digest.realm, realm_size);
63 static int find_transport_state_in_use(
void *obj,
void *arg,
int flags)
66 pjsip_rx_data *rdata = arg;
68 if (transport_state->
transport == rdata->tp_info.transport
70 && !pj_strcmp(&transport_state->
factory->addr_name.host, &rdata->tp_info.transport->local_name.host)
71 && transport_state->
factory->addr_name.port == rdata->tp_info.transport->local_name.port)) {
78 #define DOMAIN_NAME_LEN 255
79 #define USERNAME_LEN 255
81 static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata,
char *endpoint_name,
86 if (!ast_sip_get_disable_multi_domain()) {
91 char id[DOMAIN_NAME_LEN + USERNAME_LEN +
sizeof(
"@")];
94 snprintf(
id,
sizeof(
id),
"%s@%s", endpoint_name, domain_name);
104 snprintf(
id,
sizeof(
id),
"%s@%s", endpoint_name, alias->
domain);
113 if ((transport_states = ast_sip_get_transport_states())
114 && (transport_state =
ao2_callback(transport_states, 0, find_transport_state_in_use, rdata))
116 && !ast_strlen_zero(transport->
domain)) {
117 snprintf(
id,
sizeof(
id),
"%s@%s", endpoint_name, transport->
domain);
120 ao2_cleanup(transport);
121 ao2_cleanup(transport_state);
122 ao2_cleanup(transport_states);
134 char username[USERNAME_LEN + 1];
135 char domain[DOMAIN_NAME_LEN + 1];
138 if (get_from_header(rdata, username,
sizeof(username), domain,
sizeof(domain))) {
146 AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
148 ast_debug(3,
"Attempting identify by From username '%s' domain '%s'\n", username, domain);
150 endpoint = find_endpoint(rdata, username, domain);
152 ast_debug(3,
"Endpoint not found for From username '%s' domain '%s'\n", username, domain);
155 if (!(endpoint->
ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME)) {
156 ast_debug(3,
"Endpoint found for '%s' but 'username' method not supported'\n", username);
157 ao2_cleanup(endpoint);
160 ast_debug(3,
"Identified by From username '%s' domain '%s'\n", username, domain);
165 static struct ast_sip_endpoint *auth_username_identify(pjsip_rx_data *rdata)
167 char username[USERNAME_LEN + 1], realm[AST_SIP_AUTH_MAX_REALM_LENGTH + 1];
169 pjsip_authorization_hdr *auth_header = NULL;
171 while ((auth_header = get_auth_header(rdata, username,
sizeof(username), realm,
sizeof(realm),
172 auth_header ? auth_header->next : NULL))) {
173 ast_debug(3,
"Attempting identify by Authorization username '%s' realm '%s'\n", username,
176 endpoint = find_endpoint(rdata, username, realm);
178 ast_debug(3,
"Endpoint not found for Authentication username '%s' realm '%s'\n",
180 ao2_cleanup(endpoint);
183 if (!(endpoint->
ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME)) {
184 ast_debug(3,
"Endpoint found for '%s' but 'auth_username' method not supported'\n",
186 ao2_cleanup(endpoint);
189 ast_debug(3,
"Identified by Authorization username '%s' realm '%s'\n", username, realm);
207 static int load_module(
void)
209 ast_sip_register_endpoint_identifier_with_name(&username_identifier,
"username");
210 ast_sip_register_endpoint_identifier_with_name(&auth_username_identifier,
"auth_username");
214 static int unload_module(
void)
216 ast_sip_unregister_endpoint_identifier(&auth_username_identifier);
217 ast_sip_unregister_endpoint_identifier(&username_identifier);
221 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP username endpoint identifier",
222 .support_level = AST_MODULE_SUPPORT_CORE,
224 .unload = unload_module,
226 .requires =
"res_pjsip",
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
struct ast_sip_endpoint *(* identify_endpoint)(pjsip_rx_data *rdata)
Callback used to identify the source of a message. See ast_sip_identify_endpoint for more details...
enum ast_sip_endpoint_identifier_type ident_method
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Structure for SIP transport information.
struct pjsip_transport * transport
Transport itself.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ast_debug(level,...)
Log a DEBUG message.
An entity with which Asterisk communicates.
struct pjsip_tpfactory * factory
Transport factory.
const ast_string_field domain
An entity responsible for identifying the source of a SIP message.
const ast_string_field domain
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.