@@ -1003,6 +1003,89 @@ 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+ * auc_challenge returns 0 here because the new nonce without
1063+ * stale=true is not recognized as an update at the auc_challenge
1064+ * level. The nc reset still happens internally in
1065+ * auc_digest_challenge via the cnonce regeneration path. */
1066+ reinit_as (as );
1067+ auth_mod_check_client (am , as , NULL , ach );
1068+ TEST (as -> as_status , 401 );
1069+ TEST (auc_challenge (& aucs , home , (msg_auth_t * )as -> as_response ,
1070+ sip_authorization_class ), 0 );
1071+
1072+ /* Authorize with nonce B — nc MUST reset to 00000001, not 00000002 */
1073+ msg_header_remove (m2 , (void * )sip , (void * )sip -> sip_authorization );
1074+ TEST (auc_authorization (& aucs , m2 , (msg_pub_t * )sip , rq -> rq_method_name ,
1075+ (url_t * )"sip:surf3@ims3.so.noklab.net" ,
1076+ sip -> sip_payload ), 1 );
1077+ TEST_1 (sip -> sip_authorization );
1078+ TEST_S (msg_header_find_param (sip -> sip_authorization -> au_common , "nc=" ),
1079+ "00000001" );
1080+
1081+ /* Server accepts auth with nonce B */
1082+ reinit_as (as );
1083+ auth_mod_check_client (am , as , sip -> sip_authorization , ach );
1084+ TEST (as -> as_status , 0 );
1085+
1086+ auth_mod_destroy (am ); aucs = NULL ;
1087+ }
1088+
10061089 /* Test empty realm */
10071090 TEST_1 (am = auth_mod_create (root ,
10081091 AUTHTAG_METHOD ("Digest" ),
0 commit comments