From 791b90d4d54b7948e9dedd4c69adccb1b67787cf Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Fri, 22 Feb 2019 14:04:49 +0800 Subject: [PATCH 1/2] copy the GetCertificate callback when creating the qtls.Config --- internal/handshake/qtls.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/internal/handshake/qtls.go b/internal/handshake/qtls.go index 813200b36..4e528b02f 100644 --- a/internal/handshake/qtls.go +++ b/internal/handshake/qtls.go @@ -20,12 +20,11 @@ func tlsConfigToQtlsConfig(c *tls.Config) *qtls.Config { maxVersion = qtls.VersionTLS13 } return &qtls.Config{ - Rand: c.Rand, - Time: c.Time, - Certificates: c.Certificates, - NameToCertificate: c.NameToCertificate, - // TODO: make GetCertificate work - // GetCertificate: c.GetCertificate, + Rand: c.Rand, + Time: c.Time, + Certificates: c.Certificates, + NameToCertificate: c.NameToCertificate, + GetCertificate: c.GetCertificate, GetClientCertificate: c.GetClientCertificate, // TODO: make GetConfigForClient work // GetConfigForClient: c.GetConfigForClient, From d82a60c8351826c69466ddcf120ba800cdf918bf Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Fri, 22 Feb 2019 14:33:00 +0800 Subject: [PATCH 2/2] copy the GetConfigForClient callback when creating the qtls.Config --- internal/handshake/crypto_setup.go | 62 +++++++++++++++++++++++-- internal/handshake/crypto_setup_test.go | 42 +++++++++++++++++ internal/handshake/qtls.go | 49 ------------------- 3 files changed, 100 insertions(+), 53 deletions(-) delete mode 100644 internal/handshake/qtls.go diff --git a/internal/handshake/crypto_setup.go b/internal/handshake/crypto_setup.go index 7e0ffc56d..e30e42401 100644 --- a/internal/handshake/crypto_setup.go +++ b/internal/handshake/crypto_setup.go @@ -198,10 +198,7 @@ func newCryptoSetup( receivedWriteKey: make(chan struct{}), closeChan: make(chan struct{}), } - qtlsConf := tlsConfigToQtlsConfig(tlsConf) - qtlsConf.AlternativeRecordLayer = cs - qtlsConf.GetExtensions = extHandler.GetExtensions - qtlsConf.ReceivedExtensions = extHandler.ReceivedExtensions + qtlsConf := cs.tlsConfigToQtlsConfig(tlsConf) cs.tlsConf = qtlsConf return cs, cs.clientHelloWrittenChan, nil } @@ -528,3 +525,60 @@ func (h *cryptoSetup) ConnectionState() ConnectionState { PeerCertificates: connState.PeerCertificates, } } + +func (h *cryptoSetup) tlsConfigToQtlsConfig(c *tls.Config) *qtls.Config { + if c == nil { + c = &tls.Config{} + } + // QUIC requires TLS 1.3 or newer + minVersion := c.MinVersion + if minVersion < qtls.VersionTLS13 { + minVersion = qtls.VersionTLS13 + } + maxVersion := c.MaxVersion + if maxVersion < qtls.VersionTLS13 { + maxVersion = qtls.VersionTLS13 + } + var getConfigForClient func(ch *tls.ClientHelloInfo) (*qtls.Config, error) + if c.GetConfigForClient != nil { + getConfigForClient = func(ch *tls.ClientHelloInfo) (*qtls.Config, error) { + tlsConf, err := c.GetConfigForClient(ch) + if err != nil { + return nil, err + } + if tlsConf == nil { + return nil, nil + } + return h.tlsConfigToQtlsConfig(tlsConf), nil + } + } + return &qtls.Config{ + Rand: c.Rand, + Time: c.Time, + Certificates: c.Certificates, + NameToCertificate: c.NameToCertificate, + GetCertificate: c.GetCertificate, + GetClientCertificate: c.GetClientCertificate, + GetConfigForClient: getConfigForClient, + VerifyPeerCertificate: c.VerifyPeerCertificate, + RootCAs: c.RootCAs, + NextProtos: c.NextProtos, + ServerName: c.ServerName, + ClientAuth: c.ClientAuth, + ClientCAs: c.ClientCAs, + InsecureSkipVerify: c.InsecureSkipVerify, + CipherSuites: c.CipherSuites, + PreferServerCipherSuites: c.PreferServerCipherSuites, + SessionTicketsDisabled: c.SessionTicketsDisabled, + SessionTicketKey: c.SessionTicketKey, + MinVersion: minVersion, + MaxVersion: maxVersion, + CurvePreferences: c.CurvePreferences, + DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, + // no need to copy Renegotiation, it's not supported by TLS 1.3 + KeyLogWriter: c.KeyLogWriter, + AlternativeRecordLayer: h, + GetExtensions: h.extHandler.GetExtensions, + ReceivedExtensions: h.extHandler.ReceivedExtensions, + } +} diff --git a/internal/handshake/crypto_setup_test.go b/internal/handshake/crypto_setup_test.go index 6a562f543..7d09b22b4 100644 --- a/internal/handshake/crypto_setup_test.go +++ b/internal/handshake/crypto_setup_test.go @@ -7,6 +7,7 @@ import ( "crypto/tls" "crypto/x509" "crypto/x509/pkix" + "errors" "io/ioutil" "math/big" "time" @@ -65,6 +66,47 @@ var _ = Describe("Crypto Setup TLS", func() { } }) + It("creates a qtls.Config", func() { + tlsConf := &tls.Config{ + ServerName: "quic.clemente.io", + GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) { + return nil, errors.New("GetCertificate") + }, + GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + return nil, errors.New("GetClientCertificate") + }, + GetConfigForClient: func(ch *tls.ClientHelloInfo) (*tls.Config, error) { + return &tls.Config{ServerName: ch.ServerName}, nil + }, + } + server, err := NewCryptoSetupServer( + &bytes.Buffer{}, + &bytes.Buffer{}, + ioutil.Discard, + protocol.ConnectionID{}, + &EncryptedExtensionsTransportParameters{ + NegotiatedVersion: protocol.VersionTLS, + SupportedVersions: []protocol.VersionNumber{protocol.VersionTLS}, + }, + func([]byte) {}, + tlsConf, + utils.DefaultLogger.WithPrefix("server"), + ) + Expect(err).ToNot(HaveOccurred()) + qtlsConf := server.(*cryptoSetup).tlsConf + Expect(qtlsConf.ServerName).To(Equal(tlsConf.ServerName)) + _, getCertificateErr := qtlsConf.GetCertificate(nil) + Expect(getCertificateErr).To(MatchError("GetCertificate")) + _, getClientCertificateErr := qtlsConf.GetClientCertificate(nil) + Expect(getClientCertificateErr).To(MatchError("GetClientCertificate")) + cconf, err := qtlsConf.GetConfigForClient(&tls.ClientHelloInfo{ServerName: "foo.bar"}) + Expect(err).ToNot(HaveOccurred()) + Expect(cconf.ServerName).To(Equal("foo.bar")) + Expect(cconf.AlternativeRecordLayer).ToNot(BeNil()) + Expect(cconf.GetExtensions).ToNot(BeNil()) + Expect(cconf.ReceivedExtensions).ToNot(BeNil()) + }) + It("returns Handshake() when an error occurs", func() { _, sInitialStream, sHandshakeStream := initStreams() server, err := NewCryptoSetupServer( diff --git a/internal/handshake/qtls.go b/internal/handshake/qtls.go deleted file mode 100644 index 4e528b02f..000000000 --- a/internal/handshake/qtls.go +++ /dev/null @@ -1,49 +0,0 @@ -package handshake - -import ( - "crypto/tls" - - "github.com/marten-seemann/qtls" -) - -func tlsConfigToQtlsConfig(c *tls.Config) *qtls.Config { - if c == nil { - c = &tls.Config{} - } - // QUIC requires TLS 1.3 or newer - minVersion := c.MinVersion - if minVersion < qtls.VersionTLS13 { - minVersion = qtls.VersionTLS13 - } - maxVersion := c.MaxVersion - if maxVersion < qtls.VersionTLS13 { - maxVersion = qtls.VersionTLS13 - } - return &qtls.Config{ - Rand: c.Rand, - Time: c.Time, - Certificates: c.Certificates, - NameToCertificate: c.NameToCertificate, - GetCertificate: c.GetCertificate, - GetClientCertificate: c.GetClientCertificate, - // TODO: make GetConfigForClient work - // GetConfigForClient: c.GetConfigForClient, - VerifyPeerCertificate: c.VerifyPeerCertificate, - RootCAs: c.RootCAs, - NextProtos: c.NextProtos, - ServerName: c.ServerName, - ClientAuth: c.ClientAuth, - ClientCAs: c.ClientCAs, - InsecureSkipVerify: c.InsecureSkipVerify, - CipherSuites: c.CipherSuites, - PreferServerCipherSuites: c.PreferServerCipherSuites, - SessionTicketsDisabled: c.SessionTicketsDisabled, - SessionTicketKey: c.SessionTicketKey, - MinVersion: minVersion, - MaxVersion: maxVersion, - CurvePreferences: c.CurvePreferences, - DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, - // Renegotiation is not supported by TLS 1.3 - KeyLogWriter: c.KeyLogWriter, - } -}