1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package tls_test
6
7import (
8	"crypto/tls"
9	"crypto/x509"
10	"log"
11	"net/http"
12	"net/http/httptest"
13	"os"
14	"time"
15)
16
17// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
18type zeroSource struct{}
19
20func (zeroSource) Read(b []byte) (n int, err error) {
21	for i := range b {
22		b[i] = 0
23	}
24
25	return len(b), nil
26}
27
28func ExampleDial() {
29	// Connecting with a custom root-certificate set.
30
31	const rootPEM = `
32-- GlobalSign Root R2, valid until Dec 15, 2021
33-----BEGIN CERTIFICATE-----
34MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
35A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
36Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
37MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
38A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
39hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
40v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
41eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
42tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
43C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
44zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
45mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
46V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
47bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
483lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
49J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
50291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
51ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
52AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
53TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
54-----END CERTIFICATE-----`
55
56	// First, create the set of root certificates. For this example we only
57	// have one. It's also possible to omit this in order to use the
58	// default root set of the current operating system.
59	roots := x509.NewCertPool()
60	ok := roots.AppendCertsFromPEM([]byte(rootPEM))
61	if !ok {
62		panic("failed to parse root certificate")
63	}
64
65	conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{
66		RootCAs: roots,
67	})
68	if err != nil {
69		panic("failed to connect: " + err.Error())
70	}
71	conn.Close()
72}
73
74func ExampleConfig_keyLogWriter() {
75	// Debugging TLS applications by decrypting a network traffic capture.
76
77	// WARNING: Use of KeyLogWriter compromises security and should only be
78	// used for debugging.
79
80	// Dummy test HTTP server for the example with insecure random so output is
81	// reproducible.
82	server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
83	server.TLS = &tls.Config{
84		Rand: zeroSource{}, // for example only; don't do this.
85	}
86	server.StartTLS()
87	defer server.Close()
88
89	// Typically the log would go to an open file:
90	// w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
91	w := os.Stdout
92
93	client := &http.Client{
94		Transport: &http.Transport{
95			TLSClientConfig: &tls.Config{
96				KeyLogWriter: w,
97
98				Rand:               zeroSource{}, // for reproducible output; don't do this.
99				InsecureSkipVerify: true,         // test server certificate is not trusted.
100			},
101		},
102	}
103	resp, err := client.Get(server.URL)
104	if err != nil {
105		log.Fatalf("Failed to get URL: %v", err)
106	}
107	resp.Body.Close()
108
109	// The resulting file can be used with Wireshark to decrypt the TLS
110	// connection by setting (Pre)-Master-Secret log filename in SSL Protocol
111	// preferences.
112}
113
114func ExampleLoadX509KeyPair() {
115	cert, err := tls.LoadX509KeyPair("testdata/example-cert.pem", "testdata/example-key.pem")
116	if err != nil {
117		log.Fatal(err)
118	}
119	cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
120	listener, err := tls.Listen("tcp", ":2000", cfg)
121	if err != nil {
122		log.Fatal(err)
123	}
124	_ = listener
125}
126
127func ExampleX509KeyPair() {
128	certPem := []byte(`-----BEGIN CERTIFICATE-----
129MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
130DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
131EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
1327VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
1335aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
134BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
135NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
136Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
1376MF9+Yw1Yy0t
138-----END CERTIFICATE-----`)
139	keyPem := []byte(`-----BEGIN EC PRIVATE KEY-----
140MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
141AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
142EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
143-----END EC PRIVATE KEY-----`)
144	cert, err := tls.X509KeyPair(certPem, keyPem)
145	if err != nil {
146		log.Fatal(err)
147	}
148	cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
149	listener, err := tls.Listen("tcp", ":2000", cfg)
150	if err != nil {
151		log.Fatal(err)
152	}
153	_ = listener
154}
155
156func ExampleX509KeyPair_httpServer() {
157	certPem := []byte(`-----BEGIN CERTIFICATE-----
158MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
159DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
160EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
1617VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
1625aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
163BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
164NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
165Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
1666MF9+Yw1Yy0t
167-----END CERTIFICATE-----`)
168	keyPem := []byte(`-----BEGIN EC PRIVATE KEY-----
169MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
170AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
171EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
172-----END EC PRIVATE KEY-----`)
173	cert, err := tls.X509KeyPair(certPem, keyPem)
174	if err != nil {
175		log.Fatal(err)
176	}
177	cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
178	srv := &http.Server{
179		TLSConfig:    cfg,
180		ReadTimeout:  time.Minute,
181		WriteTimeout: time.Minute,
182	}
183	log.Fatal(srv.ListenAndServeTLS("", ""))
184}
185
186func ExampleConfig_verifyConnection() {
187	// VerifyConnection can be used to replace and customize connection
188	// verification. This example shows a VerifyConnection implementation that
189	// will be approximately equivalent to what crypto/tls does normally to
190	// verify the peer's certificate.
191
192	// Client side configuration.
193	_ = &tls.Config{
194		// Set InsecureSkipVerify to skip the default validation we are
195		// replacing. This will not disable VerifyConnection.
196		InsecureSkipVerify: true,
197		VerifyConnection: func(cs tls.ConnectionState) error {
198			opts := x509.VerifyOptions{
199				DNSName:       cs.ServerName,
200				Intermediates: x509.NewCertPool(),
201			}
202			for _, cert := range cs.PeerCertificates[1:] {
203				opts.Intermediates.AddCert(cert)
204			}
205			_, err := cs.PeerCertificates[0].Verify(opts)
206			return err
207		},
208	}
209
210	// Server side configuration.
211	_ = &tls.Config{
212		// Require client certificates (or VerifyConnection will run anyway and
213		// panic accessing cs.PeerCertificates[0]) but don't verify them with the
214		// default verifier. This will not disable VerifyConnection.
215		ClientAuth: tls.RequireAnyClientCert,
216		VerifyConnection: func(cs tls.ConnectionState) error {
217			opts := x509.VerifyOptions{
218				DNSName:       cs.ServerName,
219				Intermediates: x509.NewCertPool(),
220				KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
221			}
222			for _, cert := range cs.PeerCertificates[1:] {
223				opts.Intermediates.AddCert(cert)
224			}
225			_, err := cs.PeerCertificates[0].Verify(opts)
226			return err
227		},
228	}
229
230	// Note that when certificates are not handled by the default verifier
231	// ConnectionState.VerifiedChains will be nil.
232}
233