In Go 1.0, the Config struct consisted only of exported fields.
In Go 1.1, it started to grow private, uncopyable fields (sync.Once,
sync.Mutex, etc).
Ever since, people have been writing their own private Config.Clone
methods, or risking it and doing a language-level shallow copy and
copying the unexported sync variables.
Clean this up and export the Config.clone method as Config.Clone.
This matches the convention of Template.Clone from text/template and
html/template at least.
Fixes #15771
Updates #16228 (needs update in x/net/http2 before fixed)
Updates #16492 (not sure whether @agl wants to do more)
Change-Id: I48c2825d4fef55a75d2f99640a7079c56fce39ca
Reviewed-on: https://go-review.googlesource.com/28075
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
return key
}
-// clone returns a copy of c. Only the exported fields are copied.
-func (c *Config) clone() *Config {
+// Clone returns a shallow clone of c.
+// Only the exported fields are copied.
+func (c *Config) Clone() *Config {
return &Config{
Rand: c.Rand,
Time: c.Time,
func runDynamicRecordSizingTest(t *testing.T, config *Config) {
clientConn, serverConn := net.Pipe()
- serverConfig := config.clone()
+ serverConfig := config.Clone()
serverConfig.DynamicRecordSizingDisabled = false
tlsConn := Server(serverConn, serverConfig)
}
func TestDynamicRecordSizingWithStreamCipher(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
runDynamicRecordSizingTest(t, config)
}
func TestDynamicRecordSizingWithCBC(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA}
runDynamicRecordSizingTest(t, config)
}
func TestDynamicRecordSizingWithAEAD(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
runDynamicRecordSizingTest(t, config)
}
}
func TestHandshakeClientCertRSA(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
config.Certificates = []Certificate{cert}
}
func TestHandshakeClientCertECDSA(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
config.Certificates = []Certificate{cert}
}
func TestHandshakeClientKeyLog(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
buf := &bytes.Buffer{}
config.KeyLogWriter = buf
}
func TestHandshakeClientALPNMatch(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto2", "proto1"}
test := &clientTest{
}
func TestHandshakeClientALPNNoMatch(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto3"}
test := &clientTest{
const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0="
func TestHandshakClientSCTs(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
scts, err := base64.StdEncoding.DecodeString(sctsBase64)
if err != nil {
}
func TestRenegotiationRejected(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
test := &clientTest{
name: "RenegotiationRejected",
command: []string{"openssl", "s_server", "-state"},
}
func TestRenegotiateOnce(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{
}
func TestRenegotiateTwice(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Renegotiation = RenegotiateFreelyAsClient
test := &clientTest{
}
func TestRenegotiateTwiceRejected(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
// Reset the enabled cipher suites to nil in order to test the
// defaults.
serverConfig.CipherSuites = nil
supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed},
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.CipherSuites = clientHello.cipherSuites
serverConfig.Certificates = make([]Certificate, 1)
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed},
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.CipherSuites = clientHello.cipherSuites
// First test that it *does* work when the server's key is RSA.
testClientHello(t, serverConfig, clientHello)
reply, clientErr = cli.readHandshake()
c.Close()
}()
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = clientHello.cipherSuites
Server(s, config).Handshake()
s.Close()
}
func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Certificates = make([]Certificate, 1)
config.Certificates[0].Certificate = [][]byte{testECDSACertificate}
config.Certificates[0].PrivateKey = testECDSAPrivateKey
}
func TestHandshakeServerKeyLog(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
buf := &bytes.Buffer{}
config.KeyLogWriter = buf
}
func TestHandshakeServerALPN(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto1", "proto2"}
test := &serverTest{
}
func TestHandshakeServerALPNNoMatch(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto3"}
test := &serverTest{
// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but
// tests the dynamic GetCertificate method
func TestHandshakeServerSNIGetCertificate(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
// Replace the NameToCertificate map with a GetCertificate function
nameToCert := config.NameToCertificate
// GetCertificate method doesn't return a cert, we fall back to what's in
// the NameToCertificate map.
func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, nil
func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
const errMsg = "TestHandshakeServerSNIGetCertificateError error"
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg)
}
func TestHandshakeServerEmptyCertificates(t *testing.T) {
const errMsg = "TestHandshakeServerEmptyCertificates error"
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg)
}
// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}
config.PreferServerCipherSuites = true
}
runServerTestTLS12(t, test)
- config = testConfig.clone()
+ config = testConfig.Clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
config.Certificates = []Certificate{
{
sessionFilePath := tempFile("")
defer os.Remove(sessionFilePath)
- config := testConfig.clone()
+ config := testConfig.Clone()
test := &serverTest{
name: "IssueTicketPreDisable",
defer os.Remove(ecdsaKeyPath)
}
- config := testConfig.clone()
+ config := testConfig.Clone()
config.ClientAuth = RequestClientCert
test := &serverTest{
serverName: expectedServerName,
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
// Erase the server's cipher suites to ensure the handshake fails.
serverConfig.CipherSuites = nil
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
- c := config.clone()
+ c := config.Clone()
c.ServerName = hostname
config = c
}
srvCh <- nil
return
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
srvCh <- srv
}()
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
if err != nil {
t.Fatal(err)
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
t.Fatal(err)
}
}()
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
srvCh <- nil
return
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
Conn: cconn,
}
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
tconn := Client(conn, clientConfig)
if err := tconn.Handshake(); err != nil {
t.Fatal(err)
f.Set(q)
}
- c2 := c1.clone()
+ c2 := c1.Clone()
if !reflect.DeepEqual(&c1, c2) {
t.Errorf("clone failed to copy a field")
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
}()
b.SetBytes(totalBytes)
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, bufsize)
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(&slowConn{sconn, bps}, serverConfig)
if err := srv.Handshake(); err != nil {
}
}()
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 16384)
}
existingConfig := s.TLS
- s.TLS = new(tls.Config)
if existingConfig != nil {
- *s.TLS = *existingConfig
+ s.TLS = existingConfig.Clone()
+ } else {
+ s.TLS = new(tls.Config)
}
if s.TLS.NextProtos == nil {
s.TLS.NextProtos = []string{"http/1.1"}
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,
- SessionTicketsDisabled: cfg.SessionTicketsDisabled,
- SessionTicketKey: cfg.SessionTicketKey,
- ClientSessionCache: cfg.ClientSessionCache,
- MinVersion: cfg.MinVersion,
- MaxVersion: cfg.MaxVersion,
- CurvePreferences: cfg.CurvePreferences,
- DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled,
- Renegotiation: cfg.Renegotiation,
- KeyLogWriter: cfg.KeyLogWriter,
- }
+ return cfg.Clone()
}
// cloneTLSClientConfig is like cloneTLSConfig but omits