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

Update PJSUA2 docs on authentication digest AKA callback #4089

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 50 additions & 45 deletions pjsip/include/pjsua2/endpoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,57 +546,57 @@ struct DigestChallenge
struct DigestCredential
{
/**
*Realm of the credential
* Realm of the credential
*/
std::string realm;

/**
*Other parameters.
* Other parameters.
*/
StringToStringMap otherParam;

/**
*Username parameter.
* Username parameter.
*/
std::string username;

/**
*Nonce parameter.
* Nonce parameter.
*/
std::string nonce;

/**
*URI parameter.
* URI parameter.
*/
std::string uri;

/**
*Response digest.
* Response digest.
*/
std::string response;

/**
*Algorithm.
* Algorithm.
*/
std::string algorithm;

/**
*Cnonce.
* Cnonce.
*/
std::string cnonce;

/**
*Opaque value.
* Opaque value.
*/
std::string opaque;

/**
*Quality of protection.
* Quality of protection.
*/
std::string qop;

/**
*Nonce count.
* Nonce count.
*/
std::string nc;

Expand All @@ -613,20 +613,36 @@ struct DigestCredential


/**
* Parameters for onCredAuth account method.
* Parameter of Endpoint::onCredAuth() callback.
*/
struct OnCredAuthParam
{
/** Digest challenge */
/**
* Digest challenge.
* The authentication challenge sent by server in 401 or 401 response,
* as either Proxy-Authenticate or WWW-Authenticate header.
*/
DigestChallenge digestChallenge;

/** Credential info */
/**
* Credential info.
*/
AuthCredInfo credentialInfo;

/** Method */
/**
* The request method.
*/
std::string method;

/** Digest credential */
/**
* The digest credential where the digest response will be placed to.
*
* Upon calling this function, the nonce, nc, cnonce, qop, uri, and realm
* fields of this structure must be set by the caller.
*
* Upon return, the callback must set the response in
* \a DigestCredential.response.
*/
DigestCredential digestCredential;
};

Expand Down Expand Up @@ -1928,35 +1944,24 @@ class Endpoint
{ PJ_UNUSED_ARG(prm); }

/**
* Callback for computation of the digest credential.
*
* Usually, an application does not need to implement (overload) this callback.
* Use it, if your application needs to support Digest AKA authentication without
* the default digest computation back-end (i.e: using <b>libmilenage</b>).
*
* To use Digest AKA authentication, add \a PJSIP_CRED_DATA_EXT_AKA flag in the
* AuthCredInfo's \a dataType field of the AccountConfig, and fill up other
* AKA specific information in AuthCredInfo:
* - If PJSIP_HAS_DIGEST_AKA_AUTH is disabled, you have to overload this callback
* to provide your own digest computation back-end.
* - If PJSIP_HAS_DIGEST_AKA_AUTH is enabled, <b>libmilenage</b> library from
* \a third_party directory is linked, and this callback returns PJ_ENOTSUP,
* then the default digest computation back-end is used.
*
* @param prm.digestChallenge The authentication challenge sent by server in 401
* or 401 response, as either Proxy-Authenticate or
* WWW-Authenticate header.
* @param prm.credentialInfo The credential to be used.
* @param method The request method.
* @param prm.digestCredential The digest credential where the digest response
* will be placed to. Upon calling this function, the
* nonce, nc, cnonce, qop, uri, and realm fields of
* this structure must have been set by caller. Upon
* return, the \a response field will be initialized
* by this function.
*
* @return PJ_ENOTSUP is the default. If you overload this callback,
* return PJ_SUCCESS on success.
* Callback for custom computation of the digest AKA response.
*
* Usually an application does not need to implement (overload) this
* callback because by default the response digest AKA is automatically
* computed using <b>libmilenage</b>.
*
* To use Digest AKA authentication, add \a PJSIP_CRED_DATA_EXT_AKA flag
* in the AuthCredInfo's \a dataType field of the AccountConfig, and
* fill up other AKA specific information in AuthCredInfo.
* Please see \ref PJSIP_AUTH_AKA_API for more information.
*
* @param prm Callback parameter.
*
* @return Return PJ_ENOTSUP to let the library compute
* the response digest automatically.
* Return PJ_SUCCESS if application does the computation
* and sets the response digest in
* \a prm.DigestCredential.response.
*/
virtual pj_status_t onCredAuth(OnCredAuthParam &prm);

Expand Down
5 changes: 3 additions & 2 deletions pjsip/src/pjsua2/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -992,8 +992,9 @@ void Account::create(const AccountConfig &acc_cfg,
acc_cfg.toPj(pj_acc_cfg);

for (unsigned i = 0; i < pj_acc_cfg.cred_count; ++i) {
pjsip_cred_info *dst = &pj_acc_cfg.cred_info[i];
dst->ext.aka.cb = (pjsip_cred_cb)Endpoint::on_auth_create_aka_response_callback;
pjsip_cred_info *dst = &pj_acc_cfg.cred_info[i];
dst->ext.aka.cb = (pjsip_cred_cb)
&Endpoint::on_auth_create_aka_response_callback;
}
pj_acc_cfg.user_data = (void*)this;
PJSUA2_CHECK_EXPR( pjsua_acc_add(&pj_acc_cfg, make_default, &id) );
Expand Down
35 changes: 19 additions & 16 deletions pjsip/src/pjsua2/endpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2701,6 +2701,7 @@ pj_status_t Endpoint::on_auth_create_aka_response_callback(pj_pool_t *pool,
pjsip_digest_credential *auth)
{
OnCredAuthParam prm;

prm.digestChallenge.fromPj(*chal);
prm.credentialInfo.fromPj(*cred);
prm.method = pj2Str(*method);
Expand All @@ -2709,24 +2710,26 @@ pj_status_t Endpoint::on_auth_create_aka_response_callback(pj_pool_t *pool,
pj_status_t status = Endpoint::instance().onCredAuth(prm);

if (status == PJ_SUCCESS) {
pjsip_digest_credential auth_new = prm.digestCredential.toPj();
// Duplicate in the pool, so that digestCredential
// is allowed to be destructed at the end of the method.
pj_strdup(pool, &auth->realm, &auth_new.realm);
pj_strdup(pool, &auth->username, &auth_new.username);
pj_strdup(pool, &auth->nonce, &auth_new.nonce);
pj_strdup(pool, &auth->uri, &auth_new.uri);
pj_strdup(pool, &auth->response, &auth_new.response);
pj_strdup(pool, &auth->algorithm, &auth_new.algorithm);
pj_strdup(pool, &auth->cnonce, &auth_new.cnonce);
pj_strdup(pool, &auth->opaque, &auth_new.opaque);
pj_strdup(pool, &auth->qop, &auth_new.qop);
pj_strdup(pool, &auth->nc, &auth_new.nc);
pjsip_param_clone(pool, &auth->other_param, &auth_new.other_param);
pjsip_digest_credential auth_new = prm.digestCredential.toPj();

// Duplicate in the pool, so that digestCredential
// is allowed to be destructed at the end of the method.
pj_strdup(pool, &auth->realm, &auth_new.realm);
pj_strdup(pool, &auth->username, &auth_new.username);
pj_strdup(pool, &auth->nonce, &auth_new.nonce);
pj_strdup(pool, &auth->uri, &auth_new.uri);
pj_strdup(pool, &auth->response, &auth_new.response);
pj_strdup(pool, &auth->algorithm, &auth_new.algorithm);
pj_strdup(pool, &auth->cnonce, &auth_new.cnonce);
pj_strdup(pool, &auth->opaque, &auth_new.opaque);
pj_strdup(pool, &auth->qop, &auth_new.qop);
pj_strdup(pool, &auth->nc, &auth_new.nc);
pjsip_param_clone(pool, &auth->other_param, &auth_new.other_param);
}
#if PJSIP_HAS_DIGEST_AKA_AUTH
else if (status == PJ_ENOTSUP) {
status = pjsip_auth_create_aka_response(pool, chal, cred, method, auth);
else if (status == PJ_ENOTSUP) {
status = pjsip_auth_create_aka_response(pool, chal, cred, method,
auth);
}
#endif
return status;
Expand Down
Loading