mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
crypto/tls: extend NPN support to the client.
R=bradfitzgo, rsc1, bradfitzwork CC=golang-dev https://golang.org/cl/4277085
This commit is contained in:
parent
d844aae690
commit
974d2c98e0
3 changed files with 40 additions and 5 deletions
|
|
@ -96,6 +96,7 @@ type ConnectionState struct {
|
||||||
HandshakeComplete bool
|
HandshakeComplete bool
|
||||||
CipherSuite uint16
|
CipherSuite uint16
|
||||||
NegotiatedProtocol string
|
NegotiatedProtocol string
|
||||||
|
NegotiatedProtocolIsMutual bool
|
||||||
|
|
||||||
// the certificate chain that was presented by the other side
|
// the certificate chain that was presented by the other side
|
||||||
PeerCertificates []*x509.Certificate
|
PeerCertificates []*x509.Certificate
|
||||||
|
|
@ -124,7 +125,6 @@ type Config struct {
|
||||||
RootCAs *CASet
|
RootCAs *CASet
|
||||||
|
|
||||||
// NextProtos is a list of supported, application level protocols.
|
// NextProtos is a list of supported, application level protocols.
|
||||||
// Currently only server-side handling is supported.
|
|
||||||
NextProtos []string
|
NextProtos []string
|
||||||
|
|
||||||
// ServerName is included in the client's handshake to support virtual
|
// ServerName is included in the client's handshake to support virtual
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ type Conn struct {
|
||||||
peerCertificates []*x509.Certificate
|
peerCertificates []*x509.Certificate
|
||||||
|
|
||||||
clientProtocol string
|
clientProtocol string
|
||||||
|
clientProtocolFallback bool
|
||||||
|
|
||||||
// first permanent error
|
// first permanent error
|
||||||
errMutex sync.Mutex
|
errMutex sync.Mutex
|
||||||
|
|
@ -761,6 +762,7 @@ func (c *Conn) ConnectionState() ConnectionState {
|
||||||
state.HandshakeComplete = c.handshakeComplete
|
state.HandshakeComplete = c.handshakeComplete
|
||||||
if c.handshakeComplete {
|
if c.handshakeComplete {
|
||||||
state.NegotiatedProtocol = c.clientProtocol
|
state.NegotiatedProtocol = c.clientProtocol
|
||||||
|
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
|
||||||
state.CipherSuite = c.cipherSuite
|
state.CipherSuite = c.cipherSuite
|
||||||
state.PeerCertificates = c.peerCertificates
|
state.PeerCertificates = c.peerCertificates
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ func (c *Conn) clientHandshake() os.Error {
|
||||||
serverName: c.config.ServerName,
|
serverName: c.config.ServerName,
|
||||||
supportedCurves: []uint16{curveP256, curveP384, curveP521},
|
supportedCurves: []uint16{curveP256, curveP384, curveP521},
|
||||||
supportedPoints: []uint8{pointFormatUncompressed},
|
supportedPoints: []uint8{pointFormatUncompressed},
|
||||||
|
nextProtoNeg: len(c.config.NextProtos) > 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
t := uint32(c.config.time())
|
t := uint32(c.config.time())
|
||||||
|
|
@ -66,6 +67,11 @@ func (c *Conn) clientHandshake() os.Error {
|
||||||
return c.sendAlert(alertUnexpectedMessage)
|
return c.sendAlert(alertUnexpectedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !hello.nextProtoNeg && serverHello.nextProtoNeg {
|
||||||
|
c.sendAlert(alertHandshakeFailure)
|
||||||
|
return os.ErrorString("server advertised unrequested NPN")
|
||||||
|
}
|
||||||
|
|
||||||
suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
|
suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
|
||||||
if suite == nil {
|
if suite == nil {
|
||||||
return c.sendAlert(alertHandshakeFailure)
|
return c.sendAlert(alertHandshakeFailure)
|
||||||
|
|
@ -267,6 +273,17 @@ func (c *Conn) clientHandshake() os.Error {
|
||||||
c.out.prepareCipherSpec(clientCipher, clientHash)
|
c.out.prepareCipherSpec(clientCipher, clientHash)
|
||||||
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
|
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
|
||||||
|
|
||||||
|
if serverHello.nextProtoNeg {
|
||||||
|
nextProto := new(nextProtoMsg)
|
||||||
|
proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos)
|
||||||
|
nextProto.proto = proto
|
||||||
|
c.clientProtocol = proto
|
||||||
|
c.clientProtocolFallback = fallback
|
||||||
|
|
||||||
|
finishedHash.Write(nextProto.marshal())
|
||||||
|
c.writeRecord(recordTypeHandshake, nextProto.marshal())
|
||||||
|
}
|
||||||
|
|
||||||
finished := new(finishedMsg)
|
finished := new(finishedMsg)
|
||||||
finished.verifyData = finishedHash.clientSum(masterSecret)
|
finished.verifyData = finishedHash.clientSum(masterSecret)
|
||||||
finishedHash.Write(finished.marshal())
|
finishedHash.Write(finished.marshal())
|
||||||
|
|
@ -299,3 +316,19 @@ func (c *Conn) clientHandshake() os.Error {
|
||||||
c.cipherSuite = suiteId
|
c.cipherSuite = suiteId
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
|
||||||
|
// set of client and server supported protocols. The set of client supported
|
||||||
|
// protocols must not be empty. It returns the resulting protocol and flag
|
||||||
|
// indicating if the fallback case was reached.
|
||||||
|
func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
|
||||||
|
for _, s := range serverProtos {
|
||||||
|
for _, c := range clientProtos {
|
||||||
|
if s == c {
|
||||||
|
return s, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientProtos[0], true
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue