mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 04:37:36 +03:00
never allow 0-RTT when using Dial, even if the session ticket allows it (#4125)
When resuming a TLS session using Dial (and not DialEarly), 0-RTT should be disabled at the TLS layer, even if the session ticket allows for 0-RTT resumption. This bug is not critical, since Dial doesn't return an EarlyConnection, so the client wouldn't be able to actually send 0-RTT data in practice.
This commit is contained in:
parent
1bcec70978
commit
746290b78a
11 changed files with 93 additions and 14 deletions
|
@ -96,6 +96,7 @@ func NewCryptoSetupClient(
|
|||
quicConf := &qtls.QUICConfig{TLSConfig: tlsConf}
|
||||
qtls.SetupConfigForClient(quicConf, cs.marshalDataForSessionState, cs.handleDataFromSessionState)
|
||||
cs.tlsConf = tlsConf
|
||||
cs.allow0RTT = enable0RTT
|
||||
|
||||
cs.conn = qtls.QUICClient(quicConf)
|
||||
cs.conn.SetTransportParameters(cs.ourParams.Marshal(protocol.PerspectiveClient))
|
||||
|
@ -316,13 +317,20 @@ func (h *cryptoSetup) marshalDataForSessionState() []byte {
|
|||
return h.peerParams.MarshalForSessionTicket(b)
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handleDataFromSessionState(data []byte) {
|
||||
func (h *cryptoSetup) handleDataFromSessionState(data []byte) (allowEarlyData bool) {
|
||||
tp, err := h.handleDataFromSessionStateImpl(data)
|
||||
if err != nil {
|
||||
h.logger.Debugf("Restoring of transport parameters from session ticket failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
h.zeroRTTParameters = tp
|
||||
// The session ticket might have been saved from a connection that allowed 0-RTT,
|
||||
// and therefore contain transport parameters.
|
||||
// Only use them if 0-RTT is actually used on the new connection.
|
||||
if tp != nil && h.allow0RTT {
|
||||
h.zeroRTTParameters = tp
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handleDataFromSessionStateImpl(data []byte) (*wire.TransportParameters, error) {
|
||||
|
@ -383,7 +391,9 @@ func (h *cryptoSetup) GetSessionTicket() ([]byte, error) {
|
|||
}
|
||||
|
||||
// handleSessionTicket is called for the server when receiving the client's session ticket.
|
||||
// It reads parameters from the session ticket and decides whether to accept 0-RTT when the session ticket is used for 0-RTT.
|
||||
// It reads parameters from the session ticket and checks whether to accept 0-RTT if the session ticket enabled 0-RTT.
|
||||
// Note that the fact that the session ticket allows 0-RTT doesn't mean that the actual TLS handshake enables 0-RTT:
|
||||
// A client may use a 0-RTT enabled session to resume a TLS session without using 0-RTT.
|
||||
func (h *cryptoSetup) handleSessionTicket(sessionTicketData []byte, using0RTT bool) bool {
|
||||
var t sessionTicket
|
||||
if err := t.Unmarshal(sessionTicketData, using0RTT); err != nil {
|
||||
|
|
|
@ -450,8 +450,8 @@ var _ = Describe("Crypto Setup TLS", func() {
|
|||
Eventually(receivedSessionTicket).Should(BeClosed())
|
||||
Expect(server.ConnectionState().DidResume).To(BeTrue())
|
||||
Expect(client.ConnectionState().DidResume).To(BeTrue())
|
||||
Expect(clientRTTStats.SmoothedRTT()).To(Equal(clientRTT))
|
||||
if !strings.Contains(runtime.Version(), "go1.20") {
|
||||
Expect(clientRTTStats.SmoothedRTT()).To(Equal(clientRTT))
|
||||
Expect(serverRTTStats.SmoothedRTT()).To(Equal(serverRTT))
|
||||
}
|
||||
})
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
type clientSessionCache struct {
|
||||
getData func() []byte
|
||||
setData func([]byte)
|
||||
setData func([]byte) (allowEarlyData bool)
|
||||
wrapped tls.ClientSessionCache
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,12 @@ func (c clientSessionCache) Get(key string) (*tls.ClientSessionState, bool) {
|
|||
c.wrapped.Put(key, nil)
|
||||
return nil, false
|
||||
}
|
||||
var earlyData bool
|
||||
// restore QUIC transport parameters and RTT stored in state.Extra
|
||||
if extra := findExtraData(state.Extra); extra != nil {
|
||||
c.setData(extra)
|
||||
earlyData = c.setData(extra)
|
||||
}
|
||||
state.EarlyData = earlyData
|
||||
session, err := tls.NewResumptionState(ticket, state)
|
||||
if err != nil {
|
||||
// It's not clear why this would error.
|
||||
|
|
|
@ -41,7 +41,10 @@ var _ = Describe("Client Session Cache", func() {
|
|||
ClientSessionCache: &clientSessionCache{
|
||||
wrapped: tls.NewLRUClientSessionCache(10),
|
||||
getData: func() []byte { return []byte("session") },
|
||||
setData: func(data []byte) { restored <- data },
|
||||
setData: func(data []byte) bool {
|
||||
restored <- data
|
||||
return true
|
||||
},
|
||||
},
|
||||
}
|
||||
conn, err := tls.Dial(
|
||||
|
|
|
@ -52,7 +52,7 @@ func SetupConfigForServer(conf *QUICConfig, enable0RTT bool, getDataForSessionTi
|
|||
}
|
||||
}
|
||||
|
||||
func SetupConfigForClient(conf *QUICConfig, getDataForSessionState func() []byte, setDataFromSessionState func([]byte)) {
|
||||
func SetupConfigForClient(conf *QUICConfig, getDataForSessionState func() []byte, setDataFromSessionState func([]byte) bool) {
|
||||
conf.ExtraConfig = &qtls.ExtraConfig{
|
||||
GetAppDataForSessionState: getDataForSessionState,
|
||||
SetAppDataFromSessionState: setDataFromSessionState,
|
||||
|
|
|
@ -93,7 +93,7 @@ func SetupConfigForServer(qconf *QUICConfig, _ bool, getData func() []byte, hand
|
|||
}
|
||||
}
|
||||
|
||||
func SetupConfigForClient(qconf *QUICConfig, getData func() []byte, setData func([]byte)) {
|
||||
func SetupConfigForClient(qconf *QUICConfig, getData func() []byte, setData func([]byte) bool) {
|
||||
conf := qconf.TLSConfig
|
||||
if conf.ClientSessionCache != nil {
|
||||
origCache := conf.ClientSessionCache
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue