Skip to content

Commit 66ed077

Browse files
committed
Don't Allow Version Negotiation Packets for Server Connections
Adds a new test case that was able to repro the crash before the fix (in connection.c) was added.
1 parent 7fa092b commit 66ed077

File tree

8 files changed

+129
-31
lines changed

8 files changed

+129
-31
lines changed

src/core/connection.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3786,7 +3786,8 @@ QuicConnRecvHeader(
37863786
//
37873787
// Do not return FALSE here, continue with the connection.
37883788
//
3789-
} else if (Packet->Invariant->LONG_HDR.Version == QUIC_VERSION_VER_NEG &&
3789+
} else if (QuicConnIsClient(Connection) &&
3790+
Packet->Invariant->LONG_HDR.Version == QUIC_VERSION_VER_NEG &&
37903791
!Connection->Stats.VersionNegotiation) {
37913792
//
37923793
// Version negotiation packet received.

src/inc/msquic.hpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,22 +1143,33 @@ struct MsQuicConnection {
11431143
};
11441144

11451145
struct MsQuicAutoAcceptListener : public MsQuicListener {
1146-
const MsQuicConfiguration& Configuration;
1146+
const MsQuicConfiguration* Configuration;
11471147
MsQuicConnectionCallback* ConnectionHandler;
11481148
MsQuicConnection* LastConnection {nullptr};
11491149
void* ConnectionContext;
11501150
#ifdef CX_PLATFORM_TYPE
11511151
uint32_t AcceptedConnectionCount {0};
11521152
#endif
11531153

1154+
MsQuicAutoAcceptListener(
1155+
_In_ const MsQuicRegistration& Registration,
1156+
_In_ MsQuicConnectionCallback* _ConnectionHandler,
1157+
_In_ void* _ConnectionContext = nullptr
1158+
) noexcept :
1159+
MsQuicListener(Registration, ListenerCallback, this),
1160+
Configuration(nullptr),
1161+
ConnectionHandler(_ConnectionHandler),
1162+
ConnectionContext(_ConnectionContext)
1163+
{ }
1164+
11541165
MsQuicAutoAcceptListener(
11551166
_In_ const MsQuicRegistration& Registration,
11561167
_In_ const MsQuicConfiguration& Config,
11571168
_In_ MsQuicConnectionCallback* _ConnectionHandler,
11581169
_In_ void* _ConnectionContext = nullptr
11591170
) noexcept :
11601171
MsQuicListener(Registration, ListenerCallback, this),
1161-
Configuration(Config),
1172+
Configuration(&Config),
11621173
ConnectionHandler(_ConnectionHandler),
11631174
ConnectionContext(_ConnectionContext)
11641175
{ }
@@ -1180,14 +1191,15 @@ struct MsQuicAutoAcceptListener : public MsQuicListener {
11801191
if (Event->Type == QUIC_LISTENER_EVENT_NEW_CONNECTION) {
11811192
auto Connection = new(std::nothrow) MsQuicConnection(Event->NEW_CONNECTION.Connection, CleanUpAutoDelete, pThis->ConnectionHandler, pThis->ConnectionContext);
11821193
if (Connection) {
1183-
Status = Connection->SetConfiguration(pThis->Configuration);
1184-
if (QUIC_FAILED(Status)) {
1194+
if (!pThis->Configuration ||
1195+
QUIC_FAILED(Status = Connection->SetConfiguration(*pThis->Configuration))) {
11851196
//
11861197
// The connection is being rejected. Let MsQuic free the handle.
11871198
//
11881199
Connection->Handle = nullptr;
11891200
delete Connection;
11901201
} else {
1202+
Status = QUIC_STATUS_SUCCESS;
11911203
pThis->LastConnection = Connection;
11921204
#ifdef CX_PLATFORM_TYPE
11931205
InterlockedIncrement((long*)&pThis->AcceptedConnectionCount);

src/test/MsQuicTests.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ QuicDrillTestInitialToken(
554554
_In_ int Family
555555
);
556556

557+
void
558+
QuicDrillTestServerVNPacket(
559+
_In_ int Family
560+
);
561+
557562
//
558563
// Datagram tests
559564
//
@@ -1176,4 +1181,8 @@ typedef struct {
11761181
QUIC_CTL_CODE(110, METHOD_BUFFERED, FILE_WRITE_DATA)
11771182
// QUIC_RUN_CUSTOM_CERT_VALIDATION
11781183

1179-
#define QUIC_MAX_IOCTL_FUNC_CODE 110
1184+
#define IOCTL_QUIC_RUN_DRILL_VN_PACKET_TOKEN \
1185+
QUIC_CTL_CODE(111, METHOD_BUFFERED, FILE_WRITE_DATA)
1186+
// int - Family
1187+
1188+
#define QUIC_MAX_IOCTL_FUNC_CODE 111

src/test/bin/quic_gtest.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,15 @@ TEST_P(WithDrillInitialPacketTokenArgs, DrillInitialPacketToken) {
21122112
}
21132113
#endif // QUIC_USE_RAW_DATAPATH
21142114

2115+
TEST_P(WithDrillInitialPacketTokenArgs, QuicDrillTestServerVNPacket) {
2116+
TestLoggerT<ParamType> Logger("QuicDrillTestServerVNPacket", GetParam());
2117+
if (TestingKernelMode) {
2118+
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_DRILL_VN_PACKET_TOKEN, GetParam().Family));
2119+
} else {
2120+
QuicDrillTestServerVNPacket(GetParam().Family);
2121+
}
2122+
}
2123+
21152124
TEST_P(WithDatagramNegotiationArgs, DatagramNegotiation) {
21162125
TestLoggerT<ParamType> Logger("QuicTestDatagramNegotiation", GetParam());
21172126
if (TestingKernelMode) {

src/test/bin/winkernel/control.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ size_t QUIC_IOCTL_BUFFER_SIZES[] =
482482
sizeof(INT32),
483483
sizeof(INT32),
484484
sizeof(QUIC_RUN_CUSTOM_CERT_VALIDATION),
485+
sizeof(INT32),
485486
};
486487

487488
CXPLAT_STATIC_ASSERT(
@@ -1339,6 +1340,11 @@ QuicTestCtlEvtIoDeviceControl(
13391340
Params->CustomCertValidationParams.AsyncValidation));
13401341
break;
13411342

1343+
case IOCTL_QUIC_RUN_DRILL_VN_PACKET_TOKEN:
1344+
CXPLAT_FRE_ASSERT(Params != nullptr);
1345+
QuicTestCtlRun(QuicDrillTestServerVNPacket(Params->Family));
1346+
break;
1347+
13421348
default:
13431349
Status = STATUS_NOT_IMPLEMENTED;
13441350
break;

src/test/lib/DrillDescriptor.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,31 @@ DrillPacketDescriptor::write(
130130
}
131131
PacketBuffer.insert(PacketBuffer.end(), SourceCid.begin(), SourceCid.end());
132132

133-
//
134-
// TODO: Do type-specific stuff here.
135-
//
133+
return PacketBuffer;
134+
}
135+
136+
DrillBuffer
137+
DrillVNPacketDescriptor::write(
138+
) const
139+
{
140+
DrillBuffer PacketBuffer = DrillPacketDescriptor::write();
141+
142+
// uint32_t SupportedVersions[]
143+
uint32_t SupportedVer = QUIC_VERSION_2_H;
144+
for (size_t i = 0; i < sizeof(SupportedVer); ++i) {
145+
PacketBuffer.push_back((uint8_t) (SupportedVer >> (((sizeof(SupportedVer) - 1) - i) * 8)));
146+
}
147+
SupportedVer = QUIC_VERSION_1_MS_H;
148+
for (size_t i = 0; i < sizeof(SupportedVer); ++i) {
149+
PacketBuffer.push_back((uint8_t) (SupportedVer >> (((sizeof(SupportedVer) - 1) - i) * 8)));
150+
}
136151

137152
return PacketBuffer;
138153
}
139154

140-
DrillInitialPacketDescriptor::DrillInitialPacketDescriptor(
141-
) : DrillPacketDescriptor(), TokenLen(nullptr), PacketLength(nullptr), PacketNumber(0)
155+
DrillInitialPacketDescriptor::DrillInitialPacketDescriptor()
142156
{
143157
Type = Initial;
144-
Header.LongHeader = 1;
145158
Header.FixedBit = 1;
146159
Version = QUIC_VERSION_LATEST_H;
147160

@@ -197,10 +210,7 @@ DrillInitialPacketDescriptor::write(
197210
}
198211

199212
CalculatedPacketLength += PacketNumberBuffer.size();
200-
201-
//
202-
// TODO: Calculate the payload length.
203-
//
213+
CalculatedPacketLength += Payload.size();
204214

205215
//
206216
// Write packet length.
@@ -219,8 +229,11 @@ DrillInitialPacketDescriptor::write(
219229
PacketBuffer.insert(PacketBuffer.end(), PacketNumberBuffer.begin(), PacketNumberBuffer.end());
220230

221231
//
222-
// TODO: Write payload here.
232+
// Write payload.
223233
//
234+
if (Payload.size() > 0) {
235+
PacketBuffer.insert(PacketBuffer.end(), Payload.begin(), Payload.end());
236+
}
224237

225238
return PacketBuffer;
226239
}

src/test/lib/DrillDescriptor.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,39 +64,45 @@ struct DrillPacketDescriptor {
6464
//
6565
// The type of datagram this describes.
6666
//
67-
DrillPacketDescriptorType Type;
67+
DrillPacketDescriptorType Type {VersionNegotiation};
6868

69-
QuicHeader Header;
69+
QuicHeader Header {0};
7070

71-
uint32_t Version;
71+
uint32_t Version {QUIC_VERSION_VER_NEG};
7272

7373
//
7474
// Optional destination CID length. If not set, will use length of DestCid.
7575
//
76-
uint8_t* DestCidLen;
76+
uint8_t* DestCidLen {nullptr};
7777
DrillBuffer DestCid;
7878

7979
//
8080
// Optional source CID length. If not set, will use length of SourceCid.
8181
//
82-
uint8_t* SourceCidLen;
82+
uint8_t* SourceCidLen {nullptr};
8383
DrillBuffer SourceCid;
8484

85-
DrillPacketDescriptor() : DestCidLen(nullptr), SourceCidLen(nullptr) {};
85+
DrillPacketDescriptor() { Header.LongHeader = TRUE; }
8686

8787
//
8888
// Write this descriptor to a byte array to send on the wire.
8989
//
9090
virtual DrillBuffer write() const;
9191
};
9292

93+
struct DrillVNPacketDescriptor : DrillPacketDescriptor {
94+
//
95+
// Write this descriptor to a byte array to send on the wire.
96+
//
97+
virtual DrillBuffer write() const;
98+
};
9399

94100
struct DrillInitialPacketDescriptor : DrillPacketDescriptor {
95101
//
96102
// Optional Token length for the token. If unspecified, uses the length
97103
// of Token below.
98104
//
99-
uint64_t* TokenLen;
105+
uint64_t* TokenLen {nullptr};
100106

101107
//
102108
// Token is optional. If unspecified, then it is elidded.
@@ -107,13 +113,15 @@ struct DrillInitialPacketDescriptor : DrillPacketDescriptor {
107113
// If unspecified, this value is auto-calculated from the fields.
108114
// Otherwise, this value is used regardless of actual packet length.
109115
//
110-
uint64_t* PacketLength;
116+
uint64_t* PacketLength {nullptr};
111117

112118
//
113119
// The caller must ensure the packet number length bits in the header
114120
// match the magnitude of this PacketNumber.
115121
//
116-
uint32_t PacketNumber;
122+
uint32_t PacketNumber {0};
123+
124+
DrillBuffer Payload;
117125

118126

119127
DrillInitialPacketDescriptor();

src/test/lib/QuicDrill.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,12 @@ struct DrillSender {
188188

189189
QUIC_STATUS
190190
Send(
191-
_In_ const DrillBuffer* PacketBuffer
191+
_In_ const DrillBuffer& PacketBuffer
192192
)
193193
{
194194
QUIC_STATUS Status = QUIC_STATUS_SUCCESS;
195-
CXPLAT_FRE_ASSERT(PacketBuffer->size() <= UINT16_MAX);
196-
const uint16_t DatagramLength = (uint16_t) PacketBuffer->size();
195+
CXPLAT_FRE_ASSERT(PacketBuffer.size() <= UINT16_MAX);
196+
const uint16_t DatagramLength = (uint16_t) PacketBuffer.size();
197197

198198
CXPLAT_ROUTE Route = {0};
199199
CxPlatSocketGetLocalAddress(Binding, &Route.LocalAddress);
@@ -215,7 +215,7 @@ struct DrillSender {
215215
//
216216
// Copy test packet into SendBuffer.
217217
//
218-
memcpy(SendBuffer->Buffer, PacketBuffer->data(), DatagramLength);
218+
memcpy(SendBuffer->Buffer, PacketBuffer.data(), DatagramLength);
219219

220220
Status =
221221
CxPlatSocketSend(
@@ -306,7 +306,7 @@ QuicDrillInitialPacketFailureTest(
306306
//
307307
// Send test packet to the server.
308308
//
309-
Status = Sender.Send(&PacketBuffer);
309+
Status = Sender.Send(PacketBuffer);
310310
if (QUIC_FAILED(Status)) {
311311
return false;
312312
}
@@ -491,3 +491,43 @@ QuicDrillTestInitialToken(
491491
}
492492
}
493493
}
494+
495+
void
496+
QuicDrillTestServerVNPacket(
497+
_In_ int Family
498+
)
499+
{
500+
MsQuicRegistration Registration(true);
501+
TEST_QUIC_SUCCEEDED(Registration.GetInitStatus());
502+
503+
QUIC_ADDRESS_FAMILY QuicAddrFamily = (Family == 4) ? QUIC_ADDRESS_FAMILY_INET : QUIC_ADDRESS_FAMILY_INET6;
504+
QuicAddr ServerLocalAddr(QuicAddrFamily);
505+
506+
MsQuicAutoAcceptListener Listener(Registration, MsQuicConnection::NoOpCallback);
507+
TEST_QUIC_SUCCEEDED(Listener.Start("MsQuicTest", &ServerLocalAddr.SockAddr));
508+
TEST_QUIC_SUCCEEDED(Listener.GetInitStatus());
509+
TEST_QUIC_SUCCEEDED(Listener.GetLocalAddr(ServerLocalAddr));
510+
511+
DrillSender Sender;
512+
TEST_QUIC_SUCCEEDED(
513+
Sender.Initialize(
514+
QUIC_TEST_LOOPBACK_FOR_AF(QuicAddrFamily),
515+
QuicAddrFamily,
516+
(QuicAddrFamily == QUIC_ADDRESS_FAMILY_INET) ?
517+
ServerLocalAddr.SockAddr.Ipv4.sin_port :
518+
ServerLocalAddr.SockAddr.Ipv6.sin6_port));
519+
520+
uint8_t SourceCidLen = 0;
521+
DrillInitialPacketDescriptor InitialPacketBuffer;
522+
InitialPacketBuffer.SourceCidLen = &SourceCidLen;
523+
for (uint8_t i = 0; i < 8; ++i) { InitialPacketBuffer.DestCid.push_back(i); }
524+
for (uint16_t i = 0; i < 1200; ++i) { InitialPacketBuffer.Payload.push_back(0); }
525+
526+
DrillVNPacketDescriptor VNPacketBuffer;
527+
for (uint8_t i = 0; i < 8; ++i) { VNPacketBuffer.DestCid.push_back(i); }
528+
529+
TEST_QUIC_SUCCEEDED(Sender.Send(InitialPacketBuffer.write()));
530+
TEST_QUIC_SUCCEEDED(Sender.Send(VNPacketBuffer.write()));
531+
532+
CxPlatSleep(500);
533+
}

0 commit comments

Comments
 (0)