crypto/tls: replace VerifyPeerCertificate example with VerifyConnection

Look at how much better it is!

Updates #36736

Change-Id: I53a314a103a42dd869c05823fa50f37d70f9d283
Reviewed-on: https://go-review.googlesource.com/c/go/+/239560
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
diff --git a/src/crypto/tls/example_test.go b/src/crypto/tls/example_test.go
index cf58a58..6389fd7 100644
--- a/src/crypto/tls/example_test.go
+++ b/src/crypto/tls/example_test.go
@@ -7,7 +7,6 @@
 import (
 	"crypto/tls"
 	"crypto/x509"
-	"errors"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -184,54 +183,50 @@
 	log.Fatal(srv.ListenAndServeTLS("", ""))
 }
 
-func ExampleConfig_verifyPeerCertificate() {
-	// VerifyPeerCertificate can be used to replace and customize certificate
-	// verification. This example shows a VerifyPeerCertificate implementation
-	// that will be approximately equivalent to what crypto/tls does normally.
+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.
 
-	config := &tls.Config{
+	// Client side configuration.
+	_ = &tls.Config{
 		// Set InsecureSkipVerify to skip the default validation we are
-		// replacing. This will not disable VerifyPeerCertificate.
+		// replacing. This will not disable VerifyConnection.
 		InsecureSkipVerify: true,
-
-		// While packages like net/http will implicitly set ServerName, the
-		// VerifyPeerCertificate callback can't access that value, so it has to be set
-		// explicitly here or in VerifyPeerCertificate on the client side. If in
-		// an http.Transport DialTLS callback, this can be obtained by passing
-		// the addr argument to net.SplitHostPort.
-		ServerName: "example.com",
-
-		// On the server side, set ClientAuth to require client certificates (or
-		// VerifyPeerCertificate will run anyway and panic accessing certs[0])
-		// but not verify them with the default verifier.
-		// ClientAuth: tls.RequireAnyClientCert,
-	}
-
-	config.VerifyPeerCertificate = func(certificates [][]byte, _ [][]*x509.Certificate) error {
-		certs := make([]*x509.Certificate, len(certificates))
-		for i, asn1Data := range certificates {
-			cert, err := x509.ParseCertificate(asn1Data)
-			if err != nil {
-				return errors.New("tls: failed to parse certificate from server: " + err.Error())
+		VerifyConnection: func(cs tls.ConnectionState) error {
+			opts := x509.VerifyOptions{
+				DNSName:       cs.ServerName,
+				Intermediates: x509.NewCertPool(),
 			}
-			certs[i] = cert
-		}
-
-		opts := x509.VerifyOptions{
-			Roots:         config.RootCAs, // On the server side, use config.ClientCAs.
-			DNSName:       config.ServerName,
-			Intermediates: x509.NewCertPool(),
-			// On the server side, set KeyUsages to ExtKeyUsageClientAuth. The
-			// default value is appropriate for clients side verification.
-			// KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
-		}
-		for _, cert := range certs[1:] {
-			opts.Intermediates.AddCert(cert)
-		}
-		_, err := certs[0].Verify(opts)
-		return err
+			for _, cert := range cs.PeerCertificates[1:] {
+				opts.Intermediates.AddCert(cert)
+			}
+			_, err := cs.PeerCertificates[0].Verify(opts)
+			return err
+		},
 	}
 
-	// Note that when InsecureSkipVerify and VerifyPeerCertificate are in use,
+	// 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.
 }