-/*
-godlighty -- highly-customizable HTTP, HTTP/2, HTTPS server
-Copyright (C) 2021-2022 Sergey Matveev <stargrave@stargrave.org>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+// godlighty -- highly-customizable HTTP, HTTP/2, HTTPS server
+// Copyright (C) 2021-2024 Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
package godlighty
"encoding/pem"
"errors"
"fmt"
- "io/ioutil"
"log"
+ "os"
)
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]
+ var cert *tls.Certificate
+ if len(HostToECDSACertificate) == 0 {
+ cert = HostToEdDSACertificate[chi.ServerName]
+ } else {
+ 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")
}
if CHIHasGOST(chi) {
pool = HostGOSTClientAuth[chi.ServerName]
}
+ if pool == nil && (CHIHasEdDSA(chi) || len(HostECDSAClientAuth) == 0) {
+ pool = HostEdDSAClientAuth[chi.ServerName]
+ }
if pool == nil {
- pool = HostClientAuth[chi.ServerName]
+ pool = HostECDSAClientAuth[chi.ServerName]
}
if pool == nil {
return nil, nil
log.Fatalln(err)
}
if cfg.CACert != "" {
- data, err := ioutil.ReadFile(cfg.CACert)
+ data, err := os.ReadFile(cfg.CACert)
if err != nil {
log.Fatalln(err)
}
(*hostToCertificate)[host] = &cert
pool := x509.NewCertPool()
for _, p := range cfg.ClientCAs {
- data, err := ioutil.ReadFile(p)
+ data, err := os.ReadFile(p)
if err != nil {
log.Fatalln(err)
}
log.Fatalln(err)
}
pool.AddCert(ca)
+ (*hostClientAuth)[host] = pool
}
}
- if len(pool.Subjects()) > 0 {
- (*hostClientAuth)[host] = pool
- }
}
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)
}
}
func NewTLSConfig() *tls.Config {
return &tls.Config{
+ MinVersion: tls.VersionTLS12,
NextProtos: NextProtos,
GetCertificate: GetCertificate,
GetConfigForClient: GetConfigForClient,