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
7 changes: 5 additions & 2 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ INLINE static int IsMessageAllowedServer(WOLFSSH *ssh, byte msg)
{
/* Only the server should send these messages, never receive. */
if (msg == MSGID_SERVICE_ACCEPT ||
msg == MSGID_KEXDH_REPLY || /* aliases MSGID_KEXDH_GEX_GROUP */
msg == MSGID_KEXDH_REPLY || /* 31: also ECDH, KEM, GEX_GROUP */
msg == MSGID_KEXDH_GEX_REPLY) {
WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by %s %s",
msg, "server", "ever");
Expand Down Expand Up @@ -826,7 +826,10 @@ INLINE static int IsMessageAllowedServer(WOLFSSH *ssh, byte msg)
INLINE static int IsMessageAllowedClient(WOLFSSH *ssh, byte msg)
{
/* Only the client should send these messages, never receive. */
if (msg == MSGID_SERVICE_REQUEST || msg == MSGID_USERAUTH_REQUEST) {
if (msg == MSGID_SERVICE_REQUEST || msg == MSGID_USERAUTH_REQUEST ||
msg == MSGID_KEXDH_INIT || /* 30: also ECDH, KEM, GEX_REQ_OLD */
msg == MSGID_KEXDH_GEX_INIT ||
msg == MSGID_KEXDH_GEX_REQUEST) {
WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by %s %s",
msg, "client", "ever");
ssh->error = WS_MSGID_NOT_ALLOWED_E;
Expand Down
60 changes: 60 additions & 0 deletions tests/regress.c
Original file line number Diff line number Diff line change
Expand Up @@ -2263,6 +2263,55 @@ static void TestChannelAllowedAfterAuth(WOLFSSH* ssh)
}


/* Reject the key exchange messages that only the client sends. */
static void TestClientOnlyKexMsgsBlocked(WOLFSSH* ssh)
{
int allowed;

ResetSession(ssh);
/* Our KEXINIT is out, the server's group has not arrived. */
ssh->connectState = CONNECT_CLIENT_KEXINIT_SENT;
ssh->isKeying = WOLFSSH_PEER_IS_KEYING;
ssh->handshake = AllocHandshake(ssh);
ssh->handshake->kexId = ID_DH_GEX_SHA256;

allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_INIT,
WS_MSG_RECV);
AssertFalse(allowed);
AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E);

ssh->error = 0;
allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_GEX_INIT,
WS_MSG_RECV);
AssertFalse(allowed);
AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E);

ssh->error = 0;
allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_GEX_REQUEST,
WS_MSG_RECV);
AssertFalse(allowed);
AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E);

/* 31 is the server's answer to a group request, so it stays allowed
* where the client expects it. */
ssh->error = 0;
ssh->handshake->expectMsgId = MSGID_KEXDH_GEX_GROUP;
allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_GEX_GROUP,
WS_MSG_RECV);
AssertTrue(allowed);
AssertIntEQ(ssh->handshake->expectMsgId, MSGID_NONE);

/* Same answer during a rekey on an established session. */
ssh->error = 0;
ssh->connectState = CONNECT_DONE;

allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_GEX_REQUEST,
WS_MSG_RECV);
AssertFalse(allowed);
AssertIntEQ(ssh->error, WS_MSGID_NOT_ALLOWED_E);
}


/* A service accept is allowed only when no key exchange is in flight.
* connectState does not see a rekey, so isKeying is checked too. */
static void TestClientServiceAcceptBlockedDuringKeying(WOLFSSH* ssh)
Expand Down Expand Up @@ -2561,6 +2610,16 @@ static void TestServerOnlyKexMsgsBlocked(WOLFSSH* ssh)
AssertTrue(allowed);
AssertIntEQ(ssh->error, WS_SUCCESS);

/* 32 sits between the two blocked ids and has to stay allowed. Assert
* it where the server actually expects it, once it has sent the
* group. */
ssh->error = 0;
ssh->handshake->expectMsgId = MSGID_KEXDH_GEX_INIT;
allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_GEX_INIT,
WS_MSG_RECV);
AssertTrue(allowed);
AssertIntEQ(ssh->handshake->expectMsgId, MSGID_NONE);

/* Same answer during a rekey on an established session. The pre-keyed
* range check does not run this far along, so a check placed there
* would leave this window open. */
Expand Down Expand Up @@ -11332,6 +11391,7 @@ int main(int argc, char** argv)
TestChannelBlockedBeforeAuth(ssh);
TestChannelBlockedEveryPreAuthState(ssh);
TestChannelAllowedAfterAuth(ssh);
TestClientOnlyKexMsgsBlocked(ssh);
TestClientServiceAcceptBlockedDuringKeying(ssh);
TestChannelOpenRejectedBeforeKex(CONNECT_CLIENT_KEXINIT_SENT);
TestChannelOpenRejectedBeforeKex(CONNECT_CLIENT_KEXDH_INIT_SENT);
Expand Down
Loading