Skip to content
This repository was archived by the owner on Jan 31, 2024. It is now read-only.

Commit b4213ca

Browse files
fix panics when processing post-handshake messages
See https://go-review.googlesource.com/c/go/+/522595.
1 parent 5ba4259 commit b4213ca

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

quic.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,16 +230,22 @@ func (q *QUICConn) HandleData(level QUICEncryptionLevel, data []byte) error {
230230
return nil
231231
}
232232
// The handshake goroutine has exited.
233+
c.handshakeMutex.Lock()
234+
defer c.handshakeMutex.Unlock()
233235
c.hand.Write(c.quic.readbuf)
234236
c.quic.readbuf = nil
235237
for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil {
236238
b := q.conn.hand.Bytes()
237239
n := int(b[1])<<16 | int(b[2])<<8 | int(b[3])
238-
if 4+n < len(b) {
240+
if n > maxHandshake {
241+
q.conn.handshakeErr = fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)
242+
break
243+
}
244+
if len(b) < 4+n {
239245
return nil
240246
}
241247
if err := q.conn.handlePostHandshakeMessage(); err != nil {
242-
return quicError(err)
248+
q.conn.handshakeErr = err
243249
}
244250
}
245251
if q.conn.handshakeErr != nil {

quic_test.go

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (q *testQUICConn) setWriteSecret(level QUICEncryptionLevel, suite uint16, s
8585

8686
var errTransportParametersRequired = errors.New("transport parameters required")
8787

88-
func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onHandleCryptoData func()) error {
88+
func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onEvent func(e QUICEvent, src, dst *testQUICConn) bool) error {
8989
a, b := cli, srv
9090
for _, c := range []*testQUICConn{a, b} {
9191
if !c.conn.conn.quic.started {
@@ -97,6 +97,9 @@ func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onHandle
9797
idleCount := 0
9898
for {
9999
e := a.conn.NextEvent()
100+
if onEvent != nil && onEvent(e, a, b) {
101+
continue
102+
}
100103
switch e.Kind {
101104
case QUICNoEvent:
102105
idleCount++
@@ -210,6 +213,37 @@ func TestQUICSessionResumption(t *testing.T) {
210213
}
211214
}
212215

216+
func TestQUICFragmentaryData(t *testing.T) {
217+
clientConfig := testConfig.Clone()
218+
clientConfig.MinVersion = VersionTLS13
219+
clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
220+
clientConfig.ServerName = "example.go.dev"
221+
222+
serverConfig := testConfig.Clone()
223+
serverConfig.MinVersion = VersionTLS13
224+
225+
cli := newTestQUICClient(t, clientConfig)
226+
cli.conn.SetTransportParameters(nil)
227+
srv := newTestQUICServer(t, serverConfig)
228+
srv.conn.SetTransportParameters(nil)
229+
onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
230+
if e.Kind == QUICWriteData {
231+
// Provide the data one byte at a time.
232+
for i := range e.Data {
233+
if err := dst.conn.HandleData(e.Level, e.Data[i:i+1]); err != nil {
234+
t.Errorf("HandleData: %v", err)
235+
break
236+
}
237+
}
238+
return true
239+
}
240+
return false
241+
}
242+
if err := runTestQUICConnection(context.Background(), cli, srv, onEvent); err != nil {
243+
t.Fatalf("error during first connection handshake: %v", err)
244+
}
245+
}
246+
213247
func TestQUICPostHandshakeClientAuthentication(t *testing.T) {
214248
// RFC 9001, Section 4.4.
215249
config := testConfig.Clone()
@@ -263,6 +297,28 @@ func TestQUICPostHandshakeKeyUpdate(t *testing.T) {
263297
}
264298
}
265299

300+
func TestQUICPostHandshakeMessageTooLarge(t *testing.T) {
301+
config := testConfig.Clone()
302+
config.MinVersion = VersionTLS13
303+
cli := newTestQUICClient(t, config)
304+
cli.conn.SetTransportParameters(nil)
305+
srv := newTestQUICServer(t, config)
306+
srv.conn.SetTransportParameters(nil)
307+
if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
308+
t.Fatalf("error during connection handshake: %v", err)
309+
}
310+
311+
size := maxHandshake + 1
312+
if err := cli.conn.HandleData(QUICEncryptionLevelApplication, []byte{
313+
byte(typeNewSessionTicket),
314+
byte(size >> 16),
315+
byte(size >> 8),
316+
byte(size),
317+
}); err == nil {
318+
t.Fatalf("%v-byte post-handshake message: got no error, want one", size)
319+
}
320+
}
321+
266322
func TestQUICHandshakeError(t *testing.T) {
267323
clientConfig := testConfig.Clone()
268324
clientConfig.MinVersion = VersionTLS13
@@ -297,26 +353,22 @@ func TestQUICConnectionState(t *testing.T) {
297353
cli.conn.SetTransportParameters(nil)
298354
srv := newTestQUICServer(t, config)
299355
srv.conn.SetTransportParameters(nil)
300-
onHandleCryptoData := func() {
356+
onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
301357
cliCS := cli.conn.ConnectionState()
302-
cliWantALPN := ""
303358
if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; ok {
304-
cliWantALPN = "h3"
305-
}
306-
if want, got := cliCS.NegotiatedProtocol, cliWantALPN; want != got {
307-
t.Errorf("cli.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
359+
if want, got := cliCS.NegotiatedProtocol, "h3"; want != got {
360+
t.Errorf("cli.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
361+
}
308362
}
309-
310363
srvCS := srv.conn.ConnectionState()
311-
srvWantALPN := ""
312364
if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; ok {
313-
srvWantALPN = "h3"
314-
}
315-
if want, got := srvCS.NegotiatedProtocol, srvWantALPN; want != got {
316-
t.Errorf("srv.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
365+
if want, got := srvCS.NegotiatedProtocol, "h3"; want != got {
366+
t.Errorf("srv.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
367+
}
317368
}
369+
return false
318370
}
319-
if err := runTestQUICConnection(context.Background(), cli, srv, onHandleCryptoData); err != nil {
371+
if err := runTestQUICConnection(context.Background(), cli, srv, onEvent); err != nil {
320372
t.Fatalf("error during connection handshake: %v", err)
321373
}
322374
}

0 commit comments

Comments
 (0)