Description
What version of Go are you using (go version
)?
$ go version go version go1.14.5 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/felix/Library/Caches/go-build" GOENV="/Users/felix/Library/Application Support/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOINSECURE="" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/felix/workspace/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/Cellar/go/1.14.5/libexec" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.14.5/libexec/pkg/tool/darwin_amd64" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/felix/workspace/tests/go-tls-pha/go.mod" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/gr/j517787d56s73w50gnpv08gr0000gn/T/go-build528430427=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
I use the Go TLS client to implement a client for an endpoint that requires authentication with client certificates. The endpoint decides if client authentication is needed based on the path in the HTTP request. Therefore, the server can only decide if client authentication is needed after the TLS connection has been fully set up.
With TLS 1.3, the server would achieve the authentication with client certificates using post-handshake authentication. However, the Go TLS client does not support post-handshake authentication.
For reproduction of the issue, one can use the Apache httpd (I tested with version 2.4) with the config including the snippet below and a small go program like the one below.
httpd.conf snippet
<VirtualHost *:443>
LogLevel debug
SSLEngine on
SSLCertificateFile /usr/local/apache2/conf/server.crt
SSLCertificateKeyFile /usr/local/apache2/conf/server.key
SSLVerifyClient none
SSLCACertificateFile /usr/local/apache2/conf/ca.crt
<Location "/test-cert.html">
SSLVerifyClient require
SSLVerifyDepth 1
</Location>
</VirtualHost>
client.go
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"time"
"go.etcd.io/etcd/pkg/transport"
)
func main() {
f, err := os.Create("./tls.keylog")
if err != nil {
log.Fatal(err)
}
defer f.Close()
tlsInfo := transport.TLSInfo{
TrustedCAFile: "./ca.crt",
CertFile: "./client.crt",
KeyFile: "./client.key",
}
tlsTransport, err := transport.NewTransport(tlsInfo, 30*time.Second)
if err != nil {
log.Fatal(err)
}
tlsTransport.TLSClientConfig.KeyLogWriter = f
client := &http.Client{
Transport: tlsTransport,
}
r, err := client.Get("https://localhost/test-cert.html")
if err != nil {
log.Fatal(err)
}
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", body)
}
What did you expect to see?
I would have expected the TLS client to support TLS 1.3 post-handshake authentication and be able to connect to the endpoint.
What did you see instead?
The server closes the connection to the client as soon as it encounters that a client certificate would be required for a specific route. In the httpd logs this error can be found:
[ssl:debug] [pid 7:tid 139688389797632] ssl_engine_kernel.c(1148): [client 172.17.0.1:35172] AH10129: verify client post handshake
[ssl:error] [pid 7:tid 139688389797632] [client 172.17.0.1:35172] AH10158: cannot perform post-handshake authentication
[ssl:error] [pid 7:tid 139688389797632] SSL Library Error: error:14268117:SSL routines:SSL_verify_client_post_handshake:extension not received
172.17.0.1 - - [31/Jul/2020:19:40:50 +0000] "GET /test-cert.html HTTP/1.1" 403 258
This happens because the TLS client does not indicate support for post-handshake authentication in the ClientHello (which is actually correct, as it is not supported right now).
After looking at the TLS 1.3 client implementation, I think adding post-handshake authentication support for the TLS 1.3 client should be possible and I would be happy to help with this.
Metadata
Metadata
Assignees
Type
Projects
Status