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
4 changes: 3 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,9 @@ static void HandshakeInfoFree(HandshakeInfo* hs, void* heap)
INLINE static int IsMessageAllowedServer(WOLFSSH *ssh, byte msg)
{
/* Only the server should send these messages, never receive. */
if (msg == MSGID_SERVICE_ACCEPT) {
if (msg == MSGID_SERVICE_ACCEPT ||
msg == MSGID_KEXDH_REPLY || /* aliases MSGID_KEXDH_GEX_GROUP */
msg == MSGID_KEXDH_GEX_REPLY) {
WLOG(WS_LOG_DEBUG, "Message ID %u not allowed by %s %s",
Comment thread
gasbytes marked this conversation as resolved.
msg, "server", "ever");
ssh->error = WS_MSGID_NOT_ALLOWED_E;
Expand Down
53 changes: 53 additions & 0 deletions tests/regress.c
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,58 @@ static void TestServerOnlyUserauthMsgsBlocked(WOLFSSH* ssh)
}


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

ResetSession(ssh);
/* The peer's KEXINIT has landed, its GEX request has not. */
ssh->acceptState = ACCEPT_SERVER_KEXINIT_SENT;
ssh->isKeying = WOLFSSH_PEER_IS_KEYING;
ssh->handshake = AllocHandshake(ssh);
ssh->handshake->kexId = ID_DH_GEX_SHA256;
/* The server expects no particular message yet, so the expectMsgId
* check cannot catch these, the role check has to. */
AssertIntEQ(ssh->handshake->expectMsgId, MSGID_NONE);

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

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

/* The message a conformant client sends in this state is unaffected. */
ssh->error = 0;
allowed = wolfSSH_TestIsMessageAllowed(ssh, MSGID_KEXDH_GEX_REQUEST,
WS_MSG_RECV);
AssertTrue(allowed);
AssertIntEQ(ssh->error, WS_SUCCESS);

/* 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. */
ssh->error = 0;
ssh->acceptState = ACCEPT_CLIENT_SESSION_ESTABLISHED;

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

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


/* The server accepts a service request only once keyed, and never accepts
* the service accept that only it sends. */
static void TestServerServiceRequestStateGated(WOLFSSH* ssh)
Expand Down Expand Up @@ -11024,6 +11076,7 @@ int main(int argc, char** argv)
TestServerKnownAuthMsgIdBeforeAuthDisconnects();
TestServerUnknownHighMsgIdBeforeAuthDisconnects();
TestServerOnlyUserauthMsgsBlocked(serverSsh);
TestServerOnlyKexMsgsBlocked(serverSsh);
TestServerServiceRequestStateGated(serverSsh);
TestServerServiceRequestRejectedDuringKeying();
TestFailedSendClearsPendingPlaintext();
Expand Down
Loading