From 3c4737b86e55b69670b9fc4c014e77fa6fa00194 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 8 Nov 2007 09:24:30 +0000 Subject: - Added option to send empty Authorization header in outgoing requests - When UAS has sent answer in reliable 1xx, do not put SDP in 2xx - Handle the case when UPDATE is challenged with 401/407 - Obsolete --service-route option in pjsua git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1561 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/src/pjsip-ua/sip_inv.c | 36 ++++++++++- pjsip/src/pjsip-ua/sip_reg.c | 7 +++ pjsip/src/pjsip/sip_auth_client.c | 122 +++++++++++++++++++++++++++++++++++++- pjsip/src/pjsua-lib/pjsua_acc.c | 7 +-- pjsip/src/pjsua-lib/pjsua_call.c | 6 ++ pjsip/src/pjsua-lib/pjsua_im.c | 6 ++ pjsip/src/pjsua-lib/pjsua_pres.c | 6 +- 7 files changed, 182 insertions(+), 8 deletions(-) (limited to 'pjsip/src') diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c index 5ce657d4..8250b04a 100644 --- a/pjsip/src/pjsip-ua/sip_inv.c +++ b/pjsip/src/pjsip-ua/sip_inv.c @@ -1563,9 +1563,19 @@ static pj_status_t process_answer( pjsip_inv_session *inv, /* Include SDP when it's available for 2xx and 18x (but not 180) response. * Subsequent response will include this SDP. + * + * Note note: + * - When offer/answer has been completed in reliable 183, we MUST NOT + * send SDP in 2xx response. So if we don't have SDP to send, clear + * the SDP in the message body ONLY if 100rel is active in this + * session. */ if (sdp) { tdata->msg->body = create_sdp_body(tdata->pool, sdp); + } else { + if (inv->options & PJSIP_INV_REQUIRE_100REL) { + tdata->msg->body = NULL; + } } @@ -2226,8 +2236,32 @@ static void inv_handle_update_response( pjsip_inv_session *inv, struct tsx_inv_data *tsx_inv_data = NULL; pj_status_t status = -1; - /* Process 2xx response */ + /* Handle 401/407 challenge. */ if (tsx->state == PJSIP_TSX_STATE_COMPLETED && + (tsx->status_code == 401 || tsx->status_code == 407)) { + + pjsip_tx_data *tdata; + + status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess, + e->body.tsx_state.src.rdata, + tsx->last_tx, + &tdata); + + if (status != PJ_SUCCESS) { + + /* Does not have proper credentials. + * End the session anyway. + */ + inv_set_cause(inv, PJSIP_SC_OK, NULL); + inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); + + } else { + /* Re-send BYE. */ + status = pjsip_inv_send_msg(inv, tdata); + } + + /* Process 2xx response */ + } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && tsx->status_code/100 == 2 && e->body.tsx_state.src.rdata->msg_info.msg->body) { diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c index 3a257473..0a8e6d0d 100644 --- a/pjsip/src/pjsip-ua/sip_reg.c +++ b/pjsip/src/pjsip-ua/sip_reg.c @@ -307,6 +307,13 @@ PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc, return pjsip_auth_clt_set_credentials(®c->auth_sess, count, cred); } +PJ_DEF(pj_status_t) pjsip_regc_set_prefs( pjsip_regc *regc, + const pjsip_auth_clt_pref *pref) +{ + PJ_ASSERT_RETURN(regc && pref, PJ_EINVAL); + return pjsip_auth_clt_set_prefs(®c->auth_sess, pref); +} + PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc, const pjsip_route_hdr *route_set) { diff --git a/pjsip/src/pjsip/sip_auth_client.c b/pjsip/src/pjsip/sip_auth_client.c index 1c8457b9..7fcc1ec6 100644 --- a/pjsip/src/pjsip/sip_auth_client.c +++ b/pjsip/src/pjsip/sip_auth_client.c @@ -532,6 +532,36 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess, } +/* + * Set the preference for the client authentication session. + */ +PJ_DEF(pj_status_t) pjsip_auth_clt_set_prefs(pjsip_auth_clt_sess *sess, + const pjsip_auth_clt_pref *p) +{ + PJ_ASSERT_RETURN(sess && p, PJ_EINVAL); + + pj_memcpy(&sess->pref, p, sizeof(*p)); + pj_strdup(sess->pool, &sess->pref.algorithm, &p->algorithm); + //if (sess->pref.algorithm.slen == 0) + // sess->pref.algorithm = pj_str("md5"); + + return PJ_SUCCESS; +} + + +/* + * Get the preference for the client authentication session. + */ +PJ_DEF(pj_status_t) pjsip_auth_clt_get_prefs(pjsip_auth_clt_sess *sess, + pjsip_auth_clt_pref *p) +{ + PJ_ASSERT_RETURN(sess && p, PJ_EINVAL); + + pj_memcpy(p, &sess->pref, sizeof(pjsip_auth_clt_pref)); + return PJ_SUCCESS; +} + + /* * Create Authorization/Proxy-Authorization response header based on the challege * in WWW-Authenticate/Proxy-Authenticate header. @@ -698,6 +728,22 @@ static pj_status_t new_auth_for_req( pjsip_tx_data *tdata, #endif +/* Find credential in list of (Proxy-)Authorization headers */ +static pjsip_authorization_hdr* get_header_for_realm(const pjsip_hdr *hdr_list, + const pj_str_t *realm) +{ + pjsip_authorization_hdr *h; + + h = (pjsip_authorization_hdr*)hdr_list->next; + while (h != (pjsip_authorization_hdr*)hdr_list) { + if (pj_stricmp(&h->credential.digest.realm, realm)==0) + return h; + h = h->next; + } + + return NULL; +} + /* Initialize outgoing request. */ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, @@ -705,12 +751,16 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, { 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; @@ -728,7 +778,8 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, 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); + //pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); + pj_list_push_back(&added, hauth); break; } entry = entry->next; @@ -776,13 +827,80 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, if (status != PJ_SUCCESS) return status; - pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); + //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 = 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; icred_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 { + enum { HDRLEN = 256 }; + const pj_str_t hname = pj_str("Authorization"); + pj_str_t hval; + pjsip_generic_string_hdr *hs; + char *hdr; + + hdr = pj_pool_alloc(tdata->pool, HDRLEN); + len = pj_ansi_snprintf( + hdr, HDRLEN, + "%.*s username=\"%.*s\", realm=\"%.*s\"," + " nonce=\"\", uri=\"%s\",%s%.*s%s response=\"\"", + (int)c->scheme.slen, c->scheme.ptr, + (int)c->username.slen, c->username.ptr, + (int)c->realm.slen, c->realm.ptr, + uri_str, + (sess->pref.algorithm.slen ? " algorithm=" : ""), + (int)sess->pref.algorithm.slen, sess->pref.algorithm.ptr, + (sess->pref.algorithm.slen ? "," : "")); + + PJ_ASSERT_RETURN(len>0 && lenpool, &hname, + &hval); + pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hs); + } + } + } + return PJ_SUCCESS; } diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index 4262d410..6e988f09 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -544,10 +544,6 @@ void update_service_route(pjsua_acc *acc, pjsip_rx_data *rdata) pjsip_uri *uri[PJSUA_ACC_MAX_PROXIES]; unsigned i, uri_cnt = 0, rcnt; - /* Skip processing is enable_service_route is not set */ - if (!acc->cfg.enable_service_route) - return; - /* Find and parse Service-Route headers */ for (;;) { char saved; @@ -916,6 +912,9 @@ static pj_status_t pjsua_regc_init(int acc_id) pjsip_regc_set_credentials( acc->regc, acc->cred_cnt, acc->cred); } + /* Set authentication preference */ + pjsip_regc_set_prefs(acc->regc, &acc->cfg.auth_pref); + /* Set route-set */ if (!pj_list_empty(&acc->route_set)) { diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index f0f5a611..a7882b0c 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -383,6 +383,8 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, acc->cred_cnt, acc->cred); } + /* Set authentication preference */ + pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); /* Create initial INVITE: */ @@ -666,6 +668,10 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) pjsua_var.acc[acc_id].cred); } + /* Set preference */ + pjsip_auth_clt_set_prefs(&dlg->auth_sess, + &pjsua_var.acc[acc_id].cfg.auth_pref); + /* Create invite session: */ status = pjsip_inv_create_uas( dlg, rdata, answer, options, &inv); if (status != PJ_SUCCESS) { diff --git a/pjsip/src/pjsua-lib/pjsua_im.c b/pjsip/src/pjsua-lib/pjsua_im.c index 48cb802a..6eaf2b4c 100644 --- a/pjsip/src/pjsua-lib/pjsua_im.c +++ b/pjsip/src/pjsua-lib/pjsua_im.c @@ -321,6 +321,9 @@ static void im_callback(void *token, pjsip_event *e) pjsua_var.acc[im_data->acc_id].cred_cnt, pjsua_var.acc[im_data->acc_id].cred); + pjsip_auth_clt_set_prefs(&auth, + &pjsua_var.acc[im_data->acc_id].cfg.auth_pref); + status = pjsip_auth_clt_reinit_req(&auth, rdata, tsx->last_tx, &tdata); if (status == PJ_SUCCESS) { @@ -417,6 +420,9 @@ static void typing_callback(void *token, pjsip_event *e) pjsua_var.acc[im_data->acc_id].cred_cnt, pjsua_var.acc[im_data->acc_id].cred); + pjsip_auth_clt_set_prefs(&auth, + &pjsua_var.acc[im_data->acc_id].cfg.auth_pref); + status = pjsip_auth_clt_reinit_req(&auth, rdata, tsx->last_tx, &tdata); if (status == PJ_SUCCESS) { diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c index 1df81eab..d73a00d6 100644 --- a/pjsip/src/pjsua-lib/pjsua_pres.c +++ b/pjsip/src/pjsua-lib/pjsua_pres.c @@ -571,8 +571,9 @@ static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata) return PJ_TRUE; } - /* Set credentials. */ + /* Set credentials and preference. */ pjsip_auth_clt_set_credentials(&dlg->auth_sess, acc->cred_cnt, acc->cred); + pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); /* Init callback: */ pj_bzero(&pres_cb, sizeof(pres_cb)); @@ -1173,6 +1174,9 @@ static void subscribe_buddy_presence(unsigned index) acc->cred_cnt, acc->cred); } + /* Set authentication preference */ + pjsip_auth_clt_set_prefs(&buddy->dlg->auth_sess, &acc->cfg.auth_pref); + pjsip_evsub_set_mod_data(buddy->sub, pjsua_var.mod.id, buddy); status = pjsip_pres_initiate(buddy->sub, -1, &tdata); -- cgit v1.2.3