summaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorCaleb Spare <cespare@gmail.com>2015-10-20 00:23:11 -0700
committerAdam Langley <agl@golang.org>2015-11-16 21:54:44 +0000
commit45d1c8ab59cd08ef4a7976f44c8c19ed53b118f8 (patch)
treed2dbbd3d61c45d3e51b2498e126c07a3b21121b2 /src/crypto
parentbf5b4e71be59d90f35a571a644e5731c581e9f6c (diff)
downloadgo-git-45d1c8ab59cd08ef4a7976f44c8c19ed53b118f8.tar.gz
crypto/tls: return a typed error on invalid record headers
The user can inspect the record data to detect that the other side is not using the TLS protocol. This will be used by the net/http client (in a follow-on CL) to detect when an HTTPS client is speaking to an HTTP server. Updates #11111. Change-Id: I872f78717aa8e8e98cebd8075436209a52039a73 Reviewed-on: https://go-review.googlesource.com/16078 Reviewed-by: Adam Langley <agl@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/tls/conn.go27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
index 7638bbc6a9..115b6c6578 100644
--- a/src/crypto/tls/conn.go
+++ b/src/crypto/tls/conn.go
@@ -506,6 +506,23 @@ func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) {
return b, bb
}
+// RecordHeaderError results when a TLS record header is invalid.
+type RecordHeaderError struct {
+ // Msg contains a human readable string that describes the error.
+ Msg string
+ // RecordHeader contains the five bytes of TLS record header that
+ // triggered the error.
+ RecordHeader [5]byte
+}
+
+func (e RecordHeaderError) Error() string { return "tls: " + e.Msg }
+
+func (c *Conn) newRecordHeaderError(msg string) (err RecordHeaderError) {
+ err.Msg = msg
+ copy(err.RecordHeader[:], c.rawInput.data)
+ return err
+}
+
// readRecord reads the next TLS record from the connection
// and updates the record layer state.
// c.in.Mutex <= L; c.input == nil.
@@ -556,18 +573,20 @@ Again:
// an SSLv2 client.
if want == recordTypeHandshake && typ == 0x80 {
c.sendAlert(alertProtocolVersion)
- return c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+ return c.in.setErrorLocked(c.newRecordHeaderError("unsupported SSLv2 handshake received"))
}
vers := uint16(b.data[1])<<8 | uint16(b.data[2])
n := int(b.data[3])<<8 | int(b.data[4])
if c.haveVers && vers != c.vers {
c.sendAlert(alertProtocolVersion)
- return c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+ msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers)
+ return c.in.setErrorLocked(c.newRecordHeaderError(msg))
}
if n > maxCiphertext {
c.sendAlert(alertRecordOverflow)
- return c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n))
+ msg := fmt.Sprintf("oversized record received with length %d", n)
+ return c.in.setErrorLocked(c.newRecordHeaderError(msg))
}
if !c.haveVers {
// First message, be extra suspicious: this might not be a TLS
@@ -576,7 +595,7 @@ Again:
// it's probably not real.
if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 {
c.sendAlert(alertUnexpectedMessage)
- return c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake"))
+ return c.in.setErrorLocked(c.newRecordHeaderError("first record does not look like a TLS handshake"))
}
}
if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {