Commit ca34a3e1 authored by David Somers's avatar David Somers Committed by Matt Holt

httpserver: Placeholders for tls_protocol and tls_cipher (#2062)

Also add SSL_PROTOCOL and SSL_CIPHER env vars for fastcgi.

* Implement placeholders for ssl_protocol and ssl_cipher

* gofmt

* goimports

* Housekeeping and implement as {tls_protocol} and {tls_cipher}
parent 3ee6d306
...@@ -33,8 +33,11 @@ import ( ...@@ -33,8 +33,11 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"crypto/tls"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/httpserver"
"github.com/mholt/caddy/caddytls"
) )
// Handler is a middleware type that can handle requests as a FastCGI client. // Handler is a middleware type that can handle requests as a FastCGI client.
...@@ -323,6 +326,19 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string] ...@@ -323,6 +326,19 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
// Some web apps rely on knowing HTTPS or not // Some web apps rely on knowing HTTPS or not
if r.TLS != nil { if r.TLS != nil {
env["HTTPS"] = "on" env["HTTPS"] = "on"
// and pass the protocol details in a manner compatible with apache's mod_ssl
// (which is why they have a SSL_ prefix and not TLS_).
v, ok := tlsProtocolStringToMap[r.TLS.Version]
if ok {
env["SSL_PROTOCOL"] = v
}
// and pass the cipher suite in a manner compatible with apache's mod_ssl
for k, v := range caddytls.SupportedCiphersMap {
if v == r.TLS.CipherSuite {
env["SSL_CIPHER"] = k
break
}
}
} }
// Add env variables from config (with support for placeholders in values) // Add env variables from config (with support for placeholders in values)
...@@ -465,3 +481,11 @@ type LogError string ...@@ -465,3 +481,11 @@ type LogError string
func (l LogError) Error() string { func (l LogError) Error() string {
return string(l) return string(l)
} }
// Map of supported protocols to Apache ssl_mod format
// Note that these are slightly different from SupportedProtocols in caddytls/config.go's
var tlsProtocolStringToMap = map[uint16]string{
tls.VersionTLS10: "TLSv1",
tls.VersionTLS11: "TLSv1.1",
tls.VersionTLS12: "TLSv1.2",
}
...@@ -29,6 +29,7 @@ import ( ...@@ -29,6 +29,7 @@ import (
"time" "time"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/caddytls"
) )
// requestReplacer is a strings.Replacer which is used to // requestReplacer is a strings.Replacer which is used to
...@@ -375,6 +376,26 @@ func (r *replacer) getSubstitution(key string) string { ...@@ -375,6 +376,26 @@ func (r *replacer) getSubstitution(key string) string {
} }
elapsedDuration := time.Since(r.responseRecorder.start) elapsedDuration := time.Since(r.responseRecorder.start)
return strconv.FormatInt(convertToMilliseconds(elapsedDuration), 10) return strconv.FormatInt(convertToMilliseconds(elapsedDuration), 10)
case "{tls_protocol}":
if r.request.TLS != nil {
for k, v := range caddytls.SupportedProtocols {
if v == r.request.TLS.Version {
return k
}
}
return "tls" // this should never happen, but guard in case
}
return r.emptyValue // because not using a secure channel
case "{tls_cipher}":
if r.request.TLS != nil {
for k, v := range caddytls.SupportedCiphersMap {
if v == r.request.TLS.CipherSuite {
return k
}
}
return "UNKNOWN" // this should never happen, but guard in case
}
return r.emptyValue
} }
return r.emptyValue return r.emptyValue
......
...@@ -532,7 +532,8 @@ var supportedKeyTypes = map[string]acme.KeyType{ ...@@ -532,7 +532,8 @@ var supportedKeyTypes = map[string]acme.KeyType{
// Map of supported protocols. // Map of supported protocols.
// HTTP/2 only supports TLS 1.2 and higher. // HTTP/2 only supports TLS 1.2 and higher.
var supportedProtocols = map[string]uint16{ // If updating this map, also update tlsProtocolStringToMap in caddyhttp/fastcgi/fastcgi.go
var SupportedProtocols = map[string]uint16{
"tls1.0": tls.VersionTLS10, "tls1.0": tls.VersionTLS10,
"tls1.1": tls.VersionTLS11, "tls1.1": tls.VersionTLS11,
"tls1.2": tls.VersionTLS12, "tls1.2": tls.VersionTLS12,
...@@ -548,7 +549,7 @@ var supportedProtocols = map[string]uint16{ ...@@ -548,7 +549,7 @@ var supportedProtocols = map[string]uint16{
// it is always added (even though it is not technically a cipher suite). // it is always added (even though it is not technically a cipher suite).
// //
// This map, like any map, is NOT ORDERED. Do not range over this map. // This map, like any map, is NOT ORDERED. Do not range over this map.
var supportedCiphersMap = map[string]uint16{ var SupportedCiphersMap = map[string]uint16{
"ECDHE-ECDSA-AES256-GCM-SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "ECDHE-ECDSA-AES256-GCM-SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
"ECDHE-RSA-AES256-GCM-SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "ECDHE-RSA-AES256-GCM-SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
"ECDHE-ECDSA-AES128-GCM-SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "ECDHE-ECDSA-AES128-GCM-SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
......
...@@ -106,19 +106,19 @@ func setupTLS(c *caddy.Controller) error { ...@@ -106,19 +106,19 @@ func setupTLS(c *caddy.Controller) error {
case "protocols": case "protocols":
args := c.RemainingArgs() args := c.RemainingArgs()
if len(args) == 1 { if len(args) == 1 {
value, ok := supportedProtocols[strings.ToLower(args[0])] value, ok := SupportedProtocols[strings.ToLower(args[0])]
if !ok { if !ok {
return c.Errf("Wrong protocol name or protocol not supported: '%s'", args[0]) return c.Errf("Wrong protocol name or protocol not supported: '%s'", args[0])
} }
config.ProtocolMinVersion, config.ProtocolMaxVersion = value, value config.ProtocolMinVersion, config.ProtocolMaxVersion = value, value
} else { } else {
value, ok := supportedProtocols[strings.ToLower(args[0])] value, ok := SupportedProtocols[strings.ToLower(args[0])]
if !ok { if !ok {
return c.Errf("Wrong protocol name or protocol not supported: '%s'", args[0]) return c.Errf("Wrong protocol name or protocol not supported: '%s'", args[0])
} }
config.ProtocolMinVersion = value config.ProtocolMinVersion = value
value, ok = supportedProtocols[strings.ToLower(args[1])] value, ok = SupportedProtocols[strings.ToLower(args[1])]
if !ok { if !ok {
return c.Errf("Wrong protocol name or protocol not supported: '%s'", args[1]) return c.Errf("Wrong protocol name or protocol not supported: '%s'", args[1])
} }
...@@ -129,7 +129,7 @@ func setupTLS(c *caddy.Controller) error { ...@@ -129,7 +129,7 @@ func setupTLS(c *caddy.Controller) error {
} }
case "ciphers": case "ciphers":
for c.NextArg() { for c.NextArg() {
value, ok := supportedCiphersMap[strings.ToUpper(c.Val())] value, ok := SupportedCiphersMap[strings.ToUpper(c.Val())]
if !ok { if !ok {
return c.Errf("Wrong cipher name or cipher not supported: '%s'", c.Val()) return c.Errf("Wrong cipher name or cipher not supported: '%s'", c.Val())
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment