Update documentation

This commit is contained in:
adnano 2020-09-28 00:29:11 -04:00
parent 21022eb5ac
commit 622ea8e0f1
3 changed files with 40 additions and 4 deletions

View File

@ -82,5 +82,35 @@ certificate. See `examples/client` for an example.
Gemini takes advantage of client certificates for authentication.
See `examples/auth` for an example server which authenticates its users with a
If a server responds with `StatusCertificateRequired`, clients will generate a
certificate for the site and resend the request with the provided certificate.
In order for this to work, clients must specify the fields `CertificateStore`
and `GetCertificate`:
```go
// Initialize the certificate store.
client.CertificateStore = gmi.NewCertificateStore()
// GetCertificate is called when a server requests a certificate.
// The returned certificate, if not nil, will be used when resending the request.
client.GetCertificate = func(hostname string, store gmi.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 := gmi.NewCertificate(hostname, duration)
if err != nil {
return nil
}
// Store and return the certificate
store[hostname] = &cert
return &cert
}
```
Servers can then authenticate their clients with the fingerprint of their
certificates.
See `examples/auth` for an example server which authenticates its users with
username and password, and uses their client certificate to remember sessions.

View File

@ -34,6 +34,7 @@ type Request struct {
Host string
// Certificate specifies the TLS certificate to use for the request.
// Request certificates take precedence over client certificates.
// This field is ignored by the server.
Certificate *tls.Certificate
@ -188,8 +189,10 @@ type Client struct {
// CertificateStore contains all the certificates that the client has stored.
CertificateStore CertificateStore
// GetCertificate, if not nil, will be called to determine which certificate
// to use when the server responds with CertificateRequired.
// GetCertificate, if not nil, will be called when a server requests a certificate.
// The returned certificate will be used when sending the request again.
// If the certificate is nil, the request will not be sent again and
// the response will be returned.
GetCertificate func(hostname string, store CertificateStore) *tls.Certificate
// TrustCertificate, if not nil, will be called to determine whether the
@ -205,6 +208,7 @@ func (c *Client) Send(req *Request) (*Response, error) {
InsecureSkipVerify: true,
MinVersion: tls.VersionTLS12,
GetClientCertificate: func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
// Request certificates take precedence over client certificates
if req.Certificate != nil {
return req.Certificate, nil
}

View File

@ -49,15 +49,17 @@ func init() {
client.CertificateStore = gmi.NewCertificateStore()
client.GetCertificate = func(hostname string, store gmi.CertificateStore) *tls.Certificate {
// If the certificate is in the store, return it
if cert, ok := store[hostname]; ok {
return cert
}
// Generate a certificate
// Otherwise, generate a certificate
duration := time.Hour
cert, err := gmi.NewCertificate(hostname, duration)
if err != nil {
return nil
}
// Store and return the certificate
store[hostname] = &cert
return &cert
}