Skip to content

Commit c66ce91

Browse files
committed
Fix nc not resetting when server issues new nonce without stale=true.
When a server challenged with a new nonce but omitted stale=true, the nonce count (nc) carried over from the previous nonce instead of resetting to 1. Detect nonce changes by comparing the new nonce against the stored one, and regenerate cnonce/reset nc accordingly.
1 parent 0106ad0 commit c66ce91

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

libsofia-sip-ua/iptsec/auth_client.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,11 @@ static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch)
865865
if (ac->ac_qop && !ac->ac_auth && !ac->ac_auth_int)
866866
goto error;
867867

868-
stale = ac->ac_stale || cda->cda_ac->ac_nonce == NULL;
868+
stale = ac->ac_stale || cda->cda_ac->ac_nonce == NULL
869+
|| su_strcmp(ac->ac_nonce, cda->cda_ac->ac_nonce) != 0;
869870

870-
if (ac->ac_qop && (cda->cda_cnonce == NULL || ac->ac_stale || ca->ca_clear )) {
871+
if (ac->ac_qop && (cda->cda_cnonce == NULL || ac->ac_stale || ca->ca_clear
872+
|| su_strcmp(ac->ac_nonce, cda->cda_ac->ac_nonce) != 0)) {
871873
su_guid_t guid[1];
872874
char *cnonce;
873875
size_t b64len = BASE64_MINSIZE(sizeof(guid)) + 1;

libsofia-sip-ua/iptsec/test_auth_digest.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,85 @@ int test_digest_client(void)
10031003
TEST(as->as_status, 0);
10041004
auth_mod_destroy(am); aucs = NULL;
10051005

1006+
/* Test nc reset on new nonce without stale=true.
1007+
*
1008+
* When a server issues a fresh 401 with a new nonce but without
1009+
* stale=true, the nc counter must reset to 00000001 for the new nonce.
1010+
* See RFC 2617 section 3.2.2.
1011+
*/
1012+
{
1013+
1014+
TEST_1(am = auth_mod_create(root,
1015+
AUTHTAG_METHOD("Digest"),
1016+
AUTHTAG_REALM("ims3.so.noklab.net"),
1017+
AUTHTAG_DB(testpasswd),
1018+
AUTHTAG_QOP("auth"),
1019+
AUTHTAG_MAX_NCOUNT(5),
1020+
AUTHTAG_ALGORITHM("MD5"),
1021+
TAG_END()));
1022+
1023+
/* Get initial 401 challenge (nonce A) */
1024+
reinit_as(as);
1025+
auth_mod_check_client(am, as, NULL, ach);
1026+
TEST(as->as_status, 401);
1027+
TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1028+
sip_authorization_class), 1);
1029+
TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
1030+
"user1", "secret"), 1);
1031+
1032+
/* Authorize with nonce A — nc must be 00000001 */
1033+
msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1034+
TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1035+
(url_t *)"sip:surf3@ims3.so.noklab.net",
1036+
sip->sip_payload), 1);
1037+
TEST_1(sip->sip_authorization);
1038+
TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
1039+
"00000001");
1040+
1041+
/* Server accepts auth with nonce A */
1042+
reinit_as(as);
1043+
auth_mod_check_client(am, as, sip->sip_authorization, ach);
1044+
TEST(as->as_status, 0);
1045+
1046+
/* Advance time so the new auth_mod generates a different nonce.
1047+
* Nonce includes the timestamp, so a 1-second shift is enough. */
1048+
offset += 1;
1049+
1050+
/* Destroy auth_mod to get a different nonce on next challenge */
1051+
auth_mod_destroy(am);
1052+
TEST_1(am = auth_mod_create(root,
1053+
AUTHTAG_METHOD("Digest"),
1054+
AUTHTAG_REALM("ims3.so.noklab.net"),
1055+
AUTHTAG_DB(testpasswd),
1056+
AUTHTAG_QOP("auth"),
1057+
AUTHTAG_MAX_NCOUNT(5),
1058+
AUTHTAG_ALGORITHM("MD5"),
1059+
TAG_END()));
1060+
1061+
/* Get new 401 challenge (nonce B, stale=false) */
1062+
reinit_as(as);
1063+
auth_mod_check_client(am, as, NULL, ach);
1064+
TEST(as->as_status, 401);
1065+
TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1066+
sip_authorization_class), 1);
1067+
1068+
/* Authorize with nonce B — nc MUST reset to 00000001, not 00000002 */
1069+
msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1070+
TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1071+
(url_t *)"sip:surf3@ims3.so.noklab.net",
1072+
sip->sip_payload), 1);
1073+
TEST_1(sip->sip_authorization);
1074+
TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
1075+
"00000001");
1076+
1077+
/* Server accepts auth with nonce B */
1078+
reinit_as(as);
1079+
auth_mod_check_client(am, as, sip->sip_authorization, ach);
1080+
TEST(as->as_status, 0);
1081+
1082+
auth_mod_destroy(am); aucs = NULL;
1083+
}
1084+
10061085
/* Test empty realm */
10071086
TEST_1(am = auth_mod_create(root,
10081087
AUTHTAG_METHOD("Digest"),

0 commit comments

Comments
 (0)