Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -11939,7 +11939,15 @@ static int DoChannelOpen(WOLFSSH* ssh,
typeId = NameToId(type, typeSz);
switch (typeId) {
case ID_CHANTYPE_SESSION:
if (ssh->channelListSz >= 1) {
/* RFC 4254 6.1: a session open travels client-to-server, so a
* client refuses one ahead of any policy callback. */
if (ssh->ctx->side == WOLFSSH_ENDPOINT_CLIENT) {
WLOG(WS_LOG_WARN, "Rejecting session channel open "
"received by a client (wrong direction)");
ret = WS_INVALID_CHANTYPE;
fail_reason = OPEN_ADMINISTRATIVELY_PROHIBITED;
}
else if (ssh->channelListSz >= 1) {
ret = WS_INVALID_CHANID;
fail_reason = OPEN_ADMINISTRATIVELY_PROHIBITED;
}
Expand Down
75 changes: 65 additions & 10 deletions tests/regress.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ static WS_MAYBE_UNUSED void FreeChannelOpenHarness(ChannelOpenHarness* harness)
wolfSSH_CTX_free(harness->ctx);
}

#if defined(WOLFSSH_FWD) && !defined(NO_WOLFSSH_CLIENT)
#ifndef NO_WOLFSSH_CLIENT
/* The same harness on the client side, sitting past userauth so an inbound
* channel open is allowed through. */
static void InitChannelOpenHarnessClient(ChannelOpenHarness* harness,
Expand All @@ -423,7 +423,7 @@ static void InitChannelOpenHarnessClient(ChannelOpenHarness* harness,
AssertIntEQ(wolfSSH_SetHighwater(harness->ssh, 0), WS_SUCCESS);
harness->ssh->connectState = CONNECT_SERVER_USERAUTH_ACCEPT_DONE;
}
#endif /* WOLFSSH_FWD && !NO_WOLFSSH_CLIENT */
#endif /* !NO_WOLFSSH_CLIENT */

/* The tests below drive a server-side session. With NO_WOLFSSH_SERVER the
* message filter has no server branch, so every message on such a session is
Expand Down Expand Up @@ -1810,6 +1810,15 @@ static WS_MAYBE_UNUSED void AssertChannelOpenFailResponse(
AssertTrue(harness->ssh->channelList == NULL);
}

static WS_MAYBE_UNUSED int AcceptChannelOpenCb(WOLFSSH_CHANNEL* channel,
void* ctx)
{
(void)channel;
(void)ctx;

return WS_SUCCESS;
}

#ifdef WOLFSSH_FWD
/* The port a peer picks for a port-0 forward in these tests. */
#define REGRESS_FWD_ALLOC_PORT 49152
Expand Down Expand Up @@ -1930,14 +1939,6 @@ static int RejectChannelOpenCb(WOLFSSH_CHANNEL* channel, void* ctx)
}

#ifdef WOLFSSH_FWD
static int AcceptChannelOpenCb(WOLFSSH_CHANNEL* channel, void* ctx)
{
(void)channel;
(void)ctx;

return WS_SUCCESS;
}

static int RejectDirectTcpipSetup(WS_FwdCbAction action, void* ctx,
const char* host, word32 port)
{
Expand Down Expand Up @@ -2391,6 +2392,56 @@ static void TestChannelOpenRejectedBeforeKex(byte connectState)
}


#ifndef NO_WOLFSSH_CLIENT
/* RFC 4254 section 6.1 has a session open travelling client-to-server, so a
* client that receives one refuses it. OpenSSH and Dropbear reach the same
* answer by giving each role its own channel-type list. */
static void TestSessionOnClientSendsOpenFail(void)
{
ChannelOpenHarness harness;
byte in[128];
word32 inSz;
int ret;

inSz = BuildChannelOpenPacket("session", 7, 0x4000, 0x8000,
NULL, 0, in, sizeof(in));

InitChannelOpenHarnessClient(&harness, in, inSz);

ret = DoReceive(harness.ssh);
AssertChannelOpenFailResponse(&harness, ret);
AssertIntEQ(ParseChannelOpenFailReason(harness.io.out, harness.io.outSz),
OPEN_ADMINISTRATIVELY_PROHIBITED);

FreeChannelOpenHarness(&harness);
}

/* The direction check runs ahead of the open policy hook, so a registered
* channelOpenCb cannot accept a session open on a client. */
static void TestSessionOnClientBeatsOpenCb(void)
{
ChannelOpenHarness harness;
byte in[128];
word32 inSz;
int ret;

inSz = BuildChannelOpenPacket("session", 7, 0x4000, 0x8000,
NULL, 0, in, sizeof(in));

InitChannelOpenHarnessClient(&harness, in, inSz);
AssertIntEQ(wolfSSH_CTX_SetChannelOpenCb(harness.ctx, AcceptChannelOpenCb),
WS_SUCCESS);

ret = DoReceive(harness.ssh);
AssertChannelOpenFailResponse(&harness, ret);
AssertIntEQ(ParseChannelOpenFailReason(harness.io.out, harness.io.outSz),
OPEN_ADMINISTRATIVELY_PROHIBITED);

FreeChannelOpenHarness(&harness);
}
#endif /* !NO_WOLFSSH_CLIENT */


#ifndef NO_WOLFSSH_SERVER
/* The client gate tests above run against a client endpoint, so the server
* branch of IsMessageAllowed was never exercised. The tests below drive a
Expand Down Expand Up @@ -12108,6 +12159,10 @@ int main(int argc, char** argv)
TestClientServiceAcceptBlockedDuringKeying(ssh);
TestChannelOpenRejectedBeforeKex(CONNECT_CLIENT_KEXINIT_SENT);
TestChannelOpenRejectedBeforeKex(CONNECT_CLIENT_KEXDH_INIT_SENT);
#ifndef NO_WOLFSSH_CLIENT
TestSessionOnClientSendsOpenFail();
TestSessionOnClientBeatsOpenCb();
#endif
#ifndef NO_WOLFSSH_SERVER
TestServerChannelBlockedBeforeAuth(serverSsh);
TestServerChannelAllowedAfterAuth(serverSsh);
Expand Down
Loading