mirror of https://github.com/wolfSSL/wolfssh.git
internal: send LOCAL_CLEANUP on forward delete
WOLFSSH_FWD_LOCAL_CLEANUP is part of the public WS_FwdCbAction contract and the library never sent it, so an application's handler never ran and every peer-opened forward leaked what its setup callback allocated. ChannelDelete() now sends it, so a peer close, an open refused after the setup ran, wolfSSH_ChannelFree(), and freeing the session all report it. - record the setup in a new fwdSetupTxd bit on WOLFSSH_CHANNEL: a locally opened forward gets no LOCAL_SETUP, so the channel type alone cannot say whether the application holds anything - clear the bit when the cleanup goes out, so a channel reports it once - pass the channel's id in the port parameter, the way WOLFSSH_FWD_CHANNEL_ID does, so an application with two forwards can tell which one ended - TestDirectTcpipFwdCbRejectsChannelId now counts three callback callspull/1232/head
parent
f8b72ac079
commit
6485062d3d
|
|
@ -3840,12 +3840,45 @@ WOLFSSH_CHANNEL* ChannelNew(WOLFSSH* ssh, byte channelType,
|
|||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSH_FWD
|
||||
/* Counterpart of the WOLFSSH_FWD_LOCAL_SETUP sent when a forwarding channel
|
||||
* was opened, so the application can release what it set up there. Gated on
|
||||
* that setup having succeeded: a locally opened forward draws no setup, and
|
||||
* one that reported failure set nothing up. Cleaning up after either would
|
||||
* free what the application does not own. Runs from ChannelDelete() so every
|
||||
* way a channel goes, a peer close, a refused open, wolfSSH_ChannelFree(),
|
||||
* or the session being freed, reports it once.
|
||||
* The channel's id rides in the port parameter, the way CHANNEL_ID passes
|
||||
* it. */
|
||||
static void NotifyFwdLocalCleanup(WOLFSSH_CHANNEL* channel)
|
||||
{
|
||||
WOLFSSH* ssh;
|
||||
int ret;
|
||||
|
||||
if (channel == NULL || !channel->fwdSetupTxd)
|
||||
return;
|
||||
ssh = channel->ssh;
|
||||
if (ssh == NULL || ssh->ctx->fwdCb == NULL)
|
||||
return;
|
||||
|
||||
channel->fwdSetupTxd = 0;
|
||||
ret = ssh->ctx->fwdCb(WOLFSSH_FWD_LOCAL_CLEANUP, ssh->fwdCbCtx,
|
||||
NULL, channel->channel);
|
||||
if (ret != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_WARN, "Forward cleanup failed for channel %u, ret = %d",
|
||||
channel->channel, ret);
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSH_FWD */
|
||||
|
||||
|
||||
void ChannelDelete(WOLFSSH_CHANNEL* channel, void* heap)
|
||||
{
|
||||
WOLFSSH_UNUSED(heap);
|
||||
|
||||
if (channel) {
|
||||
#ifdef WOLFSSH_FWD
|
||||
NotifyFwdLocalCleanup(channel);
|
||||
if (channel->host)
|
||||
WFREE(channel->host, heap, DYNTYPE_STRING);
|
||||
if (channel->origin)
|
||||
|
|
@ -12053,6 +12086,9 @@ static int DoChannelOpen(WOLFSSH* ssh,
|
|||
ret = ssh->ctx->fwdCb(WOLFSSH_FWD_LOCAL_SETUP,
|
||||
ssh->fwdCbCtx, host, hostPort);
|
||||
if (ret == WS_SUCCESS) {
|
||||
/* The application now owns whatever the setup made,
|
||||
* so it is owed the matching cleanup. */
|
||||
newChannel->fwdSetupTxd = 1;
|
||||
ret = ssh->ctx->fwdCb(WOLFSSH_FWD_CHANNEL_ID,
|
||||
ssh->fwdCbCtx, NULL, newChannel->channel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3799,7 +3799,9 @@ static void TestDirectTcpipFwdCbRejectsChannelId(void)
|
|||
* unlike the rejections that set the reason themselves. */
|
||||
AssertIntEQ(ParseChannelOpenFailReason(harness.io.out, harness.io.outSz),
|
||||
OPEN_ADMINISTRATIVELY_PROHIBITED);
|
||||
AssertIntEQ(fwdCbCallCount, 2);
|
||||
/* Three, not two: the setup that succeeded is owed its cleanup even
|
||||
* though the open went on to fail. */
|
||||
AssertIntEQ(fwdCbCallCount, 3);
|
||||
|
||||
FreeChannelOpenHarness(&harness);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1375,6 +1375,7 @@ struct WOLFSSH_CHANNEL {
|
|||
byte eofTxd : 1;
|
||||
byte openConfirmed : 1;
|
||||
byte ptyReq : 1; /* flag for if interactive pty request was received */
|
||||
byte fwdSetupTxd : 1; /* a LOCAL_SETUP succeeded, a cleanup is owed */
|
||||
word32 channel;
|
||||
word32 windowSz;
|
||||
word32 maxPacketSz;
|
||||
|
|
|
|||
Loading…
Reference in New Issue