232 lines
7.8 KiB
Go
232 lines
7.8 KiB
Go
// Copyright 2014 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package tls_test
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
|
|
type zeroSource struct{}
|
|
|
|
func (zeroSource) Read(b []byte) (n int, err error) {
|
|
for i := range b {
|
|
b[i] = 0
|
|
}
|
|
|
|
return len(b), nil
|
|
}
|
|
|
|
func ExampleDial() {
|
|
// Connecting with a custom root-certificate set.
|
|
|
|
const rootPEM = `
|
|
-- GlobalSign Root R2, valid until Dec 15, 2021
|
|
-----BEGIN CERTIFICATE-----
|
|
MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
|
|
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
|
|
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
|
|
MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
|
|
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
|
|
hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
|
|
v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
|
|
eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
|
|
tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
|
|
C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
|
|
zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
|
|
mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
|
|
V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
|
|
bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
|
|
3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
|
|
J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
|
|
291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
|
|
ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
|
|
AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
|
|
TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
|
|
-----END CERTIFICATE-----`
|
|
|
|
// First, create the set of root certificates. For this example we only
|
|
// have one. It's also possible to omit this in order to use the
|
|
// default root set of the current operating system.
|
|
roots := x509.NewCertPool()
|
|
ok := roots.AppendCertsFromPEM([]byte(rootPEM))
|
|
if !ok {
|
|
panic("failed to parse root certificate")
|
|
}
|
|
|
|
conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{
|
|
RootCAs: roots,
|
|
})
|
|
if err != nil {
|
|
panic("failed to connect: " + err.Error())
|
|
}
|
|
conn.Close()
|
|
}
|
|
|
|
func ExampleConfig_keyLogWriter() {
|
|
// Debugging TLS applications by decrypting a network traffic capture.
|
|
|
|
// WARNING: Use of KeyLogWriter compromises security and should only be
|
|
// used for debugging.
|
|
|
|
// Dummy test HTTP server for the example with insecure random so output is
|
|
// reproducible.
|
|
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
|
|
server.TLS = &tls.Config{
|
|
Rand: zeroSource{}, // for example only; don't do this.
|
|
}
|
|
server.StartTLS()
|
|
defer server.Close()
|
|
|
|
// Typically the log would go to an open file:
|
|
// w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
|
w := os.Stdout
|
|
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
KeyLogWriter: w,
|
|
|
|
Rand: zeroSource{}, // for reproducible output; don't do this.
|
|
InsecureSkipVerify: true, // test server certificate is not trusted.
|
|
},
|
|
},
|
|
}
|
|
resp, err := client.Get(server.URL)
|
|
if err != nil {
|
|
log.Fatalf("Failed to get URL: %v", err)
|
|
}
|
|
resp.Body.Close()
|
|
|
|
// The resulting file can be used with Wireshark to decrypt the TLS
|
|
// connection by setting (Pre)-Master-Secret log filename in SSL Protocol
|
|
// preferences.
|
|
}
|
|
|
|
func ExampleLoadX509KeyPair() {
|
|
cert, err := tls.LoadX509KeyPair("testdata/example-cert.pem", "testdata/example-key.pem")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
|
|
listener, err := tls.Listen("tcp", ":2000", cfg)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
_ = listener
|
|
}
|
|
|
|
func ExampleX509KeyPair() {
|
|
certPem := []byte(`-----BEGIN CERTIFICATE-----
|
|
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
|
|
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
|
|
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
|
|
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
|
|
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
|
|
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
|
|
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
|
|
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
|
6MF9+Yw1Yy0t
|
|
-----END CERTIFICATE-----`)
|
|
keyPem := []byte(`-----BEGIN EC PRIVATE KEY-----
|
|
MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
|
|
AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
|
|
EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
|
|
-----END EC PRIVATE KEY-----`)
|
|
cert, err := tls.X509KeyPair(certPem, keyPem)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
|
|
listener, err := tls.Listen("tcp", ":2000", cfg)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
_ = listener
|
|
}
|
|
|
|
func ExampleX509KeyPair_httpServer() {
|
|
certPem := []byte(`-----BEGIN CERTIFICATE-----
|
|
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
|
|
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
|
|
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
|
|
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
|
|
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
|
|
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
|
|
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
|
|
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
|
6MF9+Yw1Yy0t
|
|
-----END CERTIFICATE-----`)
|
|
keyPem := []byte(`-----BEGIN EC PRIVATE KEY-----
|
|
MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
|
|
AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
|
|
EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
|
|
-----END EC PRIVATE KEY-----`)
|
|
cert, err := tls.X509KeyPair(certPem, keyPem)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
|
|
srv := &http.Server{
|
|
TLSConfig: cfg,
|
|
ReadTimeout: time.Minute,
|
|
WriteTimeout: time.Minute,
|
|
}
|
|
log.Fatal(srv.ListenAndServeTLS("", ""))
|
|
}
|
|
|
|
func ExampleConfig_verifyConnection() {
|
|
// VerifyConnection can be used to replace and customize connection
|
|
// verification. This example shows a VerifyConnection implementation that
|
|
// will be approximately equivalent to what crypto/tls does normally to
|
|
// verify the peer's certificate.
|
|
|
|
// Client side configuration.
|
|
_ = &tls.Config{
|
|
// Set InsecureSkipVerify to skip the default validation we are
|
|
// replacing. This will not disable VerifyConnection.
|
|
InsecureSkipVerify: true,
|
|
VerifyConnection: func(cs tls.ConnectionState) error {
|
|
opts := x509.VerifyOptions{
|
|
DNSName: cs.ServerName,
|
|
Intermediates: x509.NewCertPool(),
|
|
}
|
|
for _, cert := range cs.PeerCertificates[1:] {
|
|
opts.Intermediates.AddCert(cert)
|
|
}
|
|
_, err := cs.PeerCertificates[0].Verify(opts)
|
|
return err
|
|
},
|
|
}
|
|
|
|
// Server side configuration.
|
|
_ = &tls.Config{
|
|
// Require client certificates (or VerifyConnection will run anyway and
|
|
// panic accessing cs.PeerCertificates[0]) but don't verify them with the
|
|
// default verifier. This will not disable VerifyConnection.
|
|
ClientAuth: tls.RequireAnyClientCert,
|
|
VerifyConnection: func(cs tls.ConnectionState) error {
|
|
opts := x509.VerifyOptions{
|
|
DNSName: cs.ServerName,
|
|
Intermediates: x509.NewCertPool(),
|
|
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
}
|
|
for _, cert := range cs.PeerCertificates[1:] {
|
|
opts.Intermediates.AddCert(cert)
|
|
}
|
|
_, err := cs.PeerCertificates[0].Verify(opts)
|
|
return err
|
|
},
|
|
}
|
|
|
|
// Note that when certificates are not handled by the default verifier
|
|
// ConnectionState.VerifiedChains will be nil.
|
|
}
|