aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/caddyhttp/replacer.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/caddyhttp/replacer.go')
-rw-r--r--modules/caddyhttp/replacer.go30
1 files changed, 30 insertions, 0 deletions
diff --git a/modules/caddyhttp/replacer.go b/modules/caddyhttp/replacer.go
index 670b2e3ea..37b53d273 100644
--- a/modules/caddyhttp/replacer.go
+++ b/modules/caddyhttp/replacer.go
@@ -16,9 +16,14 @@ package caddyhttp
import (
"context"
+ "crypto/ecdsa"
+ "crypto/ed25519"
+ "crypto/elliptic"
+ "crypto/rsa"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
+ "encoding/asn1"
"fmt"
"net"
"net/http"
@@ -243,6 +248,18 @@ func getReqTLSReplacement(req *http.Request, key string) (interface{}, bool) {
switch field {
case "client.fingerprint":
return fmt.Sprintf("%x", sha256.Sum256(cert.Raw)), true
+ case "client.public_key", "client.public_key_sha256":
+ if cert.PublicKey == nil {
+ return nil, true
+ }
+ pubKeyBytes, err := marshalPublicKey(cert.PublicKey)
+ if err != nil {
+ return nil, true
+ }
+ if strings.HasSuffix(field, "_sha256") {
+ return fmt.Sprintf("%x", sha256.Sum256(pubKeyBytes)), true
+ }
+ return fmt.Sprintf("%x", pubKeyBytes), true
case "client.issuer":
return cert.Issuer, true
case "client.serial":
@@ -271,6 +288,19 @@ func getReqTLSReplacement(req *http.Request, key string) (interface{}, bool) {
return nil, false
}
+// marshalPublicKey returns the byte encoding of pubKey.
+func marshalPublicKey(pubKey interface{}) ([]byte, error) {
+ switch key := pubKey.(type) {
+ case *rsa.PublicKey:
+ return asn1.Marshal(key)
+ case *ecdsa.PublicKey:
+ return elliptic.Marshal(key.Curve, key.X, key.Y), nil
+ case ed25519.PublicKey:
+ return key, nil
+ }
+ return nil, fmt.Errorf("unrecognized public key type: %T", pubKey)
+}
+
// getTLSPeerCert retrieves the first peer certificate from a TLS session.
// Returns nil if no peer cert is in use.
func getTLSPeerCert(cs *tls.ConnectionState) *x509.Certificate {