Skip to content

Commit dff92f9

Browse files
ejohnstownphilljj
authored andcommitted
internal: skip guessed GEX requests without GEX
With WOLFSSH_NO_DH_GEX_SHA256 a guessed KEXDH_GEX_REQUEST was answered with UNIMPLEMENTED and left the skip armed, so the server then dropped the real KEXDH_INIT and stalled. DoPacket() now dispatches the message in every build, and a stub DoKexDhGexRequest() skips only a guess. - tests: a guessed GEX request through DoReceive is skipped silently - tests: the GEX request skip case runs without GEX support
1 parent ed2b8a6 commit dff92f9

3 files changed

Lines changed: 66 additions & 13 deletions

File tree

‎src/internal.c‎

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9408,6 +9408,26 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
94089408
}
94099409

94109410

9411+
#ifdef WOLFSSH_NO_DH_GEX_SHA256
9412+
/* Without GEX, a KEXDH_GEX_REQUEST is only the guessed packet of a client
9413+
* that listed GEX first; skip that one and refuse any other. */
9414+
static int DoKexDhGexRequest(WOLFSSH* ssh,
9415+
byte* buf, word32 len, word32* idx)
9416+
{
9417+
if (ssh == NULL || ssh->handshake == NULL || buf == NULL || len == 0 ||
9418+
idx == NULL)
9419+
return WS_BAD_ARGUMENT;
9420+
9421+
if (SkipGuessedKexMsg(ssh, "client's KEXDH_GEX_REQUEST message",
9422+
len, idx))
9423+
return WS_SUCCESS;
9424+
9425+
WLOG(WS_LOG_DEBUG, "KEXDH_GEX_REQUEST without GEX support");
9426+
return WS_MSGID_NOT_ALLOWED_E;
9427+
}
9428+
#endif /* WOLFSSH_NO_DH_GEX_SHA256 */
9429+
9430+
94119431
#ifndef WOLFSSH_NO_DH_GEX_SHA256
94129432
static int DoKexDhGexRequest(WOLFSSH* ssh,
94139433
byte* buf, word32 len, word32* idx)
@@ -14194,9 +14214,7 @@ INLINE static int MsgIdKnown(byte msg)
1419414214
case MSGID_NEWKEYS:
1419514215
case MSGID_KEXDH_INIT:
1419614216
case MSGID_KEXDH_REPLY:
14197-
#ifndef WOLFSSH_NO_DH_GEX_SHA256
1419814217
case MSGID_KEXDH_GEX_REQUEST:
14199-
#endif
1420014218
case MSGID_KEXDH_GEX_INIT:
1420114219
case MSGID_KEXDH_GEX_REPLY:
1420214220
case MSGID_SERVICE_REQUEST:
@@ -14413,12 +14431,10 @@ static int DoPacket(WOLFSSH* ssh, byte* bufferConsumed)
1441314431
}
1441414432
break;
1441514433

14416-
#ifndef WOLFSSH_NO_DH_GEX_SHA256
1441714434
case MSGID_KEXDH_GEX_REQUEST:
1441814435
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_GEX_REQUEST");
1441914436
ret = DoKexDhGexRequest(ssh, buf + idx, payloadSz, &payloadIdx);
1442014437
break;
14421-
#endif
1442214438

1442314439
case MSGID_KEXDH_GEX_INIT:
1442414440
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_GEX_INIT");
@@ -26517,6 +26533,12 @@ int wolfSSH_TestDoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
2651726533
return DoKexDhReply(ssh, buf, len, idx);
2651826534
}
2651926535

26536+
int wolfSSH_TestDoKexDhGexRequest(WOLFSSH* ssh, byte* buf, word32 len,
26537+
word32* idx)
26538+
{
26539+
return DoKexDhGexRequest(ssh, buf, len, idx);
26540+
}
26541+
2652026542
int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL* channel, byte* data,
2652126543
word32 dataSz)
2652226544
{
@@ -26703,12 +26725,6 @@ int wolfSSH_TestSendKexDhGexRequest(WOLFSSH* ssh)
2670326725
return SendKexDhGexRequest(ssh);
2670426726
}
2670526727

26706-
int wolfSSH_TestDoKexDhGexRequest(WOLFSSH* ssh, byte* buf, word32 len,
26707-
word32* idx)
26708-
{
26709-
return DoKexDhGexRequest(ssh, buf, len, idx);
26710-
}
26711-
2671226728
int wolfSSH_TestDoKexDhGexGroup(WOLFSSH* ssh, byte* buf, word32 len,
2671326729
word32* idx)
2671426730
{

‎tests/regress.c‎

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17780,12 +17780,49 @@ static void RunFirstPacketFollowsCrossBoundaryCase(FirstPacketFollowsSkipFn fn,
1778017780
}
1778117781
#endif /* WOLFSSH_NO_DH_GEX_SHA256 && NO_WOLFSSH_SERVER */
1778217782

17783+
#ifndef NO_WOLFSSH_SERVER
17784+
/* A client that lists GEX first may guess a KEXDH_GEX_REQUEST. DoReceive must
17785+
* discard it, with GEX compiled out too, rather than answer UNIMPLEMENTED and
17786+
* leave the skip armed for the real KEXDH_INIT. */
17787+
static void TestFirstPacketFollowsGexRequestDispatch(void)
17788+
{
17789+
ChannelOpenHarness harness;
17790+
byte payload[3 * UINT32_SZ];
17791+
byte in[64];
17792+
word32 payloadSz = 0;
17793+
word32 inSz;
17794+
17795+
payloadSz = AppendUint32(payload, sizeof(payload), payloadSz, 2048);
17796+
payloadSz = AppendUint32(payload, sizeof(payload), payloadSz, 3072);
17797+
payloadSz = AppendUint32(payload, sizeof(payload), payloadSz, 8192);
17798+
inSz = WrapPacket(MSGID_KEXDH_GEX_REQUEST, payload, payloadSz,
17799+
in, sizeof(in));
17800+
17801+
InitChannelOpenHarness(&harness, in, inSz);
17802+
harness.ssh->acceptState = ACCEPT_SERVER_KEXINIT_SENT;
17803+
harness.ssh->isKeying |= WOLFSSH_PEER_IS_KEYING;
17804+
AssertNotNull(harness.ssh->handshake);
17805+
harness.ssh->handshake->kexId = ID_DH_GROUP14_SHA256;
17806+
harness.ssh->handshake->expectMsgId = MSGID_NONE;
17807+
harness.ssh->handshake->ignoreNextKexMsg = 1;
17808+
17809+
AssertIntEQ(ReplyToPacket(&harness, in, inSz), 0);
17810+
AssertIntEQ(harness.ssh->handshake->ignoreNextKexMsg, 0);
17811+
AssertIntEQ(harness.ssh->handshake->expectMsgId, MSGID_KEXDH_INIT);
17812+
17813+
FreeChannelOpenHarness(&harness);
17814+
}
17815+
#endif /* !NO_WOLFSSH_SERVER */
17816+
1778317817
static void TestFirstPacketFollowsSkipped(void)
1778417818
{
1778517819
RunFirstPacketFollowsSkipCase(wolfSSH_TestDoKexDhInit, "DoKexDhInit");
17786-
#ifndef WOLFSSH_NO_DH_GEX_SHA256
1778717820
RunFirstPacketFollowsSkipCase(wolfSSH_TestDoKexDhGexRequest,
1778817821
"DoKexDhGexRequest");
17822+
#ifndef NO_WOLFSSH_SERVER
17823+
TestFirstPacketFollowsGexRequestDispatch();
17824+
#endif
17825+
#ifndef WOLFSSH_NO_DH_GEX_SHA256
1778917826
/* Guess/negotiation straddling the GEX boundary, both directions. */
1779017827
#ifndef NO_WOLFSSH_SERVER
1779117828
RunFirstPacketFollowsCrossBoundaryCase(wolfSSH_TestDoKexDhInit,

‎wolfssh/internal.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,6 +2159,8 @@ enum WS_MessageIdLimits {
21592159
word32 len, word32* idx);
21602160
WOLFSSH_API int wolfSSH_TestDoKexDhReply(WOLFSSH* ssh, byte* buf,
21612161
word32 len, word32* idx);
2162+
WOLFSSH_API int wolfSSH_TestDoKexDhGexRequest(WOLFSSH* ssh, byte* buf,
2163+
word32 len, word32* idx);
21622164
WOLFSSH_API int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL* channel,
21632165
byte* data, word32 dataSz);
21642166
WOLFSSH_API int wolfSSH_TestCreateMpint(byte* buf, word32* sz, byte* pad);
@@ -2212,8 +2214,6 @@ enum WS_MessageIdLimits {
22122214
#endif
22132215
#ifndef WOLFSSH_NO_DH_GEX_SHA256
22142216
WOLFSSH_API int wolfSSH_TestSendKexDhGexRequest(WOLFSSH* ssh);
2215-
WOLFSSH_API int wolfSSH_TestDoKexDhGexRequest(WOLFSSH* ssh, byte* buf,
2216-
word32 len, word32* idx);
22172217
WOLFSSH_API int wolfSSH_TestDoKexDhGexGroup(WOLFSSH* ssh, byte* buf,
22182218
word32 len, word32* idx);
22192219
WOLFSSH_API int wolfSSH_TestValidateKexDhGexGroup(const byte* primeGroup,

0 commit comments

Comments
 (0)