diff options
author | Caleb Spare <cespare@gmail.com> | 2015-10-20 00:23:11 -0700 |
---|---|---|
committer | Adam Langley <agl@golang.org> | 2015-11-16 21:54:44 +0000 |
commit | 45d1c8ab59cd08ef4a7976f44c8c19ed53b118f8 (patch) | |
tree | d2dbbd3d61c45d3e51b2498e126c07a3b21121b2 /src/crypto | |
parent | bf5b4e71be59d90f35a571a644e5731c581e9f6c (diff) | |
download | go-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.go | 27 |
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 { |