diff --git a/lib/digest_auth/dauth_nonce.c b/lib/digest_auth/dauth_nonce.c index 0e760aa1260..9d8311d7c41 100644 --- a/lib/digest_auth/dauth_nonce.c +++ b/lib/digest_auth/dauth_nonce.c @@ -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; diff --git a/modules/auth/api.c b/modules/auth/api.c index 3b384992059..0d7ced8494b 100644 --- a/modules/auth/api.c +++ b/modules/auth/api.c @@ -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_TYPE_AUTH_AUTH_INT: + case QOP_TYPE_AUTH_INT_AUTH: + 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"); diff --git a/modules/auth/challenge.c b/modules/auth/challenge.c index c4dcd0b7df7..56cf6810c04 100644 --- a/modules/auth/challenge.c +++ b/modules/auth/challenge.c @@ -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=\"" @@ -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_TYPE_AUTH: qop_param = str_const_init(QOP_AUTH); - } else if (_qop == QOP_TYPE_AUTH_INT) { + break; + case QOP_TYPE_AUTH_INT: qop_param = str_const_init(QOP_AUTH_INT); - } else { - qop_param = str_const_init(QOP_AUTH_BOTH); + break; + case QOP_TYPE_AUTH_AUTH_INT: + qop_param = str_const_init(QOP_AUTH_BOTH_AAI); + break; + case QOP_TYPE_AUTH_INT_AUTH: + qop_param = str_const_init(QOP_AUTH_BOTH_AIA); + break; + default: + LM_ERR("Wrong _qop value: %d\n", _qop); + abort(); } } if (_stale) @@ -264,12 +275,12 @@ 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; + qop_type = QOP_TYPE_AUTH_INT_AUTH; else qop_type = QOP_TYPE_AUTH; } else if (!str_strcmp(&q->s, const_str(QOP_AUTHINT_STR))) { if (qop_type == QOP_TYPE_AUTH) - qop_type = QOP_TYPE_BOTH; + qop_type = QOP_TYPE_AUTH_AUTH_INT; else qop_type = QOP_TYPE_AUTH_INT; } else { diff --git a/modules/auth/challenge.h b/modules/auth/challenge.h index 38a79a97b0a..7e32a371077 100644 --- a/modules/auth/challenge.h +++ b/modules/auth/challenge.h @@ -28,7 +28,8 @@ #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) +#define QOP_TYPE_AUTH_INT_AUTH QOP_AUTHINT_AUTH_D +#define QOP_TYPE_AUTH_AUTH_INT QOP_AUTH_AUTHINT_D int fixup_qop(void** param); diff --git a/parser/digest/digest.c b/parser/digest/digest.c index e1a134fe1e0..a957aee6f3b 100644 --- a/parser/digest/digest.c +++ b/parser/digest/digest.c @@ -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 */ @@ -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); diff --git a/parser/digest/digest_parser.h b/parser/digest/digest_parser.h index f3567206631..9c92ec3f43b 100644 --- a/parser/digest/digest_parser.h +++ b/parser/digest/digest_parser.h @@ -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 */