return the local TLS error, but don't send it on the wire

This commit is contained in:
Marten Seemann
2019-03-07 16:16:02 +09:00
parent ae12852e4c
commit 5b27076a4c
6 changed files with 35 additions and 18 deletions

View File

@@ -138,8 +138,7 @@ var _ = Describe("Handshake tests", func() {
tlsConf, tlsConf,
clientConfig, clientConfig,
) )
// TODO: check the error returned locally here Expect(err).To(MatchError("CRYPTO_ERROR: x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs"))
Expect(err).To(HaveOccurred())
}) })
It("fails the handshake if the client fails to provide the requested client cert", func() { It("fails the handshake if the client fails to provide the requested client cert", func() {

View File

@@ -65,7 +65,7 @@ type cryptoSetup struct {
handleParamsCallback func([]byte) handleParamsCallback func([]byte)
alertChan chan error alertChan chan uint8
// HandleData() sends errors on the messageErrChan // HandleData() sends errors on the messageErrChan
messageErrChan chan error messageErrChan chan error
// handshakeDone is closed as soon as the go routine running qtls.Handshake() returns // handshakeDone is closed as soon as the go routine running qtls.Handshake() returns
@@ -187,7 +187,7 @@ func newCryptoSetup(
logger: logger, logger: logger,
perspective: perspective, perspective: perspective,
handshakeDone: make(chan struct{}), handshakeDone: make(chan struct{}),
alertChan: make(chan error), alertChan: make(chan uint8),
messageErrChan: make(chan error, 1), messageErrChan: make(chan error, 1),
clientHelloWrittenChan: make(chan struct{}), clientHelloWrittenChan: make(chan struct{}),
messageChan: make(chan []byte, 100), messageChan: make(chan []byte, 100),
@@ -213,10 +213,11 @@ func (h *cryptoSetup) ChangeConnectionID(id protocol.ConnectionID) error {
func (h *cryptoSetup) RunHandshake() error { func (h *cryptoSetup) RunHandshake() error {
// Handle errors that might occur when HandleData() is called. // Handle errors that might occur when HandleData() is called.
handshakeComplete := make(chan struct{}) handshakeComplete := make(chan struct{})
handshakeErrChan := make(chan error, 1)
go func() { go func() {
defer close(h.handshakeDone) defer close(h.handshakeDone)
if err := h.conn.Handshake(); err != nil { if err := h.conn.Handshake(); err != nil {
h.logger.Debugf("qlts.Handshake error: %s", err) handshakeErrChan <- err
return return
} }
close(handshakeComplete) close(handshakeComplete)
@@ -229,9 +230,9 @@ func (h *cryptoSetup) RunHandshake() error {
return errors.New("Handshake aborted") return errors.New("Handshake aborted")
case <-handshakeComplete: // return when the handshake is done case <-handshakeComplete: // return when the handshake is done
return nil return nil
case err := <-h.alertChan: case alert := <-h.alertChan:
<-h.handshakeDone err := <-handshakeErrChan
return err return qerr.CryptoError(alert, err.Error())
case err := <-h.messageErrChan: case err := <-h.messageErrChan:
// If the handshake errored because of an error that occurred during HandleData(), // If the handshake errored because of an error that occurred during HandleData(),
// that error message will be more useful than the error message generated by Handshake(). // that error message will be more useful than the error message generated by Handshake().
@@ -462,7 +463,7 @@ func (h *cryptoSetup) WriteRecord(p []byte) (int, error) {
} }
func (h *cryptoSetup) SendAlert(alert uint8) { func (h *cryptoSetup) SendAlert(alert uint8) {
h.alertChan <- qerr.CryptoError(alert, "") h.alertChan <- alert
} }
func (h *cryptoSetup) GetSealer() (protocol.EncryptionLevel, Sealer) { func (h *cryptoSetup) GetSealer() (protocol.EncryptionLevel, Sealer) {

View File

@@ -128,7 +128,7 @@ var _ = Describe("Crypto Setup TLS", func() {
go func() { go func() {
defer GinkgoRecover() defer GinkgoRecover()
err := server.RunHandshake() err := server.RunHandshake()
Expect(err).To(MatchError("CRYPTO_ERROR: tls: unexpected message")) Expect(err).To(MatchError("CRYPTO_ERROR: local error: tls: unexpected message"))
close(done) close(done)
}() }()

View File

@@ -45,6 +45,11 @@ func (e *QuicError) Error() string {
return fmt.Sprintf("%s: %s", e.ErrorCode.String(), e.ErrorMessage) return fmt.Sprintf("%s: %s", e.ErrorCode.String(), e.ErrorMessage)
} }
// IsCryptoError says if this error is a crypto error
func (e *QuicError) IsCryptoError() bool {
return e.ErrorCode.isCryptoError()
}
// Temporary says if the error is temporary. // Temporary says if the error is temporary.
func (e *QuicError) Temporary() bool { func (e *QuicError) Temporary() bool {
return false return false

View File

@@ -25,14 +25,21 @@ var _ = Describe("QUIC Transport Errors", func() {
Expect(err.Error()).To(Equal("NO_ERROR: foobar")) Expect(err.Error()).To(Equal("NO_ERROR: foobar"))
}) })
It("has a string representation for crypto errors with a message", func() { Context("crypto errors", func() {
err := CryptoError(42, "foobar") It("has a string representation for crypto errors with a message", func() {
Expect(err.Error()).To(Equal("CRYPTO_ERROR: foobar")) err := CryptoError(42, "foobar")
}) Expect(err.Error()).To(Equal("CRYPTO_ERROR: foobar"))
})
It("has a string representation for crypto errors without a message", func() { It("has a string representation for crypto errors without a message", func() {
err := CryptoError(42, "") err := CryptoError(42, "")
Expect(err.Error()).To(Equal("CRYPTO_ERROR: tls: bad certificate")) Expect(err.Error()).To(Equal("CRYPTO_ERROR: tls: bad certificate"))
})
It("says if an error is a crypto error", func() {
Expect(Error(FlowControlError, "").IsCryptoError()).To(BeFalse())
Expect(CryptoError(42, "").IsCryptoError()).To(BeTrue())
})
}) })
Context("ErrorCode", func() { Context("ErrorCode", func() {

View File

@@ -1133,9 +1133,14 @@ func (s *session) sendPackedPacket(packet *packedPacket) error {
} }
func (s *session) sendConnectionClose(quicErr *qerr.QuicError) error { func (s *session) sendConnectionClose(quicErr *qerr.QuicError) error {
var reason string
// don't send details of crypto errors
if !quicErr.IsCryptoError() {
reason = quicErr.ErrorMessage
}
packet, err := s.packer.PackConnectionClose(&wire.ConnectionCloseFrame{ packet, err := s.packer.PackConnectionClose(&wire.ConnectionCloseFrame{
ErrorCode: quicErr.ErrorCode, ErrorCode: quicErr.ErrorCode,
ReasonPhrase: quicErr.ErrorMessage, ReasonPhrase: reason,
}) })
if err != nil { if err != nil {
return err return err