@@ -231,6 +231,21 @@ static word32 BuildDirectTcpipExtra(const char* host, word32 hostPort,
231231
232232 return idx ;
233233}
234+
235+ static word32 BuildGlobalRequestFwdPacket (const char * bindAddr , word32 bindPort ,
236+ int isCancel , byte wantReply , byte * out , word32 outSz )
237+ {
238+ byte payload [256 ];
239+ word32 idx = 0 ;
240+ const char * reqName = isCancel ? "cancel-tcpip-forward" : "tcpip-forward" ;
241+
242+ idx = AppendString (payload , sizeof (payload ), idx , reqName );
243+ idx = AppendByte (payload , sizeof (payload ), idx , wantReply );
244+ idx = AppendString (payload , sizeof (payload ), idx , bindAddr );
245+ idx = AppendUint32 (payload , sizeof (payload ), idx , bindPort );
246+
247+ return WrapPacket (MSGID_GLOBAL_REQUEST , payload , idx , out , outSz );
248+ }
234249#endif
235250
236251/* Simple in-memory transport harness */
@@ -957,6 +972,15 @@ static void AssertChannelOpenFailResponse(const ChannelOpenHarness* harness,
957972 AssertTrue (harness -> ssh -> channelList == NULL );
958973}
959974
975+ #ifdef WOLFSSH_FWD
976+ static void AssertGlobalRequestReply (const ChannelOpenHarness * harness ,
977+ byte expectedMsgId )
978+ {
979+ AssertTrue (harness -> io .outSz > 0 );
980+ AssertIntEQ (ParseMsgId (harness -> io .out , harness -> io .outSz ), expectedMsgId );
981+ }
982+ #endif
983+
960984static int RejectChannelOpenCb (WOLFSSH_CHANNEL * channel , void * ctx )
961985{
962986 (void )channel ;
@@ -978,6 +1002,17 @@ static int RejectDirectTcpipSetup(WS_FwdCbAction action, void* ctx,
9781002
9791003 return WS_SUCCESS ;
9801004}
1005+
1006+ static int AcceptFwdCb (WS_FwdCbAction action , void * ctx ,
1007+ const char * host , word32 port )
1008+ {
1009+ (void )action ;
1010+ (void )ctx ;
1011+ (void )host ;
1012+ (void )port ;
1013+
1014+ return WS_SUCCESS ;
1015+ }
9811016#endif
9821017
9831018
@@ -1239,6 +1274,101 @@ static void TestDirectTcpipNoFwdCbSendsOpenFail(void)
12391274
12401275 ret = DoReceive (harness .ssh );
12411276 AssertChannelOpenFailResponse (& harness , ret );
1277+
1278+ FreeChannelOpenHarness (& harness );
1279+ }
1280+
1281+ static void TestGlobalRequestFwdNoCbSendsFailure (void )
1282+ {
1283+ ChannelOpenHarness harness ;
1284+ byte in [256 ];
1285+ word32 inSz ;
1286+ int ret ;
1287+
1288+ inSz = BuildGlobalRequestFwdPacket ("0.0.0.0" , 2222 , 0 , 1 , in , sizeof (in ));
1289+ InitChannelOpenHarness (& harness , in , inSz );
1290+ /* no fwdCb registered */
1291+
1292+ ret = DoReceive (harness .ssh );
1293+
1294+ AssertIntEQ (ret , WS_SUCCESS );
1295+ AssertGlobalRequestReply (& harness , MSGID_REQUEST_FAILURE );
1296+
1297+ FreeChannelOpenHarness (& harness );
1298+ }
1299+
1300+ static void TestGlobalRequestFwdNoCbNoReplyKeepsConnection (void )
1301+ {
1302+ ChannelOpenHarness harness ;
1303+ byte in [256 ];
1304+ word32 inSz ;
1305+ int ret ;
1306+
1307+ /* wantReply=0: no reply sent, connection must stay alive */
1308+ inSz = BuildGlobalRequestFwdPacket ("0.0.0.0" , 2222 , 0 , 0 , in , sizeof (in ));
1309+ InitChannelOpenHarness (& harness , in , inSz );
1310+ /* no fwdCb registered */
1311+
1312+ ret = DoReceive (harness .ssh );
1313+
1314+ AssertIntEQ (ret , WS_SUCCESS );
1315+ AssertIntEQ (harness .io .outSz , 0 ); /* no reply sent */
1316+
1317+ FreeChannelOpenHarness (& harness );
1318+ }
1319+
1320+ static void TestGlobalRequestFwdWithCbSendsSuccess (void )
1321+ {
1322+ ChannelOpenHarness harness ;
1323+ byte in [256 ];
1324+ word32 inSz ;
1325+ int ret ;
1326+
1327+ inSz = BuildGlobalRequestFwdPacket ("0.0.0.0" , 2222 , 0 , 1 , in , sizeof (in ));
1328+ InitChannelOpenHarness (& harness , in , inSz );
1329+ AssertIntEQ (wolfSSH_CTX_SetFwdCb (harness .ctx , AcceptFwdCb , NULL ), WS_SUCCESS );
1330+
1331+ ret = DoReceive (harness .ssh );
1332+
1333+ AssertIntEQ (ret , WS_SUCCESS );
1334+ AssertGlobalRequestReply (& harness , MSGID_REQUEST_SUCCESS );
1335+
1336+ FreeChannelOpenHarness (& harness );
1337+ }
1338+
1339+ static void TestGlobalRequestFwdCancelNoCbSendsFailure (void )
1340+ {
1341+ ChannelOpenHarness harness ;
1342+ byte in [256 ];
1343+ word32 inSz ;
1344+ int ret ;
1345+
1346+ inSz = BuildGlobalRequestFwdPacket ("0.0.0.0" , 2222 , 1 , 1 , in , sizeof (in ));
1347+ InitChannelOpenHarness (& harness , in , inSz );
1348+
1349+ ret = DoReceive (harness .ssh );
1350+
1351+ AssertIntEQ (ret , WS_SUCCESS );
1352+ AssertGlobalRequestReply (& harness , MSGID_REQUEST_FAILURE );
1353+
1354+ FreeChannelOpenHarness (& harness );
1355+ }
1356+
1357+ static void TestGlobalRequestFwdCancelWithCbSendsSuccess (void )
1358+ {
1359+ ChannelOpenHarness harness ;
1360+ byte in [256 ];
1361+ word32 inSz ;
1362+ int ret ;
1363+
1364+ inSz = BuildGlobalRequestFwdPacket ("0.0.0.0" , 2222 , 1 , 1 , in , sizeof (in ));
1365+ InitChannelOpenHarness (& harness , in , inSz );
1366+ AssertIntEQ (wolfSSH_CTX_SetFwdCb (harness .ctx , AcceptFwdCb , NULL ), WS_SUCCESS );
1367+
1368+ ret = DoReceive (harness .ssh );
1369+
1370+ AssertIntEQ (ret , WS_SUCCESS );
1371+ AssertGlobalRequestReply (& harness , MSGID_REQUEST_SUCCESS );
12421372
12431373 FreeChannelOpenHarness (& harness );
12441374}
@@ -1707,6 +1837,11 @@ int main(int argc, char** argv)
17071837#ifdef WOLFSSH_FWD
17081838 TestDirectTcpipRejectSendsOpenFail ();
17091839 TestDirectTcpipNoFwdCbSendsOpenFail ();
1840+ TestGlobalRequestFwdNoCbSendsFailure ();
1841+ TestGlobalRequestFwdNoCbNoReplyKeepsConnection ();
1842+ TestGlobalRequestFwdWithCbSendsSuccess ();
1843+ TestGlobalRequestFwdCancelNoCbSendsFailure ();
1844+ TestGlobalRequestFwdCancelWithCbSendsSuccess ();
17101845#endif
17111846#ifdef WOLFSSH_AGENT
17121847 TestAgentChannelNullAgentSendsOpenFail ();
0 commit comments