crypto/tls: don't copy Mutex or Once values

This fixes some 40 warnings from go vet.

Fixes #16134.

Change-Id: Ib9fcba275fe692f027a2a07b581c8cf503b11087
Reviewed-on: https://go-review.googlesource.com/24287
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Ian Lance Taylor 2016-06-21 07:00:41 -07:00
parent 0d94116736
commit 4cf6d7923b
6 changed files with 174 additions and 90 deletions

View File

@ -422,6 +422,33 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) {
return key return key
} }
// clone returns a copy of c. Only the exported fields are copied.
func (c *Config) clone() *Config {
return &Config{
Rand: c.Rand,
Time: c.Time,
Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate,
RootCAs: c.RootCAs,
NextProtos: c.NextProtos,
ServerName: c.ServerName,
ClientAuth: c.ClientAuth,
ClientCAs: c.ClientCAs,
InsecureSkipVerify: c.InsecureSkipVerify,
CipherSuites: c.CipherSuites,
PreferServerCipherSuites: c.PreferServerCipherSuites,
SessionTicketsDisabled: c.SessionTicketsDisabled,
SessionTicketKey: c.SessionTicketKey,
ClientSessionCache: c.ClientSessionCache,
MinVersion: c.MinVersion,
MaxVersion: c.MaxVersion,
CurvePreferences: c.CurvePreferences,
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
Renegotiation: c.Renegotiation,
}
}
func (c *Config) serverInit() { func (c *Config) serverInit() {
if c.SessionTicketsDisabled { if c.SessionTicketsDisabled {
return return

View File

@ -124,9 +124,9 @@ func TestCertificateSelection(t *testing.T) {
func runDynamicRecordSizingTest(t *testing.T, config *Config) { func runDynamicRecordSizingTest(t *testing.T, config *Config) {
clientConn, serverConn := net.Pipe() clientConn, serverConn := net.Pipe()
serverConfig := *config serverConfig := config.clone()
serverConfig.DynamicRecordSizingDisabled = false serverConfig.DynamicRecordSizingDisabled = false
tlsConn := Server(serverConn, &serverConfig) tlsConn := Server(serverConn, serverConfig)
recordSizesChan := make(chan []int, 1) recordSizesChan := make(chan []int, 1)
go func() { go func() {
@ -225,19 +225,19 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) {
} }
func TestDynamicRecordSizingWithStreamCipher(t *testing.T) { func TestDynamicRecordSizingWithStreamCipher(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
runDynamicRecordSizingTest(t, &config) runDynamicRecordSizingTest(t, config)
} }
func TestDynamicRecordSizingWithCBC(t *testing.T) { func TestDynamicRecordSizingWithCBC(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA} config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA}
runDynamicRecordSizingTest(t, &config) runDynamicRecordSizingTest(t, config)
} }
func TestDynamicRecordSizingWithAEAD(t *testing.T) { func TestDynamicRecordSizingWithAEAD(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
runDynamicRecordSizingTest(t, &config) runDynamicRecordSizingTest(t, config)
} }

View File

@ -509,14 +509,14 @@ func TestHandshakeClientAES256GCMSHA384(t *testing.T) {
} }
func TestHandshakeClientCertRSA(t *testing.T) { func TestHandshakeClientCertRSA(t *testing.T) {
config := *testConfig config := testConfig.clone()
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
config.Certificates = []Certificate{cert} config.Certificates = []Certificate{cert}
test := &clientTest{ test := &clientTest{
name: "ClientCert-RSA-RSA", name: "ClientCert-RSA-RSA",
command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"}, command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
config: &config, config: config,
} }
runClientTestTLS10(t, test) runClientTestTLS10(t, test)
@ -525,7 +525,7 @@ func TestHandshakeClientCertRSA(t *testing.T) {
test = &clientTest{ test = &clientTest{
name: "ClientCert-RSA-ECDSA", name: "ClientCert-RSA-ECDSA",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"}, command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
config: &config, config: config,
cert: testECDSACertificate, cert: testECDSACertificate,
key: testECDSAPrivateKey, key: testECDSAPrivateKey,
} }
@ -536,7 +536,7 @@ func TestHandshakeClientCertRSA(t *testing.T) {
test = &clientTest{ test = &clientTest{
name: "ClientCert-RSA-AES256-GCM-SHA384", name: "ClientCert-RSA-AES256-GCM-SHA384",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-verify", "1"}, command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-verify", "1"},
config: &config, config: config,
cert: testRSACertificate, cert: testRSACertificate,
key: testRSAPrivateKey, key: testRSAPrivateKey,
} }
@ -545,14 +545,14 @@ func TestHandshakeClientCertRSA(t *testing.T) {
} }
func TestHandshakeClientCertECDSA(t *testing.T) { func TestHandshakeClientCertECDSA(t *testing.T) {
config := *testConfig config := testConfig.clone()
cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM)) cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
config.Certificates = []Certificate{cert} config.Certificates = []Certificate{cert}
test := &clientTest{ test := &clientTest{
name: "ClientCert-ECDSA-RSA", name: "ClientCert-ECDSA-RSA",
command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"}, command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
config: &config, config: config,
} }
runClientTestTLS10(t, test) runClientTestTLS10(t, test)
@ -561,7 +561,7 @@ func TestHandshakeClientCertECDSA(t *testing.T) {
test = &clientTest{ test = &clientTest{
name: "ClientCert-ECDSA-ECDSA", name: "ClientCert-ECDSA-ECDSA",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"}, command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
config: &config, config: config,
cert: testECDSACertificate, cert: testECDSACertificate,
key: testECDSAPrivateKey, key: testECDSAPrivateKey,
} }
@ -691,7 +691,7 @@ func TestLRUClientSessionCache(t *testing.T) {
} }
func TestHandshakeClientALPNMatch(t *testing.T) { func TestHandshakeClientALPNMatch(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.NextProtos = []string{"proto2", "proto1"} config.NextProtos = []string{"proto2", "proto1"}
test := &clientTest{ test := &clientTest{
@ -699,7 +699,7 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first // Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag. // version that supports the -alpn flag.
command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"}, command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
config: &config, config: config,
validate: func(state ConnectionState) error { validate: func(state ConnectionState) error {
// The server's preferences should override the client. // The server's preferences should override the client.
if state.NegotiatedProtocol != "proto1" { if state.NegotiatedProtocol != "proto1" {
@ -712,7 +712,7 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
} }
func TestHandshakeClientALPNNoMatch(t *testing.T) { func TestHandshakeClientALPNNoMatch(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.NextProtos = []string{"proto3"} config.NextProtos = []string{"proto3"}
test := &clientTest{ test := &clientTest{
@ -720,7 +720,7 @@ func TestHandshakeClientALPNNoMatch(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first // Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag. // version that supports the -alpn flag.
command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"}, command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
config: &config, config: config,
validate: func(state ConnectionState) error { validate: func(state ConnectionState) error {
// There's no overlap so OpenSSL will not select a protocol. // There's no overlap so OpenSSL will not select a protocol.
if state.NegotiatedProtocol != "" { if state.NegotiatedProtocol != "" {
@ -736,7 +736,7 @@ func TestHandshakeClientALPNNoMatch(t *testing.T) {
const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0=" const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0="
func TestHandshakClientSCTs(t *testing.T) { func TestHandshakClientSCTs(t *testing.T) {
config := *testConfig config := testConfig.clone()
scts, err := base64.StdEncoding.DecodeString(sctsBase64) scts, err := base64.StdEncoding.DecodeString(sctsBase64)
if err != nil { if err != nil {
@ -748,7 +748,7 @@ func TestHandshakClientSCTs(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first // Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -serverinfo flag. // version that supports the -serverinfo flag.
command: []string{"openssl", "s_server"}, command: []string{"openssl", "s_server"},
config: &config, config: config,
extensions: [][]byte{scts}, extensions: [][]byte{scts},
validate: func(state ConnectionState) error { validate: func(state ConnectionState) error {
expectedSCTs := [][]byte{ expectedSCTs := [][]byte{
@ -771,11 +771,11 @@ func TestHandshakClientSCTs(t *testing.T) {
} }
func TestRenegotiationRejected(t *testing.T) { func TestRenegotiationRejected(t *testing.T) {
config := *testConfig config := testConfig.clone()
test := &clientTest{ test := &clientTest{
name: "RenegotiationRejected", name: "RenegotiationRejected",
command: []string{"openssl", "s_server", "-state"}, command: []string{"openssl", "s_server", "-state"},
config: &config, config: config,
numRenegotiations: 1, numRenegotiations: 1,
renegotiationExpectedToFail: 1, renegotiationExpectedToFail: 1,
checkRenegotiationError: func(renegotiationNum int, err error) error { checkRenegotiationError: func(renegotiationNum int, err error) error {
@ -793,13 +793,13 @@ func TestRenegotiationRejected(t *testing.T) {
} }
func TestRenegotiateOnce(t *testing.T) { func TestRenegotiateOnce(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.Renegotiation = RenegotiateOnceAsClient config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{ test := &clientTest{
name: "RenegotiateOnce", name: "RenegotiateOnce",
command: []string{"openssl", "s_server", "-state"}, command: []string{"openssl", "s_server", "-state"},
config: &config, config: config,
numRenegotiations: 1, numRenegotiations: 1,
} }
@ -807,13 +807,13 @@ func TestRenegotiateOnce(t *testing.T) {
} }
func TestRenegotiateTwice(t *testing.T) { func TestRenegotiateTwice(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.Renegotiation = RenegotiateFreelyAsClient config.Renegotiation = RenegotiateFreelyAsClient
test := &clientTest{ test := &clientTest{
name: "RenegotiateTwice", name: "RenegotiateTwice",
command: []string{"openssl", "s_server", "-state"}, command: []string{"openssl", "s_server", "-state"},
config: &config, config: config,
numRenegotiations: 2, numRenegotiations: 2,
} }
@ -821,13 +821,13 @@ func TestRenegotiateTwice(t *testing.T) {
} }
func TestRenegotiateTwiceRejected(t *testing.T) { func TestRenegotiateTwiceRejected(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.Renegotiation = RenegotiateOnceAsClient config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{ test := &clientTest{
name: "RenegotiateTwiceRejected", name: "RenegotiateTwiceRejected",
command: []string{"openssl", "s_server", "-state"}, command: []string{"openssl", "s_server", "-state"},
config: &config, config: config,
numRenegotiations: 2, numRenegotiations: 2,
renegotiationExpectedToFail: 2, renegotiationExpectedToFail: 2,
checkRenegotiationError: func(renegotiationNum int, err error) error { checkRenegotiationError: func(renegotiationNum int, err error) error {

View File

@ -130,11 +130,11 @@ func TestNoRC4ByDefault(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone}, compressionMethods: []uint8{compressionNone},
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
// Reset the enabled cipher suites to nil in order to test the // Reset the enabled cipher suites to nil in order to test the
// defaults. // defaults.
serverConfig.CipherSuites = nil serverConfig.CipherSuites = nil
testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server") testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
} }
func TestDontSelectECDSAWithRSAKey(t *testing.T) { func TestDontSelectECDSAWithRSAKey(t *testing.T) {
@ -147,19 +147,19 @@ func TestDontSelectECDSAWithRSAKey(t *testing.T) {
supportedCurves: []CurveID{CurveP256}, supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed}, supportedPoints: []uint8{pointFormatUncompressed},
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
serverConfig.CipherSuites = clientHello.cipherSuites serverConfig.CipherSuites = clientHello.cipherSuites
serverConfig.Certificates = make([]Certificate, 1) serverConfig.Certificates = make([]Certificate, 1)
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
serverConfig.BuildNameToCertificate() serverConfig.BuildNameToCertificate()
// First test that it *does* work when the server's key is ECDSA. // First test that it *does* work when the server's key is ECDSA.
testClientHello(t, &serverConfig, clientHello) testClientHello(t, serverConfig, clientHello)
// Now test that switching to an RSA key causes the expected error (and // Now test that switching to an RSA key causes the expected error (and
// not an internal error about a signing failure). // not an internal error about a signing failure).
serverConfig.Certificates = testConfig.Certificates serverConfig.Certificates = testConfig.Certificates
testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server") testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
} }
func TestDontSelectRSAWithECDSAKey(t *testing.T) { func TestDontSelectRSAWithECDSAKey(t *testing.T) {
@ -172,10 +172,10 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
supportedCurves: []CurveID{CurveP256}, supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed}, supportedPoints: []uint8{pointFormatUncompressed},
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
serverConfig.CipherSuites = clientHello.cipherSuites serverConfig.CipherSuites = clientHello.cipherSuites
// First test that it *does* work when the server's key is RSA. // First test that it *does* work when the server's key is RSA.
testClientHello(t, &serverConfig, clientHello) testClientHello(t, serverConfig, clientHello)
// Now test that switching to an ECDSA key causes the expected error // Now test that switching to an ECDSA key causes the expected error
// (and not an internal error about a signing failure). // (and not an internal error about a signing failure).
@ -183,7 +183,7 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
serverConfig.BuildNameToCertificate() serverConfig.BuildNameToCertificate()
testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server") testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
} }
func TestRenegotiationExtension(t *testing.T) { func TestRenegotiationExtension(t *testing.T) {
@ -265,9 +265,9 @@ func TestTLS12OnlyCipherSuites(t *testing.T) {
reply, clientErr = cli.readHandshake() reply, clientErr = cli.readHandshake()
c.Close() c.Close()
}() }()
config := *testConfig config := testConfig.clone()
config.CipherSuites = clientHello.cipherSuites config.CipherSuites = clientHello.cipherSuites
Server(s, &config).Handshake() Server(s, config).Handshake()
s.Close() s.Close()
if clientErr != nil { if clientErr != nil {
t.Fatal(clientErr) t.Fatal(clientErr)
@ -732,7 +732,7 @@ func TestHandshakeServerAES256GCMSHA384(t *testing.T) {
} }
func TestHandshakeServerECDHEECDSAAES(t *testing.T) { func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.Certificates = make([]Certificate, 1) config.Certificates = make([]Certificate, 1)
config.Certificates[0].Certificate = [][]byte{testECDSACertificate} config.Certificates[0].Certificate = [][]byte{testECDSACertificate}
config.Certificates[0].PrivateKey = testECDSAPrivateKey config.Certificates[0].PrivateKey = testECDSAPrivateKey
@ -741,14 +741,14 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
test := &serverTest{ test := &serverTest{
name: "ECDHE-ECDSA-AES", name: "ECDHE-ECDSA-AES",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA"}, command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA"},
config: &config, config: config,
} }
runServerTestTLS10(t, test) runServerTestTLS10(t, test)
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
} }
func TestHandshakeServerALPN(t *testing.T) { func TestHandshakeServerALPN(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.NextProtos = []string{"proto1", "proto2"} config.NextProtos = []string{"proto1", "proto2"}
test := &serverTest{ test := &serverTest{
@ -756,7 +756,7 @@ func TestHandshakeServerALPN(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first // Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag. // version that supports the -alpn flag.
command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"}, command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"},
config: &config, config: config,
validate: func(state ConnectionState) error { validate: func(state ConnectionState) error {
// The server's preferences should override the client. // The server's preferences should override the client.
if state.NegotiatedProtocol != "proto1" { if state.NegotiatedProtocol != "proto1" {
@ -769,7 +769,7 @@ func TestHandshakeServerALPN(t *testing.T) {
} }
func TestHandshakeServerALPNNoMatch(t *testing.T) { func TestHandshakeServerALPNNoMatch(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.NextProtos = []string{"proto3"} config.NextProtos = []string{"proto3"}
test := &serverTest{ test := &serverTest{
@ -777,7 +777,7 @@ func TestHandshakeServerALPNNoMatch(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first // Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag. // version that supports the -alpn flag.
command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"}, command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"},
config: &config, config: config,
validate: func(state ConnectionState) error { validate: func(state ConnectionState) error {
// Rather than reject the connection, Go doesn't select // Rather than reject the connection, Go doesn't select
// a protocol when there is no overlap. // a protocol when there is no overlap.
@ -804,7 +804,7 @@ func TestHandshakeServerSNI(t *testing.T) {
// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but // TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but
// tests the dynamic GetCertificate method // tests the dynamic GetCertificate method
func TestHandshakeServerSNIGetCertificate(t *testing.T) { func TestHandshakeServerSNIGetCertificate(t *testing.T) {
config := *testConfig config := testConfig.clone()
// Replace the NameToCertificate map with a GetCertificate function // Replace the NameToCertificate map with a GetCertificate function
nameToCert := config.NameToCertificate nameToCert := config.NameToCertificate
@ -816,7 +816,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) {
test := &serverTest{ test := &serverTest{
name: "SNI-GetCertificate", name: "SNI-GetCertificate",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
} }
@ -826,7 +826,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) {
// GetCertificate method doesn't return a cert, we fall back to what's in // GetCertificate method doesn't return a cert, we fall back to what's in
// the NameToCertificate map. // the NameToCertificate map.
func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) { func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, nil return nil, nil
@ -834,7 +834,7 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
test := &serverTest{ test := &serverTest{
name: "SNI-GetCertificateNotFound", name: "SNI-GetCertificateNotFound",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
} }
@ -844,7 +844,7 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
func TestHandshakeServerSNIGetCertificateError(t *testing.T) { func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
const errMsg = "TestHandshakeServerSNIGetCertificateError error" const errMsg = "TestHandshakeServerSNIGetCertificateError error"
serverConfig := *testConfig serverConfig := testConfig.clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg) return nil, errors.New(errMsg)
} }
@ -855,7 +855,7 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
compressionMethods: []uint8{compressionNone}, compressionMethods: []uint8{compressionNone},
serverName: "test", serverName: "test",
} }
testClientHelloFailure(t, &serverConfig, clientHello, errMsg) testClientHelloFailure(t, serverConfig, clientHello, errMsg)
} }
// TestHandshakeServerEmptyCertificates tests that GetCertificates is called in // TestHandshakeServerEmptyCertificates tests that GetCertificates is called in
@ -863,7 +863,7 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
func TestHandshakeServerEmptyCertificates(t *testing.T) { func TestHandshakeServerEmptyCertificates(t *testing.T) {
const errMsg = "TestHandshakeServerEmptyCertificates error" const errMsg = "TestHandshakeServerEmptyCertificates error"
serverConfig := *testConfig serverConfig := testConfig.clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg) return nil, errors.New(errMsg)
} }
@ -874,7 +874,7 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone}, compressionMethods: []uint8{compressionNone},
} }
testClientHelloFailure(t, &serverConfig, clientHello, errMsg) testClientHelloFailure(t, serverConfig, clientHello, errMsg)
// With an empty Certificates and a nil GetCertificate, the server // With an empty Certificates and a nil GetCertificate, the server
// should always return a “no certificates” error. // should always return a “no certificates” error.
@ -885,23 +885,23 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone}, compressionMethods: []uint8{compressionNone},
} }
testClientHelloFailure(t, &serverConfig, clientHello, "no certificates") testClientHelloFailure(t, serverConfig, clientHello, "no certificates")
} }
// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with // TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate. // an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
func TestCipherSuiteCertPreferenceECDSA(t *testing.T) { func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
config := *testConfig config := testConfig.clone()
config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA} config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}
config.PreferServerCipherSuites = true config.PreferServerCipherSuites = true
test := &serverTest{ test := &serverTest{
name: "CipherSuiteCertPreferenceRSA", name: "CipherSuiteCertPreferenceRSA",
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
config = *testConfig config = testConfig.clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA} config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
config.Certificates = []Certificate{ config.Certificates = []Certificate{
{ {
@ -914,7 +914,7 @@ func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
test = &serverTest{ test = &serverTest{
name: "CipherSuiteCertPreferenceECDSA", name: "CipherSuiteCertPreferenceECDSA",
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
} }
@ -940,12 +940,12 @@ func TestResumptionDisabled(t *testing.T) {
sessionFilePath := tempFile("") sessionFilePath := tempFile("")
defer os.Remove(sessionFilePath) defer os.Remove(sessionFilePath)
config := *testConfig config := testConfig.clone()
test := &serverTest{ test := &serverTest{
name: "IssueTicketPreDisable", name: "IssueTicketPreDisable",
command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath}, command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath},
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
@ -954,7 +954,7 @@ func TestResumptionDisabled(t *testing.T) {
test = &serverTest{ test = &serverTest{
name: "ResumeDisabled", name: "ResumeDisabled",
command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath}, command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath},
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
@ -963,12 +963,12 @@ func TestResumptionDisabled(t *testing.T) {
} }
func TestFallbackSCSV(t *testing.T) { func TestFallbackSCSV(t *testing.T) {
serverConfig := &Config{ serverConfig := Config{
Certificates: testConfig.Certificates, Certificates: testConfig.Certificates,
} }
test := &serverTest{ test := &serverTest{
name: "FallbackSCSV", name: "FallbackSCSV",
config: serverConfig, config: &serverConfig,
// OpenSSL 1.0.1j is needed for the -fallback_scsv option. // OpenSSL 1.0.1j is needed for the -fallback_scsv option.
command: []string{"openssl", "s_client", "-fallback_scsv"}, command: []string{"openssl", "s_client", "-fallback_scsv"},
expectHandshakeErrorIncluding: "inappropriate protocol fallback", expectHandshakeErrorIncluding: "inappropriate protocol fallback",
@ -1053,20 +1053,20 @@ func TestClientAuth(t *testing.T) {
defer os.Remove(ecdsaKeyPath) defer os.Remove(ecdsaKeyPath)
} }
config := *testConfig config := testConfig.clone()
config.ClientAuth = RequestClientCert config.ClientAuth = RequestClientCert
test := &serverTest{ test := &serverTest{
name: "ClientAuthRequestedNotGiven", name: "ClientAuthRequestedNotGiven",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"}, command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"},
config: &config, config: config,
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
test = &serverTest{ test = &serverTest{
name: "ClientAuthRequestedAndGiven", name: "ClientAuthRequestedAndGiven",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath}, command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath},
config: &config, config: config,
expectedPeerCerts: []string{clientCertificatePEM}, expectedPeerCerts: []string{clientCertificatePEM},
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)
@ -1074,7 +1074,7 @@ func TestClientAuth(t *testing.T) {
test = &serverTest{ test = &serverTest{
name: "ClientAuthRequestedAndECDSAGiven", name: "ClientAuthRequestedAndECDSAGiven",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath}, command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
config: &config, config: config,
expectedPeerCerts: []string{clientECDSACertificatePEM}, expectedPeerCerts: []string{clientECDSACertificatePEM},
} }
runServerTestTLS12(t, test) runServerTestTLS12(t, test)

4
tls.go
View File

@ -135,9 +135,9 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
// from the hostname we're connecting to. // from the hostname we're connecting to.
if config.ServerName == "" { if config.ServerName == "" {
// Make a copy to avoid polluting argument or default. // Make a copy to avoid polluting argument or default.
c := *config c := config.clone()
c.ServerName = hostname c.ServerName = hostname
config = &c config = c
} }
conn := Client(rawConn, config) conn := Client(rawConn, config)

View File

@ -6,14 +6,19 @@ package tls
import ( import (
"bytes" "bytes"
"crypto/x509"
"errors" "errors"
"fmt" "fmt"
"internal/testenv" "internal/testenv"
"io" "io"
"math" "math"
"math/rand"
"net" "net"
"os"
"reflect"
"strings" "strings"
"testing" "testing"
"testing/quick"
"time" "time"
) )
@ -236,8 +241,8 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
srvCh <- nil srvCh <- nil
return return
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
srv := Server(sconn, &serverConfig) srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil { if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err) serr = fmt.Errorf("handshake: %v", err)
srvCh <- nil srvCh <- nil
@ -246,8 +251,8 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
srvCh <- srv srvCh <- srv
}() }()
clientConfig := *testConfig clientConfig := testConfig.clone()
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -290,8 +295,8 @@ func TestTLSUniqueMatches(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
srv := Server(sconn, &serverConfig) srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil { if err := srv.Handshake(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -299,9 +304,9 @@ func TestTLSUniqueMatches(t *testing.T) {
} }
}() }()
clientConfig := *testConfig clientConfig := testConfig.clone()
clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -310,7 +315,7 @@ func TestTLSUniqueMatches(t *testing.T) {
} }
conn.Close() conn.Close()
conn, err = Dial("tcp", ln.Addr().String(), &clientConfig) conn, err = Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -389,8 +394,8 @@ func TestConnCloseBreakingWrite(t *testing.T) {
srvCh <- nil srvCh <- nil
return return
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
srv := Server(sconn, &serverConfig) srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil { if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err) serr = fmt.Errorf("handshake: %v", err)
srvCh <- nil srvCh <- nil
@ -409,8 +414,8 @@ func TestConnCloseBreakingWrite(t *testing.T) {
Conn: cconn, Conn: cconn,
} }
clientConfig := *testConfig clientConfig := testConfig.clone()
tconn := Client(conn, &clientConfig) tconn := Client(conn, clientConfig)
if err := tconn.Handshake(); err != nil { if err := tconn.Handshake(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -453,6 +458,58 @@ func TestConnCloseBreakingWrite(t *testing.T) {
} }
} }
func TestClone(t *testing.T) {
var c1 Config
v := reflect.ValueOf(&c1).Elem()
rnd := rand.New(rand.NewSource(time.Now().Unix()))
typ := v.Type()
for i := 0; i < typ.NumField(); i++ {
f := v.Field(i)
if !f.CanSet() {
// unexported field; not cloned.
continue
}
// testing/quick can't handle functions or interfaces.
fn := typ.Field(i).Name
switch fn {
case "Rand":
f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
continue
case "Time", "GetCertificate":
// DeepEqual can't compare functions.
continue
case "Certificates":
f.Set(reflect.ValueOf([]Certificate{
{Certificate: [][]byte{[]byte{'b'}}},
}))
continue
case "NameToCertificate":
f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil}))
continue
case "RootCAs", "ClientCAs":
f.Set(reflect.ValueOf(x509.NewCertPool()))
continue
case "ClientSessionCache":
f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
continue
}
q, ok := quick.Value(f.Type(), rnd)
if !ok {
t.Fatalf("quick.Value failed on field %s", fn)
}
f.Set(q)
}
c2 := c1.clone()
if !reflect.DeepEqual(&c1, c2) {
t.Errorf("clone failed to copy a field")
}
}
// changeImplConn is a net.Conn which can change its Write and Close // changeImplConn is a net.Conn which can change its Write and Close
// methods. // methods.
type changeImplConn struct { type changeImplConn struct {
@ -489,9 +546,9 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
// (cannot call b.Fatal in goroutine) // (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err)) panic(fmt.Errorf("accept: %v", err))
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(sconn, &serverConfig) srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil { if err := srv.Handshake(); err != nil {
panic(fmt.Errorf("handshake: %v", err)) panic(fmt.Errorf("handshake: %v", err))
} }
@ -500,13 +557,13 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
}() }()
b.SetBytes(totalBytes) b.SetBytes(totalBytes)
clientConfig := *testConfig clientConfig := testConfig.clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 1<<14) buf := make([]byte, 1<<14)
chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf)))) chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -577,9 +634,9 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
// (cannot call b.Fatal in goroutine) // (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err)) panic(fmt.Errorf("accept: %v", err))
} }
serverConfig := *testConfig serverConfig := testConfig.clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(&slowConn{sconn, bps}, &serverConfig) srv := Server(&slowConn{sconn, bps}, serverConfig)
if err := srv.Handshake(); err != nil { if err := srv.Handshake(); err != nil {
panic(fmt.Errorf("handshake: %v", err)) panic(fmt.Errorf("handshake: %v", err))
} }
@ -587,14 +644,14 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
} }
}() }()
clientConfig := *testConfig clientConfig := testConfig.clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 16384) buf := make([]byte, 16384)
peek := make([]byte, 1) peek := make([]byte, 1)
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }