@@ -8,8 +8,12 @@ import ( | |||||
"crypto/hmac" | "crypto/hmac" | ||||
"crypto/rsa" | "crypto/rsa" | ||||
"crypto/subtle" | "crypto/subtle" | ||||
"encoding/hex" | |||||
"errors" | "errors" | ||||
"fmt" | |||||
"io" | "io" | ||||
"os" | |||||
"runtime/debug" | |||||
"golang_org/x/crypto/curve25519" | "golang_org/x/crypto/curve25519" | ||||
) | ) | ||||
@@ -333,3 +337,30 @@ func hkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L | |||||
return hkdfExpand(hash, secret, hkdfLabel, L) | return hkdfExpand(hash, secret, hkdfLabel, L) | ||||
} | } | ||||
// QuietError is an error wrapper that prevents the verbose handshake log | |||||
// dump on errors. Exposed for use by GetCertificate. | |||||
type QuietError struct { | |||||
Err error | |||||
} | |||||
func (e QuietError) Error() string { | |||||
return e.Err.Error() + " [quiet]" | |||||
} | |||||
func (hs *serverHandshakeState) traceErr(err error) { | |||||
if err == nil { | |||||
return | |||||
} | |||||
if _, ok := err.(QuietError); ok { | |||||
return | |||||
} | |||||
if os.Getenv("TLSDEBUG") == "error" { | |||||
if hs != nil && hs.clientHello != nil { | |||||
os.Stderr.WriteString(hex.Dump(hs.clientHello.marshal())) | |||||
} else if err == io.EOF { | |||||
return // don't stack trace on EOF before CH | |||||
} | |||||
fmt.Fprintf(os.Stderr, "\n%s\n", debug.Stack()) | |||||
} | |||||
} |
@@ -156,10 +156,15 @@ type halfConn struct { | |||||
// used to save allocating a new buffer for each MAC. | // used to save allocating a new buffer for each MAC. | ||||
inDigestBuf, outDigestBuf []byte | inDigestBuf, outDigestBuf []byte | ||||
traceErr func(error) | |||||
} | } | ||||
func (hc *halfConn) setErrorLocked(err error) error { | func (hc *halfConn) setErrorLocked(err error) error { | ||||
hc.err = err | hc.err = err | ||||
if hc.traceErr != nil { | |||||
hc.traceErr(err) | |||||
} | |||||
return err | return err | ||||
} | } | ||||
@@ -51,6 +51,9 @@ func (c *Conn) serverHandshake() error { | |||||
hs := serverHandshakeState{ | hs := serverHandshakeState{ | ||||
c: c, | c: c, | ||||
} | } | ||||
c.in.traceErr = hs.traceErr | |||||
c.out.traceErr = hs.traceErr | |||||
defer func() { c.in.traceErr, c.out.traceErr = nil, nil }() | |||||
isResume, err := hs.readClientHello() | isResume, err := hs.readClientHello() | ||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
@@ -265,6 +268,9 @@ Curves: | |||||
hs.cert, err = c.config.getCertificate(hs.clientHelloInfo()) | hs.cert, err = c.config.getCertificate(hs.clientHelloInfo()) | ||||
if err != nil { | if err != nil { | ||||
if _, ok := err.(QuietError); ok { | |||||
c.out.traceErr, c.in.traceErr = nil, nil | |||||
} | |||||
c.sendAlert(alertInternalError) | c.sendAlert(alertInternalError) | ||||
return false, err | return false, err | ||||
} | } | ||||