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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
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.
*/
sauwming marked this conversation as resolved.
Show resolved Hide resolved
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
Loading