@@ -194,6 +194,10 @@ static int test_ConfigDefaults(void)
194194 if (wolfSSHD_ConfigGetPwAuth (conf ) == 0 )
195195 ret = WS_FATAL_ERROR ;
196196 }
197+ if (ret == WS_SUCCESS ) {
198+ if (wolfSSHD_ConfigGetPubKeyAuth (conf ) == 0 )
199+ ret = WS_FATAL_ERROR ;
200+ }
197201
198202 wolfSSHD_ConfigFree (conf );
199203 return ret ;
@@ -242,6 +246,11 @@ static int test_ParseConfigLine(void)
242246 {"Password auth yes" , "PasswordAuthentication yes" , 0 },
243247 {"Password auth invalid" , "PasswordAuthentication wolfsshd" , 1 },
244248
249+ /* Public key auth tests. */
250+ {"Pubkey auth no" , "PubkeyAuthentication no" , 0 },
251+ {"Pubkey auth yes" , "PubkeyAuthentication yes" , 0 },
252+ {"Pubkey auth invalid" , "PubkeyAuthentication wolfsshd" , 1 },
253+
245254 /* Include files tests. */
246255 {"Include file bad" , "Include sshd_config.d/test.bad" , 1 },
247256 {"Include file exists" , "Include sshd_config.d/01-test.conf" , 0 },
@@ -312,6 +321,9 @@ static int test_ConfigCopy(void)
312321 if (ret == WS_SUCCESS ) ret = PCL ("Port 2222" );
313322 if (ret == WS_SUCCESS ) ret = PCL ("LoginGraceTime 30" );
314323 if (ret == WS_SUCCESS ) ret = PCL ("PasswordAuthentication yes" );
324+ /* set to the non-default value so a dropped copy (which would leave the
325+ * wolfSSHD_ConfigNew default of 1) is caught */
326+ if (ret == WS_SUCCESS ) ret = PCL ("PubkeyAuthentication no" );
315327 if (ret == WS_SUCCESS ) ret = PCL ("PermitEmptyPasswords yes" );
316328 if (ret == WS_SUCCESS ) ret = PCL ("PermitRootLogin yes" );
317329 if (ret == WS_SUCCESS ) ret = PCL ("UsePrivilegeSeparation sandbox" );
@@ -389,6 +401,12 @@ static int test_ConfigCopy(void)
389401 if (wolfSSHD_ConfigGetPwAuth (match ) == 0 )
390402 ret = WS_FATAL_ERROR ;
391403 }
404+ /* pubKeyAuth was set to the non-default 'no' (0) on the head, so the copy
405+ * must carry 0; a dropped copy would surface as the default 1 here */
406+ if (ret == WS_SUCCESS ) {
407+ if (wolfSSHD_ConfigGetPubKeyAuth (match ) != 0 )
408+ ret = WS_FATAL_ERROR ;
409+ }
392410 if (ret == WS_SUCCESS ) {
393411 if (wolfSSHD_ConfigGetPermitEmptyPw (match ) == 0 )
394412 ret = WS_FATAL_ERROR ;
@@ -448,14 +466,17 @@ static int test_GetUserConfMatchOverride(void)
448466 * global head node unchanged. */
449467 if (ret == WS_SUCCESS ) ret = PCL ("Match User testuser" );
450468 if (ret == WS_SUCCESS ) ret = PCL ("PasswordAuthentication no" );
469+ if (ret == WS_SUCCESS ) ret = PCL ("PubkeyAuthentication no" );
451470 if (ret == WS_SUCCESS ) ret = PCL ("PermitEmptyPasswords no" );
452471 if (ret == WS_SUCCESS ) ret = PCL ("PermitRootLogin no" );
453472 if (ret == WS_SUCCESS ) ret = PCL ("AuthorizedKeysFile .ssh/match_keys" );
454473#undef PCL
455474
456- /* the global head node must keep the permissive values */
475+ /* the global head node must keep the permissive values (pubKeyAuth keeps
476+ * its default of 1, proving the Match override did not leak to the head) */
457477 if (ret == WS_SUCCESS ) {
458478 if (wolfSSHD_ConfigGetPwAuth (head ) != 1 ||
479+ wolfSSHD_ConfigGetPubKeyAuth (head ) != 1 ||
459480 wolfSSHD_ConfigGetPermitEmptyPw (head ) != 1 ||
460481 wolfSSHD_ConfigGetPermitRoot (head ) != 1 )
461482 ret = WS_FATAL_ERROR ;
@@ -473,6 +494,7 @@ static int test_GetUserConfMatchOverride(void)
473494 * ones RequestAuthentication and DoCheckUser will now enforce */
474495 if (ret == WS_SUCCESS ) {
475496 if (wolfSSHD_ConfigGetPwAuth (match ) != 0 ||
497+ wolfSSHD_ConfigGetPubKeyAuth (match ) != 0 ||
476498 wolfSSHD_ConfigGetPermitEmptyPw (match ) != 0 ||
477499 wolfSSHD_ConfigGetPermitRoot (match ) != 0 )
478500 ret = WS_FATAL_ERROR ;
@@ -855,12 +877,80 @@ static int test_CAKeysFileDiffers(void)
855877 return ret ;
856878}
857879
880+ /* Exercises the auth-method advertisement logic used by DefaultUserAuthTypes:
881+ * a method is only offered when its config option is enabled. Covers all four
882+ * permutations of PasswordAuthentication and PubkeyAuthentication, including the
883+ * security-relevant cases where pubkey is disabled and where both are disabled
884+ * (no methods advertised, mask == 0). */
885+ static int test_GetUserAuthTypes (void )
886+ {
887+ int ret = WS_SUCCESS ;
888+ int i ;
889+
890+ static const struct {
891+ const char * desc ;
892+ int pwAuth ; /* 1 = leave enabled, 0 = PasswordAuthentication no */
893+ int pubKeyAuth ; /* 1 = leave enabled, 0 = PubkeyAuthentication no */
894+ int expected ;
895+ } vectors [] = {
896+ {"both enabled advertises both" , 1 , 1 ,
897+ WOLFSSH_USERAUTH_PASSWORD | WOLFSSH_USERAUTH_PUBLICKEY },
898+ {"pubkey disabled advertises password only" , 1 , 0 ,
899+ WOLFSSH_USERAUTH_PASSWORD },
900+ {"password disabled advertises pubkey only" , 0 , 1 ,
901+ WOLFSSH_USERAUTH_PUBLICKEY },
902+ {"both disabled advertises nothing" , 0 , 0 , 0 },
903+ };
904+ const int numVectors = (int )(sizeof (vectors ) / sizeof (* vectors ));
905+ WOLFSSHD_CONFIG * conf ;
906+
907+ for (i = 0 ; i < numVectors && ret == WS_SUCCESS ; ++ i ) {
908+ Log (" Testing scenario: %s." , vectors [i ].desc );
909+
910+ conf = wolfSSHD_ConfigNew (NULL );
911+ if (conf == NULL ) {
912+ Log (" FAILED.\n" );
913+ ret = WS_MEMORY_E ;
914+ break ;
915+ }
916+
917+ /* both options default to enabled in wolfSSHD_ConfigNew, so only the
918+ * disabled cases need an explicit directive */
919+ if (vectors [i ].pwAuth == 0 ) {
920+ ret = ParseConfigLine (& conf , "PasswordAuthentication no" ,
921+ (int )WSTRLEN ("PasswordAuthentication no" ));
922+ }
923+ if (ret == WS_SUCCESS && vectors [i ].pubKeyAuth == 0 ) {
924+ ret = ParseConfigLine (& conf , "PubkeyAuthentication no" ,
925+ (int )WSTRLEN ("PubkeyAuthentication no" ));
926+ }
927+
928+ if (ret == WS_SUCCESS ) {
929+ if (wolfSSHD_GetUserAuthTypes (conf ) != vectors [i ].expected ) {
930+ Log (" FAILED.\n" );
931+ ret = WS_FATAL_ERROR ;
932+ }
933+ else {
934+ Log (" PASSED.\n" );
935+ }
936+ }
937+ else {
938+ Log (" FAILED.\n" );
939+ }
940+
941+ wolfSSHD_ConfigFree (conf );
942+ }
943+
944+ return ret ;
945+ }
946+
858947const TEST_CASE testCases [] = {
859948 TEST_DECL (test_ConfigDefaults ),
860949 TEST_DECL (test_ParseConfigLine ),
861950 TEST_DECL (test_ConfigCopy ),
862951 TEST_DECL (test_GetUserConfMatchOverride ),
863952 TEST_DECL (test_CAKeysFileDiffers ),
953+ TEST_DECL (test_GetUserAuthTypes ),
864954 TEST_DECL (test_ConfigFree ),
865955#ifdef WOLFSSL_BASE64_ENCODE
866956 TEST_DECL (test_CheckAuthKeysLine ),
0 commit comments