summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--caddyconfig/httpcaddyfile/builtins.go67
-rw-r--r--caddyconfig/httpcaddyfile/options.go14
-rw-r--r--modules/caddytls/connpolicy.go46
3 files changed, 87 insertions, 40 deletions
diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go
index 103b7a1..7f23fd5 100644
--- a/caddyconfig/httpcaddyfile/builtins.go
+++ b/caddyconfig/httpcaddyfile/builtins.go
@@ -53,8 +53,7 @@ func init() {
// parseBind parses the bind directive. Syntax:
//
-// bind <addresses...>
-//
+// bind <addresses...>
func parseBind(h Helper) ([]ConfigValue, error) {
var lnHosts []string
for h.Next() {
@@ -65,28 +64,28 @@ func parseBind(h Helper) ([]ConfigValue, error) {
// parseTLS parses the tls directive. Syntax:
//
-// tls [<email>|internal]|[<cert_file> <key_file>] {
-// protocols <min> [<max>]
-// ciphers <cipher_suites...>
-// curves <curves...>
-// client_auth {
-// mode [request|require|verify_if_given|require_and_verify]
-// trusted_ca_cert <base64_der>
-// trusted_ca_cert_file <filename>
-// trusted_leaf_cert <base64_der>
-// trusted_leaf_cert_file <filename>
-// }
-// alpn <values...>
-// load <paths...>
-// ca <acme_ca_endpoint>
-// ca_root <pem_file>
-// dns <provider_name> [...]
-// on_demand
-// eab <key_id> <mac_key>
-// issuer <module_name> [...]
-// get_certificate <module_name> [...]
-// }
-//
+// tls [<email>|internal]|[<cert_file> <key_file>] {
+// protocols <min> [<max>]
+// ciphers <cipher_suites...>
+// curves <curves...>
+// client_auth {
+// mode [request|require|verify_if_given|require_and_verify]
+// trusted_ca_cert <base64_der>
+// trusted_ca_cert_file <filename>
+// trusted_leaf_cert <base64_der>
+// trusted_leaf_cert_file <filename>
+// }
+// alpn <values...>
+// load <paths...>
+// ca <acme_ca_endpoint>
+// ca_root <pem_file>
+// dns <provider_name> [...]
+// on_demand
+// eab <key_id> <mac_key>
+// issuer <module_name> [...]
+// get_certificate <module_name> [...]
+// insecure_secrets_log <log_file>
+// }
func parseTLS(h Helper) ([]ConfigValue, error) {
cp := new(caddytls.ConnectionPolicy)
var fileLoader caddytls.FileLoader
@@ -396,6 +395,12 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
}
onDemand = true
+ case "insecure_secrets_log":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ cp.InsecureSecretsLog = h.Val()
+
default:
return nil, h.Errf("unknown subdirective: %s", h.Val())
}
@@ -516,8 +521,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
// parseRoot parses the root directive. Syntax:
//
-// root [<matcher>] <path>
-//
+// root [<matcher>] <path>
func parseRoot(h Helper) (caddyhttp.MiddlewareHandler, error) {
var root string
for h.Next() {
@@ -695,12 +699,11 @@ func parseHandleErrors(h Helper) ([]ConfigValue, error) {
// parseLog parses the log directive. Syntax:
//
-// log {
-// output <writer_module> ...
-// format <encoder_module> ...
-// level <level>
-// }
-//
+// log {
+// output <writer_module> ...
+// format <encoder_module> ...
+// level <level>
+// }
func parseLog(h Helper) ([]ConfigValue, error) {
return parseLogHelper(h, nil)
}
diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go
index c41e8bc..1775c93 100644
--- a/caddyconfig/httpcaddyfile/options.go
+++ b/caddyconfig/httpcaddyfile/options.go
@@ -421,13 +421,13 @@ func parseOCSPStaplingOptions(d *caddyfile.Dispenser, _ any) (any, error) {
// parseLogOptions parses the global log option. Syntax:
//
-// log [name] {
-// output <writer_module> ...
-// format <encoder_module> ...
-// level <level>
-// include <namespaces...>
-// exclude <namespaces...>
-// }
+// log [name] {
+// output <writer_module> ...
+// format <encoder_module> ...
+// level <level>
+// include <namespaces...>
+// exclude <namespaces...>
+// }
//
// When the name argument is unspecified, this directive modifies the default
// logger.
diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go
index f7b9c46..bce69bc 100644
--- a/modules/caddytls/connpolicy.go
+++ b/modules/caddytls/connpolicy.go
@@ -20,11 +20,14 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
+ "io"
"os"
+ "path/filepath"
"strings"
"github.com/caddyserver/caddy/v2"
"github.com/mholt/acmez"
+ "go.uber.org/zap"
)
func init() {
@@ -156,6 +159,16 @@ type ConnectionPolicy struct {
// is no policy configured for the empty SNI value.
DefaultSNI string `json:"default_sni,omitempty"`
+ // Also known as "SSLKEYLOGFILE", TLS secrets will be written to
+ // this file in NSS key log format which can then be parsed by
+ // Wireshark and other tools. This is INSECURE as it allows other
+ // programs or tools to decrypt TLS connections. However, this
+ // capability can be useful for debugging and troubleshooting.
+ // **ENABLING THIS LOG COMPROMISES SECURITY!**
+ //
+ // This feature is EXPERIMENTAL and subject to change or removal.
+ InsecureSecretsLog string `json:"insecure_secrets_log,omitempty"`
+
// TLSConfig is the fully-formed, standard lib TLS config
// used to serve TLS connections. Provision all
// ConnectionPolicies to populate this. It is exported only
@@ -280,6 +293,30 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
}
}
+ if p.InsecureSecretsLog != "" {
+ filename, err := caddy.NewReplacer().ReplaceOrErr(p.InsecureSecretsLog, true, true)
+ if err != nil {
+ return err
+ }
+ filename, err = filepath.Abs(filename)
+ if err != nil {
+ return err
+ }
+ logFile, _, err := secretsLogPool.LoadOrNew(filename, func() (caddy.Destructor, error) {
+ w, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
+ return destructableWriter{w}, err
+ })
+ if err != nil {
+ return err
+ }
+ ctx.OnCancel(func() { _, _ = secretsLogPool.Delete(filename) })
+
+ cfg.KeyLogWriter = logFile.(io.Writer)
+
+ tlsApp.logger.Warn("TLS SECURITY COMPROMISED: secrets logging is enabled!",
+ zap.String("log_filename", filename))
+ }
+
setDefaultTLSParams(cfg)
p.TLSConfig = cfg
@@ -297,7 +334,8 @@ func (p ConnectionPolicy) SettingsEmpty() bool {
p.ProtocolMin == "" &&
p.ProtocolMax == "" &&
p.ClientAuthentication == nil &&
- p.DefaultSNI == ""
+ p.DefaultSNI == "" &&
+ p.InsecureSecretsLog == ""
}
// ClientAuthentication configures TLS client auth.
@@ -542,3 +580,9 @@ type ClientCertificateVerifier interface {
}
var defaultALPN = []string{"h2", "http/1.1"}
+
+type destructableWriter struct{ *os.File }
+
+func (d destructableWriter) Destruct() error { return d.Close() }
+
+var secretsLogPool = caddy.NewUsagePool()