143 const char *auth_id,
const char *realm,
const pjsip_rx_data *rdata)
145 const char *src_name = rdata->pkt_info.src_name;
146 struct pjsip_authorization_hdr *auth_hdr =
147 (pjsip_authorization_hdr *) &rdata->msg_info.msg->hdr;
148 SCOPE_ENTER(3,
"%s:%s: realm: %s\n", auth_id, src_name, realm);
150 while ((auth_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg,
151 PJSIP_H_AUTHORIZATION, auth_hdr ? auth_hdr->next :
NULL))) {
152 if (pj_strcmp2(&auth_hdr->credential.common.realm, realm) == 0) {
154 auth_id, src_name, realm);
158 auth_id, src_name, realm);
179 const pjsip_auth_lookup_cred_param *param,
180 pjsip_cred_info *cred_info)
189 const char *src_name = param->rdata->pkt_info.src_name;
209 auth_name, src_name);
218 auth_name, src_name);
221 if (pj_strcmp2(¶m->realm, realm) != 0) {
227 auth_name, src_name, realm);
230 if (pj_strcmp2(¶m->acc_name, auth->
auth_user) != 0) {
242 "' not supported or auth doesn't contain appropriate credentials\n",
246 pj_strdup2(pool, &cred_info->realm, realm);
247 pj_strdup2(pool, &cred_info->username, auth->
auth_user);
259 pj_strdup2(pool, &cred_info->data, creds);
260#ifdef HAVE_PJSIP_AUTH_NEW_DIGESTS
261 if (cred_info->data_type == PJSIP_CRED_DATA_DIGEST) {
288 const pjsip_rx_data *rdata,
const char *realm)
325 time_t now = time(
NULL);
333 if (sscanf(timestamp,
"%30d", ×tamp_int) != 1) {
371 const struct ast_sip_auth *auth,
const pjsip_rx_data *rdata)
374 const char *src_name = rdata->pkt_info.src_name;
376 struct pjsip_authorization_hdr *auth_hdr =
377 (pjsip_authorization_hdr *) &rdata->msg_info.msg->hdr;
379 int authorization_found = 0;
382 endpoint_id, auth_id, src_name, realm);
384 while ((auth_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg,
385 PJSIP_H_AUTHORIZATION, auth_hdr ? auth_hdr->next :
NULL))) {
386 ast_copy_pj_str(nonce, &auth_hdr->credential.digest.nonce,
sizeof(nonce));
388 endpoint_id, auth_id, src_name, nonce,
391 authorization_found++;
393 && pj_strcmp2(&auth_hdr->credential.digest.realm, realm) == 0) {
400 if (!authorization_found) {
401 ast_trace(-1,
"%s:%s:%s: No Authorization header found\n",
402 endpoint_id, auth_id, src_name);
413static void setup_auth_srv(pj_pool_t *pool, pjsip_auth_srv *auth_server,
const char *realm)
415 pjsip_auth_srv_init_param *param = pj_pool_alloc(pool,
sizeof(*param));
416 pj_str_t *pj_realm = pj_pool_alloc(pool,
sizeof(*pj_realm));
418 pj_cstr(pj_realm, realm);
419 param->realm = pj_realm;
423 pjsip_auth_srv_init2(pool, auth_server, param);
436 pjsip_rx_data *rdata, pj_pool_t *pool)
440 const char *src_name = rdata->pkt_info.src_name;
443 pjsip_auth_srv auth_server;
447 endpoint_id, auth_id, src_name, realm);
458 endpoint_id, auth_id, src_name);
471 authed =
SCOPE_CALL_WITH_RESULT(-1, pj_status_t, pjsip_auth_srv_verify, &auth_server, rdata, &response_code);
473 if (authed == PJ_SUCCESS) {
482 pj_strerror(authed, err,
sizeof(err));
483 ast_trace(-1,
"%s:%s:%s: authed: %s\n", endpoint_id, auth_id, src_name, err);
493 endpoint_id, auth_id, src_name, realm,
508 pjsip_tx_data *tdata,
const pjsip_rx_data *rdata,
int is_stale,
513 pjsip_auth_srv auth_server;
516 time_t timestamp = time(
NULL);
520 const char *src_name = rdata->pkt_info.src_name;
522 endpoint_id, auth_id, src_name, realm, (
int)timestamp,
525 snprintf(time_buf,
sizeof(time_buf),
"%d", (
int) timestamp);
532 pj_cstr(&qop,
"auth");
533#ifdef HAVE_PJSIP_AUTH_NEW_DIGESTS
534 res = pjsip_auth_srv_challenge2(&auth_server, &qop, &pj_nonce,
537 res = pjsip_auth_srv_challenge(&auth_server, &qop, &pj_nonce,
538 NULL, is_stale ? PJ_TRUE : PJ_FALSE, tdata);
543 res == PJ_SUCCESS ?
"succeeded" :
"failed");
584 pjsip_rx_data *rdata, pjsip_tx_data *tdata)
595 char *src_name = rdata->pkt_info.src_name;
601 auths =
ast_alloca(auth_size *
sizeof(*auths));
602 verify_res =
ast_alloca(auth_size *
sizeof(*verify_res));
613 ast_trace(3,
"%s:%s: Using artificial endpoint for authentication\n",
614 endpoint_id, src_name);
622 ast_trace(3,
"%s:%s: Using endpoint for authentication\n",
623 endpoint_id, src_name);
624 memset(auths, 0, auth_size *
sizeof(*auths));
633 "%s:%s: Failed to retrieve some or all auth objects from endpoint\n",
634 endpoint_id, src_name);
647 for (idx = 0; idx < auth_size; ++idx) {
650 SCOPE_ENTER(4,
"%s:%s:%s: Auth %d of %d: Verifying\n",
651 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size);
654 switch((
int)verify_res[idx]) {
666 SCOPE_EXIT(
"%s:%s:%s: Auth %d of %d: Result: %s Failure count: %d\n",
667 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size,
682 endpoint_id, src_name,
685 ast_trace(-1,
"%s:%s: Done with verification. Failures: %d of %d\n",
686 endpoint_id, src_name, failures, (
int)auth_size);
694 for (idx = 0; idx < auth_size; ++idx) {
699 SCOPE_ENTER(4,
"%s:%s:%s: Auth %d of %d: Sending challenges\n",
700 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size);
705 pjsip_www_authenticate_hdr *auth_hdr =
NULL;
706 int already_sent_challenge = 0;
708 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size,
715 while ((auth_hdr = pjsip_msg_find_hdr(tdata->msg,
716 PJSIP_H_WWW_AUTHENTICATE, auth_hdr ? auth_hdr->next :
NULL))) {
717 if (pj_strcmp2(&auth_hdr->challenge.common.realm,
realm) == 0 &&
718 !pj_stricmp(&auth_hdr->challenge.digest.algorithm, &algorithm->
iana_name)) {
719 ast_trace(-1,
"%s:%s:%s: Auth %d of %d: Not sending duplicate challenge for realm: %s algorithm: "
721 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size,
723 already_sent_challenge = 1;
726 if (already_sent_challenge) {
735 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size,
738 SCOPE_EXIT(
"%s:%s:%s: Auth %d of %d: Done with challenges\n",
739 endpoint_id, auth_id, src_name, idx + 1, (
int)auth_size);
759 if (failures == auth_size) {
765 endpoint_id, src_name,
838 .
requires =
"res_pjsip",
static int copy(char *infile, char *outfile)
Utility function to copy a file.
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
#define ao2_alloc(data_size, destructor_fn)
#define SCOPE_EXIT_RTN(...)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_CALL_WITH_RESULT(level, __var, __funcname,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_EXIT_EXPR(__expr,...)
#define SCOPE_CALL(level, __funcname,...)
#define ast_trace(level,...)
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
static struct ast_sip_endpoint * artificial_endpoint
struct ast_sip_auth * ast_sip_get_artificial_auth(void)
Retrieves a reference to the artificial auth.
pjsip_auth_algorithm_type
const pjsip_auth_algorithm * ast_sip_auth_get_algorithm_by_iana_name(const pj_str_t *iana_name)
Get algorithm by IANA name.
const pjsip_auth_algorithm * ast_sip_auth_get_algorithm_by_type(pjsip_auth_algorithm_type algorithm_type)
Get algorithm by algorithm type.
struct ast_sip_endpoint * ast_sip_get_artificial_endpoint(void)
Retrieves a reference to the artificial endpoint.
void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
Clean up retrieved auth structures from memory.
int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out)
Retrieve relevant SIP auth structures from sorcery.
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)
Unregister a SIP authenticator.
void ast_sip_get_default_realm(char *realm, size_t size)
Retrieve the global default realm.
#define AST_SIP_AUTH_MAX_REALM_LENGTH
int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)
Register a SIP authenticator.
@ AST_SIP_AUTH_TYPE_ARTIFICIAL
const char * ast_sip_auth_get_creds(const struct ast_sip_auth *auth, const pjsip_auth_algorithm_type algorithm_type, int *cred_type)
Get the plain text or digest password from an auth object.
int ast_sip_auth_is_algorithm_available(const struct ast_sip_auth *auth, const struct pjsip_auth_algorithm_type_vector *algorithms, pjsip_auth_algorithm_type algorithm_type)
Checks an pjsip_auth_algorithm_type_vector to see if it contains an algorithm.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
ast_sip_check_auth_result
Possible returns from ast_sip_check_authentication.
@ AST_SIP_AUTHENTICATION_CHALLENGE
@ AST_SIP_AUTHENTICATION_ERROR
@ AST_SIP_AUTHENTICATION_SUCCESS
@ AST_SIP_AUTHENTICATION_FAILED
#define PJSTR_PRINTF_VAR(_v)
#define PJSTR_PRINTF_SPEC
static struct pjsip_authorization_hdr * get_authorization_hdr(const char *auth_id, const char *realm, const pjsip_rx_data *rdata)
static void setup_auth_srv(pj_pool_t *pool, pjsip_auth_srv *auth_server, const char *realm)
Common code for initializing a pjsip_auth_srv.
static struct ast_sorcery_observer global_observer
Observer which is used to update our default_realm when the global setting changes.
static int check_nonce(const char *candidate, const pjsip_rx_data *rdata, const struct ast_sip_auth *auth)
Ensure that a nonce on an incoming request is sane.
digest_verify_result
Result of digest verification.
static void global_loaded(const char *object_type)
AO2_GLOBAL_OBJ_STATIC(entity_id)
static enum digest_verify_result find_authorization(const char *endpoint_id, const struct ast_sip_auth *auth, const pjsip_rx_data *rdata)
static int verify(const char *endpoint_id, const struct ast_sip_auth *auth, pjsip_rx_data *rdata, pj_pool_t *pool)
Verify incoming credentials.
static struct ast_threadstorage auth_store
static int build_entity_id(void)
static const struct ast_sip_auth * get_auth(void)
Retrieve shallow copy authentication information from thread-local storage.
static int reload_module(void)
static int store_auth(const struct ast_sip_auth *auth)
Store shallow copy authentication information in thread-local storage.
static void challenge(const char *endpoint_id, struct ast_sip_auth *auth, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale, const pjsip_auth_algorithm *algorithm)
Send a WWW-Authenticate challenge.
static char default_realm[AST_SIP_AUTH_MAX_REALM_LENGTH+1]
static char * check_auth_result_str[]
static int remove_auth(void)
Remove shallow copy authentication information from thread-local storage.
static enum ast_sip_check_auth_result digest_check_auth(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Check authentication using Digest scheme.
static int load_module(void)
static char * verify_result_str[]
static int unload_module(void)
static void auth_store_cleanup(void *data)
static int digest_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Determine if authentication is required.
static struct ast_sip_authenticator digest_authenticator
static pj_status_t digest_lookup(pj_pool_t *pool, const pjsip_auth_lookup_cred_param *param, pjsip_cred_info *cred_info)
Lookup callback for authentication verification.
static int build_nonce(struct ast_str **nonce, const char *timestamp, const pjsip_rx_data *rdata, const char *realm)
Calculate a nonce.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
#define ast_str_alloca(init_len)
const ast_string_field realm
unsigned int nonce_lifetime
const ast_string_field auth_user
struct pjsip_auth_algorithm_type_vector supported_algorithms_uas
enum ast_sip_auth_type type
An interchangeable way of handling digest authentication for SIP.
int(* requires_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Check if a request requires authentication See ast_sip_requires_authentication for more details.
An entity with which Asterisk communicates.
struct ast_sip_auth_vector inbound_auths
Interface for a sorcery object type observer.
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
Support for dynamic strings.
pjsip_auth_algorithm_type algorithm_type
#define ast_test_suite_event_notify(s, f,...)
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.