48 if (challenge->msg_info.msg->line.status.code == PJSIP_SC_UNAUTHORIZED) {
49 return PJSIP_H_WWW_AUTHENTICATE;
50 }
else if (challenge->msg_info.msg->line.status.code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) {
51 return PJSIP_H_PROXY_AUTHENTICATE;
54 "Status code %d was received when it should have been 401 or 407.\n",
55 challenge->msg_info.msg->line.status.code);
73 if (pj_strlen(&auth_hdr->challenge.digest.algorithm) == 0) {
128 const struct ast_sip_auth_objects_vector *auth_objects_vector, pjsip_rx_data *
challenge,
132 size_t auth_object_count;
133 pjsip_www_authenticate_hdr *auth_hdr =
NULL;
134 pj_status_t res = PJ_SUCCESS;
135 pjsip_hdr_e search_type;
137 pjsip_cred_info *creds_array;
150 AST_VECTOR(cred_info, pjsip_cred_info) auth_creds;
153 if (search_type == PJSIP_H_OTHER) {
163 if (auth_object_count == 0) {
187 while ((auth_hdr = pjsip_msg_find_hdr(challenge->msg_info.msg,
188 search_type, auth_hdr ? auth_hdr->next :
NULL))) {
189 int exact_match_index = -1;
190 int wildcard_match_index = -1;
192 pjsip_cred_info auth_cred;
195 memset(&auth_cred, 0,
sizeof(auth_cred));
210 ast_debug(3,
"Skipping header with realm '%.*s' and unsupported '%.*s' algorithm \n",
211 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr,
212 (
int)auth_hdr->challenge.digest.algorithm.slen, auth_hdr->challenge.digest.algorithm.ptr);
224 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr);
227 ast_debug(3,
"Searching auths to find matching ones for header with realm '%.*s' and algorithm '%.*s'\n",
228 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr,
229 (
int)auth_hdr->challenge.digest.algorithm.slen, auth_hdr->challenge.digest.algorithm.ptr);
240 for (i = 0; i < auth_object_count; ++i) {
250 if (pj_stricmp2(&auth_hdr->challenge.digest.realm, auth->
realm) == 0) {
253 exact_match_index = i;
269 if (wildcard_match_index < 0
272 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr);
273 wildcard_match_index = i;
277 if (exact_match_index < 0 && wildcard_match_index < 0) {
282 ast_debug(3,
"No auth matching realm or no wildcard found for realm '%.*s'\n",
283 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr);
287 if (exact_match_index >= 0) {
291 match_index = exact_match_index;
294 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr);
299 match_index = wildcard_match_index;
302 (
int)auth_hdr->challenge.digest.realm.slen, auth_hdr->challenge.digest.realm.ptr);
309 auth_cred.realm = auth_hdr->challenge.common.realm;
310 pj_cstr(&auth_cred.username, auth->
auth_user);
311 pj_cstr(&auth_cred.scheme,
"digest");
312 switch (auth->
type) {
314 pj_cstr(&auth_cred.data, auth->
auth_pass);
315 auth_cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
318 pj_cstr(&auth_cred.data, auth->
md5_creds);
319 auth_cred.data_type = PJSIP_CRED_DATA_DIGEST;
326 "Trying to set artificial outbound auth credentials shouldn't happen.\n");
344 if (res != PJ_SUCCESS) {
362 res = PJSIP_ENOCREDENTIAL;
384 res = pjsip_auth_clt_set_credentials(auth_sess, cred_count, creds_array);
386 if (res == PJ_SUCCESS) {
387 ast_debug(3,
"Set %"PRIu64
" credentials in auth session\n", cred_count);
389 ast_log(
LOG_ERROR,
"Failed to set %"PRIu64
" credentials in auth session\n", cred_count);
411 pjsip_rx_data *
challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
413 pjsip_auth_clt_sess auth_sess;
414 pjsip_cseq_hdr *cseq;
416 struct ast_sip_auth_objects_vector auth_objects_vector;
417 size_t auth_object_count = 0;
430 memset(&auth_sess, 0,
sizeof(auth_sess));
432 dlg = pjsip_rdata_get_dlg(challenge);
438 id_type =
"Endpoint";
450 ast_log(
LOG_ERROR,
"%s: '%s': There were no auth ids available\n", id_type,
id);
455 ast_log(
LOG_ERROR,
"%s: '%s': Couldn't initialize auth object vector\n", id_type,
id);
470 if (auth_object_count == 0) {
482 old_request->pool, 0) != PJ_SUCCESS) {
483 ast_log(
LOG_ERROR,
"%s: '%s': Failed to initialize client authentication session\n",
506 case PJSIP_ENOCREDENTIAL:
508 "%s: '%s': No auth objects matching realm(s) '%s' from challenge found.\n", id_type,
id,
513 ast_log(
LOG_WARNING,
"%s: '%s': Failed to set authentication credentials\n", id_type,
id);
524 status = pjsip_auth_clt_reinit_req(&auth_sess, challenge, old_request, new_request);
534 cseq = pjsip_msg_find_hdr((*new_request)->msg, PJSIP_H_CSEQ,
NULL);
539 case PJSIP_ENOCREDENTIAL:
545 "%s: '%s': No auth objects matching realm(s) '%s' from challenge found.\n", id_type,
id,
548 case PJSIP_EAUTHSTALECOUNT:
550 "%s: '%s': Unable to create request with auth. Number of stale retries exceeded.\n",
553 case PJSIP_EFAILEDCREDENTIAL:
554 ast_log(
LOG_WARNING,
"%s: '%s': Authentication credentials not accepted by server.\n",
558 ast_log(
LOG_WARNING,
"%s: '%s': Unable to create request with auth. Unknown failure.\n",
565 #if defined(HAVE_PJSIP_AUTH_CLT_DEINIT) 567 pjsip_auth_clt_deinit(&auth_sess);
600 .requires =
"res_pjsip",
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_SOCKADDR_BUFLEN
int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticator *outbound_auth)
Register an outbound SIP authenticator.
Asterisk main include file. File version handling, generic pbx functions.
String manipulation functions.
const ast_string_field md5_creds
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Unregister an outbound SIP authenticator.
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.
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)
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
#define ast_strlen_zero(foo)
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
struct ast_sip_endpoint * ast_sip_dialog_get_endpoint(pjsip_dialog *dlg)
Get the endpoint associated with this dialog.
static int unload_module(void)
#define ast_strdupa(s)
duplicate a string in memory from the stack
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
astobj2 callback for adding digest challenges to responses
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
#define AST_VECTOR(name, type)
Define a vector structure.
static int load_module(void)
An entity with which Asterisk communicates.
static pjsip_hdr_e get_auth_search_type(pjsip_rx_data *challenge)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
const ast_string_field realm
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
static pj_status_t set_outbound_authentication_credentials(pjsip_auth_clt_sess *auth_sess, const struct ast_sip_auth_objects_vector *auth_objects_vector, pjsip_rx_data *challenge, struct ast_str **realms)
const ast_string_field auth_pass
enum ast_sip_auth_type type
Module has failed to load, may be in an inconsistent state.
Vector container support.
static void * cleanup(void *unused)
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static struct ast_sip_outbound_authenticator digest_authenticator
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
pj_str_t supported_digest_algorithms[]
static int is_digest_algorithm_supported(pjsip_www_authenticate_hdr *auth_hdr)
int ast_sip_retrieve_auths_vector(const struct ast_sip_auth_vector *auth_ids, struct ast_sip_auth_objects_vector *auth_objects)
#define ast_sip_cleanup_auth_objects_vector(auth_objects)
Clean up retrieved auth objects in vector.
an interchangeable way of responding to authentication challenges
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
const ast_string_field auth_user
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.