From c79a1f44842500ac48fb65edd92bc27c6fa75c49 Mon Sep 17 00:00:00 2001 From: adnano Date: Sun, 27 Sep 2020 16:21:56 -0400 Subject: [PATCH] Update documentation --- README.md | 30 ++++++++++++++++++++---------- examples/client/client.go | 6 +++++- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e0c3501..ba047d3 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,7 @@ The way this is implemented in this package is like so: 1. Client makes a request with `NewRequest`. The client then sends the request with `(*Client).Send(*Request) (*Response, error)`. The client then determines whether - to trust the certificate in `TrustCertificte(*x509.Certificate, *KnownHosts) bool`. - (See [TOFU](#tofu)). + to trust the certificate (see [TOFU](#tofu)). 2. Server recieves the request and constructs a response. The server calls the `Serve(*ResponseWriter, *Request)` method on the `Handler` field. The handler writes the response. The server then closes @@ -47,37 +46,46 @@ The way this is implemented in this package is like so: `go-gemini` makes it easy to implement Trust On First Use in your clients. -Clients can load the default list of known hosts: +The default client loads known hosts from `$XDG_DATA_HOME/gemini/known_hosts`. +If that is all you need, you can simply use the top-level `Send` function: + +```go +// Send uses the default client, which will load the default list of known +hosts. +req := gemini.NewRequest("gemini://example.com") +gemini.Send(req) +``` + +Clients can also load their own list of known hosts: ```go client := &Client{} -knownHosts, err := gemini.LoadKnownHosts() -if err != nil { +if err := client.KnownHosts.LoadFrom("path/to/my/known_hosts"); err != nil { log.Fatal(err) } -client.KnownHosts = knownHosts ``` Clients can then specify how to trust certificates in the `TrustCertificate` field: ```go -client.TrustCertificate = func(cert *x509.Certificate, knownHosts *gemini.KnownHosts) error { +client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gemini.KnownHosts) error { // If the certificate is in the known hosts list, allow the connection - return knownHosts.Lookup(cert) + return knownHosts.Lookup(hostname, cert) } ``` Advanced clients can prompt the user for what to do when encountering an unknown certificate: ```go -client.TrustCertificate = func(cert *x509.Certificate, knownHosts *gemini.KnownHosts) error { +client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gemini.KnownHosts) error { err := knownHosts.Lookup(cert) if err != nil { switch err { case gemini.ErrCertificateNotTrusted: // Alert the user that the certificate is not trusted - alertUser() + fmt.Printf("Warning: certificate for %s is not trusted!\n", hostname) + fmt.Println("This could indicate a Man-in-the-Middle attack.") case gemini.ErrCertificateUnknown: // Prompt the user to trust the certificate if userTrustsCertificateTemporarily() { @@ -93,3 +101,5 @@ client.TrustCertificate = func(cert *x509.Certificate, knownHosts *gemini.KnownH return err } ``` + +See `examples/client` for an example client. diff --git a/examples/client/client.go b/examples/client/client.go index 5b853de..5c1c104 100644 --- a/examples/client/client.go +++ b/examples/client/client.go @@ -28,7 +28,7 @@ func init() { switch err { case gemini.ErrCertificateNotTrusted: // Alert the user that the certificate is not trusted - fmt.Println("error: certificate is not trusted!") + fmt.Printf("Warning: certificate for %s is not trusted!\n", hostname) fmt.Println("This could indicate a Man-in-the-Middle attack.") case gemini.ErrCertificateUnknown: // Prompt the user to trust the certificate @@ -45,6 +45,10 @@ func init() { return err } + client.GetCertificate = func(req *gemini.Request, store *gemini.CertificateStore) *tls.Certificate { + return &cert + } + // Configure a client side certificate. // To generate a TLS key pair, run: //