diff --git a/main.go b/main.go index a83f301..0abfe5d 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "context" "crypto/tls" + "crypto/x509" "encoding/pem" "flag" "fmt" @@ -62,6 +63,7 @@ var ( clientCertFile string fourOnly bool sixOnly bool + cacert string // number of redirects followed redirectsFollowed int @@ -84,6 +86,7 @@ func init() { flag.StringVar(&clientCertFile, "E", "", "client cert file for tls config") flag.BoolVar(&fourOnly, "4", false, "resolve IPv4 addresses only") flag.BoolVar(&sixOnly, "6", false, "resolve IPv6 addresses only") + flag.StringVar(&cacert, "cacert", "", "CA certificate to verify peer against (SSL)") flag.Usage = usage } @@ -140,6 +143,23 @@ func main() { visit(url) } +// readCACerts - helper function to load additional CA certificates +func readCACerts(filename string) (*x509.CertPool, error) { + if filename == "" { + return nil, nil + } + certFileBytes, err := ioutil.ReadFile(filename) + + if err != nil { + return nil, fmt.Errorf("failed to read CA certificate file: %v", err) + } + + certPool := x509.NewCertPool() + certPool.AppendCertsFromPEM(certFileBytes) + + return certPool, nil +} + // readClientCert - helper function to read client certificate // from pem formatted file func readClientCert(filename string) []tls.Certificate { @@ -269,10 +289,16 @@ func visit(url *url.URL) { host = req.Host } + rootCAs, err := readCACerts(cacert) + if err != nil { + log.Printf("warning: failed to read CA certificates: %s\n", err) + } + tr.TLSClientConfig = &tls.Config{ ServerName: host, InsecureSkipVerify: insecure, Certificates: readClientCert(clientCertFile), + RootCAs: rootCAs, } // Because we create a custom TLSClientConfig, we have to opt-in to HTTP/2.