Add tooling to enable strict TLS.

This commit is contained in:
2025-11-18 17:25:49 -08:00
parent 3f92963c74
commit b714c75a43
10 changed files with 217 additions and 101 deletions

View File

@@ -7,6 +7,7 @@ import (
"crypto/elliptic"
"crypto/rsa"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"flag"
@@ -350,14 +351,11 @@ func main() {
flag.BoolVar(&leafOnly, "l", false, "only show the leaf certificate")
flag.Parse()
opts := &lib.FetcherOpts{
SkipVerify: true,
Roots: nil,
}
tlsCfg := &tls.Config{InsecureSkipVerify: true} // #nosec G402 - tool intentionally inspects broken TLS
for _, filename := range flag.Args() {
fmt.Fprintf(os.Stdout, "--%s ---%s", filename, "\n")
certs, err := lib.GetCertificateChain(filename, opts)
certs, err := lib.GetCertificateChain(filename, tlsCfg)
if err != nil {
_, _ = lib.Warn(err, "couldn't read certificate")
continue

View File

@@ -63,6 +63,7 @@ func checkCert(cert *x509.Certificate) {
warn := inDanger(cert)
name := displayName(cert.Subject)
name = fmt.Sprintf("%s/SN=%s", name, cert.SerialNumber)
expiry := expires(cert)
if warnOnly {
if warn {
@@ -74,15 +75,22 @@ func checkCert(cert *x509.Certificate) {
}
func main() {
opts := &lib.FetcherOpts{}
var skipVerify bool
var strictTLS bool
lib.StrictTLSFlag(&strictTLS)
flag.BoolVar(&opts.SkipVerify, "k", false, "skip server verification")
flag.BoolVar(&skipVerify, "k", false, "skip server verification") // #nosec G402
flag.BoolVar(&warnOnly, "q", false, "only warn about expiring certs")
flag.DurationVar(&leeway, "t", leeway, "warn if certificates are closer than this to expiring")
flag.Parse()
tlsCfg, err := lib.BaselineTLSConfig(skipVerify, strictTLS)
die.If(err)
for _, file := range flag.Args() {
certs, err := lib.GetCertificateChain(file, opts)
var certs []*x509.Certificate
certs, err = lib.GetCertificateChain(file, tlsCfg)
if err != nil {
_, _ = lib.Warn(err, "while parsing certificates")
continue

View File

@@ -31,16 +31,23 @@ func serialString(cert *x509.Certificate, mode lib.HexEncodeMode) string {
}
func main() {
opts := &lib.FetcherOpts{}
var skipVerify bool
var strictTLS bool
lib.StrictTLSFlag(&strictTLS)
displayAs := flag.String("d", "int", "display mode (int, hex, uhex)")
showExpiry := flag.Bool("e", false, "show expiry date")
flag.BoolVar(&opts.SkipVerify, "k", false, "skip server verification")
flag.BoolVar(&skipVerify, "k", false, "skip server verification") // #nosec G402
flag.Parse()
tlsCfg, err := lib.BaselineTLSConfig(skipVerify, strictTLS)
die.If(err)
displayMode := parseDisplayMode(*displayAs)
for _, arg := range flag.Args() {
cert, err := lib.GetCertificate(arg, opts)
var cert *x509.Certificate
cert, err = lib.GetCertificate(arg, tlsCfg)
die.If(err)
fmt.Printf("%s: %s", arg, serialString(cert, displayMode))

View File

@@ -32,6 +32,7 @@ type appConfig struct {
caFile, intFile string
forceIntermediateBundle bool
revexp, skipVerify, verbose bool
strictTLS bool
}
func parseFlags() appConfig {
@@ -43,6 +44,7 @@ func parseFlags() appConfig {
flag.BoolVar(&cfg.skipVerify, "k", false, "skip CA verification")
flag.BoolVar(&cfg.revexp, "r", false, "print revocation and expiry information")
flag.BoolVar(&cfg.verbose, "v", false, "verbose")
lib.StrictTLSFlag(&cfg.strictTLS)
flag.Parse()
return cfg
}
@@ -108,12 +110,13 @@ func run(cfg appConfig) error {
return fmt.Errorf("failed to build combined pool: %w", err)
}
opts := &lib.FetcherOpts{
Roots: combinedPool,
SkipVerify: cfg.skipVerify,
tlsCfg, err := lib.BaselineTLSConfig(cfg.skipVerify, cfg.strictTLS)
if err != nil {
return err
}
tlsCfg.RootCAs = combinedPool
chain, err := lib.GetCertificateChain(flag.Arg(0), opts)
chain, err := lib.GetCertificateChain(flag.Arg(0), tlsCfg)
if err != nil {
return err
}

View File

@@ -3,50 +3,47 @@ package main
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"flag"
"fmt"
"net"
"os"
"git.wntrmute.dev/kyle/goutils/certlib"
"git.wntrmute.dev/kyle/goutils/die"
"git.wntrmute.dev/kyle/goutils/lib"
)
func main() {
var cfg = &tls.Config{} // #nosec G402
var sysRoot, serverName string
var skipVerify bool
var strictTLS bool
lib.StrictTLSFlag(&strictTLS)
flag.StringVar(&sysRoot, "ca", "", "provide an alternate CA bundle")
flag.StringVar(&cfg.ServerName, "sni", cfg.ServerName, "provide an SNI name")
flag.BoolVar(&cfg.InsecureSkipVerify, "noverify", false, "don't verify certificates")
flag.StringVar(&serverName, "sni", "", "provide an SNI name")
flag.BoolVar(&skipVerify, "noverify", false, "don't verify certificates")
flag.Parse()
tlsCfg, err := lib.BaselineTLSConfig(skipVerify, strictTLS)
die.If(err)
if sysRoot != "" {
pemList, err := os.ReadFile(sysRoot)
tlsCfg.RootCAs, err = certlib.LoadPEMCertPool(sysRoot)
die.If(err)
roots := x509.NewCertPool()
if !roots.AppendCertsFromPEM(pemList) {
fmt.Printf("[!] no valid roots found")
roots = nil
}
cfg.RootCAs = roots
}
if serverName != "" {
cfg.ServerName = serverName
tlsCfg.ServerName = serverName
}
for _, site := range flag.Args() {
_, _, err := net.SplitHostPort(site)
_, _, err = net.SplitHostPort(site)
if err != nil {
site += ":443"
}
// Use proxy-aware TLS dialer
conn, err := lib.DialTLS(context.Background(), site, lib.DialerOpts{TLSConfig: cfg})
var conn *tls.Conn
conn, err = lib.DialTLS(context.Background(), site, lib.DialerOpts{TLSConfig: tlsCfg})
die.If(err)
cs := conn.ConnectionState()