Commit 6eae03e1 authored by Adam Langley's avatar Adam Langley Committed by Brad Fitzpatrick

net/http: drop custom tls.Config cloning code.

Now that we have the Clone method on tls.Config, net/http doesn't need
any custom functions to do that any more.

Change-Id: Ib60707d37f1a7f9a7d7723045f83e59eceffd026
Reviewed-on: https://go-review.googlesource.com/31595Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 3d4ea227
...@@ -455,9 +455,13 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) { ...@@ -455,9 +455,13 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) {
return key return key
} }
// Clone returns a shallow clone of c. // Clone returns a shallow clone of c. It is safe to clone a Config that is
// Only the exported fields are copied. // being used concurrently by a TLS client or server.
func (c *Config) Clone() *Config { func (c *Config) Clone() *Config {
// Running serverInit ensures that it's safe to read
// SessionTicketsDisabled.
c.serverInitOnce.Do(c.serverInit)
var sessionTicketKeys []ticketKey var sessionTicketKeys []ticketKey
c.mutex.RLock() c.mutex.RLock()
sessionTicketKeys = c.sessionTicketKeys sessionTicketKeys = c.sessionTicketKeys
......
...@@ -508,6 +508,10 @@ func TestClone(t *testing.T) { ...@@ -508,6 +508,10 @@ func TestClone(t *testing.T) {
} }
c2 := c1.Clone() c2 := c1.Clone()
// DeepEqual also compares unexported fields, thus c2 needs to have run
// serverInit in order to be DeepEqual to c1. Cloning it and discarding
// the result is sufficient.
c2.Clone()
if !reflect.DeepEqual(&c1, c2) { if !reflect.DeepEqual(&c1, c2) {
t.Errorf("clone failed to copy a field") t.Errorf("clone failed to copy a field")
......
...@@ -1040,7 +1040,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon ...@@ -1040,7 +1040,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
if cm.targetScheme == "https" && !tlsDial { if cm.targetScheme == "https" && !tlsDial {
// Initiate TLS and check remote host name against certificate. // Initiate TLS and check remote host name against certificate.
cfg := cloneTLSClientConfig(t.TLSClientConfig) cfg := cloneTLSConfig(t.TLSClientConfig)
if cfg.ServerName == "" { if cfg.ServerName == "" {
cfg.ServerName = cm.tlsHost() cfg.ServerName = cm.tlsHost()
} }
...@@ -2099,17 +2099,9 @@ type fakeLocker struct{} ...@@ -2099,17 +2099,9 @@ type fakeLocker struct{}
func (fakeLocker) Lock() {} func (fakeLocker) Lock() {}
func (fakeLocker) Unlock() {} func (fakeLocker) Unlock() {}
// cloneTLSConfig returns a shallow clone of the exported // clneTLSConfig returns a shallow clone of cfg, or a new zero tls.Config if
// fields of cfg, ignoring the unexported sync.Once, which // cfg is nil. This is safe to call even if cfg is in active use by a TLS
// contains a mutex and must not be copied. // client or server.
//
// The cfg must not be in active use by tls.Server, or else
// there can still be a race with tls.Server updating SessionTicketKey
// and our copying it, and also a race with the server setting
// SessionTicketsDisabled=false on failure to set the random
// ticket key.
//
// If cfg is nil, a new zero tls.Config is returned.
func cloneTLSConfig(cfg *tls.Config) *tls.Config { func cloneTLSConfig(cfg *tls.Config) *tls.Config {
if cfg == nil { if cfg == nil {
return &tls.Config{} return &tls.Config{}
...@@ -2117,38 +2109,6 @@ func cloneTLSConfig(cfg *tls.Config) *tls.Config { ...@@ -2117,38 +2109,6 @@ func cloneTLSConfig(cfg *tls.Config) *tls.Config {
return cfg.Clone() return cfg.Clone()
} }
// cloneTLSClientConfig is like cloneTLSConfig but omits
// the fields SessionTicketsDisabled and SessionTicketKey.
// This makes it safe to call cloneTLSClientConfig on a config
// in active use by a server.
func cloneTLSClientConfig(cfg *tls.Config) *tls.Config {
if cfg == nil {
return &tls.Config{}
}
return &tls.Config{
Rand: cfg.Rand,
Time: cfg.Time,
Certificates: cfg.Certificates,
NameToCertificate: cfg.NameToCertificate,
GetCertificate: cfg.GetCertificate,
RootCAs: cfg.RootCAs,
NextProtos: cfg.NextProtos,
ServerName: cfg.ServerName,
ClientAuth: cfg.ClientAuth,
ClientCAs: cfg.ClientCAs,
InsecureSkipVerify: cfg.InsecureSkipVerify,
CipherSuites: cfg.CipherSuites,
PreferServerCipherSuites: cfg.PreferServerCipherSuites,
ClientSessionCache: cfg.ClientSessionCache,
MinVersion: cfg.MinVersion,
MaxVersion: cfg.MaxVersion,
CurvePreferences: cfg.CurvePreferences,
DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled,
Renegotiation: cfg.Renegotiation,
KeyLogWriter: cfg.KeyLogWriter,
}
}
type connLRU struct { type connLRU struct {
ll *list.List // list.Element.Value type is of *persistConn ll *list.List // list.Element.Value type is of *persistConn
m map[*persistConn]*list.Element m map[*persistConn]*list.Element
......
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