forked from quic-go/quic-go
@@ -25,7 +25,8 @@ func (u *packetUnpacker) Unpack(publicHeaderBinary []byte, publicHeader *PublicH
|
||||
ciphertext, _ := ioutil.ReadAll(r)
|
||||
plaintext, err := u.aead.Open(publicHeader.PacketNumber, publicHeaderBinary, ciphertext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Wrap err in quicError so that public reset is sent by session
|
||||
return nil, protocol.NewQuicError(errorcodes.QUIC_DECRYPTION_FAILURE, err.Error())
|
||||
}
|
||||
r = bytes.NewReader(plaintext)
|
||||
|
||||
|
||||
20
session.go
20
session.go
@@ -51,7 +51,8 @@ type Session struct {
|
||||
closeChan chan struct{}
|
||||
closed bool
|
||||
|
||||
// Used to calculate the next packet number from the truncated wire representation
|
||||
// Used to calculate the next packet number from the truncated wire
|
||||
// representation, and sent back in public reset packets
|
||||
lastRcvdPacketNumber protocol.PacketNumber
|
||||
|
||||
rttStats congestion.RTTStats
|
||||
@@ -232,6 +233,11 @@ func (s *Session) Close(e error) error {
|
||||
errorCode = quicError.ErrorCode
|
||||
}
|
||||
s.closeStreamsWithError(e)
|
||||
|
||||
if errorCode == errorcodes.QUIC_DECRYPTION_FAILURE {
|
||||
return s.sendPublicReset(s.lastRcvdPacketNumber)
|
||||
}
|
||||
|
||||
packet, err := s.packer.PackPacket(nil, []frames.Frame{
|
||||
&frames.ConnectionCloseFrame{ErrorCode: errorCode, ReasonPhrase: reasonPhrase},
|
||||
}, false)
|
||||
@@ -339,3 +345,15 @@ func (s *Session) garbageCollectStreams() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) sendPublicReset(rejectedPacketNumber protocol.PacketNumber) error {
|
||||
fmt.Printf("Sending public reset for connection %d, packet number %d\n", s.connectionID, rejectedPacketNumber)
|
||||
packet := &publicResetPacket{
|
||||
connectionID: s.connectionID,
|
||||
rejectedPacketNumber: rejectedPacketNumber,
|
||||
nonceProof: 0, // TODO: Currently ignored by chrome.
|
||||
}
|
||||
var b bytes.Buffer
|
||||
packet.Write(&b)
|
||||
return s.conn.write(b.Bytes())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
@@ -243,6 +244,13 @@ var _ = Describe("Session", func() {
|
||||
Expect(conn.written[0]).To(ContainSubstring(string([]byte{0x4c, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0})))
|
||||
Expect(conn.written[0]).To(ContainSubstring(string("foobar")))
|
||||
})
|
||||
|
||||
It("sends public reset", func() {
|
||||
err := session.sendPublicReset(1)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(conn.written).To(HaveLen(1))
|
||||
Expect(conn.written[0]).To(ContainSubstring(string([]byte("PRST"))))
|
||||
})
|
||||
})
|
||||
|
||||
It("closes when crypto stream errors", func() {
|
||||
@@ -263,4 +271,23 @@ var _ = Describe("Session", func() {
|
||||
_, err = s.Write([]byte{})
|
||||
Expect(err).To(MatchError("CryptoSetup: expected CHLO"))
|
||||
})
|
||||
|
||||
It("sends public reset when receiving invalid message", func() {
|
||||
path := os.Getenv("GOPATH") + "/src/github.com/lucas-clemente/quic-go/example/"
|
||||
signer, err := crypto.NewRSASigner(path+"cert.der", path+"key.der")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
scfg := handshake.NewServerConfig(crypto.NewCurve25519KEX(), signer)
|
||||
session = NewSession(conn, 0, 0, scfg, nil).(*Session)
|
||||
hdr := &PublicHeader{
|
||||
PacketNumber: 42,
|
||||
}
|
||||
r := bytes.NewReader([]byte("foo"))
|
||||
err = session.handlePacket(nil, hdr, r)
|
||||
Expect(err).To(HaveOccurred())
|
||||
// Close() should send public reset
|
||||
err = session.Close(err)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(conn.written).To(HaveLen(1))
|
||||
Expect(conn.written[0]).To(ContainSubstring(string([]byte("PRST"))))
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user