aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdnan Maolood <[email protected]>2020-10-28 16:02:04 -0400
committerAdnan Maolood <[email protected]>2020-10-28 16:02:04 -0400
commitb5fbd197a15e6991552c48f401206ead0501b52d (patch)
tree5f69fc679f8eee9a92dcd6ca11b2651024609a9f
parentUse strings.Builder in Fingerprint (diff)
downloadgo-gemini-b5fbd197a15e6991552c48f401206ead0501b52d.tar.xz
go-gemini-b5fbd197a15e6991552c48f401206ead0501b52d.zip
Update documentation
-rw-r--r--cert.go29
-rw-r--r--client.go22
-rw-r--r--doc.go24
-rw-r--r--server.go9
4 files changed, 38 insertions, 46 deletions
diff --git a/cert.go b/cert.go
index 6ecf119..7c151f6 100644
--- a/cert.go
+++ b/cert.go
@@ -8,7 +8,6 @@ import (
"crypto/x509"
"math/big"
"net"
- "path"
"path/filepath"
"strings"
"time"
@@ -36,9 +35,9 @@ func (c *CertificateStore) Add(scope string, cert tls.Certificate) {
c.store[scope] = cert
}
-// Lookup returns the certificate for the given hostname.
-func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
- cert, ok := c.store[hostname]
+// Lookup returns the certificate for the given scope.
+func (c *CertificateStore) Lookup(scope string) (*tls.Certificate, error) {
+ cert, ok := c.store[scope]
if !ok {
return nil, ErrCertificateUnknown
}
@@ -49,25 +48,9 @@ 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.
+// in the form scope.crt and scope.key.
// For example, the hostname "localhost" would have the corresponding files
// localhost.crt (certificate) and localhost.key (private key).
func (c *CertificateStore) Load(path string) error {
@@ -81,8 +64,8 @@ func (c *CertificateStore) Load(path string) error {
if err != nil {
continue
}
- hostname := strings.TrimSuffix(filepath.Base(crtPath), ".crt")
- c.Add(hostname, cert)
+ scope := strings.TrimSuffix(filepath.Base(crtPath), ".crt")
+ c.Add(scope, cert)
}
return nil
}
diff --git a/client.go b/client.go
index 5ab3ded..5d58895 100644
--- a/client.go
+++ b/client.go
@@ -6,6 +6,7 @@ import (
"crypto/x509"
"net"
"net/url"
+ "path"
"strings"
)
@@ -153,12 +154,23 @@ func (c *Client) getClientCertificate(req *Request) (*tls.Certificate, error) {
if req.Certificate != nil {
return req.Certificate, nil
}
- hostname, path := req.URL.Hostname(), strings.TrimSuffix(req.URL.Path, "/")
- if cert, err := c.Certificates.lookup(hostname + path); err == nil {
- // Remember the certificate used
- req.Certificate = cert
- return cert, nil
+
+ // Search recursively for the certificate
+ scope := req.URL.Hostname() + strings.TrimSuffix(req.URL.Path, "/")
+ for {
+ cert, err := c.Certificates.Lookup(scope)
+ if err == nil {
+ return cert, err
+ }
+ if err == ErrCertificateExpired {
+ break
+ }
+ scope = path.Dir(scope)
+ if scope == "." {
+ break
+ }
}
+
return &tls.Certificate{}, nil
}
diff --git a/doc.go b/doc.go
index 3c97595..f0d3fdb 100644
--- a/doc.go
+++ b/doc.go
@@ -41,22 +41,12 @@ Clients can control when to trust certificates with TrustCertificate:
return knownHosts.Lookup(hostname, cert)
}
-Clients can control what to do when a server requests a certificate:
-
- client.GetCertificate = func(hostname string, store *gemini.CertificateStore) *tls.Certificate {
- // If the certificate is in the store, return it
- if cert, err := store.Lookup(hostname); err == nil {
- return &cert
- }
- // Otherwise, generate a certificate
- duration := time.Hour
- cert, err := gemini.NewCertificate(hostname, duration)
- if err != nil {
- return nil
- }
- // Store and return the certificate
- store.Add(hostname, cert)
- return &cert
+Clients can create client certificates upon the request of a server:
+
+ client.CreateCertificate = func(hostname, path string) *tls.Certificate {
+ return gemini.CreateCertificate(gemini.CertificateOptions{
+ Duration: time.Hour,
+ })
}
Server is a Gemini server.
@@ -65,7 +55,7 @@ Server is a Gemini server.
Servers must be configured with certificates:
- err := server.CertificateStore.Load("/var/lib/gemini/certs")
+ err := server.Certificates.Load("/var/lib/gemini/certs")
if err != nil {
// handle error
}
diff --git a/server.go b/server.go
index f991f08..5d2f724 100644
--- a/server.go
+++ b/server.go
@@ -36,9 +36,16 @@ type responderKey struct {
}
// Register registers a responder for the given pattern.
-// Patterns must be in the form of scheme://hostname (e.g. gemini://example.com).
+//
+// Patterns must be in the form of hostname or scheme://hostname
+// (e.g. gemini://example.com).
// If no scheme is specified, a default scheme of gemini:// is assumed.
+//
// Wildcard patterns are supported (e.g. *.example.com).
+// To register a certificate for a wildcard domain, call Certificates.Add:
+//
+// var s gemini.Server
+// s.Certificates.Add("*.example.com", cert)
func (s *Server) Register(pattern string, responder Responder) {
if pattern == "" {
panic("gemini: invalid pattern")