@@ -918,6 +918,86 @@ static int test_DoChannelRequest(void)
918918 return result ;
919919}
920920
921+ /* IO send callback that discards all output (returns sz as if sent).
922+ * Used by tests that call functions which send packets but have no real
923+ * socket — e.g., SendUserAuthFailure in test_DoUserAuthRequest_serviceName. */
924+ static int discardSend (WOLFSSH * ssh , void * buf , word32 sz , void * ctx )
925+ {
926+ (void )ssh ; (void )buf ; (void )ctx ;
927+ return (int )sz ;
928+ }
929+
930+ /* Verify DoUserAuthRequest rejects non-"ssh-connection" service names per
931+ * RFC 4252 Section 5. Invalid names must:
932+ * - send SSH_MSG_USERAUTH_FAILURE (partial_success = false)
933+ * - return WS_SUCCESS so the connection stays open for retry
934+ * - set *idx = len to consume the entire payload (keeps buffer aligned)
935+ * Valid "ssh-connection" must proceed to the auth-method dispatch normally. */
936+ static int test_DoUserAuthRequest_serviceName (void )
937+ {
938+ WOLFSSH_CTX * ctx = NULL ;
939+ WOLFSSH * ssh = NULL ;
940+ int result = 0 ;
941+ struct {
942+ const char * svcName ;
943+ word32 svcNameSz ;
944+ int expectRet ;
945+ const char * label ;
946+ } cases [] = {
947+ { "ssh-connection" , 14 , WS_SUCCESS , "valid service name" },
948+ { "ssh-agent" , 9 , WS_SUCCESS , "ssh-agent rejected conn open" },
949+ { "bad" , 3 , WS_SUCCESS , "unknown name rejected conn open" },
950+ };
951+ int i ;
952+
953+ ctx = wolfSSH_CTX_new (WOLFSSH_ENDPOINT_SERVER , NULL );
954+ if (ctx == NULL ) return -500 ;
955+ wolfSSH_SetIOSend (ctx , discardSend );
956+
957+ ssh = wolfSSH_new (ctx );
958+ if (ssh == NULL ) { wolfSSH_CTX_free (ctx ); return -501 ; }
959+
960+ for (i = 0 ; i < (int )(sizeof (cases )/sizeof (cases [0 ])); i ++ ) {
961+ byte buf [128 ];
962+ word32 len = 0 , idx = 0 ;
963+ word32 snsz = cases [i ].svcNameSz ;
964+ int ret ;
965+
966+ /* username: "user" (4 bytes) */
967+ buf [len ++ ] = 0 ; buf [len ++ ] = 0 ; buf [len ++ ] = 0 ; buf [len ++ ] = 4 ;
968+ WMEMCPY (buf + len , "user" , 4 ); len += 4 ;
969+
970+ /* service name */
971+ buf [len ++ ] = (byte )(snsz >> 24 ); buf [len ++ ] = (byte )(snsz >> 16 );
972+ buf [len ++ ] = (byte )(snsz >> 8 ); buf [len ++ ] = (byte )snsz ;
973+ WMEMCPY (buf + len , cases [i ].svcName , snsz ); len += snsz ;
974+
975+ /* auth method: "none" */
976+ buf [len ++ ] = 0 ; buf [len ++ ] = 0 ; buf [len ++ ] = 0 ; buf [len ++ ] = 4 ;
977+ WMEMCPY (buf + len , "none" , 4 ); len += 4 ;
978+
979+ ret = wolfSSH_TestDoUserAuthRequest (ssh , buf , len , & idx );
980+
981+ if (ret != cases [i ].expectRet ) {
982+ printf ("DoUserAuthRequest_svcName[%s]: ret=%d expected=%d\n" ,
983+ cases [i ].label , ret , cases [i ].expectRet );
984+ result = -502 - i ;
985+ break ;
986+ }
987+
988+ if (i > 0 && idx != len ) {
989+ printf ("DoUserAuthRequest_svcName[%s]: idx=%u expected len=%u\n" ,
990+ cases [i ].label , idx , len );
991+ result = -510 - i ;
992+ break ;
993+ }
994+ }
995+
996+ wolfSSH_free (ssh );
997+ wolfSSH_CTX_free (ctx );
998+ return result ;
999+ }
1000+
9211001#if !defined(WOLFSSH_NO_RSA )
9221002
9231003/* 2048-bit RSA private key (PKCS#1 DER).
@@ -1210,6 +1290,11 @@ int wolfSSH_UnitTest(int argc, char** argv)
12101290 unitResult = test_ChannelPutData ();
12111291 printf ("ChannelPutData: %s\n" , (unitResult == 0 ? "SUCCESS" : "FAILED" ));
12121292 testResult = testResult || unitResult ;
1293+
1294+ unitResult = test_DoUserAuthRequest_serviceName ();
1295+ printf ("DoUserAuthRequest_serviceName: %s\n" ,
1296+ (unitResult == 0 ? "SUCCESS" : "FAILED" ));
1297+ testResult = testResult || unitResult ;
12131298#endif
12141299
12151300#ifdef WOLFSSH_KEYGEN
0 commit comments