Commit 7be849d4 authored by Adam Langley's avatar Adam Langley

crypto/tls: add client-side SNI support and PeerCertificates.

SNI (Server Name Indication) is a way for a TLS client to
indicate to the server which name it knows the server by. This
allows the server to have several names and return the correct
certificate for each (virtual hosting).

PeerCertificates returns the list of certificates presented by
server.

R=r
CC=golang-dev
https://golang.org/cl/1741053
parent 8286ee4c
...@@ -85,6 +85,9 @@ type Config struct { ...@@ -85,6 +85,9 @@ type Config struct {
// 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. // Currently only server-side handling is supported.
NextProtos []string NextProtos []string
// ServerName is included in the client's handshake to support virtual
// hosting.
ServerName string
} }
type Certificate struct { type Certificate struct {
......
...@@ -5,6 +5,7 @@ package tls ...@@ -5,6 +5,7 @@ package tls
import ( import (
"bytes" "bytes"
"crypto/subtle" "crypto/subtle"
"crypto/x509"
"hash" "hash"
"io" "io"
"net" "net"
...@@ -27,6 +28,7 @@ type Conn struct { ...@@ -27,6 +28,7 @@ type Conn struct {
handshakeComplete bool handshakeComplete bool
cipherSuite uint16 cipherSuite uint16
ocspResponse []byte // stapled OCSP response ocspResponse []byte // stapled OCSP response
peerCertificates []*x509.Certificate
clientProtocol string clientProtocol string
...@@ -651,3 +653,12 @@ func (c *Conn) OCSPResponse() []byte { ...@@ -651,3 +653,12 @@ func (c *Conn) OCSPResponse() []byte {
return c.ocspResponse return c.ocspResponse
} }
// PeerCertificates returns the certificate chain that was presented by the
// other side.
func (c *Conn) PeerCertificates() []*x509.Certificate {
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
return c.peerCertificates
}
...@@ -28,6 +28,7 @@ func (c *Conn) clientHandshake() os.Error { ...@@ -28,6 +28,7 @@ func (c *Conn) clientHandshake() os.Error {
compressionMethods: []uint8{compressionNone}, compressionMethods: []uint8{compressionNone},
random: make([]byte, 32), random: make([]byte, 32),
ocspStapling: true, ocspStapling: true,
serverName: c.config.ServerName,
} }
t := uint32(c.config.Time()) t := uint32(c.config.Time())
...@@ -107,6 +108,8 @@ func (c *Conn) clientHandshake() os.Error { ...@@ -107,6 +108,8 @@ func (c *Conn) clientHandshake() os.Error {
return c.sendAlert(alertUnsupportedCertificate) return c.sendAlert(alertUnsupportedCertificate)
} }
c.peerCertificates = certs
if serverHello.certStatus { if serverHello.certStatus {
msg, err = c.readHandshake() msg, err = c.readHandshake()
if err != nil { if err != nil {
......
...@@ -100,7 +100,8 @@ func (m *clientHelloMsg) marshal() []byte { ...@@ -100,7 +100,8 @@ func (m *clientHelloMsg) marshal() []byte {
// ServerName server_name_list<1..2^16-1> // ServerName server_name_list<1..2^16-1>
// } ServerNameList; // } ServerNameList;
z[1] = 1 z[0] = byte((len(m.serverName) + 3) >> 8)
z[1] = byte(len(m.serverName) + 3)
z[3] = byte(len(m.serverName) >> 8) z[3] = byte(len(m.serverName) >> 8)
z[4] = byte(len(m.serverName)) z[4] = byte(len(m.serverName))
copy(z[5:], []byte(m.serverName)) copy(z[5:], []byte(m.serverName))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment