aboutsummaryrefslogtreecommitdiff
path: root/cert.go
diff options
context:
space:
mode:
authorAdnan Maolood <[email protected]>2020-10-28 13:40:25 -0400
committerAdnan Maolood <[email protected]>2020-10-28 13:41:24 -0400
commitfbd97a62dec02ad22b7cf520cfc6ab519ea0e990 (patch)
tree8a19117713cddce2d3ed2d31c24bec59fe616a48 /cert.go
parentAdd ErrInputRequired and ErrCertificateRequired (diff)
downloadgo-gemini-fbd97a62dec02ad22b7cf520cfc6ab519ea0e990.tar.xz
go-gemini-fbd97a62dec02ad22b7cf520cfc6ab519ea0e990.zip
Refactor client certificates
Diffstat (limited to 'cert.go')
-rw-r--r--cert.go75
1 files changed, 31 insertions, 44 deletions
diff --git a/cert.go b/cert.go
index da77478..6ecf119 100644
--- a/cert.go
+++ b/cert.go
@@ -20,9 +20,9 @@ type CertificateStore struct {
store map[string]tls.Certificate
}
-// Add adds a certificate for the given hostname to the store.
+// Add adds a certificate for the given scope to the store.
// It tries to parse the certificate if it is not already parsed.
-func (c *CertificateStore) Add(hostname string, cert tls.Certificate) {
+func (c *CertificateStore) Add(scope string, cert tls.Certificate) {
if c.store == nil {
c.store = map[string]tls.Certificate{}
}
@@ -33,7 +33,7 @@ func (c *CertificateStore) Add(hostname string, cert tls.Certificate) {
cert.Leaf = parsed
}
}
- c.store[hostname] = cert
+ c.store[scope] = cert
}
// Lookup returns the certificate for the given hostname.
@@ -49,6 +49,22 @@ func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
return &cert, nil
}
+// lookup returns the certificate for the given hostname + path.
+func (c *CertificateStore) lookup(scope string) (*tls.Certificate, error) {
+ for {
+ cert, err := c.Lookup(scope)
+ switch err {
+ case ErrCertificateExpired, nil:
+ return cert, err
+ }
+ scope = path.Dir(scope)
+ if scope == "." {
+ break
+ }
+ }
+ return nil, ErrCertificateUnknown
+}
+
// Load loads certificates from the given path.
// The path should lead to a directory containing certificates and private keys
// in the form hostname.crt and hostname.key.
@@ -71,36 +87,16 @@ func (c *CertificateStore) Load(path string) error {
return nil
}
-type ClientCertificateStore struct {
- CertificateStore
+// CertificateOptions configures how a certificate is created.
+type CertificateOptions struct {
+ IPAddresses []net.IP
+ DNSNames []string
+ Duration time.Duration
}
-func (c *ClientCertificateStore) Lookup(hostname, urlPath string) (*tls.Certificate, error) {
- urlPath = path.Clean(urlPath)
- if urlPath == "." {
- urlPath = "/"
- }
- if urlPath[0] != '/' {
- urlPath = "/" + urlPath
- }
- for {
- cert, err := c.CertificateStore.Lookup(hostname + urlPath)
- switch err {
- case ErrCertificateExpired, nil:
- return cert, err
- }
- slash := urlPath == "/"
- urlPath = path.Dir(urlPath)
- if slash && urlPath == "/" {
- break
- }
- }
- return nil, ErrCertificateUnknown
-}
-
-// NewCertificate creates and returns a new parsed certificate.
-func NewCertificate(host string, duration time.Duration) (tls.Certificate, error) {
- crt, priv, err := newX509KeyPair(host, duration)
+// CreateCertificate creates a new TLS certificate.
+func CreateCertificate(options CertificateOptions) (tls.Certificate, error) {
+ crt, priv, err := newX509KeyPair(options)
if err != nil {
return tls.Certificate{}, err
}
@@ -112,7 +108,7 @@ func NewCertificate(host string, duration time.Duration) (tls.Certificate, error
}
// newX509KeyPair creates and returns a new certificate and private key.
-func newX509KeyPair(host string, duration time.Duration) (*x509.Certificate, crypto.PrivateKey, error) {
+func newX509KeyPair(options CertificateOptions) (*x509.Certificate, crypto.PrivateKey, error) {
// Generate an ED25519 private key
_, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
@@ -131,7 +127,7 @@ func newX509KeyPair(host string, duration time.Duration) (*x509.Certificate, cry
}
notBefore := time.Now()
- notAfter := notBefore.Add(duration)
+ notAfter := notBefore.Add(options.Duration)
template := x509.Certificate{
SerialNumber: serialNumber,
@@ -140,17 +136,8 @@ func newX509KeyPair(host string, duration time.Duration) (*x509.Certificate, cry
KeyUsage: keyUsage,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
- }
-
- if host != "" {
- hosts := strings.Split(host, ",")
- for _, h := range hosts {
- if ip := net.ParseIP(h); ip != nil {
- template.IPAddresses = append(template.IPAddresses, ip)
- } else {
- template.DNSNames = append(template.DNSNames, h)
- }
- }
+ IPAddresses: options.IPAddresses,
+ DNSNames: options.DNSNames,
}
crt, err := x509.CreateCertificate(rand.Reader, &template, &template, public, priv)