forked from quic-go/quic-go
add a version to marshaled transport parameters in the session ticket
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package handshake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -448,12 +449,28 @@ func (h *cryptoSetup) marshalPeerParamsForSessionState() []byte {
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handlePeerParamsFromSessionState(data []byte) {
|
||||
var tp TransportParameters
|
||||
if err := tp.Unmarshal(data, protocol.PerspectiveServer); err != nil {
|
||||
tp, err := h.handlePeerParamsFromSessionStateImpl(data)
|
||||
if err != nil {
|
||||
h.logger.Debugf("Restoring of transport parameters from session ticket failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
h.zeroRTTParameters = &tp
|
||||
h.zeroRTTParameters = tp
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handlePeerParamsFromSessionStateImpl(data []byte) (*TransportParameters, error) {
|
||||
r := bytes.NewReader(data)
|
||||
version, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version != transportParameterMarshalingVersion {
|
||||
return nil, fmt.Errorf("unknown transport parameter marshaling version: %d", version)
|
||||
}
|
||||
var tp TransportParameters
|
||||
if err := tp.Unmarshal(data[len(data)-r.Len():], protocol.PerspectiveServer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tp, nil
|
||||
}
|
||||
|
||||
// only valid for the server
|
||||
@@ -469,7 +486,12 @@ func (h *cryptoSetup) maybeSendSessionTicket() {
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) accept0RTT(sessionTicketData []byte) bool {
|
||||
return h.ourParams.ValidFromSessionTicket(sessionTicketData)
|
||||
var tp TransportParameters
|
||||
if err := tp.UnmarshalFromSessionTicket(sessionTicketData); err != nil {
|
||||
h.logger.Debugf("Unmarshaling transport parameters from session ticket failed: %s", err.Error())
|
||||
return false
|
||||
}
|
||||
return h.ourParams.ValidFor0RTT(&tp)
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handlePostHandshakeMessage() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package handshake
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -341,13 +342,21 @@ var _ = Describe("Transport Parameters", func() {
|
||||
MaxBidiStreamNum: protocol.StreamNum(getRandomValue()),
|
||||
MaxUniStreamNum: protocol.StreamNum(getRandomValue()),
|
||||
}
|
||||
data := params.MarshalForSessionTicket()
|
||||
Expect(params.ValidFromSessionTicket(data)).To(BeTrue())
|
||||
Expect(params.ValidFor0RTT(params)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("rejects the parameters if it can't parse them", func() {
|
||||
params := &TransportParameters{}
|
||||
Expect(params.ValidFromSessionTicket([]byte("foobar"))).To(BeFalse())
|
||||
var p TransportParameters
|
||||
Expect(p.UnmarshalFromSessionTicket([]byte("foobar"))).ToNot(Succeed())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the version changed", func() {
|
||||
var p TransportParameters
|
||||
data := p.MarshalForSessionTicket()
|
||||
b := &bytes.Buffer{}
|
||||
utils.WriteVarInt(b, transportParameterMarshalingVersion+1)
|
||||
b.Write(data[utils.VarIntLen(transportParameterMarshalingVersion):])
|
||||
Expect(p.UnmarshalFromSessionTicket(b.Bytes())).To(MatchError(fmt.Sprintf("unknown transport parameter marshaling version: %d", transportParameterMarshalingVersion+1)))
|
||||
})
|
||||
|
||||
Context("rejects the parameters if they changed", func() {
|
||||
@@ -370,37 +379,37 @@ var _ = Describe("Transport Parameters", func() {
|
||||
MaxBidiStreamNum: 5,
|
||||
MaxUniStreamNum: 6,
|
||||
}
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeTrue())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the InitialMaxStreamDataBidiLocal changed", func() {
|
||||
p.InitialMaxStreamDataBidiLocal = 0
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the InitialMaxStreamDataBidiRemote changed", func() {
|
||||
p.InitialMaxStreamDataBidiRemote = 0
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the InitialMaxStreamDataUni changed", func() {
|
||||
p.InitialMaxStreamDataUni = 0
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the InitialMaxData changed", func() {
|
||||
p.InitialMaxData = 0
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the MaxBidiStreamNum changed", func() {
|
||||
p.MaxBidiStreamNum = 0
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("rejects the parameters if the MaxUniStreamNum changed", func() {
|
||||
p.MaxUniStreamNum = 0
|
||||
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
|
||||
Expect(params.ValidFor0RTT(p)).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
const transportParameterMarshalingVersion = 1
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
}
|
||||
@@ -379,6 +381,8 @@ func (p *TransportParameters) marshalVarintParam(b *bytes.Buffer, id transportPa
|
||||
// For convenience, we use the same format that we also use for sending the transport parameters.
|
||||
func (p *TransportParameters) MarshalForSessionTicket() []byte {
|
||||
b := &bytes.Buffer{}
|
||||
utils.WriteVarInt(b, transportParameterMarshalingVersion)
|
||||
startLen := b.Len()
|
||||
b.Write([]byte{0, 0}) // length. Will be replaced later
|
||||
|
||||
// initial_max_stream_data_bidi_local
|
||||
@@ -395,17 +399,26 @@ func (p *TransportParameters) MarshalForSessionTicket() []byte {
|
||||
p.marshalVarintParam(b, initialMaxStreamsUniParameterID, uint64(p.MaxUniStreamNum))
|
||||
|
||||
data := b.Bytes()
|
||||
binary.BigEndian.PutUint16(data[:2], uint16(b.Len()-2))
|
||||
binary.BigEndian.PutUint16(data[startLen:startLen+2], uint16(b.Len()-2-startLen))
|
||||
return data
|
||||
}
|
||||
|
||||
// ValidFromSessionTicket checks if the transport parameters match those saved in the session ticket.
|
||||
func (p *TransportParameters) ValidFromSessionTicket(data []byte) bool {
|
||||
tp := &TransportParameters{}
|
||||
if err := tp.Unmarshal(data, protocol.PerspectiveServer); err != nil {
|
||||
return false
|
||||
// UnmarshalFromSessionTicket unmarshals transport parameters from a session ticket.
|
||||
func (p *TransportParameters) UnmarshalFromSessionTicket(data []byte) error {
|
||||
r := bytes.NewReader(data)
|
||||
version, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if version != transportParameterMarshalingVersion {
|
||||
return fmt.Errorf("unknown transport parameter marshaling version: %d", version)
|
||||
}
|
||||
tp := &TransportParameters{}
|
||||
return tp.Unmarshal(data[len(data)-r.Len():], protocol.PerspectiveServer)
|
||||
}
|
||||
|
||||
// ValidFor0RTT checks if the transport parameters match those saved in the session ticket.
|
||||
func (p *TransportParameters) ValidFor0RTT(tp *TransportParameters) bool {
|
||||
return p.InitialMaxStreamDataBidiLocal == tp.InitialMaxStreamDataBidiLocal &&
|
||||
p.InitialMaxStreamDataBidiRemote == tp.InitialMaxStreamDataBidiRemote &&
|
||||
p.InitialMaxStreamDataUni == tp.InitialMaxStreamDataUni &&
|
||||
|
||||
Reference in New Issue
Block a user