mirror of https://github.com/wolfSSL/wolfssh.git
Fix the shutdown channel teardown
wolfSSH_shutdown() searched for the session channel by the peer's channel ID while telling ChannelFind() to match the local ID field. Each side numbers its channels independently, so the search usually found nothing. - The session channel is the head of the list; take it directly instead of searching for what is already in hand. - Restores the EOF, exit-status and close sends, and the drain that waits on the peer's close, all skipped on the NULL result. - Only bit when the two IDs differ, so the single-channel tests, where both sides pick 0, never saw it. - unit.c: shut down a channel whose peer ID is not its local ID, then check that EOF and close went out. Issue: F-8817pull/1192/head
parent
5336ee5aca
commit
5303681b91
|
|
@ -1113,9 +1113,9 @@ int wolfSSH_shutdown(WOLFSSH* ssh)
|
|||
if (ssh == NULL || ssh->channelList == NULL)
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
|
||||
/* look up the channel if it still exists */
|
||||
/* The session channel is the head of the list. */
|
||||
if (ret == WS_SUCCESS) {
|
||||
channel = ChannelFind(ssh, ssh->channelList->peerChannel, WS_CHANNEL_ID_SELF);
|
||||
channel = ssh->channelList;
|
||||
}
|
||||
|
||||
/* if channel close was not already sent then send it */
|
||||
|
|
|
|||
76
tests/unit.c
76
tests/unit.c
|
|
@ -16797,6 +16797,75 @@ static int test_ResolveOffset(void)
|
|||
#endif /* WOLFSSH_TEST_RESOLVE_OFFSET */
|
||||
|
||||
|
||||
#if defined(WOLFSSH_TEST_INTERNAL) && !defined(NO_WOLFSSH_SERVER)
|
||||
|
||||
/* IORecv mock reporting nothing to read yet, so the shutdown drain below
|
||||
* completes without a live socket. */
|
||||
static int ShutdownIoRecv(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
|
||||
{
|
||||
WOLFSSH_UNUSED(ssh);
|
||||
WOLFSSH_UNUSED(data);
|
||||
WOLFSSH_UNUSED(sz);
|
||||
WOLFSSH_UNUSED(ctx);
|
||||
return WS_CBIO_ERR_WANT_READ;
|
||||
}
|
||||
|
||||
/* wolfSSH_shutdown() has to reach the session channel when the peer numbered
|
||||
* it differently than this side did, which is the normal case: each side
|
||||
* picks its own channel IDs. Looking the channel up by the peer's ID while
|
||||
* matching against the local ID field found nothing, and the whole teardown
|
||||
* was skipped. Only the EOF and close sends leave a flag behind to check;
|
||||
* the exit-status request in between does not. */
|
||||
static int test_ShutdownPeerChannelId(void)
|
||||
{
|
||||
WOLFSSH_CTX* ctx = NULL;
|
||||
WOLFSSH* ssh = NULL;
|
||||
WOLFSSH_CHANNEL* ch = NULL;
|
||||
word32 peerChannel;
|
||||
int result = 0;
|
||||
|
||||
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
|
||||
if (ctx == NULL)
|
||||
return -1080;
|
||||
wolfSSH_SetIOSend(ctx, DiscardIoSend);
|
||||
wolfSSH_SetIORecv(ctx, ShutdownIoRecv);
|
||||
|
||||
ssh = wolfSSH_new(ctx);
|
||||
if (ssh == NULL) { result = -1081; goto done; }
|
||||
|
||||
/* Let the channel messages past the message filter. */
|
||||
ssh->acceptState = ACCEPT_SERVER_USERAUTH_SENT;
|
||||
|
||||
ch = ChannelNew(ssh, ID_CHANTYPE_SESSION, 128, 64);
|
||||
if (ch == NULL) { result = -1082; goto done; }
|
||||
if (ChannelAppend(ssh, ch) != WS_SUCCESS) {
|
||||
ChannelDelete(ch, ssh->ctx->heap);
|
||||
result = -1083;
|
||||
goto done;
|
||||
}
|
||||
|
||||
peerChannel = ch->channel + 7;
|
||||
ch->peerChannel = peerChannel;
|
||||
ch->openConfirmed = 1;
|
||||
|
||||
/* The drain at the end of shutdown only sees a want-read, so the return
|
||||
* is not the interesting part here; what got sent is. */
|
||||
(void)wolfSSH_shutdown(ssh);
|
||||
|
||||
ch = ChannelFind(ssh, peerChannel, WS_CHANNEL_ID_PEER);
|
||||
if (ch == NULL) { result = -1084; goto done; }
|
||||
if (!ch->eofTxd) { result = -1085; goto done; }
|
||||
if (!ch->closeTxd) { result = -1086; goto done; }
|
||||
|
||||
done:
|
||||
wolfSSH_free(ssh);
|
||||
wolfSSH_CTX_free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSH_TEST_INTERNAL && !NO_WOLFSSH_SERVER */
|
||||
|
||||
|
||||
int wolfSSH_UnitTest(int argc, char** argv)
|
||||
{
|
||||
int testResult = 0, unitResult = 0;
|
||||
|
|
@ -17502,6 +17571,13 @@ int wolfSSH_UnitTest(int argc, char** argv)
|
|||
testResult = testResult || unitResult;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSH_TEST_INTERNAL) && !defined(NO_WOLFSSH_SERVER)
|
||||
unitResult = test_ShutdownPeerChannelId();
|
||||
printf("ShutdownPeerChannelId: %s\n",
|
||||
(unitResult == 0 ? "SUCCESS" : "FAILED"));
|
||||
testResult = testResult || unitResult;
|
||||
#endif
|
||||
|
||||
wolfSSH_Cleanup();
|
||||
|
||||
return (testResult ? 1 : 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue