Skip to content

Commit 42a22c0

Browse files
authored
Share an auth session between multiple dialogs/regc (pjsip#4262)
1 parent 883536e commit 42a22c0

File tree

14 files changed

+186
-6
lines changed

14 files changed

+186
-6
lines changed

pjsip/include/pjsip-ua/sip_regc.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,20 @@ PJ_DECL(pj_status_t) pjsip_regc_update_expires( pjsip_regc *regc,
488488
PJ_DECL(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata);
489489

490490

491+
/**
492+
* set a shared auth session to be used by this register client.
493+
* This will try to reuse authorization headers from another source
494+
* (e.g. subscribe dialog).
495+
*
496+
* If available, the internal auth session will be ignored.
497+
* To reset client registration, pass NULL as session parameter.
498+
*
499+
* @param regc The client registration structure.
500+
* @param session Pointer to the external session.
501+
*/
502+
PJ_DECL(pj_status_t) pjsip_regc_set_auth_sess( pjsip_regc *regc,
503+
pjsip_auth_clt_sess *session );
504+
491505
PJ_END_DECL
492506

493507
/**

pjsip/include/pjsip/sip_auth.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,12 @@ typedef struct pjsip_auth_clt_sess
343343
unsigned cred_cnt; /**< Number of credentials. */
344344
pjsip_cred_info *cred_info; /**< Array of credential information*/
345345
pjsip_cached_auth cached_auth; /**< Cached authorization info. */
346-
346+
pj_lock_t *lock; /**< Prevent concurrent usage when
347+
using a shared parent. Is only
348+
used in parent. Set up by
349+
pjsip_auth_clt_set_parent */
350+
struct pjsip_auth_clt_sess *parent; /**< allow a common parent
351+
for multiple sessions. */
347352
} pjsip_auth_clt_sess;
348353

349354

@@ -602,6 +607,19 @@ PJ_DECL(pj_status_t) pjsip_auth_srv_init( pj_pool_t *pool,
602607
unsigned options );
603608

604609

610+
/**
611+
* Set a parent session to be used instead of the current.
612+
* This allows a central caching of authorization headers over multiple
613+
* dialogs.
614+
*
615+
* @param sess session that will be delegating the requests.
616+
* @param p parent that will be shared.
617+
*
618+
* @return PJ_SUCCESS on success.
619+
*/
620+
PJ_DECL(pj_status_t) pjsip_auth_clt_set_parent(pjsip_auth_clt_sess *sess,
621+
const pjsip_auth_clt_sess *p);
622+
605623
/**
606624
* This structure describes initialization settings of server authorization
607625
* session.

pjsip/include/pjsip/sip_dialog.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,19 @@ PJ_DECL(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg,
903903
const pjsip_msg *msg,
904904
pj_bool_t strict);
905905

906-
906+
/**
907+
* set a shared auth session to be used by this dialog.
908+
* This will try to reuse authorization headers from another source
909+
* (e.g. register).
910+
*
911+
* If available, the internal auth session will be ignored.
912+
* To reset client registration, pass NULL as session parameter.
913+
*
914+
* @param dlg The dialog
915+
* @param session Pointer to the external session
916+
*/
917+
PJ_DECL(pj_status_t) pjsip_dlg_set_auth_sess(pjsip_dialog *dlg,
918+
pjsip_auth_clt_sess *session);
907919

908920
/**
909921
* @}
@@ -927,7 +939,6 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg,
927939
pjsip_rx_data *rdata );
928940

929941

930-
931942
PJ_END_DECL
932943

933944

pjsip/include/pjsua-lib/pjsua.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4661,6 +4661,19 @@ typedef struct pjsua_acc_config
46614661
*/
46624662
pj_bool_t enable_rtcp_xr;
46634663

4664+
/**
4665+
* Use a shared authorization session within this account.
4666+
* This will use the accounts credentials on outgoing requests,
4667+
* so that less 401/407 Responses will be returned.
4668+
*
4669+
* Needs PJSIP_AUTH_AUTO_SEND_NEXT and PJSIP_AUTH_HEADER_CACHING
4670+
* enabled to work properly, and also will grow usage of the used pool for
4671+
* the cached headers.
4672+
*
4673+
* Default: PJ_FALSE
4674+
*/
4675+
pj_bool_t use_shared_auth;
4676+
46644677
} pjsua_acc_config;
46654678

46664679

pjsip/include/pjsua-lib/pjsua_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ typedef struct pjsua_acc
334334
pjsip_transport_type_e tp_type; /**< Transport type (for local acc or
335335
transport binding) */
336336
pjsua_ip_change_op ip_change_op;/**< IP change process progress. */
337+
pjsip_auth_clt_sess shared_auth_sess; /**< share one auth over all requests */
337338
} pjsua_acc;
338339

339340

pjsip/include/pjsua2/account.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,19 @@ struct AccountSipConfig : public PersistentObject
298298
*/
299299
pjsua_ipv6_use ipv6Use;
300300

301+
/**
302+
* Use a shared authorization session within this account.
303+
* This will use the accounts credentials on outgoing requests,
304+
* so that less 401/407 Responses will be returned.
305+
*
306+
* Needs PJSIP_AUTH_AUTO_SEND_NEXT and PJSIP_AUTH_HEADER_CACHING
307+
* enabled to work properly, and also will grow usage of the used pool for
308+
* the cached headers.
309+
*
310+
* Default is disabled/false.
311+
*/
312+
bool useSharedAuth;
313+
301314
public:
302315
/**
303316
* Read this object from a container node.

pjsip/src/pjsip-ua/sip_reg.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct pjsip_regc
9696

9797
/* Authorization sessions. */
9898
pjsip_auth_clt_sess auth_sess;
99+
pjsip_auth_clt_sess *ext_auth_sess; /**< User defined auth session. */
99100

100101
/* Auto refresh registration. */
101102
pj_bool_t auto_reg;
@@ -1555,4 +1556,8 @@ PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata)
15551556
return status;
15561557
}
15571558

1558-
1559+
PJ_DEF(pj_status_t) pjsip_regc_set_auth_sess( pjsip_regc *regc,
1560+
pjsip_auth_clt_sess *session ) {
1561+
PJ_ASSERT_RETURN(regc, PJ_EINVAL);
1562+
return pjsip_auth_clt_set_parent(&regc->auth_sess, session);
1563+
}

pjsip/src/pjsip/sip_auth_client.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <pj/guid.h>
3232
#include <pj/assert.h>
3333
#include <pj/ctype.h>
34+
#include <pj/lock.h>
3435

3536

3637
#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \
@@ -105,6 +106,20 @@ const pjsip_auth_algorithm pjsip_auth_algorithms[] = {
105106
# define AUTH_TRACE_(expr)
106107
#endif
107108

109+
#define DO_ON_PARENT_LOCKED(sess, call) \
110+
do { \
111+
pj_status_t on_parent; \
112+
pj_bool_t with_parent = PJ_FALSE; \
113+
if (sess->parent) { \
114+
pj_lock_acquire(sess->parent->lock); \
115+
with_parent = PJ_TRUE; \
116+
on_parent = call; \
117+
pj_lock_release(sess->parent->lock); \
118+
} \
119+
if (with_parent) { \
120+
return on_parent; \
121+
} \
122+
} while(0)
108123

109124
static void dup_bin(pj_pool_t *pool, pj_str_t *dst, const pj_str_t *src)
110125
{
@@ -712,6 +727,17 @@ static pjsip_cached_auth *find_cached_auth( pjsip_auth_clt_sess *sess,
712727
const pj_str_t *realm,
713728
pjsip_auth_algorithm_type algorithm_type)
714729
{
730+
pj_bool_t with_parent = PJ_FALSE;
731+
pjsip_cached_auth * pauth = NULL;
732+
if (sess->parent) {
733+
pj_lock_acquire(sess->parent->lock);
734+
pauth = find_cached_auth(sess->parent, realm, algorithm_type);
735+
pj_lock_release(sess->parent->lock);
736+
}
737+
if (pauth != NULL) {
738+
return pauth;
739+
}
740+
715741
pjsip_cached_auth *auth = sess->cached_auth.next;
716742
while (auth != &sess->cached_auth) {
717743
if (pj_stricmp(&auth->realm, realm) == 0
@@ -734,6 +760,17 @@ static const pjsip_cred_info* auth_find_cred( const pjsip_auth_clt_sess *sess,
734760

735761
PJ_UNUSED_ARG(auth_scheme);
736762

763+
pj_bool_t with_parent = PJ_FALSE;
764+
const pjsip_cred_info * ptr = NULL;
765+
if (sess->parent) {
766+
pj_lock_acquire(sess->parent->lock);
767+
ptr = auth_find_cred(sess->parent, realm, auth_scheme, algorithm_type);
768+
pj_lock_release(sess->parent->lock);
769+
}
770+
if (ptr != NULL) {
771+
return ptr;
772+
}
773+
737774
for (i=0; i<sess->cred_cnt; ++i) {
738775
switch(sess->cred_info[i].data_type) {
739776
case PJSIP_CRED_DATA_PLAIN_PASSWD:
@@ -795,6 +832,21 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess,
795832
sess->cred_info = NULL;
796833
pj_list_init(&sess->cached_auth);
797834

835+
sess->parent = NULL;
836+
sess->lock = NULL;
837+
return PJ_SUCCESS;
838+
}
839+
840+
PJ_DEF(pj_status_t) pjsip_auth_clt_set_parent(pjsip_auth_clt_sess *sess,
841+
const pjsip_auth_clt_sess *parent)
842+
{
843+
PJ_ASSERT_RETURN(sess && parent, PJ_EINVAL);
844+
if (parent->lock == NULL) {
845+
pj_lock_create_simple_mutex( parent->pool,
846+
"auth_clt_parent_lock",
847+
&parent->lock );
848+
}
849+
sess->parent = parent;
798850
return PJ_SUCCESS;
799851
}
800852

@@ -812,7 +864,12 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_deinit(pjsip_auth_clt_sess *sess)
812864
auth = auth->next;
813865
}
814866

815-
return PJ_SUCCESS;
867+
sess->parent = NULL;
868+
if (sess->lock) {
869+
return pj_lock_destroy(sess->lock);
870+
} else {
871+
return PJ_SUCCESS;
872+
}
816873
}
817874

818875

@@ -849,6 +906,21 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_clone( pj_pool_t *pool,
849906
}
850907
}
851908

909+
pj_status_t status;
910+
if (sess->parent) {
911+
pj_lock_acquire(sess->parent->lock);
912+
sess->parent = PJ_POOL_ZALLOC_T(pool, pjsip_auth_clt_sess);
913+
if (sess->parent == NULL) {
914+
status = PJ_ENOMEM;
915+
} else {
916+
status = pjsip_auth_clt_clone(pool, sess->parent, rhs->parent);
917+
}
918+
pj_lock_release(sess->parent->lock);
919+
}
920+
if (status != PJ_SUCCESS) {
921+
return status;
922+
}
923+
852924
/* TODO note:
853925
* Cloning the full authentication client is quite a big task.
854926
* We do only the necessary bits here, i.e. cloning the credentials.
@@ -868,6 +940,7 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess,
868940
const pjsip_cred_info *c)
869941
{
870942
PJ_ASSERT_RETURN(sess && c, PJ_EINVAL);
943+
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_set_credentials(sess->parent, cred_cnt, c));
871944

872945
if (cred_cnt == 0) {
873946
sess->cred_cnt = 0;
@@ -943,6 +1016,7 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_set_prefs(pjsip_auth_clt_sess *sess,
9431016
const pjsip_auth_clt_pref *p)
9441017
{
9451018
PJ_ASSERT_RETURN(sess && p, PJ_EINVAL);
1019+
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_set_prefs(sess->parent, p));
9461020

9471021
pj_memcpy(&sess->pref, p, sizeof(*p));
9481022
pj_strdup(sess->pool, &sess->pref.algorithm, &p->algorithm);
@@ -960,7 +1034,7 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_get_prefs(pjsip_auth_clt_sess *sess,
9601034
pjsip_auth_clt_pref *p)
9611035
{
9621036
PJ_ASSERT_RETURN(sess && p, PJ_EINVAL);
963-
1037+
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_get_prefs(sess->parent, p));
9641038
pj_memcpy(p, &sess->pref, sizeof(pjsip_auth_clt_pref));
9651039
return PJ_SUCCESS;
9661040
}
@@ -1197,6 +1271,8 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess,
11971271
PJ_ASSERT_RETURN(tdata->msg->type==PJSIP_REQUEST_MSG,
11981272
PJSIP_ENOTREQUESTMSG);
11991273

1274+
1275+
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_init_req(sess->parent, tdata));
12001276
/* Init list */
12011277
pj_list_init(&added);
12021278

@@ -1548,6 +1624,8 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess,
15481624
rdata->msg_info.msg->line.status.code == 407,
15491625
PJSIP_EINVALIDSTATUS);
15501626

1627+
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_reinit_req(sess->parent, rdata, old_request, new_request));
1628+
15511629
tdata = old_request;
15521630
tdata->auth_retry = PJ_FALSE;
15531631

pjsip/src/pjsip/sip_dialog.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,3 +2493,9 @@ PJ_DEF(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg,
24932493

24942494
return PJ_SUCCESS;
24952495
}
2496+
2497+
PJ_DEF(pj_status_t) pjsip_dlg_set_auth_sess( pjsip_dialog *dlg,
2498+
pjsip_auth_clt_sess *session ) {
2499+
PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
2500+
return pjsip_auth_clt_set_parent(&dlg->auth_sess, session);
2501+
}

pjsip/src/pjsua-lib/pjsua_acc.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ static pj_status_t initialize_acc(unsigned acc_id)
329329
} else {
330330
sip_reg_uri = NULL;
331331
}
332+
pjsip_auth_clt_init( &acc->shared_auth_sess, pjsua_var.endpt, acc->pool, 0);
332333

333334
if (sip_reg_uri) {
334335
acc->srv_port = sip_reg_uri->port;
@@ -1297,6 +1298,9 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id,
12971298
unreg_first = PJ_TRUE;
12981299
}
12991300

1301+
/* Shared authentication session */
1302+
acc->cfg.use_shared_auth = cfg->use_shared_auth;
1303+
13001304
/* Registration */
13011305
if (acc->cfg.reg_timeout != cfg->reg_timeout) {
13021306
acc->cfg.reg_timeout = cfg->reg_timeout;
@@ -2754,6 +2758,10 @@ static pj_status_t pjsua_regc_init(int acc_id)
27542758
pjsua_init_tpselector(acc_id, &tp_sel);
27552759
pjsip_regc_set_transport(acc->regc, &tp_sel);
27562760

2761+
if (acc->cfg.use_shared_auth) {
2762+
pjsip_regc_set_auth_sess(acc->regc, &acc->shared_auth_sess);
2763+
}
2764+
27572765
/* Set credentials
27582766
*/
27592767
if (acc->cred_cnt) {

0 commit comments

Comments
 (0)