From 207e7c4030e6402b16ba0fa1e2ae81f32562a40a Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Tue, 15 Dec 2020 14:02:25 -0800 Subject: [PATCH] Include client certificate hashes in FastCGI requests --- CONFIGURATION.md | 7 +++++-- go.mod | 2 +- go.sum | 4 ++-- serve_fcgi.go | 12 ++++++++++-- server.go | 5 +++-- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 95bbab4..56ea1f9 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -129,9 +129,12 @@ for more information. ##### FastCGI Forward requests to [FastCGI](https://en.wikipedia.org/wiki/FastCGI) server at -specified address or path. +specified address or path. A `Root` attribute must also be specified. -A `Root` attribute must also be specified. +When a client certificate is provided with a request, the SHA-1 hash of the +first certificate is available as `$_SERVER['CLIENT_CERT_A']`. If a second +certificate is provided, it is available as `$_SERVER['CLIENT_CERT_B']`, and so +on. Connect via Unix socket: diff --git a/go.mod b/go.mod index a0723b3..f042825 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,6 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/yookoala/gofast v0.4.1-0.20201013050739-975113c54107 gitlab.com/tslocum/gmitohtml v1.0.3-0.20201203184239-2a1abe8efe7c - golang.org/x/tools v0.0.0-20201206230334-368bee879bfd // indirect + golang.org/x/tools v0.0.0-20201215192005-fa10ef0b8743 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 ) diff --git a/go.sum b/go.sum index 9063a6e..3d15cf8 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200908211811-12e1bf57a112/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201206230334-368bee879bfd h1:EqFvKLTxjH6gEy2baWxX2AgJwZkBIDIcZFYcoYlI9RA= -golang.org/x/tools v0.0.0-20201206230334-368bee879bfd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201215192005-fa10ef0b8743 h1:SLHKXsC4wI4NdEGVGe/yxcTBkF/mPUS7agW3Qt5smVg= +golang.org/x/tools v0.0.0-20201215192005-fa10ef0b8743/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/serve_fcgi.go b/serve_fcgi.go index 3e52062..90a9e4c 100644 --- a/serve_fcgi.go +++ b/serve_fcgi.go @@ -2,10 +2,12 @@ package main import ( "bytes" + "crypto/sha1" + "crypto/tls" + "fmt" "io" "io/ioutil" "log" - "net" "net/http" "net/url" "path/filepath" @@ -34,7 +36,7 @@ func (w *fakeResponseWriter) WriteHeader(statusCode int) { // Do nothing } -func serveFastCGI(c net.Conn, connFactory gofast.ConnFactory, u *url.URL, filePath string) { +func serveFastCGI(c *tls.Conn, connFactory gofast.ConnFactory, u *url.URL, filePath string) { header := map[string][]string{ "Accept": {"*/*"}, "Host": {u.Hostname()}, @@ -73,6 +75,12 @@ func serveFastCGI(c net.Conn, connFactory gofast.ConnFactory, u *url.URL, filePa req.Params["SCRIPT_FILENAME"] = filePath req.Params["SCRIPT_NAME"] = filepath.Base(filePath) + certLabel := 'A' + clientCerts := c.ConnectionState().PeerCertificates + for i := 0; i < len(clientCerts) && i < 26; i++ { + req.Params["CLIENT_CERT_"+string(certLabel+rune(i))] = fmt.Sprintf("%x", sha1.Sum(clientCerts[i].Raw)) + } + w := newFakeResponseWriter(c) client, err := gofast.SimpleClientFactory(connFactory, 0)() diff --git a/server.go b/server.go index 7afdd54..5067c98 100644 --- a/server.go +++ b/server.go @@ -491,8 +491,9 @@ func getCertificate(info *tls.ClientHelloInfo) (*tls.Certificate, error) { func listen(address string) { tlsConfig := &tls.Config{ - ClientAuth: tls.RequestClientCert, - GetCertificate: getCertificate, + ClientAuth: tls.RequestClientCert, + GetCertificate: getCertificate, + InsecureSkipVerify: true, } listener, err := tls.Listen("tcp", address, tlsConfig)