Add option to skip trust checks

This commit is contained in:
Adnan Maolood 2020-10-31 22:45:21 -04:00
parent 65a5065250
commit 8181b86759
3 changed files with 21 additions and 31 deletions

View File

@ -27,6 +27,12 @@ type Client struct {
// A Timeout of zero means no timeout. // A Timeout of zero means no timeout.
Timeout time.Duration Timeout time.Duration
// InsecureTrustAlways specifies whether the client should trust
// any certificate it recieves without checking KnownHosts
// or calling TrustCertificate.
// Use with caution.
InsecureTrustAlways bool
// GetInput is called to retrieve input when the server requests it. // GetInput is called to retrieve input when the server requests it.
// If GetInput is nil or returns false, no input will be sent and // If GetInput is nil or returns false, no input will be sent and
// the response will be returned. // the response will be returned.
@ -196,27 +202,25 @@ func (c *Client) verifyConnection(req *Request, cs tls.ConnectionState) error {
if err := verifyHostname(cert, hostname); err != nil { if err := verifyHostname(cert, hostname); err != nil {
return err return err
} }
if c.InsecureTrustAlways {
return nil
}
// Check the known hosts // Check the known hosts
err := c.KnownHosts.Lookup(hostname, cert) err := c.KnownHosts.Lookup(hostname, cert)
switch err { switch err {
case ErrCertificateExpired, ErrCertificateNotFound: case ErrCertificateExpired, ErrCertificateNotFound:
default: // See if the client trusts the certificate
return err if c.TrustCertificate != nil {
} switch c.TrustCertificate(hostname, cert) {
// See if the client trusts the certificate case TrustOnce:
if c.TrustCertificate != nil { c.KnownHosts.AddTemporary(hostname, cert)
switch c.TrustCertificate(hostname, cert) { return nil
case TrustOnce: case TrustAlways:
c.KnownHosts.AddTemporary(hostname, cert) c.KnownHosts.Add(hostname, cert)
return nil return nil
case TrustAlways: }
c.KnownHosts.Add(hostname, cert)
return nil
default:
return ErrCertificateNotTrusted
} }
} else { return ErrCertificateNotTrusted
err = c.KnownHosts.Lookup(hostname, cert)
} }
return err return err
} }

View File

@ -5,7 +5,6 @@ package main
import ( import (
"bufio" "bufio"
"crypto/tls" "crypto/tls"
"crypto/x509"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@ -31,19 +30,6 @@ var (
func init() { func init() {
client.Timeout = 2 * time.Minute client.Timeout = 2 * time.Minute
client.KnownHosts.LoadDefault()
client.TrustCertificate = func(hostname string, cert *x509.Certificate) gemini.Trust {
fmt.Printf(trustPrompt, hostname, gemini.Fingerprint(cert))
scanner.Scan()
switch scanner.Text() {
case "t":
return gemini.TrustAlways
case "o":
return gemini.TrustOnce
default:
return gemini.TrustNone
}
}
client.CreateCertificate = func(hostname, path string) (tls.Certificate, error) { client.CreateCertificate = func(hostname, path string) (tls.Certificate, error) {
fmt.Println("Generating client certificate for", hostname, path) fmt.Println("Generating client certificate for", hostname, path)
return gemini.CreateCertificate(gemini.CertificateOptions{ return gemini.CreateCertificate(gemini.CertificateOptions{

View File

@ -13,7 +13,7 @@ var (
ErrInvalidResponse = errors.New("gemini: invalid response") ErrInvalidResponse = errors.New("gemini: invalid response")
ErrCertificateExpired = errors.New("gemini: certificate expired") ErrCertificateExpired = errors.New("gemini: certificate expired")
ErrCertificateNotFound = errors.New("gemini: certificate not found") ErrCertificateNotFound = errors.New("gemini: certificate not found")
ErrCertificateNotTrusted = errors.New("gemini: certificate is not trusted") ErrCertificateNotTrusted = errors.New("gemini: certificate not trusted")
ErrCertificateRequired = errors.New("gemini: certificate required") ErrCertificateRequired = errors.New("gemini: certificate required")
ErrNotAFile = errors.New("gemini: not a file") ErrNotAFile = errors.New("gemini: not a file")
ErrNotAGeminiURL = errors.New("gemini: not a Gemini URL") ErrNotAGeminiURL = errors.New("gemini: not a Gemini URL")