mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 12:47:36 +03:00
parse IETF headers independent of the sender's perspective
The IETF header format allows parsing of the header without knowing which peer sent the packet.
This commit is contained in:
parent
70f6e3651e
commit
8f2fed1b10
9 changed files with 74 additions and 74 deletions
|
@ -346,6 +346,9 @@ func (c *client) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remot
|
|||
return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", hdr.DestConnectionID, c.srcConnID)
|
||||
}
|
||||
if hdr.IsLongHeader {
|
||||
if hdr.Type != protocol.PacketTypeRetry && hdr.Type != protocol.PacketTypeHandshake {
|
||||
return fmt.Errorf("Received unsupported packet type: %s", hdr.Type)
|
||||
}
|
||||
c.logger.Debugf("len(packet data): %d, payloadLen: %d", len(packetData), hdr.PayloadLen)
|
||||
if protocol.ByteCount(len(packetData)) < hdr.PayloadLen {
|
||||
return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(packetData), hdr.PayloadLen)
|
||||
|
|
|
@ -547,11 +547,27 @@ var _ = Describe("Client", func() {
|
|||
Version: versionIETFFrames,
|
||||
}
|
||||
Expect(hdr.Write(b, protocol.PerspectiveClient, versionIETFFrames)).To(Succeed())
|
||||
cl.handlePacket(addr, append(b.Bytes(), make([]byte, 456)...))
|
||||
err := cl.handlePacket(addr, append(b.Bytes(), make([]byte, 456)...))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(sess.handledPackets).To(HaveLen(1))
|
||||
Expect(sess.handledPackets[0].data).To(HaveLen(123))
|
||||
})
|
||||
|
||||
It("ignores packets with the wrong Long Header Type", func() {
|
||||
b := &bytes.Buffer{}
|
||||
hdr := &wire.Header{
|
||||
IsLongHeader: true,
|
||||
Type: protocol.PacketTypeInitial,
|
||||
PayloadLen: 123,
|
||||
SrcConnectionID: connID,
|
||||
DestConnectionID: connID,
|
||||
Version: versionIETFFrames,
|
||||
}
|
||||
Expect(hdr.Write(b, protocol.PerspectiveServer, versionIETFFrames)).To(Succeed())
|
||||
err := cl.handlePacket(addr, append(b.Bytes(), make([]byte, 456)...))
|
||||
Expect(err).To(MatchError("Received unsupported packet type: Initial"))
|
||||
})
|
||||
|
||||
It("ignores packets without connection id, if it didn't request connection id trunctation", func() {
|
||||
cl.config = &Config{RequestConnectionIDOmission: false}
|
||||
buf := &bytes.Buffer{}
|
||||
|
|
|
@ -87,7 +87,7 @@ func parsePacketHeader(b *bytes.Reader, sentBy protocol.Perspective, isPublicHea
|
|||
hdr.IsPublicHeader = true // save that this is a Public Header, so we can log it correctly later
|
||||
return hdr, nil
|
||||
}
|
||||
return parseHeader(b, sentBy)
|
||||
return parseHeader(b)
|
||||
}
|
||||
|
||||
// Write writes the Header.
|
||||
|
|
|
@ -190,6 +190,7 @@ var _ = Describe("Header", func() {
|
|||
It("writes a IETF draft header", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
hdr := &Header{
|
||||
Type: protocol.PacketTypeHandshake,
|
||||
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
|
||||
SrcConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
|
||||
PacketNumber: 0x42,
|
||||
|
@ -198,7 +199,7 @@ var _ = Describe("Header", func() {
|
|||
}
|
||||
err := hdr.Write(buf, protocol.PerspectiveServer, versionIETFHeader)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = parseHeader(bytes.NewReader(buf.Bytes()), protocol.PerspectiveServer)
|
||||
_, err = ParseHeaderSentByServer(bytes.NewReader(buf.Bytes()), versionIETFFrames)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(hdr.IsPublicHeader).To(BeFalse())
|
||||
})
|
||||
|
|
|
@ -12,19 +12,19 @@ import (
|
|||
)
|
||||
|
||||
// parseHeader parses the header.
|
||||
func parseHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Header, error) {
|
||||
func parseHeader(b *bytes.Reader) (*Header, error) {
|
||||
typeByte, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if typeByte&0x80 > 0 {
|
||||
return parseLongHeader(b, packetSentBy, typeByte)
|
||||
return parseLongHeader(b, typeByte)
|
||||
}
|
||||
return parseShortHeader(b, typeByte)
|
||||
}
|
||||
|
||||
// parse long header and version negotiation packets
|
||||
func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte) (*Header, error) {
|
||||
func parseLongHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
|
||||
v, err := utils.BigEndian.ReadUint32(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -52,9 +52,6 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
|
|||
}
|
||||
|
||||
if v == 0 { // version negotiation packet
|
||||
if sentBy == protocol.PerspectiveClient {
|
||||
return nil, qerr.InvalidVersion
|
||||
}
|
||||
if b.Len() == 0 {
|
||||
return nil, qerr.Error(qerr.InvalidVersionNegotiationPacket, "empty version list")
|
||||
}
|
||||
|
@ -82,10 +79,8 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte
|
|||
h.PacketNumber = protocol.PacketNumber(pn)
|
||||
h.PacketNumberLen = protocol.PacketNumberLen4
|
||||
h.Type = protocol.PacketType(typeByte & 0x7f)
|
||||
if sentBy == protocol.PerspectiveClient && (h.Type != protocol.PacketTypeInitial && h.Type != protocol.PacketTypeHandshake && h.Type != protocol.PacketType0RTT) {
|
||||
return nil, qerr.Error(qerr.InvalidPacketHeader, fmt.Sprintf("Received packet with invalid packet type: %d", h.Type))
|
||||
}
|
||||
if sentBy == protocol.PerspectiveServer && (h.Type != protocol.PacketTypeRetry && h.Type != protocol.PacketTypeHandshake) {
|
||||
|
||||
if h.Type != protocol.PacketTypeInitial && h.Type != protocol.PacketTypeRetry && h.Type != protocol.PacketType0RTT && h.Type != protocol.PacketTypeHandshake {
|
||||
return nil, qerr.Error(qerr.InvalidPacketHeader, fmt.Sprintf("Received packet with invalid packet type: %d", h.Type))
|
||||
}
|
||||
return h, nil
|
||||
|
|
|
@ -2,7 +2,6 @@ package wire
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -26,7 +25,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
data, err := ComposeVersionNegotiation(connID, connID, versions)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveServer)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.IsVersionNegotiation).To(BeTrue())
|
||||
Expect(h.Version).To(BeZero())
|
||||
|
@ -43,7 +42,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
data, err := ComposeVersionNegotiation(connID, connID, versions)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
b := bytes.NewReader(data[:len(data)-2])
|
||||
_, err = parseHeader(b, protocol.PerspectiveServer)
|
||||
_, err = parseHeader(b)
|
||||
Expect(err).To(MatchError(qerr.InvalidVersionNegotiationPacket))
|
||||
})
|
||||
|
||||
|
@ -53,7 +52,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
data, err := ComposeVersionNegotiation(connID, connID, versions)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// remove 8 bytes (two versions), since ComposeVersionNegotiation also added a reserved version number
|
||||
_, err = parseHeader(bytes.NewReader(data[:len(data)-8]), protocol.PerspectiveServer)
|
||||
_, err = parseHeader(bytes.NewReader(data[:len(data)-8]))
|
||||
Expect(err).To(MatchError("InvalidVersionNegotiationPacket: empty version list"))
|
||||
})
|
||||
})
|
||||
|
@ -74,7 +73,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
|
||||
It("parses a long header", func() {
|
||||
b := bytes.NewReader(generatePacket(protocol.PacketTypeInitial))
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.Type).To(Equal(protocol.PacketTypeInitial))
|
||||
Expect(h.IsLongHeader).To(BeTrue())
|
||||
|
@ -99,7 +98,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
data = append(data, encodeVarInt(0x42)...) // payload length
|
||||
data = append(data, []byte{0xde, 0xca, 0xfb, 0xad}...)
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.SrcConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}))
|
||||
Expect(h.DestConnectionID).To(BeEmpty())
|
||||
|
@ -115,40 +114,12 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
data = append(data, encodeVarInt(0x42)...) // payload length
|
||||
data = append(data, []byte{0xde, 0xca, 0xfb, 0xad}...)
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.SrcConnectionID).To(BeEmpty())
|
||||
Expect(h.DestConnectionID).To(Equal(protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))
|
||||
})
|
||||
|
||||
It("rejects packets sent by the client that use packet types for packets sent by the server", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
err := (&Header{
|
||||
IsLongHeader: true,
|
||||
Type: protocol.PacketTypeRetry,
|
||||
SrcConnectionID: srcConnID,
|
||||
Version: 0x10203040,
|
||||
}).Write(buf, protocol.PerspectiveServer, protocol.VersionTLS)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
b := bytes.NewReader(buf.Bytes())
|
||||
_, err = parseHeader(b, protocol.PerspectiveClient)
|
||||
Expect(err).To(MatchError(fmt.Sprintf("InvalidPacketHeader: Received packet with invalid packet type: %d", protocol.PacketTypeRetry)))
|
||||
})
|
||||
|
||||
It("rejects packets sent by the client that use packet types for packets sent by the server", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
err := (&Header{
|
||||
IsLongHeader: true,
|
||||
Type: protocol.PacketType0RTT,
|
||||
SrcConnectionID: srcConnID,
|
||||
Version: 0x10203040,
|
||||
}).Write(buf, protocol.PerspectiveClient, protocol.VersionTLS)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
b := bytes.NewReader(buf.Bytes())
|
||||
_, err = parseHeader(b, protocol.PerspectiveServer)
|
||||
Expect(err).To(MatchError(fmt.Sprintf("InvalidPacketHeader: Received packet with invalid packet type: %d", protocol.PacketType0RTT)))
|
||||
})
|
||||
|
||||
It("rejects packets sent with an unknown packet type", func() {
|
||||
buf := &bytes.Buffer{}
|
||||
err := (&Header{
|
||||
|
@ -159,21 +130,10 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
}).Write(buf, protocol.PerspectiveClient, protocol.VersionTLS)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
b := bytes.NewReader(buf.Bytes())
|
||||
_, err = parseHeader(b, protocol.PerspectiveServer)
|
||||
_, err = parseHeader(b)
|
||||
Expect(err).To(MatchError("InvalidPacketHeader: Received packet with invalid packet type: 42"))
|
||||
})
|
||||
|
||||
It("rejects version 0 for packets sent by the client", func() {
|
||||
data := []byte{
|
||||
0x80 ^ uint8(protocol.PacketTypeInitial),
|
||||
0x0, 0x0, 0x0, 0x0, // version number
|
||||
0x0, // no connection IDs
|
||||
0xde, 0xca, 0xfb, 0xad, // packet number
|
||||
}
|
||||
_, err := parseHeader(bytes.NewReader(data), protocol.PerspectiveClient)
|
||||
Expect(err).To(MatchError(qerr.InvalidVersion))
|
||||
})
|
||||
|
||||
It("errors on EOF", func() {
|
||||
data := []byte{
|
||||
0x80 ^ uint8(protocol.PacketTypeInitial),
|
||||
|
@ -184,7 +144,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0xde, 0xca, 0xfb, 0xad, // packet number
|
||||
}
|
||||
for i := 0; i < len(data); i++ {
|
||||
_, err := parseHeader(bytes.NewReader(data[:i]), protocol.PerspectiveClient)
|
||||
_, err := parseHeader(bytes.NewReader(data[:i]))
|
||||
Expect(err).To(Equal(io.EOF))
|
||||
}
|
||||
})
|
||||
|
@ -198,7 +158,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0x42, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.IsLongHeader).To(BeFalse())
|
||||
Expect(h.KeyPhase).To(Equal(0))
|
||||
|
@ -217,7 +177,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0x11,
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.IsLongHeader).To(BeFalse())
|
||||
Expect(h.KeyPhase).To(Equal(1))
|
||||
|
@ -231,7 +191,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0x13, 0x37, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.IsLongHeader).To(BeFalse())
|
||||
Expect(h.PacketNumber).To(Equal(protocol.PacketNumber(0x1337)))
|
||||
|
@ -246,7 +206,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0xde, 0xad, 0xbe, 0xef, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
h, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
h, err := parseHeader(b)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(h.IsLongHeader).To(BeFalse())
|
||||
Expect(h.PacketNumber).To(Equal(protocol.PacketNumber(0xdeadbeef)))
|
||||
|
@ -261,7 +221,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0xde, 0xad, 0xbe, 0xef, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
_, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
_, err := parseHeader(b)
|
||||
Expect(err).To(MatchError("invalid short header type"))
|
||||
})
|
||||
|
||||
|
@ -272,7 +232,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0xde, 0xca, 0xfb, 0xad, // packet number
|
||||
}
|
||||
b := bytes.NewReader(data)
|
||||
_, err := parseHeader(b, protocol.PerspectiveClient)
|
||||
_, err := parseHeader(b)
|
||||
Expect(err).To(MatchError("invalid bits 3, 4 and 5"))
|
||||
})
|
||||
|
||||
|
@ -283,7 +243,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
0xde, 0xca, 0xfb, 0xad, // packet number
|
||||
}
|
||||
for i := 0; i < len(data); i++ {
|
||||
_, err := parseHeader(bytes.NewReader(data[:i]), protocol.PerspectiveClient)
|
||||
_, err := parseHeader(bytes.NewReader(data[:i]))
|
||||
Expect(err).To(Equal(io.EOF))
|
||||
}
|
||||
})
|
||||
|
@ -545,7 +505,7 @@ var _ = Describe("IETF QUIC Header", func() {
|
|||
srcConnID := protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad, 0x013, 0x37, 0x13, 0x37}
|
||||
data, err := ComposeVersionNegotiation(destConnID, srcConnID, []protocol.VersionNumber{0x12345678, 0x87654321})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
hdr, err := parseLongHeader(bytes.NewReader(data[1:]), protocol.PerspectiveServer, data[0])
|
||||
hdr, err := parseLongHeader(bytes.NewReader(data[1:]), data[0])
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
hdr.logHeader(logger)
|
||||
Expect(buf.String()).To(ContainSubstring("VersionNegotiationPacket{DestConnectionID: 0xdeadbeefcafe1337, SrcConnectionID: 0xdecafbad13371337"))
|
||||
|
|
|
@ -28,7 +28,7 @@ var _ = Describe("Version Negotiation Packets", func() {
|
|||
data, err := ComposeVersionNegotiation(destConnID, srcConnID, versions)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(data[0] & 0x80).ToNot(BeZero())
|
||||
hdr, err := parseHeader(bytes.NewReader(data), protocol.PerspectiveServer)
|
||||
hdr, err := parseHeader(bytes.NewReader(data))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(hdr.IsVersionNegotiation).To(BeTrue())
|
||||
Expect(hdr.DestConnectionID).To(Equal(destConnID))
|
||||
|
|
15
server.go
15
server.go
|
@ -314,18 +314,25 @@ func (s *server) handlePacket(remoteAddr net.Addr, packet []byte) error {
|
|||
|
||||
func (s *server) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error {
|
||||
if hdr.IsLongHeader {
|
||||
if !s.supportsTLS {
|
||||
return errors.New("Received an IETF QUIC Long Header")
|
||||
}
|
||||
if protocol.ByteCount(len(packetData)) < hdr.PayloadLen {
|
||||
return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(packetData), hdr.PayloadLen)
|
||||
}
|
||||
packetData = packetData[:int(hdr.PayloadLen)]
|
||||
// TODO(#1312): implement parsing of compound packets
|
||||
}
|
||||
|
||||
if hdr.Type == protocol.PacketTypeInitial {
|
||||
if s.supportsTLS {
|
||||
switch hdr.Type {
|
||||
case protocol.PacketTypeInitial:
|
||||
go s.serverTLS.HandleInitial(remoteAddr, hdr, packetData)
|
||||
}
|
||||
return nil
|
||||
case protocol.PacketTypeHandshake:
|
||||
// nothing to do here. Packet will be passed to the session.
|
||||
default:
|
||||
// Note that this also drops 0-RTT packets.
|
||||
return fmt.Errorf("Received unsupported packet type: %s", hdr.Type)
|
||||
}
|
||||
}
|
||||
|
||||
s.sessionsMutex.RLock()
|
||||
|
|
|
@ -386,6 +386,7 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
It("errors on packets that are smaller than the Payload Length in the packet header", func() {
|
||||
serv.supportsTLS = true
|
||||
b := &bytes.Buffer{}
|
||||
hdr := &wire.Header{
|
||||
IsLongHeader: true,
|
||||
|
@ -401,6 +402,7 @@ var _ = Describe("Server", func() {
|
|||
})
|
||||
|
||||
It("cuts packets at the payload length", func() {
|
||||
serv.supportsTLS = true
|
||||
err := serv.handlePacket(nil, firstPacket)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
b := &bytes.Buffer{}
|
||||
|
@ -419,6 +421,22 @@ var _ = Describe("Server", func() {
|
|||
Expect(serv.sessions[string(connID)].(*mockSession).handledPackets[1].data).To(HaveLen(123))
|
||||
})
|
||||
|
||||
It("drops packets with invalid packet types", func() {
|
||||
serv.supportsTLS = true
|
||||
b := &bytes.Buffer{}
|
||||
hdr := &wire.Header{
|
||||
IsLongHeader: true,
|
||||
Type: protocol.PacketTypeRetry,
|
||||
PayloadLen: 123,
|
||||
SrcConnectionID: connID,
|
||||
DestConnectionID: connID,
|
||||
Version: versionIETFFrames,
|
||||
}
|
||||
Expect(hdr.Write(b, protocol.PerspectiveClient, versionIETFFrames)).To(Succeed())
|
||||
err := serv.handlePacket(nil, append(b.Bytes(), make([]byte, 456)...))
|
||||
Expect(err).To(MatchError("Received unsupported packet type: Retry"))
|
||||
})
|
||||
|
||||
It("ignores Public Resets", func() {
|
||||
err := serv.handlePacket(nil, firstPacket)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue