Make the default client generate certificates

This commit is contained in:
adnano 2020-09-28 00:38:11 -04:00
parent 622ea8e0f1
commit cad2d25185
2 changed files with 21 additions and 2 deletions

View File

@ -84,8 +84,8 @@ Gemini takes advantage of client certificates for authentication.
If a server responds with `StatusCertificateRequired`, clients will generate a If a server responds with `StatusCertificateRequired`, clients will generate a
certificate for the site and resend the request with the provided certificate. certificate for the site and resend the request with the provided certificate.
In order for this to work, clients must specify the fields `CertificateStore` The default client handles this for you. Other clients must specify the fields
and `GetCertificate`: `CertificateStore` and `GetCertificate`:
```go ```go
// Initialize the certificate store. // Initialize the certificate store.
@ -109,6 +109,7 @@ client.GetCertificate = func(hostname string, store gmi.CertificateStore) *tls.C
} }
``` ```
Servers can then authenticate their clients with the fingerprint of their Servers can then authenticate their clients with the fingerprint of their
certificates. certificates.

View File

@ -2,8 +2,10 @@
package gmi package gmi
import ( import (
"crypto/tls"
"crypto/x509" "crypto/x509"
"sync" "sync"
"time"
) )
// Status codes. // Status codes.
@ -54,11 +56,27 @@ func init() {
setupDefaultClientOnce.Do(setupDefaultClient) setupDefaultClientOnce.Do(setupDefaultClient)
return knownHosts.Lookup(hostname, cert) return knownHosts.Lookup(hostname, cert)
} }
DefaultClient.GetCertificate = func(hostname string, store CertificateStore) *tls.Certificate {
// If the certificate is in the store, return it
if cert, ok := store[hostname]; ok {
return cert
}
// Otherwise, generate a certificate
duration := time.Hour
cert, err := NewCertificate(hostname, duration)
if err != nil {
return nil
}
// Store and return the certificate
store[hostname] = &cert
return &cert
}
} }
var setupDefaultClientOnce sync.Once var setupDefaultClientOnce sync.Once
func setupDefaultClient() { func setupDefaultClient() {
DefaultClient.CertificateStore = NewCertificateStore()
DefaultClient.KnownHosts.Load() DefaultClient.KnownHosts.Load()
} }