/* Initialize outgoing request. */ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, pjsip_tx_data *tdata ) { const pjsip_method *method; pjsip_cached_auth *auth; pjsip_hdr added; PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL); PJ_ASSERT_RETURN(sess->pool, PJSIP_ENOTINITIALIZED); PJ_ASSERT_RETURN(tdata->msg->type==PJSIP_REQUEST_MSG, PJSIP_ENOTREQUESTMSG); /* Init list */ pj_list_init(&added); /* Get the method. */ method = &tdata->msg->line.req.method; auth = sess->cached_auth.next; while (auth != &sess->cached_auth) { /* Reset stale counter */ auth->stale_cnt = 0; if (auth->qop_value == PJSIP_AUTH_QOP_NONE) { # if defined(PJSIP_AUTH_HEADER_CACHING) && \ PJSIP_AUTH_HEADER_CACHING!=0 { pjsip_cached_auth_hdr *entry = auth->cached_hdr.next; while (entry != &auth->cached_hdr) { if (pjsip_method_cmp(&entry->method, method)==0) { pjsip_authorization_hdr *hauth; hauth = pjsip_hdr_shallow_clone(tdata->pool, entry->hdr); //pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); pj_list_push_back(&added, hauth); break; } entry = entry->next; } # if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ PJSIP_AUTH_AUTO_SEND_NEXT!=0 { if (entry == &auth->cached_hdr) new_auth_for_req( tdata, sess, auth, NULL); } # endif } # elif defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ PJSIP_AUTH_AUTO_SEND_NEXT!=0 { new_auth_for_req( tdata, sess, auth, NULL); } # endif } # if defined(PJSIP_AUTH_QOP_SUPPORT) && \ defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ (PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT) else if (auth->qop_value == PJSIP_AUTH_QOP_AUTH) { /* For qop="auth", we have to re-create the authorization header. */ const pjsip_cred_info *cred; pjsip_authorization_hdr *hauth; pj_status_t status; cred = auth_find_cred(sess, &auth->realm, &auth->last_chal->scheme); if (!cred) { auth = auth->next; continue; } status = auth_respond( tdata->pool, auth->last_chal, tdata->msg->line.req.uri, cred, &tdata->msg->line.req.method, sess->pool, auth, &hauth); if (status != PJ_SUCCESS) return status; //pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); pj_list_push_back(&added, hauth); } # endif /* PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT */ auth = auth->next; } if (sess->pref.initial_auth == PJ_FALSE) { pjsip_hdr *h; /* Don't want to send initial empty Authorization header, so * just send whatever available in the list (maybe empty). */ h = added.next; while (h != &added) { pjsip_hdr *next = h->next; pjsip_msg_add_hdr(tdata->msg, h); h = next; } } else { /* For each realm, add either the cached authorization header * or add an empty authorization header. */ unsigned i; char *uri_str; int len; uri_str = (char*)pj_pool_alloc(tdata->pool, PJSIP_MAX_URL_SIZE); len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, tdata->msg->line.req.uri, uri_str, PJSIP_MAX_URL_SIZE); if (len < 1 || len >= PJSIP_MAX_URL_SIZE) return PJSIP_EURITOOLONG; for (i=0; i<sess->cred_cnt; ++i) { pjsip_cred_info *c = &sess->cred_info[i]; pjsip_authorization_hdr *h; h = get_header_for_realm(&added, &c->realm); if (h) { pj_list_erase(h); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)h); } else { pjsip_authorization_hdr *hs; hs = pjsip_authorization_hdr_create(tdata->pool); pj_strdup(tdata->pool, &hs->scheme, &c->scheme); pj_strdup(tdata->pool, &hs->credential.digest.username, &c->username); pj_strdup(tdata->pool, &hs->credential.digest.realm, &c->realm); pj_strdup2(tdata->pool, &hs->credential.digest.uri, uri_str); pj_strdup(tdata->pool, &hs->credential.digest.algorithm, &sess->pref.algorithm); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hs); } } } return PJ_SUCCESS; }
/* * Initialize new request message with authorization headers. * This function will put Authorization/Proxy-Authorization headers to the * outgoing request message. If caching is enabled (PJSIP_AUTH_HEADER_CACHING) * and the session has previously sent Authorization/Proxy-Authorization header * with the same method, then the same Authorization/Proxy-Authorization header * will be resent from the cache only if qop is not present. If the stack is * configured to automatically generate next Authorization/Proxy-Authorization * headers (PJSIP_AUTH_AUTO_SEND_NEXT flag), then new Authorization/Proxy- * Authorization headers are calculated and generated when they are not present * in the case or if authorization session has qop. * * If both PJSIP_AUTH_HEADER_CACHING flag and PJSIP_AUTH_AUTO_SEND_NEXT flag * are not set, this function will do nothing. The stack then will only send * Authorization/Proxy-Authorization to respond 401/407 response. */ PJ_DEF(pj_status_t) pjsip_auth_init_req( pj_pool_t *sess_pool, pjsip_tx_data *tdata, pjsip_auth_session *sess_list, int cred_count, const pjsip_cred_info cred_info[]) { pjsip_auth_session *sess; pjsip_method *method = &tdata->msg->line.req.method; pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); if (!sess_list) return 0; sess = sess_list->next; while (sess != sess_list) { if (sess->qop_value == PJSIP_AUTH_QOP_NONE) { # if (PJSIP_AUTH_HEADER_CACHING) { pjsip_cached_auth_hdr *entry = sess->cached_hdr.next; while (entry != &sess->cached_hdr) { if (pjsip_method_cmp(&entry->method, method)==0) { pjsip_authorization_hdr *hauth; hauth = pjsip_hdr_shallow_clone(tdata->pool, entry->hdr); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); } else { # if (PJSIP_AUTH_AUTO_SEND_NEXT) { new_auth_for_req( tdata, sess_pool, sess, cred_count, cred_info); } # else { PJ_UNUSED_ARG(sess_pool); PJ_UNUSED_ARG(cred_count); PJ_UNUSED_ARG(cred_info); } # endif /* PJSIP_AUTH_AUTO_SEND_NEXT */ } entry = entry->next; } } # elif (PJSIP_AUTH_AUTO_SEND_NEXT) { new_auth_for_req( tdata, sess_pool, sess, cred_count, cred_info); } # else { PJ_UNUSED_ARG(sess_pool); PJ_UNUSED_ARG(cred_count); PJ_UNUSED_ARG(cred_info); } # endif /* PJSIP_AUTH_HEADER_CACHING */ } # if (PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT) else if (sess->qop_value == PJSIP_AUTH_QOP_AUTH) { /* For qop="auth", we have to re-create the authorization header. */ const pjsip_cred_info *cred; pjsip_authorization_hdr *hauth; cred = pjsip_auth_find_cred( cred_count, cred_info, &sess->realm, &sess->last_chal->scheme); if (!cred) { sess = sess->next; continue; } hauth = pjsip_auth_respond( tdata->pool, sess->last_chal, tdata->msg->line.req.uri, cred, &tdata->msg->line.req.method, sess_pool, sess ); if (hauth) { pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); } } # endif /* PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT */ sess = sess->next; } return 0; }