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>
This commit is contained in:
parent
e90a6f8498
commit
4d57d90e8e
27
conn.go
27
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user