1
0
Fork 0
molly-brown/certificate.go
Solderpunk eb85a6e94c Another big refactor, splitting the Config struct in two.
The split reflects that between variables which can and cannot be
overridden by .molly files, and this greatly simplifies the
processing of said files, getting rid of the need for lots of
ugly temporary variable thrashing.
2023-02-25 11:29:13 +01:00

63 lines
1.6 KiB
Go

package main
import (
"crypto/sha256"
"crypto/x509"
"encoding/hex"
"net"
"net/url"
"regexp"
"time"
)
func enforceCertificateValidity(clientCerts []*x509.Certificate, conn net.Conn, logEntry *LogEntry) {
// This will fail if any of multiple certs are invalid
// Maybe we should just require one valid?
now := time.Now()
for _, cert := range clientCerts {
if now.Before(cert.NotBefore) {
conn.Write([]byte("64 Client certificate not yet valid!\r\n"))
logEntry.Status = 64
return
} else if now.After(cert.NotAfter) {
conn.Write([]byte("65 Client certificate has expired!\r\n"))
logEntry.Status = 65
return
}
}
}
func handleCertificateZones(URL *url.URL, clientCerts []*x509.Certificate, config UserConfig, conn net.Conn, logEntry *LogEntry) {
authorised := true
for zone, allowedFingerprints := range config.CertificateZones {
matched, err := regexp.Match(zone, []byte(URL.Path))
if !matched || err != nil {
continue
}
authorised = false
for _, clientCert := range clientCerts {
for _, allowedFingerprint := range allowedFingerprints {
if getCertFingerprint(clientCert) == allowedFingerprint {
authorised = true
break
}
}
}
}
if !authorised {
if len(clientCerts) > 0 {
conn.Write([]byte("61 Provided certificate not authorised for this resource\r\n"))
logEntry.Status = 61
} else {
conn.Write([]byte("60 A pre-authorised certificate is required to access this resource\r\n"))
logEntry.Status = 60
}
return
}
}
func getCertFingerprint(cert *x509.Certificate) string {
hash := sha256.Sum256(cert.Raw)
fingerprint := hex.EncodeToString(hash[:])
return fingerprint
}