tris: accept other post-handshake messages as client

Do not assume that every post-handshake messages are HelloRequests that
try to trigger a renegotiation. This could result in a no_renegotiation
(rather than an unexpected_message) alert even for other message types
(like NewSessionTicket).

This change makes the caller of readRecord(recordTypeApplicationData)
responsible for checking for renegotiation in case of a handshake
message, but that is currently already the case. And the condition
"c.phase == waitingClientFinished" can only be hit by the server, so
that won't have break the handshake either.

Related: https://github.com/cloudflare/tls-tris/issues/50
This commit is contained in:
Peter Wu 2017-11-12 01:02:42 +00:00 committed by Peter Wu
parent 4e6ebb63dd
commit de3ae8f61d

26
conn.go
View File

@ -837,9 +837,11 @@ Again:
case recordTypeHandshake: case recordTypeHandshake:
// TODO(rsc): Should at least pick off connection close. // TODO(rsc): Should at least pick off connection close.
if typ != want && !(c.isClient && c.config.Renegotiation != RenegotiateNever) && // If early data was being read, a Finished message is expected
c.phase != waitingClientFinished { // instead of (early) application data. Other post-handshake
return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation)) // messages include HelloRequest and NewSessionTicket.
if typ != want && want != recordTypeApplicationData {
return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
} }
c.hand.Write(data) c.hand.Write(data)
if typ != want && c.phase == waitingClientFinished { if typ != want && c.phase == waitingClientFinished {
@ -1243,20 +1245,26 @@ func (c *Conn) Write(b []byte) (int, error) {
return n + m, c.out.setErrorLocked(err) return n + m, c.out.setErrorLocked(err)
} }
// handleRenegotiation processes a HelloRequest handshake message. // Process Handshake messages after the handshake has completed.
// c.in.Mutex <= L // c.in.Mutex <= L
func (c *Conn) handleRenegotiation() error { func (c *Conn) handlePostHandshake() error {
msg, err := c.readHandshake() msg, err := c.readHandshake()
if err != nil { if err != nil {
return err return err
} }
_, ok := msg.(*helloRequestMsg) switch hm := msg.(type) {
if !ok { case *helloRequestMsg:
return c.handleRenegotiation(hm)
default:
c.sendAlert(alertUnexpectedMessage) c.sendAlert(alertUnexpectedMessage)
return alertUnexpectedMessage return alertUnexpectedMessage
} }
}
// handleRenegotiation processes a HelloRequest handshake message.
// c.in.Mutex <= L
func (c *Conn) handleRenegotiation(*helloRequestMsg) error {
if !c.isClient { if !c.isClient {
return c.sendAlert(alertNoRenegotiation) return c.sendAlert(alertNoRenegotiation)
} }
@ -1432,9 +1440,7 @@ func (c *Conn) Read(b []byte) (n int, err error) {
return 0, err return 0, err
} }
if c.hand.Len() > 0 { if c.hand.Len() > 0 {
// We received handshake bytes, indicating the if err := c.handlePostHandshake(); err != nil {
// start of a renegotiation.
if err := c.handleRenegotiation(); err != nil {
return 0, err return 0, err
} }
} }