Implement server certificate store
This commit is contained in:
parent
3b5cc23d28
commit
065ed828fb
35
cert.go
35
cert.go
@ -15,7 +15,40 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CertificateStore maps hostnames to certificates.
|
// CertificateStore maps hostnames to certificates.
|
||||||
type CertificateStore map[string]*tls.Certificate
|
type CertificateStore struct {
|
||||||
|
store map[string]tls.Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a certificate for the given hostname to the store.
|
||||||
|
func (c *CertificateStore) Add(hostname string, cert tls.Certificate) {
|
||||||
|
if c.store == nil {
|
||||||
|
c.store = map[string]tls.Certificate{}
|
||||||
|
}
|
||||||
|
c.store[hostname] = cert
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the certificate for the given hostname.
|
||||||
|
func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
|
||||||
|
cert, ok := c.store[hostname]
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrUnknownCertificate
|
||||||
|
}
|
||||||
|
// TODO: Ensure that the certificate is not expired
|
||||||
|
// if expired {
|
||||||
|
// return nil, ErrInvalidCertificate
|
||||||
|
// }
|
||||||
|
return &cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// 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 {
|
||||||
|
// TODO: Implement this
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewCertificate creates and returns a new parsed certificate.
|
// NewCertificate creates and returns a new parsed certificate.
|
||||||
func NewCertificate(host string, duration time.Duration) (tls.Certificate, error) {
|
func NewCertificate(host string, duration time.Duration) (tls.Certificate, error) {
|
||||||
|
10
client.go
10
client.go
@ -218,10 +218,8 @@ func (c *Client) Send(req *Request) (*Response, error) {
|
|||||||
return req.Certificate, nil
|
return req.Certificate, nil
|
||||||
}
|
}
|
||||||
// If we have already stored the certificate, return it
|
// If we have already stored the certificate, return it
|
||||||
if c.CertificateStore != nil {
|
if cert, err := c.CertificateStore.Lookup(req.Hostname()); err == nil {
|
||||||
if cert, ok := c.CertificateStore[req.Hostname()]; ok {
|
return cert, nil
|
||||||
return cert, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &tls.Certificate{}, nil
|
return &tls.Certificate{}, nil
|
||||||
},
|
},
|
||||||
@ -280,10 +278,6 @@ func (c *Client) Send(req *Request) (*Response, error) {
|
|||||||
if req.Certificate != nil {
|
if req.Certificate != nil {
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
// Create the certificate store if it does not exist
|
|
||||||
if c.CertificateStore == nil {
|
|
||||||
c.CertificateStore = CertificateStore{}
|
|
||||||
}
|
|
||||||
if c.GetCertificate != nil {
|
if c.GetCertificate != nil {
|
||||||
if cert := c.GetCertificate(req.Hostname(), c.CertificateStore); cert != nil {
|
if cert := c.GetCertificate(req.Hostname(), c.CertificateStore); cert != nil {
|
||||||
req.Certificate = cert
|
req.Certificate = cert
|
||||||
|
@ -52,9 +52,8 @@ func main() {
|
|||||||
handler.HandleFunc("/admin", admin)
|
handler.HandleFunc("/admin", admin)
|
||||||
handler.HandleFunc("/logout", logout)
|
handler.HandleFunc("/logout", logout)
|
||||||
|
|
||||||
server := &gmi.Server{
|
server := &gmi.Server{}
|
||||||
Certificate: cert,
|
server.CertificateStore.Add("localhost", cert)
|
||||||
}
|
|
||||||
server.Handle("localhost", handler)
|
server.Handle("localhost", handler)
|
||||||
|
|
||||||
if err := server.ListenAndServe(); err != nil {
|
if err := server.ListenAndServe(); err != nil {
|
||||||
|
@ -48,7 +48,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
client.GetCertificate = func(hostname string, store gmi.CertificateStore) *tls.Certificate {
|
client.GetCertificate = func(hostname string, store gmi.CertificateStore) *tls.Certificate {
|
||||||
// If the certificate is in the store, return it
|
// If the certificate is in the store, return it
|
||||||
if cert, ok := store[hostname]; ok {
|
if cert, err := store.Lookup(hostname); err == nil {
|
||||||
return cert
|
return cert
|
||||||
}
|
}
|
||||||
// Otherwise, generate a certificate
|
// Otherwise, generate a certificate
|
||||||
@ -59,7 +59,7 @@ func init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Store and return the certificate
|
// Store and return the certificate
|
||||||
store[hostname] = &cert
|
store.Add(hostname, cert)
|
||||||
return &cert
|
return &cert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,8 @@ func main() {
|
|||||||
mux := &gmi.ServeMux{}
|
mux := &gmi.ServeMux{}
|
||||||
mux.Handle("/", gmi.FileServer(gmi.Dir("/var/www")))
|
mux.Handle("/", gmi.FileServer(gmi.Dir("/var/www")))
|
||||||
|
|
||||||
server := gmi.Server{
|
server := gmi.Server{}
|
||||||
Certificate: cert,
|
server.CertificateStore.Add("localhost", cert)
|
||||||
}
|
|
||||||
server.Handle("localhost", mux)
|
server.Handle("localhost", mux)
|
||||||
server.ListenAndServe()
|
server.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
DefaultClient.GetCertificate = func(hostname string, store CertificateStore) *tls.Certificate {
|
DefaultClient.GetCertificate = func(hostname string, store CertificateStore) *tls.Certificate {
|
||||||
// If the certificate is in the store, return it
|
// If the certificate is in the store, return it
|
||||||
if cert, ok := store[hostname]; ok {
|
if cert, err := store.Lookup(hostname); err == nil {
|
||||||
return cert
|
return cert
|
||||||
}
|
}
|
||||||
// Otherwise, generate a certificate
|
// Otherwise, generate a certificate
|
||||||
@ -68,7 +68,7 @@ func init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Store and return the certificate
|
// Store and return the certificate
|
||||||
store[hostname] = &cert
|
store.Add(hostname, cert)
|
||||||
return &cert
|
return &cert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
server.go
20
server.go
@ -27,9 +27,13 @@ type Server struct {
|
|||||||
// If Addr is empty, the server will listen on the address ":1965".
|
// If Addr is empty, the server will listen on the address ":1965".
|
||||||
Addr string
|
Addr string
|
||||||
|
|
||||||
// Certificate provides a TLS certificate for use by the server.
|
// CertificateStore contains the certificates used by the server.
|
||||||
// A self-signed certificate is recommended.
|
CertificateStore CertificateStore
|
||||||
Certificate tls.Certificate
|
|
||||||
|
// GetCertificate, if not nil, will be called to retrieve the certificate
|
||||||
|
// to use for a given hostname.
|
||||||
|
// If the certificate is nil, the connection will be aborted.
|
||||||
|
GetCertificate func(hostname string) *tls.Certificate
|
||||||
|
|
||||||
// registered handlers
|
// registered handlers
|
||||||
handlers []handlerEntry
|
handlers []handlerEntry
|
||||||
@ -44,7 +48,6 @@ func (s *Server) Handle(host string, handler Handler) {
|
|||||||
if handler == nil {
|
if handler == nil {
|
||||||
panic("gmi: nil handler")
|
panic("gmi: nil handler")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.HandleScheme("gemini", host, handler)
|
s.HandleScheme("gemini", host, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +82,13 @@ func (s *Server) ListenAndServe() error {
|
|||||||
config := &tls.Config{
|
config := &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
Certificates: []tls.Certificate{s.Certificate},
|
GetCertificate: func(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
ClientAuth: tls.RequestClientCert,
|
if s.GetCertificate != nil {
|
||||||
|
return s.GetCertificate(h.ServerName), nil
|
||||||
|
}
|
||||||
|
return s.CertificateStore.Lookup(h.ServerName)
|
||||||
|
},
|
||||||
|
ClientAuth: tls.RequestClientCert,
|
||||||
}
|
}
|
||||||
tlsListener := tls.NewListener(ln, config)
|
tlsListener := tls.NewListener(ln, config)
|
||||||
return s.Serve(tlsListener)
|
return s.Serve(tlsListener)
|
||||||
|
Loading…
Reference in New Issue
Block a user