Add function to write known hosts to io.Writer
This commit is contained in:
parent
2eb7fb9ba4
commit
013b2a4d3e
@ -168,7 +168,7 @@ func (resp *Response) read(r *bufio.Reader) error {
|
|||||||
// Client represents a Gemini client.
|
// Client represents a Gemini client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
// KnownHosts is a list of known hosts that the client trusts.
|
// KnownHosts is a list of known hosts that the client trusts.
|
||||||
KnownHosts *KnownHosts
|
KnownHosts KnownHosts
|
||||||
|
|
||||||
// CertificateStore contains all the certificates that the client has stored.
|
// CertificateStore contains all the certificates that the client has stored.
|
||||||
CertificateStore *CertificateStore
|
CertificateStore *CertificateStore
|
||||||
@ -210,12 +210,10 @@ func (c *Client) Send(req *Request) (*Response, error) {
|
|||||||
}
|
}
|
||||||
// Check that the client trusts the certificate
|
// Check that the client trusts the certificate
|
||||||
if c.TrustCertificate == nil {
|
if c.TrustCertificate == nil {
|
||||||
if c.KnownHosts == nil {
|
if err := c.KnownHosts.Lookup(cert); err != nil {
|
||||||
return ErrCertificateNotTrusted
|
|
||||||
} else if err := c.KnownHosts.Lookup(cert); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if err := c.TrustCertificate(cert, c.KnownHosts); err != nil {
|
} else if err := c.TrustCertificate(cert, &c.KnownHosts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -19,15 +19,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Load the list of known hosts
|
client = &gemini.Client{}
|
||||||
knownHosts, err := gemini.LoadKnownHosts()
|
client.KnownHosts.Load()
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client = &gemini.Client{
|
|
||||||
KnownHosts: knownHosts,
|
|
||||||
}
|
|
||||||
|
|
||||||
client.TrustCertificate = func(cert *x509.Certificate, knownHosts *gemini.KnownHosts) error {
|
client.TrustCertificate = func(cert *x509.Certificate, knownHosts *gemini.KnownHosts) error {
|
||||||
err := knownHosts.Lookup(cert)
|
err := knownHosts.Lookup(cert)
|
||||||
@ -53,12 +46,10 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configure a client side certificate.
|
// Configure a client side certificate.
|
||||||
// To generate a certificate, run:
|
// To generate a TLS key pair, run:
|
||||||
//
|
|
||||||
// openssl genrsa -out client.key 2048
|
|
||||||
// openssl ecparam -genkey -name secp384r1 -out client.key
|
|
||||||
// openssl req -new -x509 -sha512 -key client.key -out client.crt -days 365
|
|
||||||
//
|
//
|
||||||
|
// go run -tags=example ../cert
|
||||||
|
var cert tls.Certificate
|
||||||
cert, err = tls.LoadX509KeyPair("examples/client/localhost.crt", "examples/client/localhost.key")
|
cert, err = tls.LoadX509KeyPair("examples/client/localhost.crt", "examples/client/localhost.key")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -13,10 +13,7 @@ func main() {
|
|||||||
// Load a TLS key pair.
|
// Load a TLS key pair.
|
||||||
// To generate a TLS key pair, run:
|
// To generate a TLS key pair, run:
|
||||||
//
|
//
|
||||||
// openssl genrsa -out server.key 2048
|
// go run -tags=example ../cert
|
||||||
// openssl ecparam -genkey -name secp384r1 -out server.key
|
|
||||||
// openssl req -new -x509 -sha512 -key server.key -out server.crt -days 365
|
|
||||||
//
|
|
||||||
cert, err := tls.LoadX509KeyPair("examples/server/localhost.crt", "examples/server/localhost.key")
|
cert, err := tls.LoadX509KeyPair("examples/server/localhost.crt", "examples/server/localhost.key")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -60,11 +60,7 @@ func init() {
|
|||||||
var setupDefaultClientOnce sync.Once
|
var setupDefaultClientOnce sync.Once
|
||||||
|
|
||||||
func setupDefaultClient() {
|
func setupDefaultClient() {
|
||||||
knownHosts, err := LoadKnownHosts()
|
DefaultClient.KnownHosts.Load()
|
||||||
if err != nil {
|
|
||||||
knownHosts = &KnownHosts{}
|
|
||||||
}
|
|
||||||
DefaultClient.KnownHosts = knownHosts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send sends a Gemini request and returns a Gemini response.
|
// Send sends a Gemini request and returns a Gemini response.
|
||||||
|
37
tofu.go
37
tofu.go
@ -15,50 +15,50 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// KnownHosts represents a list of known hosts.
|
// KnownHosts represents a list of known hosts.
|
||||||
|
// The zero value for KnownHosts is an empty list ready to use.
|
||||||
type KnownHosts struct {
|
type KnownHosts struct {
|
||||||
hosts []KnownHost
|
hosts []KnownHost
|
||||||
file *os.File
|
file *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadKnownHosts loads the known hosts from the default known hosts path.
|
// Load loads the known hosts from the default known hosts path, which is
|
||||||
// The default path is $XDG_DATA_HOME/gemini/known_hosts
|
// `$XDG_DATA_HOME/gemini/known_hosts`.
|
||||||
// It creates the path and any of its parent directories if they do not exist.
|
// It creates the path and any of its parent directories if they do not exist.
|
||||||
// The returned KnownHosts appends to the file whenever a certificate is added.
|
// KnownHosts will append to the file whenever a certificate is added.
|
||||||
func LoadKnownHosts() (*KnownHosts, error) {
|
func (k *KnownHosts) Load() error {
|
||||||
path, err := defaultKnownHostsPath()
|
path, err := defaultKnownHostsPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return LoadKnownHostsFrom(path)
|
return k.LoadFrom(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadKnownHosts loads the known hosts from the provided path.
|
// LoadFrom loads the known hosts from the provided path.
|
||||||
// It creates the path and any of its parent directories if they do not exist.
|
// It creates the path and any of its parent directories if they do not exist.
|
||||||
// The returned KnownHosts appends to the file whenever a certificate is added.
|
// KnownHosts will append to the file whenever a certificate is added.
|
||||||
func LoadKnownHostsFrom(path string) (*KnownHosts, error) {
|
func (k *KnownHosts) LoadFrom(path string) error {
|
||||||
if dir := filepath.Dir(path); dir != "." {
|
if dir := filepath.Dir(path); dir != "." {
|
||||||
err := os.MkdirAll(dir, 0755)
|
err := os.MkdirAll(dir, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDONLY, 0644)
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
k := &KnownHosts{}
|
|
||||||
k.Parse(f)
|
k.Parse(f)
|
||||||
f.Close()
|
f.Close()
|
||||||
// Open the file for append-only use
|
// Open the file for append-only use
|
||||||
f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
k.file = f
|
k.file = f
|
||||||
return k, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a certificate to the KnownHosts.
|
// Add adds a certificate to the list of known hosts.
|
||||||
// If KnownHosts was loaded from a file, Add will append to the file.
|
// If KnownHosts was loaded from a file, Add will append to the file.
|
||||||
func (k *KnownHosts) Add(cert *x509.Certificate) {
|
func (k *KnownHosts) Add(cert *x509.Certificate) {
|
||||||
host := NewKnownHost(cert)
|
host := NewKnownHost(cert)
|
||||||
@ -125,6 +125,13 @@ func (k *KnownHosts) Parse(r io.Reader) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write writes the known hosts to the provided io.Writer.
|
||||||
|
func (k *KnownHosts) Write(w io.Writer) {
|
||||||
|
for _, h := range k.hosts {
|
||||||
|
h.Write(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// KnownHost represents a known host.
|
// KnownHost represents a known host.
|
||||||
type KnownHost struct {
|
type KnownHost struct {
|
||||||
Hostname string // e.g. gemini.circumlunar.space
|
Hostname string // e.g. gemini.circumlunar.space
|
||||||
|
Loading…
Reference in New Issue
Block a user