Skip to content

Commit

Permalink
Merge pull request #2689 from sippy/pr_opensipit02_qop
Browse files Browse the repository at this point in the history
Improve xyz_challenge() API to allow generating challenges like qop="auth,auth-int" as well as qop="auth-int,auth"; Make qop mandatory for the MD5-sess as well.
  • Loading branch information
liviuchircu committed Nov 17, 2021
2 parents f3abb0f + f90f20c commit 2825caa
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 30 deletions.
2 changes: 1 addition & 1 deletion lib/digest_auth/dauth_nonce.c
Expand Up @@ -59,7 +59,7 @@ _Static_assert(offsetof(struct nonce_context_priv, pub) == 0,

struct nonce_payload {
int index;
uint64_t qop:2;
uint64_t qop:3;
uint64_t alg:3;
uint64_t expires_sec:34;
uint64_t expires_usec:20;
Expand Down
15 changes: 11 additions & 4 deletions modules/auth/api.c
Expand Up @@ -229,10 +229,17 @@ auth_result_t pre_auth(struct sip_msg* _m, str* _realm, hdr_types_t _hftype,
goto stalenonce;
}
qop_type_t qop = dcp->qop.qop_parsed;
if ((np.qop != qop) &&
(np.qop != QOP_TYPE_BOTH || (qop != QOP_AUTH_D && qop != QOP_AUTHINT_D))) {
LM_DBG("nonce does not match qop\n");
goto stalenonce;
if (np.qop != qop) {
switch (np.qop) {
case QOP_AUTH_AUTHINT_D:
case QOP_AUTHINT_AUTH_D:
if (qop == QOP_AUTH_D || qop == QOP_AUTHINT_D)
break;
/* Fall through */
default:
LM_DBG("nonce (%d) does not match qop (%d)\n", np.qop, qop);
goto stalenonce;
}
}
if (is_nonce_stale(&np, nonce_expire)) {
LM_DBG("stale nonce value received\n");
Expand Down
49 changes: 30 additions & 19 deletions modules/auth/challenge.c
Expand Up @@ -60,7 +60,8 @@

#define QOP_AUTH ", qop=\"" QOP_AUTH_STR "\""
#define QOP_AUTH_INT ", qop=\"" QOP_AUTHINT_STR "\""
#define QOP_AUTH_BOTH ", qop=\"" QOP_AUTH_STR "," QOP_AUTHINT_STR "\""
#define QOP_AUTH_BOTH_AAI ", qop=\"" QOP_AUTH_STR "," QOP_AUTHINT_STR "\""
#define QOP_AUTH_BOTH_AIA ", qop=\"" QOP_AUTHINT_STR "," QOP_AUTH_STR "\""
#define STALE_PARAM ", stale=true"
#define DIGEST_REALM ": Digest realm=\""
#define DIGEST_NONCE "\", nonce=\""
Expand All @@ -71,7 +72,7 @@
* Create {WWW,Proxy}-Authenticate header field
*/
static inline char *build_auth_hf(int _retries, int _stale,
const str_const *_realm, int* _len, int _qop, alg_t alg,
const str_const *_realm, int* _len, qop_type_t _qop, alg_t alg,
const str_const *alg_val, const str_const* _hf_name,
int index)
{
Expand All @@ -84,12 +85,22 @@ static inline char *build_auth_hf(int _retries, int _stale,
struct nonce_params calc_np;

if (_qop) {
if (_qop == QOP_TYPE_AUTH) {
switch (_qop) {
case QOP_AUTH_D:
qop_param = str_const_init(QOP_AUTH);
} else if (_qop == QOP_TYPE_AUTH_INT) {
break;
case QOP_AUTHINT_D:
qop_param = str_const_init(QOP_AUTH_INT);
} else {
qop_param = str_const_init(QOP_AUTH_BOTH);
break;
case QOP_AUTHINT_AUTH_D:
qop_param = str_const_init(QOP_AUTH_BOTH_AAI);
break;
case QOP_AUTH_AUTHINT_D:
qop_param = str_const_init(QOP_AUTH_BOTH_AIA);
break;
default:
LM_ERR("Wrong _qop value: %d\n", _qop);
abort();
}
}
if (_stale)
Expand Down Expand Up @@ -164,7 +175,7 @@ static inline char *build_auth_hf(int _retries, int _stale,
/*
* Create and send a challenge
*/
static inline int challenge(struct sip_msg* _msg, str *realm, int _qop,
static inline int challenge(struct sip_msg* _msg, str *realm, qop_type_t _qop,
int _code, const str *reason, const str_const *_challenge_msg, int algmask)
{
struct hdr_field* h = NULL;
Expand Down Expand Up @@ -204,9 +215,9 @@ static inline int challenge(struct sip_msg* _msg, str *realm, int _qop,
}

nalgs = 0;
if (algmask >= ALGFLG_SHA256 && _qop == 0) {
/* RFC8760 mandates QOP */
_qop = QOP_TYPE_AUTH;
if (algmask >= ALG_MD5SESS && _qop == QOP_UNSPEC_D) {
/* RFC8760 algos and XYZ-sess mandates QOP */
_qop = QOP_AUTH_D;
}
if(!disable_nonce_check) {
/* get the nonce index and mark it as used */
Expand Down Expand Up @@ -253,7 +264,7 @@ static inline int challenge(struct sip_msg* _msg, str *realm, int _qop,
int fixup_qop(void** param)
{
str *s = (str*)*param;
int qop_type = 0;
qop_type_t qop_type = QOP_UNSPEC_D;
csv_record *q_csv, *q;

q_csv = parse_csv_record(s);
Expand All @@ -263,15 +274,15 @@ int fixup_qop(void** param)
}
for (q = q_csv; q; q = q->next) {
if (!str_strcmp(&q->s, const_str(QOP_AUTH_STR))) {
if (qop_type == QOP_TYPE_AUTH_INT)
qop_type = QOP_TYPE_BOTH;
if (qop_type == QOP_AUTHINT_D)
qop_type = QOP_AUTHINT_AUTH_D;
else
qop_type = QOP_TYPE_AUTH;
qop_type = QOP_AUTH_D;
} else if (!str_strcmp(&q->s, const_str(QOP_AUTHINT_STR))) {
if (qop_type == QOP_TYPE_AUTH)
qop_type = QOP_TYPE_BOTH;
if (qop_type == QOP_AUTH_D)
qop_type = QOP_AUTH_AUTHINT_D;
else
qop_type = QOP_TYPE_AUTH_INT;
qop_type = QOP_AUTHINT_D;
} else {
LM_ERR("Bad qop type\n");
free_csv_record(q_csv);
Expand All @@ -291,7 +302,7 @@ int www_challenge(struct sip_msg* _msg, str* _realm, void* _qop,
intptr_t algmask)
{

return challenge(_msg, _realm, (int)(long)_qop, WWW_AUTH_CODE,
return challenge(_msg, _realm, (qop_type_t)(long)_qop, WWW_AUTH_CODE,
&str_init(MESSAGE_401), &str_const_init(WWW_AUTH_HDR),
algmask ? algmask : ALGFLG_UNSPEC);
}
Expand All @@ -304,7 +315,7 @@ int proxy_challenge(struct sip_msg* _msg, str* _realm, void* _qop,
intptr_t algmask)
{

return challenge(_msg, _realm, (int)(long)_qop, PROXY_AUTH_CODE,
return challenge(_msg, _realm, (qop_type_t)(long)_qop, PROXY_AUTH_CODE,
&str_init(MESSAGE_407), &str_const_init(PROXY_AUTH_HDR),
algmask ? algmask : ALGFLG_UNSPEC);
}
Expand Down
4 changes: 0 additions & 4 deletions modules/auth/challenge.h
Expand Up @@ -26,10 +26,6 @@

#include "../../parser/msg_parser.h"

#define QOP_TYPE_AUTH QOP_AUTH_D
#define QOP_TYPE_AUTH_INT QOP_AUTHINT_D
#define QOP_TYPE_BOTH (QOP_AUTH_D + QOP_AUTHINT_D)

int fixup_qop(void** param);

/*
Expand Down
4 changes: 3 additions & 1 deletion parser/digest/digest.c
Expand Up @@ -125,7 +125,7 @@ dig_err_t check_dig_cred(dig_cred_t* _c)
/* If QOP parameter is present, some additional
* requirements must be met
*/
if ((_c->qop.qop_parsed == QOP_AUTH_D) || (_c->qop.qop_parsed == QOP_AUTHINT_D)) {
if (_c->qop.qop_parsed != QOP_UNSPEC_D) {
/* CNONCE must be specified */
if (_c->cnonce.s == 0) res |= E_DIG_CNONCE;
/* and also nonce count must be specified */
Expand Down Expand Up @@ -175,6 +175,8 @@ void print_cred(dig_cred_t* _c)
CASE_PRINTENUM(QOP_UNSPEC_D);
CASE_PRINTENUM(QOP_AUTH_D);
CASE_PRINTENUM(QOP_AUTHINT_D);
CASE_PRINTENUM(QOP_AUTHINT_AUTH_D);
CASE_PRINTENUM(QOP_AUTH_AUTHINT_D);
CASE_PRINTENUM(QOP_OTHER_D);
}
printf("NC = \'%.*s\'\n", _c->nc.len, _c->nc.s);
Expand Down
4 changes: 3 additions & 1 deletion parser/digest/digest_parser.h
Expand Up @@ -69,7 +69,9 @@ typedef enum qop_type {
QOP_UNSPEC_D = 0, /* QOP parameter not present in response */
QOP_AUTH_D = 1, /* Authentication only */
QOP_AUTHINT_D = 2, /* Authentication with integrity checks */
QOP_OTHER_D = 4 /* Unknown */
QOP_AUTHINT_AUTH_D = 3, /* Authentication with integrity checks+Authentication only */
QOP_AUTH_AUTHINT_D = 4, /* Authentication only+Authentication with integrity checks */
QOP_OTHER_D = 5 /* Unknown */
} qop_type_t;

/* Canonical QOP names */
Expand Down

0 comments on commit 2825caa

Please sign in to comment.