mirror of https://github.com/wolfSSL/wolfssh.git
Reject client conn messages before key exchange
- IsMessageAllowedClient() gated the post-userauth rejection on connectState >= CONNECT_KEYED, so every state below it allowed msgid 80 and above. - A client in the pre-key-exchange DoReceive() loops accepted an unencrypted CHANNEL_OPEN, created the channel and replied with CHANNEL_OPEN_CONF. - Add a state sweep over the connection-protocol range and a full DoReceive() of a plaintext CHANNEL_OPEN from a pre-auth state. Issue: F-7628pull/1157/head
parent
ab8058d7cd
commit
4f827ca4a9
|
|
@ -852,8 +852,7 @@ INLINE static int IsMessageAllowedClient(WOLFSSH *ssh, byte msg)
|
|||
}
|
||||
|
||||
/* Is client userauth complete? */
|
||||
if (ssh->connectState >= CONNECT_KEYED
|
||||
&& ssh->connectState < CONNECT_SERVER_USERAUTH_ACCEPT_DONE) {
|
||||
if (ssh->connectState < CONNECT_SERVER_USERAUTH_ACCEPT_DONE) {
|
||||
/* The endpoints should not allow message IDs greater than or
|
||||
* equal to msgid 80 before user authentication is complete.
|
||||
* Per RFC 4252 section 6. */
|
||||
|
|
|
|||
|
|
@ -1685,6 +1685,38 @@ static void TestChannelBlockedBeforeAuth(WOLFSSH* ssh)
|
|||
}
|
||||
|
||||
|
||||
/* Reject connection-protocol messages in every state before user
|
||||
* authentication completes, keying or not. */
|
||||
static void TestChannelBlockedEveryPreAuthState(WOLFSSH* ssh)
|
||||
{
|
||||
static const byte connMsgs[] = {
|
||||
MSGID_GLOBAL_REQUEST, MSGID_CHANNEL_OPEN, MSGID_CHANNEL_DATA,
|
||||
MSGID_CHANNEL_REQUEST, MSGIDLIMIT_CONN_MAX
|
||||
};
|
||||
int state;
|
||||
word32 i;
|
||||
byte keying;
|
||||
|
||||
for (keying = 0; keying <= 1; keying++) {
|
||||
for (state = CONNECT_BEGIN;
|
||||
state < CONNECT_SERVER_USERAUTH_ACCEPT_DONE; state++) {
|
||||
for (i = 0; i < sizeof(connMsgs)/sizeof(*connMsgs); i++) {
|
||||
int allowed;
|
||||
|
||||
ResetSession(ssh);
|
||||
ssh->isKeying = keying ? WOLFSSH_PEER_IS_KEYING : 0;
|
||||
ssh->connectState = (byte)state;
|
||||
|
||||
allowed = wolfSSH_TestIsMessageAllowed(ssh, connMsgs[i],
|
||||
WS_MSG_RECV);
|
||||
AssertFalse(allowed);
|
||||
AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allow channel messages after user authentication completes. */
|
||||
static void TestChannelAllowedAfterAuth(WOLFSSH* ssh)
|
||||
{
|
||||
|
|
@ -1699,6 +1731,47 @@ static void TestChannelAllowedAfterAuth(WOLFSSH* ssh)
|
|||
}
|
||||
|
||||
|
||||
/* Drive the whole receive path with a CHANNEL_OPEN sent from a pre-auth
|
||||
* connectState: no channel created, no reply emitted. The connectState
|
||||
* gate does the rejecting; isKeying below is scene-setting only. */
|
||||
static void TestChannelOpenRejectedBeforeKex(byte connectState)
|
||||
{
|
||||
WOLFSSH_CTX* ctx;
|
||||
WOLFSSH* ssh;
|
||||
MemIo io;
|
||||
byte pkt[256];
|
||||
byte out[256];
|
||||
word32 pktSz;
|
||||
|
||||
pktSz = BuildChannelOpenPacket("session", 0, 131072, 16384, NULL, 0,
|
||||
pkt, sizeof(pkt));
|
||||
|
||||
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
|
||||
AssertNotNull(ctx);
|
||||
wolfSSH_SetIORecv(ctx, MemRecv);
|
||||
wolfSSH_SetIOSend(ctx, MemSend);
|
||||
|
||||
ssh = wolfSSH_new(ctx);
|
||||
AssertNotNull(ssh);
|
||||
|
||||
MemIoInit(&io, pkt, pktSz, out, sizeof(out));
|
||||
wolfSSH_SetIOReadCtx(ssh, &io);
|
||||
wolfSSH_SetIOWriteCtx(ssh, &io);
|
||||
|
||||
ssh->connectState = connectState;
|
||||
ssh->isKeying = WOLFSSH_PEER_IS_KEYING;
|
||||
|
||||
AssertIntEQ(wolfSSH_TestDoReceive(ssh), WS_FATAL_ERROR);
|
||||
AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E);
|
||||
AssertNull(ssh->channelList);
|
||||
AssertIntEQ(ssh->channelListSz, 0);
|
||||
AssertIntEQ(io.outSz, 0);
|
||||
|
||||
wolfSSH_free(ssh);
|
||||
wolfSSH_CTX_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
#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
|
||||
|
|
@ -5765,7 +5838,10 @@ int main(int argc, char** argv)
|
|||
TestPublicKeyFailureBeforeRequest(ssh);
|
||||
TestPublicKeyFailureAborts(ssh);
|
||||
TestChannelBlockedBeforeAuth(ssh);
|
||||
TestChannelBlockedEveryPreAuthState(ssh);
|
||||
TestChannelAllowedAfterAuth(ssh);
|
||||
TestChannelOpenRejectedBeforeKex(CONNECT_CLIENT_KEXINIT_SENT);
|
||||
TestChannelOpenRejectedBeforeKex(CONNECT_CLIENT_KEXDH_INIT_SENT);
|
||||
#ifndef NO_WOLFSSH_SERVER
|
||||
TestServerChannelBlockedBeforeAuth(serverSsh);
|
||||
TestServerChannelAllowedAfterAuth(serverSsh);
|
||||
|
|
|
|||
Loading…
Reference in New Issue