/*! * \brief Check authentication using Digest scheme * * This function will check an incoming message against configured authentication * options. If \b any of the incoming Authorization headers result in successful * authentication, then authentication is considered successful. * * \see ast_sip_check_authentication */ static enum ast_sip_check_auth_result digest_check_auth(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata) { struct ast_sip_auth **auths; enum digest_verify_result *verify_res; enum ast_sip_check_auth_result res; int i; int failures = 0; size_t auth_size; RAII_VAR(struct ast_sip_endpoint *, artificial_endpoint, ast_sip_get_artificial_endpoint(), ao2_cleanup); auth_size = AST_VECTOR_SIZE(&endpoint->inbound_auths); auths = ast_alloca(auth_size * sizeof(*auths)); verify_res = ast_alloca(auth_size * sizeof(*verify_res)); if (!auths) { return AST_SIP_AUTHENTICATION_ERROR; } if (endpoint == artificial_endpoint) { auths[0] = ast_sip_get_artificial_auth(); } else if (ast_sip_retrieve_auths(&endpoint->inbound_auths, auths)) { res = AST_SIP_AUTHENTICATION_ERROR; goto cleanup; } for (i = 0; i < auth_size; ++i) { if (ast_strlen_zero(auths[i]->realm)) { ast_string_field_set(auths[i], realm, "asterisk"); } verify_res[i] = verify(auths[i], rdata, tdata->pool); if (verify_res[i] == AUTH_SUCCESS) { res = AST_SIP_AUTHENTICATION_SUCCESS; goto cleanup; } if (verify_res[i] == AUTH_FAIL) { failures++; } } for (i = 0; i < auth_size; ++i) { challenge(auths[i]->realm, tdata, rdata, verify_res[i] == AUTH_STALE); } if (failures == auth_size) { res = AST_SIP_AUTHENTICATION_FAILED; } else { res = AST_SIP_AUTHENTICATION_CHALLENGE; } cleanup: ast_sip_cleanup_auths(auths, auth_size); return res; }
static int set_outbound_authentication_credentials(pjsip_auth_clt_sess *auth_sess, const struct ast_sip_auth_vector *auth_vector, pjsip_rx_data *challenge) { size_t auth_size = AST_VECTOR_SIZE(auth_vector); struct ast_sip_auth **auths = ast_alloca(auth_size * sizeof(*auths)); pjsip_cred_info *auth_creds = ast_alloca(auth_size * sizeof(*auth_creds)); pjsip_www_authenticate_hdr *auth_hdr = NULL; int res = 0; int i; if (ast_sip_retrieve_auths(auth_vector, auths)) { res = -1; goto cleanup; } auth_hdr = get_auth_header(challenge); if (auth_hdr == NULL) { res = -1; ast_log(LOG_ERROR, "Unable to find authenticate header in challenge.\n"); goto cleanup; } for (i = 0; i < auth_size; ++i) { if (ast_strlen_zero(auths[i]->realm)) { auth_creds[i].realm = auth_hdr->challenge.common.realm; } else { pj_cstr(&auth_creds[i].realm, auths[i]->realm); } pj_cstr(&auth_creds[i].username, auths[i]->auth_user); pj_cstr(&auth_creds[i].scheme, "digest"); switch (auths[i]->type) { case AST_SIP_AUTH_TYPE_USER_PASS: pj_cstr(&auth_creds[i].data, auths[i]->auth_pass); auth_creds[i].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; break; case AST_SIP_AUTH_TYPE_MD5: pj_cstr(&auth_creds[i].data, auths[i]->md5_creds); auth_creds[i].data_type = PJSIP_CRED_DATA_DIGEST; break; case AST_SIP_AUTH_TYPE_ARTIFICIAL: ast_log(LOG_ERROR, "Trying to set artificial outbound auth credentials shouldn't happen.\n"); break; } } pjsip_auth_clt_set_credentials(auth_sess, auth_size, auth_creds); cleanup: ast_sip_cleanup_auths(auths, auth_size); return res; }