summaryrefslogtreecommitdiff
path: root/pjsip/src
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-11-08 09:24:30 +0000
committerBenny Prijono <bennylp@teluu.com>2007-11-08 09:24:30 +0000
commit3c4737b86e55b69670b9fc4c014e77fa6fa00194 (patch)
tree6489d04d93e86f329f490d57963251fb31be0633 /pjsip/src
parent11ace76446c9ff2c2afc0b0d6eab9c2b5ecc30b9 (diff)
- 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
Diffstat (limited to 'pjsip/src')
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c36
-rw-r--r--pjsip/src/pjsip-ua/sip_reg.c7
-rw-r--r--pjsip/src/pjsip/sip_auth_client.c122
-rw-r--r--pjsip/src/pjsua-lib/pjsua_acc.c7
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c6
-rw-r--r--pjsip/src/pjsua-lib/pjsua_im.c6
-rw-r--r--pjsip/src/pjsua-lib/pjsua_pres.c6
7 files changed, 182 insertions, 8 deletions
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(&regc->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(&regc->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; 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 {
+ 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 && len<HDRLEN, PJ_ETOOBIG);
+
+ hval.ptr = hdr;
+ hval.slen = len;
+ hs = pjsip_generic_string_hdr_create(tdata->pool, &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);