From e057b4615b830e49508b76f722f1461755aafdda Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 7 Dec 2022 17:37:13 +0300 Subject: [PATCH] Simultaneous ECDSA and EdDSA support --- cfg.go | 15 ++++---- doc/cfg.texi | 2 +- godlighty.go | 2 +- handler.go | 4 ++- rc/example.cfg/git.go | 6 ++-- rc/example.cfg/go.go | 8 ++--- rc/example.cfg/lists.cypherpunks.ru.go | 4 +-- rc/example.cfg/static.go | 4 +-- tls.go | 49 ++++++++++++++++++++++---- tls_gost.go | 9 +---- 10 files changed, 67 insertions(+), 36 deletions(-) diff --git a/cfg.go b/cfg.go index b1e274b..96811b4 100644 --- a/cfg.go +++ b/cfg.go @@ -38,13 +38,14 @@ type AuthCfg struct { type Hook func(http.ResponseWriter, *http.Request) bool type HostCfg struct { - Root string - TLS *TLSCfg - GOSTTLS *TLSCfg - DirList bool - WebDAV bool - Hooks []Hook - Auth *AuthCfg + Root string + ECDSATLS *TLSCfg + EdDSATLS *TLSCfg + GOSTTLS *TLSCfg + DirList bool + WebDAV bool + Hooks []Hook + Auth *AuthCfg Indices []string Readmes []string diff --git a/doc/cfg.texi b/doc/cfg.texi index 79b3d05..530502d 100644 --- a/doc/cfg.texi +++ b/doc/cfg.texi @@ -9,7 +9,7 @@ Also look for @file{rc/example.cfg}. @verbatim Hosts["example.com"] = &godlighty.HostCfg{ Root: "/www/example.com", - TLS: &godlighty.TLSCfg{ + EdDSATLS: &godlighty.TLSCfg{ Cert: "/path/to/example.com.pem", Key: "/path/to/example.com.key.pem", CACert: "/path/to/ca.pem", diff --git a/godlighty.go b/godlighty.go index 42ca132..213cd3a 100644 --- a/godlighty.go +++ b/godlighty.go @@ -1,6 +1,6 @@ // Highly-customizable HTTP, HTTP/2, HTTPS server package godlighty -const Version = "godlighty/0.3.0" +const Version = "godlighty/0.4.0" var BindAddr string diff --git a/handler.go b/handler.go index a8a9e31..6da3989 100644 --- a/handler.go +++ b/handler.go @@ -119,7 +119,9 @@ func (h Handler) Handle( return } - if cfg.TLS != nil && len(cfg.TLS.ClientCAs) > 0 { + if (cfg.ECDSATLS != nil && len(cfg.ECDSATLS.ClientCAs) > 0) || + (cfg.EdDSATLS != nil && len(cfg.EdDSATLS.ClientCAs) > 0) || + (cfg.GOSTTLS != nil && len(cfg.GOSTTLS.ClientCAs) > 0) { if r.TLS == nil { err = errors.New("TLS client authentication required") printErr(http.StatusForbidden, err) diff --git a/rc/example.cfg/git.go b/rc/example.cfg/git.go index 5803850..f15bdea 100644 --- a/rc/example.cfg/git.go +++ b/rc/example.cfg/git.go @@ -12,7 +12,7 @@ import ( func addGitRepoCfg(host, root, gitwebCfg string) { godlighty.Hosts[host] = &godlighty.HostCfg{ - TLS: newTLSCfg(host), + EdDSATLS: newTLSCfg(host), Hooks: []godlighty.Hook{ func(w http.ResponseWriter, r *http.Request) bool { if r.URL.Path == "/" { @@ -36,8 +36,8 @@ func addGitRepoCfg(host, root, gitwebCfg string) { } host = "www." + host godlighty.Hosts[host] = &godlighty.HostCfg{ - Root: "/usr/local/share/gitweb", - TLS: newTLSCfg(host), + Root: "/usr/local/share/gitweb", + EdDSATLS: newTLSCfg(host), Hooks: []godlighty.Hook{ func(w http.ResponseWriter, r *http.Request) bool { if r.URL.Path == "/" { diff --git a/rc/example.cfg/go.go b/rc/example.cfg/go.go index 845dfcc..e2e6bdd 100644 --- a/rc/example.cfg/go.go +++ b/rc/example.cfg/go.go @@ -8,10 +8,10 @@ import ( func addGoRepoCfg(host string) { godlighty.Hosts[host] = &godlighty.HostCfg{ - Root: path.Join(WWW, host), - TLS: newTLSCfg(host), - MIMEs: map[string]string{"": "text/html"}, - Indices: []string{"v1"}, + Root: path.Join(WWW, host), + EdDSATLS: newTLSCfg(host), + MIMEs: map[string]string{"": "text/html"}, + Indices: []string{"v1"}, } } diff --git a/rc/example.cfg/lists.cypherpunks.ru.go b/rc/example.cfg/lists.cypherpunks.ru.go index 66322c0..f10e4bd 100644 --- a/rc/example.cfg/lists.cypherpunks.ru.go +++ b/rc/example.cfg/lists.cypherpunks.ru.go @@ -12,8 +12,8 @@ import ( func init() { host := "lists.cypherpunks.ru" godlighty.Hosts[host] = &godlighty.HostCfg{ - Root: path.Join(WWW, host), - TLS: newTLSCfg(host), + Root: path.Join(WWW, host), + EdDSATLS: newTLSCfg(host), Hooks: []godlighty.Hook{ func(w http.ResponseWriter, r *http.Request) bool { if strings.HasPrefix(r.URL.Path, "/archive/") { diff --git a/rc/example.cfg/static.go b/rc/example.cfg/static.go index fc56013..a28bf77 100644 --- a/rc/example.cfg/static.go +++ b/rc/example.cfg/static.go @@ -13,8 +13,8 @@ func addStaticCfg(host, root string) { root = path.Join(WWW, root) } godlighty.Hosts[host] = &godlighty.HostCfg{ - Root: root, - TLS: newTLSCfg(host), + Root: root, + EdDSATLS: newTLSCfg(host), } } diff --git a/tls.go b/tls.go index 40395f0..51470f3 100644 --- a/tls.go +++ b/tls.go @@ -30,20 +30,49 @@ import ( var ( NextProtos = []string{"h2", "http/1.1"} - HostToCertificate map[string]*tls.Certificate - HostClientAuth map[string]*x509.CertPool + HostToECDSACertificate map[string]*tls.Certificate + HostECDSAClientAuth map[string]*x509.CertPool + + HostToEdDSACertificate map[string]*tls.Certificate + HostEdDSAClientAuth map[string]*x509.CertPool HostToGOSTCertificate map[string]*tls.Certificate HostGOSTClientAuth map[string]*x509.CertPool ) +func CHIHasTLS13(chi *tls.ClientHelloInfo) bool { + for _, v := range chi.SupportedVersions { + if v == tls.VersionTLS13 { + return true + } + } + return false +} + +func CHIHasEdDSA(chi *tls.ClientHelloInfo) bool { + if !CHIHasTLS13(chi) { + return false + } + for _, ss := range chi.SignatureSchemes { + if ss == tls.Ed25519 { + return true + } + } + return false +} + func GetCertificate(chi *tls.ClientHelloInfo) (*tls.Certificate, error) { if CHIHasGOST(chi) { if cert := HostToGOSTCertificate[chi.ServerName]; cert != nil { return cert, nil } } - cert := HostToCertificate[chi.ServerName] + if CHIHasEdDSA(chi) { + if cert := HostToEdDSACertificate[chi.ServerName]; cert != nil { + return cert, nil + } + } + cert := HostToECDSACertificate[chi.ServerName] if cert == nil { return nil, errors.New("no certificate found") } @@ -55,8 +84,11 @@ func GetConfigForClient(chi *tls.ClientHelloInfo) (*tls.Config, error) { if CHIHasGOST(chi) { pool = HostGOSTClientAuth[chi.ServerName] } + if pool == nil && CHIHasEdDSA(chi) { + pool = HostEdDSAClientAuth[chi.ServerName] + } if pool == nil { - pool = HostClientAuth[chi.ServerName] + pool = HostECDSAClientAuth[chi.ServerName] } if pool == nil { return nil, nil @@ -125,12 +157,15 @@ func loadCertificates( } func LoadCertificates() { - HostToCertificate = make(map[string]*tls.Certificate, len(Hosts)) - HostClientAuth = make(map[string]*x509.CertPool) + HostToECDSACertificate = make(map[string]*tls.Certificate, len(Hosts)) + HostECDSAClientAuth = make(map[string]*x509.CertPool) + HostToEdDSACertificate = make(map[string]*tls.Certificate, len(Hosts)) + HostEdDSAClientAuth = make(map[string]*x509.CertPool) HostToGOSTCertificate = make(map[string]*tls.Certificate, len(Hosts)) HostGOSTClientAuth = make(map[string]*x509.CertPool) for host, cfg := range Hosts { - loadCertificates(host, cfg.TLS, &HostToCertificate, &HostClientAuth) + loadCertificates(host, cfg.ECDSATLS, &HostToECDSACertificate, &HostECDSAClientAuth) + loadCertificates(host, cfg.EdDSATLS, &HostToEdDSACertificate, &HostEdDSAClientAuth) loadCertificates(host, cfg.GOSTTLS, &HostToGOSTCertificate, &HostGOSTClientAuth) } } diff --git a/tls_gost.go b/tls_gost.go index 6500443..0acb778 100644 --- a/tls_gost.go +++ b/tls_gost.go @@ -6,14 +6,7 @@ package godlighty import "crypto/tls" func CHIHasGOST(chi *tls.ClientHelloInfo) bool { - tls13Found := false - for _, v := range chi.SupportedVersions { - if v == tls.VersionTLS13 { - tls13Found = true - break - } - } - if !tls13Found { + if !CHIHasTLS13(chi) { return false } for _, ss := range chi.SignatureSchemes { -- 2.44.0