Skip to content

Commit a1d1493

Browse files
Report allocated port in tcpip-forward success reply
1 parent 1efd647 commit a1d1493

6 files changed

Lines changed: 204 additions & 18 deletions

File tree

examples/echoserver/echoserver.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -501,15 +501,15 @@ static WS_SOCKET_T connect_addr(const char* name, word16 port)
501501

502502

503503
static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
504-
const char* name, word32 port)
504+
const char* name, word32* port)
505505
{
506506
WS_AppCtx *appCtx = (WS_AppCtx *)vCtx;
507507
WS_FwdCbActionCtx* fwdCbCtx = (WS_FwdCbActionCtx *)appCtx->privateData;
508508
int ret = 0;
509509

510510
if (action == WOLFSSH_FWD_LOCAL_SETUP) {
511511
fwdCbCtx->hostName = WSTRDUP(name, NULL, 0);
512-
fwdCbCtx->hostPort = port;
512+
fwdCbCtx->hostPort = *port;
513513
fwdCbCtx->isDirect = 1;
514514
appCtx->state = APP_STATE_CONNECT;
515515
}
@@ -529,9 +529,10 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
529529
else if (action == WOLFSSH_FWD_REMOTE_SETUP) {
530530
struct sockaddr_in addr;
531531
socklen_t addrSz = 0;
532+
socklen_t boundSz = sizeof(addr);
532533

533534
fwdCbCtx->hostName = WSTRDUP(name, NULL, 0);
534-
fwdCbCtx->hostPort = port;
535+
fwdCbCtx->hostPort = *port;
535536

536537
appCtx->listenFd = socket(AF_INET, SOCK_STREAM, 0);
537538
if (appCtx->listenFd == -1) {
@@ -548,7 +549,7 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
548549

549550
addr.sin_addr.s_addr = INADDR_ANY;
550551
addr.sin_family = AF_INET;
551-
addr.sin_port = htons((word16)port);
552+
addr.sin_port = htons((word16)*port);
552553
addrSz = sizeof addr;
553554
}
554555
else {
@@ -566,6 +567,21 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
566567
ret = listen(appCtx->listenFd, 5);
567568
}
568569

570+
if (ret == 0 && *port == 0) {
571+
/* The peer requested port 0, so the OS picked the port during
572+
* bind(). Report the actual port back to the caller. */
573+
WMEMSET(&addr, 0, sizeof addr);
574+
if (getsockname(appCtx->listenFd,
575+
(struct sockaddr*)&addr, &boundSz) == 0) {
576+
*port = (word32)ntohs(addr.sin_port);
577+
fwdCbCtx->hostPort = *port;
578+
}
579+
else {
580+
printf("getsockname failed for forwarded port.\n");
581+
ret = -1;
582+
}
583+
}
584+
569585
if (ret == 0) {
570586
appCtx->state = APP_STATE_LISTEN;
571587
}
@@ -597,7 +613,7 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
597613
appCtx->state = APP_STATE_INIT;
598614
}
599615
else if (action == WOLFSSH_FWD_CHANNEL_ID) {
600-
appCtx->channelId = port;
616+
appCtx->channelId = *port;
601617
}
602618
else
603619
ret = WS_FWD_INVALID_ACTION;

ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -495,14 +495,14 @@ static WS_SOCKET_T connect_addr(const char* name, word16 port)
495495

496496

497497
static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
498-
const char* name, word32 port)
498+
const char* name, word32* port)
499499
{
500500
WS_FwdCbActionCtx* ctx = (WS_FwdCbActionCtx*)vCtx;
501501
int ret = 0;
502502

503503
if (action == WOLFSSH_FWD_LOCAL_SETUP) {
504504
ctx->hostName = WSTRDUP(name, NULL, 0);
505-
ctx->hostPort = port;
505+
ctx->hostPort = *port;
506506
ctx->isDirect = 1;
507507
ctx->state = FWD_STATE_DIRECT;
508508
}
@@ -521,9 +521,10 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
521521
else if (action == WOLFSSH_FWD_REMOTE_SETUP) {
522522
struct sockaddr_in addr;
523523
socklen_t addrSz = 0;
524+
socklen_t boundSz = sizeof(addr);
524525

525526
ctx->hostName = WSTRDUP(name, NULL, 0);
526-
ctx->hostPort = port;
527+
ctx->hostPort = *port;
527528

528529
ctx->listenFd = socket(AF_INET, SOCK_STREAM, 0);
529530
if (ctx->listenFd == -1) {
@@ -540,7 +541,7 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
540541

541542
addr.sin_addr.s_addr = INADDR_ANY;
542543
addr.sin_family = AF_INET;
543-
addr.sin_port = htons((word16)port);
544+
addr.sin_port = htons((word16)*port);
544545
addrSz = sizeof addr;
545546
}
546547
else {
@@ -558,6 +559,21 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
558559
ret = listen(ctx->listenFd, 5);
559560
}
560561

562+
if (ret == 0 && *port == 0) {
563+
/* The peer requested port 0, so the OS picked the port during
564+
* bind(). Report the actual port back to the caller. */
565+
WMEMSET(&addr, 0, sizeof addr);
566+
if (getsockname(ctx->listenFd,
567+
(struct sockaddr*)&addr, &boundSz) == 0) {
568+
*port = (word32)ntohs(addr.sin_port);
569+
ctx->hostPort = *port;
570+
}
571+
else {
572+
printf("getsockname failed for forwarded port.\n");
573+
ret = -1;
574+
}
575+
}
576+
561577
if (ret == 0) {
562578
ctx->state = FWD_STATE_LISTEN;
563579
}
@@ -589,7 +605,7 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
589605
ctx->state = FWD_STATE_INIT;
590606
}
591607
else if (action == WOLFSSH_FWD_CHANNEL_ID) {
592-
ctx->channelId = port;
608+
ctx->channelId = *port;
593609
}
594610
else
595611
ret = WS_FWD_INVALID_ACTION;

src/internal.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8917,6 +8917,7 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh,
89178917
int ret = WS_SUCCESS;
89188918
char* bindAddr = NULL;
89198919
word32 bindPort;
8920+
word32 requestedPort = 0;
89208921

89218922
WLOG(WS_LOG_DEBUG, "Entering DoGlobalRequestFwd()");
89228923

@@ -8935,6 +8936,7 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh,
89358936
}
89368937

89378938
if (ret == WS_SUCCESS) {
8939+
requestedPort = bindPort;
89388940
WLOG(WS_LOG_INFO, "Requesting forwarding%s for address %s on port %u.",
89398941
isCancel ? " cancel" : "", bindAddr, bindPort);
89408942
}
@@ -8943,7 +8945,7 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh,
89438945
if (ssh->ctx->fwdCb) {
89448946
ret = ssh->ctx->fwdCb(isCancel ? WOLFSSH_FWD_REMOTE_CLEANUP :
89458947
WOLFSSH_FWD_REMOTE_SETUP,
8946-
ssh->fwdCbCtx, bindAddr, bindPort);
8948+
ssh->fwdCbCtx, bindAddr, &bindPort);
89478949
}
89488950
else {
89498951
WLOG(WS_LOG_WARN, "No forwarding callback set, rejecting request. "
@@ -8952,6 +8954,27 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh,
89528954
}
89538955
}
89548956

8957+
if (ret == WS_SUCCESS && !isCancel) {
8958+
/* A remote forward was set up successfully. RFC 4254 7.1 requires a
8959+
* port-0 (dynamic) request to be answered with the allocated port; if
8960+
* the callback reported none we cannot comply, so undo the setup and
8961+
* reject instead of sending a success carrying port 0. */
8962+
if (requestedPort == 0 && bindPort == 0) {
8963+
int cleanupRet;
8964+
word32 cleanupPort = bindPort;
8965+
8966+
WLOG(WS_LOG_WARN, "Forward callback reported no allocated port "
8967+
"for a port-0 request; rejecting.");
8968+
cleanupRet = ssh->ctx->fwdCb(WOLFSSH_FWD_REMOTE_CLEANUP,
8969+
ssh->fwdCbCtx, bindAddr, &cleanupPort);
8970+
if (cleanupRet != WS_SUCCESS) {
8971+
WLOG(WS_LOG_WARN, "Forward cleanup after rejection failed, "
8972+
"ret = %d", cleanupRet);
8973+
}
8974+
ret = WS_RESOURCE_E;
8975+
}
8976+
}
8977+
89558978
if (wantReply) {
89568979
if (ret == WS_SUCCESS) {
89578980
if (isCancel) {
@@ -8965,7 +8988,7 @@ static int DoGlobalRequestFwd(WOLFSSH* ssh,
89658988
ret = SendRequestSuccess(ssh, 0);
89668989
}
89678990
}
8968-
else if (ret == WS_UNIMPLEMENTED_E) {
8991+
else if (ret == WS_UNIMPLEMENTED_E || ret == WS_RESOURCE_E) {
89698992
/* No reply expected; silently reject without terminating connection. */
89708993
ret = WS_SUCCESS;
89718994
}
@@ -9105,6 +9128,7 @@ static int DoChannelOpen(WOLFSSH* ssh,
91059128
char* host = NULL;
91069129
char* origin = NULL;
91079130
word32 hostPort = 0, originPort = 0;
9131+
word32 channelId = 0;
91089132
int isDirect = 0;
91099133
#endif /* WOLFSSH_FWD */
91109134
WOLFSSH_CHANNEL* newChannel = NULL;
@@ -9201,10 +9225,13 @@ static int DoChannelOpen(WOLFSSH* ssh,
92019225

92029226
if (ssh->ctx->fwdCb) {
92039227
ret = ssh->ctx->fwdCb(WOLFSSH_FWD_LOCAL_SETUP,
9204-
ssh->fwdCbCtx, host, hostPort);
9228+
ssh->fwdCbCtx, host, &hostPort);
92059229
if (ret == WS_SUCCESS) {
9230+
/* Pass a copy so the callback cannot mutate the
9231+
* channel id and corrupt channel bookkeeping. */
9232+
channelId = newChannel->channel;
92069233
ret = ssh->ctx->fwdCb(WOLFSSH_FWD_CHANNEL_ID,
9207-
ssh->fwdCbCtx, NULL, newChannel->channel);
9234+
ssh->fwdCbCtx, NULL, &channelId);
92089235
}
92099236
}
92109237
else {

src/ssh.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2828,6 +2828,7 @@ WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNewRemote(WOLFSSH* ssh,
28282828
const char* origin, word32 originPort)
28292829
{
28302830
WOLFSSH_CHANNEL* newChannel = NULL;
2831+
word32 channelId = 0;
28312832
int ret = WS_SUCCESS;
28322833

28332834
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelFwdNewRemote()");
@@ -2848,8 +2849,11 @@ WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNewRemote(WOLFSSH* ssh,
28482849
ret = SendChannelOpenForward(ssh, newChannel);
28492850
if (ret == WS_SUCCESS) {
28502851
if (ssh->ctx->fwdCb) {
2852+
/* Pass a copy so the callback cannot mutate the channel id and
2853+
* corrupt channel bookkeeping. */
2854+
channelId = newChannel->channel;
28512855
ret = ssh->ctx->fwdCb(WOLFSSH_FWD_CHANNEL_ID, ssh->fwdCbCtx,
2852-
NULL, newChannel->channel);
2856+
NULL, &channelId);
28532857
}
28542858
}
28552859

0 commit comments

Comments
 (0)