Skip to content

Commit

Permalink
Share an auth session between multiple dialogs/regc (#4262)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwes authored Feb 3, 2025
1 parent 46111c4 commit 986fc78
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 6 deletions.
14 changes: 14 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,20 @@ 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);


/**
* 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 client registration, pass NULL as session parameter.
*
* @param regc The client registration structure.
* @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 );

PJ_END_DECL

/**
Expand Down
20 changes: 19 additions & 1 deletion pjsip/include/pjsip/sip_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,12 @@ 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. */

pj_lock_t *lock; /**< Prevent concurrent usage when
using a shared parent. Is only
used in parent. Set up by
pjsip_auth_clt_set_parent */
struct pjsip_auth_clt_sess *parent; /**< allow a common parent
for multiple sessions. */
} pjsip_auth_clt_sess;


Expand Down Expand Up @@ -602,6 +607,19 @@ PJ_DECL(pj_status_t) pjsip_auth_srv_init( pj_pool_t *pool,
unsigned options );


/**
* Set a parent session to be used instead of the current.
* This allows a central caching of authorization headers over multiple
* dialogs.
*
* @param sess session that will be delegating the requests.
* @param p parent that will be shared.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjsip_auth_clt_set_parent(pjsip_auth_clt_sess *sess,
const pjsip_auth_clt_sess *p);

/**
* This structure describes initialization settings of server authorization
* session.
Expand Down
15 changes: 13 additions & 2 deletions pjsip/include/pjsip/sip_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,19 @@ PJ_DECL(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg,
const pjsip_msg *msg,
pj_bool_t strict);


/**
* 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 client registration, pass NULL as 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);

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



PJ_END_DECL


Expand Down
13 changes: 13 additions & 0 deletions pjsip/include/pjsua-lib/pjsua.h
Original file line number Diff line number Diff line change
Expand Up @@ -4661,6 +4661,19 @@ typedef struct pjsua_acc_config
*/
pj_bool_t enable_rtcp_xr;

/**
* Use a shared authorization session within this account.
* This will use the accounts credentials on outgoing requests,
* so that less 401/407 Responses will be returned.
*
* Needs 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: PJ_FALSE
*/
pj_bool_t use_shared_auth;

} pjsua_acc_config;


Expand Down
1 change: 1 addition & 0 deletions pjsip/include/pjsua-lib/pjsua_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ 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. */
pjsip_auth_clt_sess shared_auth_sess; /**< share one auth over all requests */
} pjsua_acc;


Expand Down
13 changes: 13 additions & 0 deletions pjsip/include/pjsua2/account.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,19 @@ struct AccountSipConfig : public PersistentObject
*/
pjsua_ipv6_use ipv6Use;

/**
* Use a shared authorization session within this account.
* This will use the accounts credentials on outgoing requests,
* so that less 401/407 Responses will be returned.
*
* Needs 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 is disabled/false.
*/
bool useSharedAuth;

public:
/**
* Read this object from a container node.
Expand Down
7 changes: 6 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,8 @@ PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata)
return status;
}


PJ_DEF(pj_status_t) pjsip_regc_set_auth_sess( pjsip_regc *regc,
pjsip_auth_clt_sess *session ) {
PJ_ASSERT_RETURN(regc, PJ_EINVAL);
return pjsip_auth_clt_set_parent(&regc->auth_sess, session);
}
82 changes: 80 additions & 2 deletions pjsip/src/pjsip/sip_auth_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <pj/guid.h>
#include <pj/assert.h>
#include <pj/ctype.h>
#include <pj/lock.h>


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

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

static void dup_bin(pj_pool_t *pool, pj_str_t *dst, const pj_str_t *src)
{
Expand Down Expand Up @@ -712,6 +727,17 @@ static pjsip_cached_auth *find_cached_auth( pjsip_auth_clt_sess *sess,
const pj_str_t *realm,
pjsip_auth_algorithm_type algorithm_type)
{
pj_bool_t with_parent = PJ_FALSE;
pjsip_cached_auth * pauth = NULL;
if (sess->parent) {
pj_lock_acquire(sess->parent->lock);
pauth = find_cached_auth(sess->parent, realm, algorithm_type);
pj_lock_release(sess->parent->lock);
}
if (pauth != NULL) {
return pauth;
}

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

PJ_UNUSED_ARG(auth_scheme);

pj_bool_t with_parent = PJ_FALSE;
const pjsip_cred_info * ptr = NULL;
if (sess->parent) {
pj_lock_acquire(sess->parent->lock);
ptr = auth_find_cred(sess->parent, realm, auth_scheme, algorithm_type);
pj_lock_release(sess->parent->lock);
}
if (ptr != NULL) {
return ptr;
}

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,6 +832,21 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess,
sess->cred_info = NULL;
pj_list_init(&sess->cached_auth);

sess->parent = NULL;
sess->lock = NULL;
return PJ_SUCCESS;
}

PJ_DEF(pj_status_t) pjsip_auth_clt_set_parent(pjsip_auth_clt_sess *sess,
const pjsip_auth_clt_sess *parent)
{
PJ_ASSERT_RETURN(sess && parent, PJ_EINVAL);
if (parent->lock == NULL) {
pj_lock_create_simple_mutex( parent->pool,
"auth_clt_parent_lock",
&parent->lock );
}
sess->parent = parent;
return PJ_SUCCESS;
}

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

return PJ_SUCCESS;
sess->parent = NULL;
if (sess->lock) {
return pj_lock_destroy(sess->lock);
} else {
return PJ_SUCCESS;
}
}


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

pj_status_t status;
if (sess->parent) {
pj_lock_acquire(sess->parent->lock);
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);
}
pj_lock_release(sess->parent->lock);
}
if (status != PJ_SUCCESS) {
return status;
}

/* 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 +940,7 @@ 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);
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_set_credentials(sess->parent, cred_cnt, c));

if (cred_cnt == 0) {
sess->cred_cnt = 0;
Expand Down Expand Up @@ -943,6 +1016,7 @@ 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);
DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_set_prefs(sess->parent, p));

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

DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_get_prefs(sess->parent, p));
pj_memcpy(p, &sess->pref, sizeof(pjsip_auth_clt_pref));
return PJ_SUCCESS;
}
Expand Down Expand Up @@ -1197,6 +1271,8 @@ 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);


DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_init_req(sess->parent, tdata));
/* Init list */
pj_list_init(&added);

Expand Down Expand Up @@ -1548,6 +1624,8 @@ 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);

DO_ON_PARENT_LOCKED(sess, pjsip_auth_clt_reinit_req(sess->parent, rdata, old_request, new_request));

tdata = old_request;
tdata->auth_retry = PJ_FALSE;

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

return PJ_SUCCESS;
}

PJ_DEF(pj_status_t) pjsip_dlg_set_auth_sess( pjsip_dialog *dlg,
pjsip_auth_clt_sess *session ) {
PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
return pjsip_auth_clt_set_parent(&dlg->auth_sess, session);
}
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 @@ -329,6 +329,7 @@ static pj_status_t initialize_acc(unsigned acc_id)
} else {
sip_reg_uri = NULL;
}
pjsip_auth_clt_init( &acc->shared_auth_sess, pjsua_var.endpt, acc->pool, 0);

if (sip_reg_uri) {
acc->srv_port = sip_reg_uri->port;
Expand Down Expand Up @@ -1297,6 +1298,9 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id,
unreg_first = PJ_TRUE;
}

/* Shared authentication session */
acc->cfg.use_shared_auth = cfg->use_shared_auth;

/* Registration */
if (acc->cfg.reg_timeout != cfg->reg_timeout) {
acc->cfg.reg_timeout = cfg->reg_timeout;
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 (acc->cfg.use_shared_auth) {
pjsip_regc_set_auth_sess(acc->regc, &acc->shared_auth_sess);
}

/* 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 @@ -983,6 +983,10 @@ PJ_DEF(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,

dlg_set_via(dlg, acc);

if (acc->cfg.use_shared_auth) {
pjsip_dlg_set_auth_sess(dlg, &acc->shared_auth_sess);
}

/* Calculate call's secure level */
call->secure_level = get_secure_level(acc_id, dest_uri);

Expand Down
1 change: 1 addition & 0 deletions pjsip/src/pjsua-lib/pjsua_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
PJSUA_CALL_UPDATE_CONTACT |
PJSUA_CALL_UPDATE_VIA;
cfg->enable_rtcp_xr = (PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR);
cfg->use_shared_auth = PJ_FALSE;
}

PJ_DEF(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg)
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 (acc->cfg.use_shared_auth) {
pjsip_dlg_set_auth_sess(buddy->dlg, &acc->shared_auth_sess);
}

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

0 comments on commit 986fc78

Please sign in to comment.