52    if (
challenge->msg_info.msg->line.status.code == PJSIP_SC_UNAUTHORIZED) {
 
   53        return PJSIP_H_WWW_AUTHENTICATE;
 
   54    } 
else if (
challenge->msg_info.msg->line.status.code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) {
 
   55        return PJSIP_H_PROXY_AUTHENTICATE;
 
   58                "Status code %d was received when it should have been 401 or 407.\n",
 
   59                challenge->msg_info.msg->line.status.code);
 
 
   99    pjsip_www_authenticate_hdr *auth_hdr, 
size_t auth_object_count,
 
  103    int exact_match_index = -1;
 
  104    int wildcard_match_index = -1;
 
  109    pjsip_cred_info auth_cred;
 
  110    const char *cred_data;
 
  117    if (!challenge_algorithm) {
 
  130        if (pj_stricmp(&auth_cred.realm, &auth_hdr->challenge.common.realm) == 0) {
 
  132                "because we already have credentials for it\n", 
id, src_name,
 
  156    ast_trace(-1, 
"%s:%s: Searching %zu auths to find matching ones for header with realm " 
  158        id, src_name, auth_object_count,
 
  162    for (i = 0; i < auth_object_count; ++i) {
 
  165        SCOPE_ENTER(5, 
"%s:%s: Checking auth '%s' with realm '%s'\n",
 
  166            id, src_name, auth_id, auth->
realm);
 
  175            SCOPE_EXIT_EXPR(
continue, 
"%s:%s: Skipping auth '%s' with realm '%s' because it doesn't support " 
  177                auth_id, auth->
realm,
 
  188        if (pj_stricmp2(&auth_hdr->challenge.digest.realm, auth->
realm) == 0) {
 
  189            exact_match_index = i;
 
  194            SCOPE_EXIT_EXPR(
break, 
"%s:%s: Found matching auth '%s' with realm '%s'\n",
 
  195                id, src_name, auth_id, auth->
realm);
 
  206        if (wildcard_match_index < 0
 
  209                id, src_name, auth_id,
 
  211            wildcard_match_index = i;
 
  213        SCOPE_EXIT(
"%s:%s: Done checking auth '%s' with realm '%s'. " 
  214            "Found exact? %s  Found wildcard? %s\n", 
id, src_name,
 
  215            auth_id, auth->
realm, exact_match_index >= 0 ? 
"yes" : 
"no",
 
  216                wildcard_match_index >= 0 ? 
"yes" : 
"no");
 
  219    if (exact_match_index < 0 && wildcard_match_index < 0) {
 
  228    if (exact_match_index >= 0) {
 
  232        found_auth = 
AST_VECTOR_GET(auth_objects_vector, exact_match_index);
 
  240        found_auth = 
AST_VECTOR_GET(auth_objects_vector, wildcard_match_index);
 
  251    memset(&auth_cred, 0, 
sizeof(auth_cred));
 
  256    auth_cred.realm = auth_hdr->challenge.common.realm;
 
  257    pj_cstr(&auth_cred.username, found_auth->
auth_user);
 
  258    pj_cstr(&auth_cred.scheme, 
"digest");
 
  265        found_auth, challenge_algorithm->
algorithm_type, &auth_cred.data_type);
 
  275    pj_cstr(&auth_cred.data, cred_data);
 
  276#ifdef HAVE_PJSIP_AUTH_NEW_DIGESTS 
  277    if (auth_cred.data_type == PJSIP_CRED_DATA_DIGEST) {
 
  297        res == 0 ? 
"Added" : 
"Failed to add",
 
 
  343    size_t auth_object_count;
 
  344    pjsip_www_authenticate_hdr *auth_hdr = 
NULL;
 
  345    pj_status_t res = PJ_SUCCESS;
 
  346    pjsip_hdr_e search_type;
 
  347    size_t cred_count = 0;
 
  348    pjsip_cred_info *creds_array;
 
  350    const char *src_name = 
challenge->pkt_info.src_name;
 
  366    if (search_type == PJSIP_H_OTHER) {
 
  372        SCOPE_EXIT_RTN_VALUE(PJ_ENOTSUP, 
"%s:%s: Status code %d was received when it should have been 401 or 407.\n",
 
  373        id, src_name, 
challenge->msg_info.msg->line.status.code);
 
  377    if (auth_object_count == 0) {
 
  405    while ((auth_hdr = pjsip_msg_find_hdr(
challenge->msg_info.msg,
 
  406        search_type, auth_hdr ? auth_hdr->next : 
NULL))) {
 
  409            auth_objects_vector, &auth_creds, realms);
 
  422        res = PJSIP_ENOCREDENTIAL;
 
  444    res = pjsip_auth_clt_set_credentials(auth_sess, cred_count, creds_array);
 
  449    if (res != PJ_SUCCESS) {
 
  451        pj_strerror(res, pj_err, PJ_ERR_MSG_SIZE);
 
  454        id, src_name, cred_count, 
S_OR(pj_err, 
"success"));
 
 
  471    pjsip_rx_data *
challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
 
  473    pjsip_auth_clt_sess auth_sess;
 
  474    pjsip_cseq_hdr *cseq;
 
  477    size_t auth_object_count = 0;
 
  478    pjsip_dialog *dlg = pjsip_rdata_get_dlg(
challenge);
 
  486    char *
id = endpoint_id ?: 
"noendpoint";
 
  487    char *src_name = 
challenge->pkt_info.src_name;
 
  501    memset(&auth_sess, 0, 
sizeof(auth_sess));
 
  526    ast_trace(-1, 
"%s:%s: Retrieving %d auth objects\n", 
id, src_name,
 
  530    if (auth_object_count == 0) {
 
  538        ast_trace(-1, 
"%s:%s: No auth objects found\n", 
id, src_name);
 
  541    ast_trace(-1, 
"%s:%s: Retrieved %d auth objects\n", 
id, src_name,
 
  542        (
int)auth_object_count);
 
  545        old_request->pool, 0);
 
  546    if (
status != PJ_SUCCESS) {
 
  548        pj_strerror(
status, pj_err, PJ_ERR_MSG_SIZE);
 
  549        ast_log(
LOG_ERROR, 
"%s:%s: Failed to initialize client authentication session: %s\n",
 
  550            id, src_name, pj_err);
 
  569    if (
status != PJ_SUCCESS && 
status != PJSIP_ENOCREDENTIAL) {
 
  576    case PJSIP_ENOCREDENTIAL:
 
  578            "%s:%s: No auth objects matching realm/algorithm(s) '%s' from challenge found.\n",
 
  583        pj_strerror(
status, pj_err, PJ_ERR_MSG_SIZE);
 
  585            id, src_name, pj_err);
 
  597        &auth_sess, 
challenge, old_request, new_request);
 
  598    if (
status != PJ_SUCCESS) {
 
  610        cseq = pjsip_msg_find_hdr((*new_request)->msg, PJSIP_H_CSEQ, 
NULL);
 
  614        ast_trace(-1, 
"%s:%s: Created new request with auth\n", 
id, src_name);
 
  616    case PJSIP_ENOCREDENTIAL:
 
  622            "%s:%s: No auth objects matching realm(s) '%s' from challenge found.\n",
 
  625    case PJSIP_EAUTHSTALECOUNT:
 
  626        pj_strerror(
status, pj_err, PJ_ERR_MSG_SIZE);
 
  628            "%s:%s: Unable to create request with auth: %s\n",
 
  629            id, src_name, pj_err);
 
  631    case PJSIP_EFAILEDCREDENTIAL:
 
  632        pj_strerror(
status, pj_err, PJ_ERR_MSG_SIZE);
 
  633        ast_log(
LOG_WARNING, 
"%s:%s: Authentication credentials not accepted by server. %s\n",
 
  634            id, src_name, pj_err);
 
  637        pj_strerror(
status, pj_err, PJ_ERR_MSG_SIZE);
 
  639            id, src_name, pj_err);
 
  645#if defined(HAVE_PJSIP_AUTH_CLT_DEINIT) 
  647    if (auth_sess.endpt) {
 
  648        pjsip_auth_clt_deinit(&auth_sess);
 
  657        res == 0 ? 
"success" : 
"failure");
 
 
  683    .
requires = 
"res_pjsip",
 
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 SCOPE_EXIT_RTN(...)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_CALL_WITH_RESULT(level, __var, __funcname,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_EXIT_EXPR(__expr,...)
#define ast_trace(level,...)
struct ast_sip_endpoint * ast_sip_dialog_get_endpoint(pjsip_dialog *dlg)
Get the endpoint associated with this dialog.
Support for logging to various files, console and syslog Configuration in file logger....
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.
const pjsip_auth_algorithm * ast_sip_auth_get_algorithm_by_iana_name(const pj_str_t *iana_name)
Get algorithm by IANA name.
void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Unregister an outbound SIP authenticator.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
pj_bool_t ast_sip_auth_is_algorithm_supported(pjsip_auth_algorithm_type algorithm_type)
Is algorithm supported by OpenSSL and pjproject?
int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticator *outbound_auth)
Register an outbound SIP authenticator.
#define ast_sip_cleanup_auth_objects_vector(auth_objects)
Clean up retrieved auth objects in vector.
int ast_sip_retrieve_auths_vector(const struct ast_sip_auth_vector *auth_ids, struct ast_sip_auth_objects_vector *auth_objects)
Retrieve relevant SIP auth structures from sorcery as a vector.
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.
#define PJSTR_PRINTF_VAR(_v)
#define PJSTR_PRINTF_SPEC
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 void get_creds_for_header(const char *id, const char *src_name, pjsip_www_authenticate_hdr *auth_hdr, size_t auth_object_count, const struct ast_sip_auth_objects_vector *auth_objects_vector, struct cred_info_vector *auth_creds, struct ast_str **realms)
Get credentials (if any) from auth objects for a WWW/Proxy-Authenticate header.
static struct ast_sip_outbound_authenticator digest_authenticator
static int digest_create_request_with_auth(const struct ast_sip_auth_vector *auth_ids_vector, pjsip_rx_data *challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
static pj_status_t set_auth_creds(const char *id, pjsip_auth_clt_sess *auth_sess, const struct ast_sip_auth_objects_vector *auth_objects_vector, pjsip_rx_data *challenge, struct ast_str **realms)
static int load_module(void)
static int unload_module(void)
static pjsip_hdr_e get_auth_search_type(pjsip_rx_data *challenge)
static const pjsip_auth_algorithm * get_supported_algorithm(pjsip_www_authenticate_hdr *auth_hdr)
static void cleanup(void)
Clean up any old apps that we don't need any more.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
String manipulation functions.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
struct pjsip_auth_algorithm_type_vector supported_algorithms_uac
const ast_string_field realm
const ast_string_field auth_user
An entity with which Asterisk communicates.
an interchangeable way of responding to authentication challenges
int(* create_request_with_auth)(const struct ast_sip_auth_vector *auths, struct pjsip_rx_data *challenge, struct pjsip_tx_data *old_request, struct pjsip_tx_data **new_request)
Create a new request with authentication credentials.
Support for dynamic strings.
pjsip_auth_algorithm_type algorithm_type
Vector container support.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR(name, type)
Define a vector structure.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.