Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share an auth session between multiple dialogs/regc #4262

Merged
merged 9 commits into from
Feb 3, 2025
16 changes: 16 additions & 0 deletions pjsip/include/pjsip-ua/sip_regc.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,22 @@ PJ_DECL(pj_status_t) pjsip_regc_update_expires( pjsip_regc *regc,
PJ_DECL(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata);


#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
/**
* set a shared auth session to be used by this register client.
* This will try to reuse authorization headers from another source
* (e.g. subscribe dialog).
*
* If available, the internal auth session will be ignored. To reset
* call with NULL for session parameter
*
* @param dlg The dialog
* @param session Pointer to the external session
*/
PJ_DECL(pj_status_t) pjsip_regc_set_auth_sess( pjsip_regc *regc,
pjsip_auth_clt_sess *session );
#endif

PJ_END_DECL

/**
Expand Down
5 changes: 4 additions & 1 deletion pjsip/include/pjsip/sip_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,10 @@ typedef struct pjsip_auth_clt_sess
unsigned cred_cnt; /**< Number of credentials. */
pjsip_cred_info *cred_info; /**< Array of credential information*/
pjsip_cached_auth cached_auth; /**< Cached authorization info. */

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pj_lock_t *lock; /**< Prevent concurrent usage when shared.*/
struct pjsip_auth_clt_sess *parent; /**< allow a common parent for multiple sessions.*/
#endif
} pjsip_auth_clt_sess;


Expand Down
17 changes: 17 additions & 0 deletions pjsip/include/pjsip/sip_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,23 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
# define PJSIP_AUTH_AUTO_SEND_NEXT 0
#endif

/**
* If this flag is set, the stack will allow sharing of a auth session.
* The session can be set to each dialog and will try to reuse auth headers
* if possible. This can drastically reduce the amount of messages, that are
* required to communicate with the same account.
*
* May need to have PJSIP_AUTH_AUTO_SEND_NEXT and PJSIP_AUTH_HEADER_CACHING
* enabled to work properly, and also will grow usage of the used pool for
* the cached headers.
*
* Default: 0
*/
#if !defined(PJSIP_SHARED_AUTH_SESSION)
# define PJSIP_SHARED_AUTH_SESSION 0
#endif


/**
* Support qop="auth" directive.
* This option also requires client to cache the last challenge offered by
Expand Down
17 changes: 15 additions & 2 deletions pjsip/include/pjsip/sip_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,21 @@ PJ_DECL(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg,
const pjsip_msg *msg,
pj_bool_t strict);


#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
/**
* set a shared auth session to be used by this dialog.
* This will try to reuse authorization headers from another source
* (e.g. register).
*
* If available, the internal auth session will be ignored. To reset
* call with NULL for session parameter
*
* @param dlg The dialog
* @param session Pointer to the external session
*/
PJ_DECL(pj_status_t) pjsip_dlg_set_auth_sess(pjsip_dialog *dlg,
pjsip_auth_clt_sess *session);
#endif

/**
* @}
Expand All @@ -927,7 +941,6 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg,
pjsip_rx_data *rdata );



PJ_END_DECL


Expand Down
3 changes: 3 additions & 0 deletions pjsip/include/pjsua-lib/pjsua_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ typedef struct pjsua_acc
pjsip_transport_type_e tp_type; /**< Transport type (for local acc or
transport binding) */
pjsua_ip_change_op ip_change_op;/**< IP change process progress. */
#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pjsip_auth_clt_sess shared_auth_sess; /**< share one auth over all requests */
#endif
} pjsua_acc;


Expand Down
19 changes: 18 additions & 1 deletion pjsip/src/pjsip-ua/sip_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct pjsip_regc

/* Authorization sessions. */
pjsip_auth_clt_sess auth_sess;
pjsip_auth_clt_sess *ext_auth_sess; /**< User defined auth session. */

/* Auto refresh registration. */
pj_bool_t auto_reg;
Expand Down Expand Up @@ -1555,4 +1556,20 @@ PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata)
return status;
}


#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
PJ_DEF(pj_status_t) pjsip_regc_set_auth_sess( pjsip_regc *regc,
pjsip_auth_clt_sess *session ) {
PJ_ASSERT_RETURN(regc, PJ_EINVAL);
pj_status_t status = PJ_SUCCESS;
status = pj_lock_acquire(regc->auth_sess.lock);
if (status != PJ_SUCCESS) {
return status;
}
regc->auth_sess.parent = session;
status = pj_lock_release(regc->auth_sess.lock);
if (status != PJ_SUCCESS) {
return status;
}
return PJ_SUCCESS;
}
#endif
116 changes: 115 additions & 1 deletion pjsip/src/pjsip/sip_auth_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
#include <pj/guid.h>
#include <pj/assert.h>
#include <pj/ctype.h>
#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
#include <pj/lock.h>
#endif


#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \
Expand Down Expand Up @@ -105,6 +108,28 @@ const pjsip_auth_algorithm pjsip_auth_algorithms[] = {
# define AUTH_TRACE_(expr)
#endif

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
#define DO_ON_PARENT_LOCKED(sess, call) \
do { \
pj_status_t on_parent, lock_status; \
pj_bool_t with_parent = PJ_FALSE; \
lock_status = pj_lock_acquire(sess->lock); \
if (lock_status != PJ_SUCCESS) { \
return lock_status; \
} \
if (sess->parent) { \
with_parent = PJ_TRUE; \
on_parent = call; \
} \
lock_status = pj_lock_release(sess->lock); \
if (lock_status != PJ_SUCCESS) { \
return lock_status; \
} \
if (with_parent) { \
return on_parent; \
} \
} while(0)
#endif

static void dup_bin(pj_pool_t *pool, pj_str_t *dst, const pj_str_t *src)
{
Expand Down Expand Up @@ -712,6 +737,26 @@ static pjsip_cached_auth *find_cached_auth( pjsip_auth_clt_sess *sess,
const pj_str_t *realm,
pjsip_auth_algorithm_type algorithm_type)
{
#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pj_status_t lock_status;
pj_bool_t with_parent = PJ_FALSE;
lock_status = pj_lock_acquire(sess->lock);
pjsip_cached_auth * pauth = NULL;
if (lock_status != PJ_SUCCESS) {
return NULL;
}
if (sess->parent) {
pauth = sess->parent->cached_auth.next;
}
lock_status = pj_lock_release(sess->lock);
if (lock_status != PJ_SUCCESS) {
return NULL;
}
if (pauth != NULL) {
return pauth;
}
#endif

pjsip_cached_auth *auth = sess->cached_auth.next;
while (auth != &sess->cached_auth) {
if (pj_stricmp(&auth->realm, realm) == 0
Expand All @@ -734,6 +779,26 @@ static const pjsip_cred_info* auth_find_cred( const pjsip_auth_clt_sess *sess,

PJ_UNUSED_ARG(auth_scheme);

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pj_status_t lock_status;
pj_bool_t with_parent = PJ_FALSE;
lock_status = pj_lock_acquire(sess->lock);
const pjsip_cred_info * ptr = NULL;
if (lock_status != PJ_SUCCESS) {
return NULL;
}
if (sess->parent) {
ptr = auth_find_cred(sess->parent, realm, auth_scheme);
}
lock_status = pj_lock_release(sess->lock);
if (lock_status != PJ_SUCCESS) {
return NULL;
}
if (ptr != NULL) {
return ptr;
}
#endif

for (i=0; i<sess->cred_cnt; ++i) {
switch(sess->cred_info[i].data_type) {
case PJSIP_CRED_DATA_PLAIN_PASSWD:
Expand Down Expand Up @@ -795,7 +860,12 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess,
sess->cred_info = NULL;
pj_list_init(&sess->cached_auth);

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
sess->parent = NULL;
return pj_lock_create_simple_mutex(pool, "auth_clt_lock", &sess->lock);
#else
return PJ_SUCCESS;
#endif
}


Expand All @@ -812,7 +882,12 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_deinit(pjsip_auth_clt_sess *sess)
auth = auth->next;
}

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
sess->parent = NULL;
return pj_lock_destroy(sess->lock);
#else
return PJ_SUCCESS;
#endif
}


Expand Down Expand Up @@ -849,6 +924,29 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_clone( pj_pool_t *pool,
}
}

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pj_status_t status, lock_status;
lock_status = pj_lock_acquire(sess->lock);
if (lock_status != PJ_SUCCESS) {
return lock_status;
}
if (sess->parent) {
sess->parent = PJ_POOL_ZALLOC_T(pool, pjsip_auth_clt_sess);
if (sess->parent == NULL) {
status = PJ_ENOMEM;
} else {
status = pjsip_auth_clt_clone(pool, sess->parent, rhs->parent);
}
}
lock_status = pj_lock_release(sess->lock);
if (lock_status != PJ_SUCCESS) {
return lock_status;
}
if (status != PJ_SUCCESS) {
return status;
}
#endif

/* TODO note:
* Cloning the full authentication client is quite a big task.
* We do only the necessary bits here, i.e. cloning the credentials.
Expand All @@ -868,6 +966,9 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess,
const pjsip_cred_info *c)
{
PJ_ASSERT_RETURN(sess && c, PJ_EINVAL);
#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_set_credentials(sess->parent, cred_cnt, c));
#endif

if (cred_cnt == 0) {
sess->cred_cnt = 0;
Expand Down Expand Up @@ -943,6 +1044,9 @@ 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);
#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_set_prefs(sess->parent, p));
#endif

pj_memcpy(&sess->pref, p, sizeof(*p));
pj_strdup(sess->pool, &sess->pref.algorithm, &p->algorithm);
Expand All @@ -960,7 +1064,9 @@ 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);

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_get_prefs(sess->parent, p));
#endif
pj_memcpy(p, &sess->pref, sizeof(pjsip_auth_clt_pref));
return PJ_SUCCESS;
}
Expand Down Expand Up @@ -1197,6 +1303,10 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess,
PJ_ASSERT_RETURN(tdata->msg->type==PJSIP_REQUEST_MSG,
PJSIP_ENOTREQUESTMSG);


#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_init_req(sess->parent, tdata));
#endif
/* Init list */
pj_list_init(&added);

Expand Down Expand Up @@ -1548,6 +1658,10 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess,
rdata->msg_info.msg->line.status.code == 407,
PJSIP_EINVALIDSTATUS);

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_reinit_req(sess->parent, rdata, old_request, new_request));
#endif

tdata = old_request;
tdata->auth_retry = PJ_FALSE;

Expand Down
18 changes: 18 additions & 0 deletions pjsip/src/pjsip/sip_dialog.c
Original file line number Diff line number Diff line change
Expand Up @@ -2493,3 +2493,21 @@ PJ_DEF(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg,

return PJ_SUCCESS;
}

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
PJ_DEF(pj_status_t) pjsip_dlg_set_auth_sess( pjsip_dialog *dlg,
pjsip_auth_clt_sess *session ) {
PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
pj_status_t status = PJ_SUCCESS;
status = pj_lock_acquire(dlg->auth_sess.lock);
if (status != PJ_SUCCESS) {
return status;
}
dlg->auth_sess.parent = session;
status = pj_lock_release(dlg->auth_sess.lock);
if (status != PJ_SUCCESS) {
return status;
}
return PJ_SUCCESS;
}
#endif
8 changes: 8 additions & 0 deletions pjsip/src/pjsua-lib/pjsua_acc.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ static pj_status_t initialize_acc(unsigned acc_id)
sip_reg_uri = NULL;
}

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pjsip_auth_clt_init( &acc->shared_auth_sess, pjsua_var.endpt, acc->pool, 0);
#endif

if (sip_reg_uri) {
acc->srv_port = sip_reg_uri->port;
}
Expand Down Expand Up @@ -2754,6 +2758,10 @@ static pj_status_t pjsua_regc_init(int acc_id)
pjsua_init_tpselector(acc_id, &tp_sel);
pjsip_regc_set_transport(acc->regc, &tp_sel);

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pjsip_regc_set_auth_sess(acc->regc, &acc->shared_auth_sess);
#endif

/* Set credentials
*/
if (acc->cred_cnt) {
Expand Down
4 changes: 4 additions & 0 deletions pjsip/src/pjsua-lib/pjsua_call.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,10 @@ PJ_DEF(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
pjsip_dlg_inc_lock(dlg);

dlg_set_via(dlg, acc);

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pjsip_dlg_set_auth_sess(dlg, &acc->shared_auth_sess);
#endif

/* Calculate call's secure level */
call->secure_level = get_secure_level(acc_id, dest_uri);
Expand Down
4 changes: 4 additions & 0 deletions pjsip/src/pjsua-lib/pjsua_pres.c
Original file line number Diff line number Diff line change
Expand Up @@ -2127,6 +2127,10 @@ static void subscribe_buddy(pjsua_buddy_id buddy_id,
pjsip_dlg_set_route_set(buddy->dlg, &acc->route_set);
}

#if defined(PJSIP_SHARED_AUTH_SESSION) && PJSIP_SHARED_AUTH_SESSION
pjsip_dlg_set_auth_sess(buddy->dlg, &acc->shared_auth_sess);
#endif

/* Set credentials */
if (acc->cred_cnt) {
pjsip_auth_clt_set_credentials( &buddy->dlg->auth_sess,
Expand Down
Loading