📄 sip_auth_client.c
字号:
pjsip_authorization_hdr *hauth; char tmp[PJSIP_MAX_URL_SIZE]; pj_str_t uri_str; pj_pool_t *pool; pj_status_t status; /* Verify arguments. */ PJ_ASSERT_RETURN(req_pool && hdr && uri && cred_info && method && sess_pool && cached_auth && p_h_auth, PJ_EINVAL); /* Print URL in the original request. */ uri_str.ptr = tmp; uri_str.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, tmp,sizeof(tmp)); if (uri_str.slen < 1) { pj_assert(!"URL is too long!"); return PJSIP_EURITOOLONG; }# if (PJSIP_AUTH_HEADER_CACHING) { pool = sess_pool; PJ_UNUSED_ARG(req_pool); }# else { pool = req_pool; PJ_UNUSED_ARG(sess_pool); }# endif if (hdr->type == PJSIP_H_WWW_AUTHENTICATE) hauth = pjsip_authorization_hdr_create(pool); else if (hdr->type == PJSIP_H_PROXY_AUTHENTICATE) hauth = pjsip_proxy_authorization_hdr_create(pool); else { pj_assert(!"Invalid response header!"); return PJSIP_EINVALIDHDR; } /* Only support digest scheme at the moment. */ if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) { pj_str_t *cnonce = NULL; pj_uint32_t nc = 1; /* Update the session (nonce-count etc) if required. */# if PJSIP_AUTH_QOP_SUPPORT { if (cached_auth) { update_digest_session( sess_pool, cached_auth, hdr ); cnonce = &cached_auth->cnonce; nc = cached_auth->nc; } }# endif /* PJSIP_AUTH_QOP_SUPPORT */ hauth->scheme = pjsip_DIGEST_STR; status = respond_digest( pool, &hauth->credential.digest, &hdr->challenge.digest, &uri_str, cred_info, cnonce, nc, &method->name); if (status != PJ_SUCCESS) return status; /* Set qop type in auth session the first time only. */ if (hdr->challenge.digest.qop.slen != 0 && cached_auth) { if (cached_auth->qop_value == PJSIP_AUTH_QOP_NONE) { pj_str_t *qop_val = &hauth->credential.digest.qop; if (!pj_strcmp(qop_val, &pjsip_AUTH_STR)) { cached_auth->qop_value = PJSIP_AUTH_QOP_AUTH; } else { cached_auth->qop_value = PJSIP_AUTH_QOP_UNKNOWN; } } } } else { return PJSIP_EINVALIDAUTHSCHEME; } /* Keep the new authorization header in the cache, only * if no qop is not present. */# if PJSIP_AUTH_HEADER_CACHING { if (hauth && cached_auth && cached_auth->qop_value == PJSIP_AUTH_QOP_NONE) { pjsip_cached_auth_hdr *cached_hdr; /* Delete old header with the same method. */ cached_hdr = cached_auth->cached_hdr.next; while (cached_hdr != &cached_auth->cached_hdr) { if (pjsip_method_cmp(method, &cached_hdr->method)==0) break; cached_hdr = cached_hdr->next; } /* Save the header to the list. */ if (cached_hdr != &cached_auth->cached_hdr) { cached_hdr->hdr = hauth; } else { cached_hdr = pj_pool_alloc(pool, sizeof(*cached_hdr)); pjsip_method_copy( pool, &cached_hdr->method, method); cached_hdr->hdr = hauth; pj_list_insert_before( &cached_auth->cached_hdr, cached_hdr ); } }# if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && PJSIP_AUTH_AUTO_SEND_NEXT!=0 if (hdr != cached_auth->last_chal) { cached_auth->last_chal = pjsip_hdr_clone(sess_pool, hdr); }# endif }# endif *p_h_auth = hauth; return PJ_SUCCESS;}#if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && PJSIP_AUTH_AUTO_SEND_NEXT!=0static pj_status_t new_auth_for_req( pjsip_tx_data *tdata, pjsip_auth_clt_sess *sess, pjsip_cached_auth *auth, pjsip_authorization_hdr **p_h_auth){ const pjsip_cred_info *cred; pjsip_authorization_hdr *hauth; pj_status_t status; PJ_ASSERT_RETURN(tdata && sess && auth, PJ_EINVAL); PJ_ASSERT_RETURN(auth->last_chal != NULL, PJSIP_EAUTHNOPREVCHAL); cred = auth_find_cred( sess, &auth->realm, &auth->last_chal->scheme ); if (!cred) return PJSIP_ENOCREDENTIAL; 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); if (p_h_auth) *p_h_auth = hauth; return PJ_SUCCESS;}#endif/* 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; 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); /* 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); 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); }# endif /* PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT */ auth = auth->next; } return PJ_SUCCESS;}/* Process authorization challenge */static pj_status_t process_auth( pj_pool_t *req_pool, const pjsip_www_authenticate_hdr *hchal, const pjsip_uri *uri, pjsip_tx_data *tdata, pjsip_auth_clt_sess *sess, pjsip_cached_auth *cached_auth, pjsip_authorization_hdr **h_auth){ const pjsip_cred_info *cred; pjsip_authorization_hdr *sent_auth = NULL; pjsip_hdr *hdr; pj_status_t status; /* See if we have sent authorization header for this realm */ hdr = tdata->msg->hdr.next; while (hdr != &tdata->msg->hdr) { if ((hchal->type == PJSIP_H_WWW_AUTHENTICATE && hdr->type == PJSIP_H_AUTHORIZATION) || (hchal->type == PJSIP_H_PROXY_AUTHENTICATE && hdr->type == PJSIP_H_PROXY_AUTHORIZATION)) { sent_auth = (pjsip_authorization_hdr*) hdr; if (pj_stricmp(&hchal->challenge.common.realm, &sent_auth->credential.common.realm )==0) { break; } } hdr = hdr->next; } /* If we have sent, see if server rejected because of stale nonce or * other causes. */ if (hdr != &tdata->msg->hdr) { if (hchal->challenge.digest.stale == 0) { /* Our credential is rejected. No point in trying to re-supply * the same credential. */ PJ_LOG(4, (THIS_FILE, "Authorization failed for %.*s@%.*s: " "server rejected with stale=false", sent_auth->credential.digest.username.slen, sent_auth->credential.digest.username.ptr, sent_auth->credential.digest.realm.slen, sent_auth->credential.digest.realm.ptr)); return PJSIP_EFAILEDCREDENTIAL; } cached_auth->stale_cnt++; if (cached_auth->stale_cnt >= PJSIP_MAX_STALE_COUNT) { /* Our credential is rejected. No point in trying to re-supply * the same credential. */ PJ_LOG(4, (THIS_FILE, "Authorization failed for %.*s@%.*s: " "maximum number of stale retries exceeded", sent_auth->credential.digest.username.slen, sent_auth->credential.digest.username.ptr, sent_auth->credential.digest.realm.slen, sent_auth->credential.digest.realm.ptr)); return PJSIP_EAUTHSTALECOUNT; } /* Otherwise remove old, stale authorization header from the mesasge. * We will supply a new one. */ pj_list_erase(sent_auth); } /* Find credential to be used for the challenge. */ cred = auth_find_cred( sess, &hchal->challenge.common.realm, &hchal->scheme); if (!cred) { const pj_str_t *realm = &hchal->challenge.common.realm; PJ_LOG(4,(THIS_FILE, "Unable to set auth for %s: can not find credential for %.*s/%.*s", tdata->obj_name, realm->slen, realm->ptr, hchal->scheme.slen, hchal->scheme.ptr)); return PJSIP_ENOCREDENTIAL; } /* Respond to authorization challenge. */ status = auth_respond( req_pool, hchal, uri, cred, &tdata->msg->line.req.method, sess->pool, cached_auth, h_auth); return status;}/* Reinitialize outgoing request after 401/407 response is received. * The purpose of this function is: * - to add a Authorization/Proxy-Authorization header. * - to put the newly created Authorization/Proxy-Authorization header * in cached_list. */PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess, const pjsip_rx_data *rdata, pjsip_tx_data *old_request, pjsip_tx_data **new_request ){ pjsip_tx_data *tdata; const pjsip_hdr *hdr; pjsip_via_hdr *via; pj_status_t status; PJ_ASSERT_RETURN(sess && rdata && old_request && new_request, PJ_EINVAL); PJ_ASSERT_RETURN(sess->pool, PJSIP_ENOTINITIALIZED); PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG, PJSIP_ENOTRESPONSEMSG); PJ_ASSERT_RETURN(old_request->msg->type == PJSIP_REQUEST_MSG, PJSIP_ENOTREQUESTMSG); PJ_ASSERT_RETURN(rdata->msg_info.msg->line.status.code == 401 || rdata->msg_info.msg->line.status.code == 407, PJSIP_EINVALIDSTATUS); tdata = old_request; /* * Respond to each authentication challenge. */ hdr = rdata->msg_info.msg->hdr.next; while (hdr != &rdata->msg_info.msg->hdr) { pjsip_cached_auth *cached_auth; const pjsip_www_authenticate_hdr *hchal; pjsip_authorization_hdr *hauth; /* Find WWW-Authenticate or Proxy-Authenticate header. */ while (hdr->type != PJSIP_H_WWW_AUTHENTICATE && hdr->type != PJSIP_H_PROXY_AUTHENTICATE && hdr != &rdata->msg_info.msg->hdr) { hdr = hdr->next; } if (hdr == &rdata->msg_info.msg->hdr) break; hchal = (const pjsip_www_authenticate_hdr*) hdr; /* Find authentication session for this realm, create a new one * if not present. */ cached_auth = find_cached_auth(sess, &hchal->challenge.common.realm ); if (!cached_auth) { cached_auth = pj_pool_zalloc( sess->pool, sizeof(*cached_auth)); pj_strdup( sess->pool, &cached_auth->realm, &hchal->challenge.common.realm); cached_auth->is_proxy = (hchal->type == PJSIP_H_PROXY_AUTHENTICATE);# if (PJSIP_AUTH_HEADER_CACHING) { pj_list_init(&cached_auth->cached_hdr); }# endif pj_list_insert_before( &sess->cached_auth, cached_auth ); } /* Create authorization header for this challenge, and update * authorization session. */ status = process_auth( tdata->pool, hchal, tdata->msg->line.req.uri, tdata, sess, cached_auth, &hauth); if (status != PJ_SUCCESS) return status; /* Add to the message. */ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); /* Process next header. */ hdr = hdr->next; } /* Remove branch param in Via header. */ via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); via->branch_param.slen = 0; /* Must invalidate the message! */ pjsip_tx_data_invalidate_msg(tdata); /* Increment reference counter. */ pjsip_tx_data_add_ref(tdata); /* Done. */ *new_request = tdata; return PJ_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -