func verifyPeerCertificateFunc()

in internal/cloudsql/tls_verify.go [65:129]


func verifyPeerCertificateFunc(
	serverName string, cn instance.ConnName, roots *x509.CertPool,
) func(certs [][]byte, chain [][]*x509.Certificate) error {
	return func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
		if len(rawCerts) == 0 {
			return errtype.NewDialError(
				"no certificate to verify", cn.String(), nil,
			)
		}
		// Parse the raw certificates
		certs := make([]*x509.Certificate, 0, len(rawCerts))
		var err error
		for _, certBytes := range rawCerts {
			cert, err := x509.ParseCertificate(certBytes)
			if err != nil {
				return errtype.NewDialError(
					"failed to parse X.509 certificate", cn.String(), err,
				)
			}
			certs = append(certs, cert)
		}
		serverCert := certs[0]

		// Verify the validity of the certificate chain
		_, err = serverCert.Verify(x509.VerifyOptions{
			Roots: roots,
		})
		if err != nil {
			err = &tls.CertificateVerificationError{
				UnverifiedCertificates: certs,
				Err:                    err,
			}
			return errtype.NewDialError(
				"failed to verify certificate", cn.String(), err,
			)
		}

		var serverNameErr error

		if serverName == "" {
			// The instance has no DNS name.
			// Verify only the CN
			return verifyCn(cn, serverCert)
		}

		// The instance has a DNS name.
		// First, verify the server hostname
		serverNameErr = serverCert.VerifyHostname(serverName)
		if serverNameErr != nil {
			// If that failed, verify the CN field.
			cnErr := verifyCn(cn, serverCert)
			if cnErr != nil {
				// If both failed, return the server hostname error.
				serverNameErr = &tls.CertificateVerificationError{
					UnverifiedCertificates: certs,
					Err:                    serverNameErr,
				}
				return serverNameErr
			}
		}

		// All checks passed
		return nil
	}
}