Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto/tls: RequireAndVerifyClientCert is not working as intended. #63122

Closed
Manikishore-S opened this issue Sep 20, 2023 · 6 comments
Closed

Comments

@Manikishore-S
Copy link

Manikishore-S commented Sep 20, 2023

What version of Go are you using (go version)?

$ go version

go1.21.1 darwin/amd64

Does this issue reproduce with the latest release?

Yes i tried with latest and older releases as well

What operating system and processor architecture are you using (go env)?

go env Output
$ go env

manikishore.s$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/Users/manikishore.s/Library/Caches/go-build'
GOENV='/Users/manikishore.s/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/manikishore.s/go/pkg/mod'
GONOPROXY='github.com/Manikishore-S'
GONOSUMDB='github.com/Manikishore-S'
GOOS='darwin'
GOPATH='/Users/manikishore.s/go'
GOPRIVATE='github.com/Manikishore-S'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_amd64'
GOVCS=''
GOVERSION='go1.21.1'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/q0/chzy5trn5s17x4d7k4mg38qhw1k3zr/T/go-build3453854944=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

Start a crypto/tls-based webserver with mtls connection as show below.

Server.go

package main

import (
	"crypto/tls"
	"crypto/x509"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
	// Write "Hello, world!" to the response body
	io.WriteString(w, "Hello, world!\n")
}

func main() {
	// Set up a /hello resource handler
	http.HandleFunc("/hello", helloHandler)

	// Create a CA certificate pool and add cert.pem to it
	caCert, err := ioutil.ReadFile("ca.pem")
	if err != nil {
		log.Fatal(err)
	}
	caCertPool := x509.NewCertPool()
	ok := caCertPool.AppendCertsFromPEM(caCert)
	if !ok {
		panic("failed to parse root certificate")
	}

	// Create the TLS Config with the CA pool and enable Client certificate validation
	tlsConfig := &tls.Config{
		MinVersion:               tls.VersionTLS12,
		ClientCAs:                caCertPool,
		ClientAuth:               tls.RequireAndVerifyClientCert,
	}

	// Create a Server instance to listen on port 8443 with the TLS config
	server := &http.Server{
		Addr:      ":8443",
		TLSConfig: tlsConfig,
	}

	// Listen to HTTPS connections with the server certificate and wait
	log.Fatal(server.ListenAndServeTLS("server-cert.pem", "server-key.pem"))
}

Client.go

package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

func main() {
	// Read the key pair to create certificate
	cert, err := tls.LoadX509KeyPair("client-cert.pem", "client-key.pem")
	if err != nil {
		log.Fatal(err)
	}

	// Create a CA certificate pool and add cert.pem to it
	caCert, err := ioutil.ReadFile("ca.pem")
	if err != nil {
		log.Fatal(err)
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	// Create a HTTPS client and supply the created CA pool and certificate
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				RootCAs:      caCertPool,
				Certificates: []tls.Certificate{cert},
			},
		},
	}

	// Request /hello via the created HTTPS client over port 8443 via GET
	r, err := client.Get("https://localhost:8443/hello")
	if err != nil {
		log.Fatal(err)
	}

	// Read the response body
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Fatal(err)
	}

	// Print the response body to stdout
	fmt.Printf("%s\n", body)
}

What did you expect to see?

You may expect to see a client certificate is getting exchanged for client auth verification. but it is not happening and the connection is normal TLS instead of mTLS.

What did you see instead?

A TLS handshake without client certificate verification in mTLS.
image

I have tried with other option requestClientCertificate etc but none of them worked. seems a bug.

@bcmills
Copy link
Contributor

bcmills commented Sep 20, 2023

Please fill out the complete issue template. What program did you run? What did you expect to see? What actually happened instead?

@bcmills bcmills added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Sep 20, 2023
@Manikishore-S
Copy link
Author

Manikishore-S commented Sep 20, 2023

Updated with necessary info. Thanks for pointing it out

@bcmills bcmills removed the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Sep 20, 2023
@seankhliao
Copy link
Member

this looks working as intended for TLS1.3 which encrypts everything after server hello.

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Sep 20, 2023
@Manikishore-S
Copy link
Author

Where can i see this behavior change notes/doc

@rittneje
Copy link

@Manikishore-S It is a TLS 1.3 spec point, not specific to Go. See RFC 8446.

All handshake messages after the ServerHello are now encrypted.
The newly introduced EncryptedExtensions message allows various
extensions previously sent in the clear in the ServerHello to also
enjoy confidentiality protection.

@Manikishore-S
Copy link
Author

@rittneje @seankhliao Thanks a lot!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants