cmd: cleaning up programs

This commit is contained in:
2025-11-15 23:17:40 -08:00
parent ed8c07c1c5
commit c99ffd4394
3 changed files with 183 additions and 136 deletions

View File

@@ -450,6 +450,8 @@ linters:
linters: [ forbidigo ] linters: [ forbidigo ]
- path: 'logging/example_test.go' - path: 'logging/example_test.go'
linters: [ testableexamples ] linters: [ testableexamples ]
- path: 'main.go'
linters: [ forbidigo, mnd ]
- source: 'TODO' - source: 'TODO'
linters: [ godot ] linters: [ godot ]
- text: 'should have a package comment' - text: 'should have a package comment'

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"flag" "flag"
"fmt" "fmt"
"net" "net"
@@ -28,10 +29,16 @@ func connect(addr string, dport string, six bool, timeout time.Duration) error {
if verbose { if verbose {
fmt.Printf("connecting to %s/%s... ", addr, proto) fmt.Printf("connecting to %s/%s... ", addr, proto)
os.Stdout.Sync() if err = os.Stdout.Sync(); err != nil {
return err
}
} }
conn, err := net.DialTimeout(proto, addr, timeout) dialer := &net.Dialer{
Timeout: timeout,
}
conn, err := dialer.DialContext(context.Background(), proto, addr)
if err != nil { if err != nil {
if verbose { if verbose {
fmt.Println("failed.") fmt.Println("failed.")
@@ -42,8 +49,8 @@ func connect(addr string, dport string, six bool, timeout time.Duration) error {
if verbose { if verbose {
fmt.Println("OK") fmt.Println("OK")
} }
conn.Close()
return nil return conn.Close()
} }
func main() { func main() {

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"crypto/x509" "crypto/x509"
"embed" "embed"
"errors"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
@@ -14,22 +15,22 @@ import (
// loadCertsFromFile attempts to parse certificates from a file that may be in // loadCertsFromFile attempts to parse certificates from a file that may be in
// PEM or DER/PKCS#7 format. Returns the parsed certificates or an error. // PEM or DER/PKCS#7 format. Returns the parsed certificates or an error.
func loadCertsFromFile(path string) ([]*x509.Certificate, error) { func loadCertsFromFile(path string) ([]*x509.Certificate, error) {
var certs []*x509.Certificate
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Try PEM first if certs, err = certlib.ParseCertificatesPEM(data); err == nil {
if certs, err := certlib.ParseCertificatesPEM(data); err == nil {
return certs, nil return certs, nil
} }
// Try DER/PKCS7/PKCS12 (with no password) if certs, _, err = certlib.ParseCertificatesDER(data, ""); err == nil {
if certs, _, err := certlib.ParseCertificatesDER(data, ""); err == nil {
return certs, nil return certs, nil
} else {
return nil, err
} }
return nil, err
} }
func makePoolFromFile(path string) (*x509.CertPool, error) { func makePoolFromFile(path string) (*x509.CertPool, error) {
@@ -56,49 +57,50 @@ var embeddedTestdata embed.FS
// loadCertsFromBytes attempts to parse certificates from bytes that may be in // loadCertsFromBytes attempts to parse certificates from bytes that may be in
// PEM or DER/PKCS#7 format. // PEM or DER/PKCS#7 format.
func loadCertsFromBytes(data []byte) ([]*x509.Certificate, error) { func loadCertsFromBytes(data []byte) ([]*x509.Certificate, error) {
// Try PEM first certs, err := certlib.ParseCertificatesPEM(data)
if certs, err := certlib.ParseCertificatesPEM(data); err == nil { if err == nil {
return certs, nil return certs, nil
} }
// Try DER/PKCS7/PKCS12 (with no password)
if certs, _, err := certlib.ParseCertificatesDER(data, ""); err == nil { certs, _, err = certlib.ParseCertificatesDER(data, "")
if err == nil {
return certs, nil return certs, nil
} else {
return nil, err
} }
return nil, err
} }
func makePoolFromBytes(data []byte) (*x509.CertPool, error) { func makePoolFromBytes(data []byte) (*x509.CertPool, error) {
certs, err := loadCertsFromBytes(data) certs, err := loadCertsFromBytes(data)
if err != nil || len(certs) == 0 { if err != nil || len(certs) == 0 {
return nil, fmt.Errorf("failed to load CA certificates from embedded bytes") return nil, errors.New("failed to load CA certificates from embedded bytes")
} }
pool := x509.NewCertPool() pool := x509.NewCertPool()
for _, c := range certs { for _, c := range certs {
pool.AddCert(c) pool.AddCert(c)
} }
return pool, nil return pool, nil
} }
// isSelfSigned returns true if the given certificate is self-signed. // isSelfSigned returns true if the given certificate is self-signed.
// It checks that the subject and issuer match and that the certificate's // It checks that the subject and issuer match and that the certificate's
// signature verifies against its own public key. // signature verifies against its own public key.
func isSelfSigned(cert *x509.Certificate) bool { func isSelfSigned(cert *x509.Certificate) bool {
if cert == nil { if cert == nil {
return false return false
} }
// Quick check: subject and issuer match // Quick check: subject and issuer match
if cert.Subject.String() != cert.Issuer.String() { if cert.Subject.String() != cert.Issuer.String() {
return false return false
} }
// Cryptographic check: the certificate is signed by itself // Cryptographic check: the certificate is signed by itself
if err := cert.CheckSignatureFrom(cert); err != nil { if err := cert.CheckSignatureFrom(cert); err != nil {
return false return false
} }
return true return true
} }
func verifyAgainstCA(caPool *x509.CertPool, path string) (ok bool, expiry string) { func verifyAgainstCA(caPool *x509.CertPool, path string) (bool, string) {
certs, err := loadCertsFromFile(path) certs, err := loadCertsFromFile(path)
if err != nil || len(certs) == 0 { if err != nil || len(certs) == 0 {
return false, "" return false, ""
@@ -117,14 +119,14 @@ func verifyAgainstCA(caPool *x509.CertPool, path string) (ok bool, expiry string
Intermediates: ints, Intermediates: ints,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
} }
if _, err := leaf.Verify(opts); err != nil { if _, err = leaf.Verify(opts); err != nil {
return false, "" return false, ""
} }
return true, leaf.NotAfter.Format("2006-01-02") return true, leaf.NotAfter.Format("2006-01-02")
} }
func verifyAgainstCABytes(caPool *x509.CertPool, certData []byte) (ok bool, expiry string) { func verifyAgainstCABytes(caPool *x509.CertPool, certData []byte) (bool, string) {
certs, err := loadCertsFromBytes(certData) certs, err := loadCertsFromBytes(certData)
if err != nil || len(certs) == 0 { if err != nil || len(certs) == 0 {
return false, "" return false, ""
@@ -143,92 +145,159 @@ func verifyAgainstCABytes(caPool *x509.CertPool, certData []byte) (ok bool, expi
Intermediates: ints, Intermediates: ints,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
} }
if _, err := leaf.Verify(opts); err != nil { if _, err = leaf.Verify(opts); err != nil {
return false, "" return false, ""
} }
return true, leaf.NotAfter.Format("2006-01-02") return true, leaf.NotAfter.Format("2006-01-02")
} }
// selftest runs built-in validation using embedded certificates. type testCase struct {
func selftest() int { name string
type testCase struct { caFile string
name string certFile string
caFile string expectOK bool
certFile string }
expectOK bool
func (tc testCase) Run() error {
caBytes, err := embeddedTestdata.ReadFile(tc.caFile)
if err != nil {
return fmt.Errorf("selftest: failed to read embedded %s: %w", tc.caFile, err)
} }
cases := []testCase{ certBytes, err := embeddedTestdata.ReadFile(tc.certFile)
{name: "ISRG Root X1 validates LE E7", caFile: "testdata/isrg-root-x1.pem", certFile: "testdata/le-e7.pem", expectOK: true}, if err != nil {
{name: "ISRG Root X1 does NOT validate Google WR2", caFile: "testdata/isrg-root-x1.pem", certFile: "testdata/goog-wr2.pem", expectOK: false}, return fmt.Errorf("selftest: failed to read embedded %s: %w", tc.certFile, err)
{name: "GTS R1 validates Google WR2", caFile: "testdata/gts-r1.pem", certFile: "testdata/goog-wr2.pem", expectOK: true}, }
{name: "GTS R1 does NOT validate LE E7", caFile: "testdata/gts-r1.pem", certFile: "testdata/le-e7.pem", expectOK: false},
}
failures := 0 pool, err := makePoolFromBytes(caBytes)
for _, tc := range cases { if err != nil || pool == nil {
caBytes, err := embeddedTestdata.ReadFile(tc.caFile) return fmt.Errorf("selftest: failed to build CA pool for %s: %w", tc.caFile, err)
}
ok, exp := verifyAgainstCABytes(pool, certBytes)
if ok != tc.expectOK {
return fmt.Errorf("%s: unexpected result: got %v, want %v", tc.name, ok, tc.expectOK)
}
if ok {
fmt.Printf("%s: OK (expires %s)\n", tc.name, exp)
}
fmt.Printf("%s: INVALID (as expected)\n", tc.name)
return nil
}
var cases = []testCase{
{
name: "ISRG Root X1 validates LE E7",
caFile: "testdata/isrg-root-x1.pem",
certFile: "testdata/le-e7.pem",
expectOK: true,
},
{
name: "ISRG Root X1 does NOT validate Google WR2",
caFile: "testdata/isrg-root-x1.pem",
certFile: "testdata/goog-wr2.pem",
expectOK: false,
},
{
name: "GTS R1 validates Google WR2",
caFile: "testdata/gts-r1.pem",
certFile: "testdata/goog-wr2.pem",
expectOK: true,
},
{
name: "GTS R1 does NOT validate LE E7",
caFile: "testdata/gts-r1.pem",
certFile: "testdata/le-e7.pem",
expectOK: false,
},
}
// selftest runs built-in validation using embedded certificates.
func selftest() int {
failures := 0
for _, tc := range cases {
err := tc.Run()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "selftest: failed to read embedded %s: %v\n", tc.caFile, err) fmt.Fprintln(os.Stderr, err)
failures++ failures++
continue continue
} }
certBytes, err := embeddedTestdata.ReadFile(tc.certFile) }
// Verify that both embedded root CAs are detected as self-signed
roots := []string{"testdata/gts-r1.pem", "testdata/isrg-root-x1.pem"}
for _, root := range roots {
b, err := embeddedTestdata.ReadFile(root)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "selftest: failed to read embedded %s: %v\n", tc.certFile, err) fmt.Fprintf(os.Stderr, "selftest: failed to read embedded %s: %v\n", root, err)
failures++ failures++
continue continue
} }
pool, err := makePoolFromBytes(caBytes) certs, err := loadCertsFromBytes(b)
if err != nil || pool == nil { if err != nil || len(certs) == 0 {
fmt.Fprintf(os.Stderr, "selftest: failed to build CA pool for %s: %v\n", tc.caFile, err) fmt.Fprintf(os.Stderr, "selftest: failed to parse cert(s) from %s: %v\n", root, err)
failures++ failures++
continue continue
} }
ok, exp := verifyAgainstCABytes(pool, certBytes) leaf := certs[0]
if ok != tc.expectOK { if isSelfSigned(leaf) {
fmt.Printf("%s: unexpected result: got %v, want %v\n", tc.name, ok, tc.expectOK) fmt.Printf("%s: SELF-SIGNED (as expected)\n", root)
failures++
} else { } else {
if ok { fmt.Printf("%s: expected SELF-SIGNED, but was not detected as such\n", root)
fmt.Printf("%s: OK (expires %s)\n", tc.name, exp) failures++
} else {
fmt.Printf("%s: INVALID (as expected)\n", tc.name)
}
} }
} }
// Verify that both embedded root CAs are detected as self-signed if failures == 0 {
roots := []string{"testdata/gts-r1.pem", "testdata/isrg-root-x1.pem"} fmt.Println("selftest: PASS")
for _, root := range roots { return 0
b, err := embeddedTestdata.ReadFile(root) }
if err != nil { fmt.Fprintf(os.Stderr, "selftest: FAIL (%d failure(s))\n", failures)
fmt.Fprintf(os.Stderr, "selftest: failed to read embedded %s: %v\n", root, err) return 1
failures++ }
continue
}
certs, err := loadCertsFromBytes(b)
if err != nil || len(certs) == 0 {
fmt.Fprintf(os.Stderr, "selftest: failed to parse cert(s) from %s: %v\n", root, err)
failures++
continue
}
leaf := certs[0]
if isSelfSigned(leaf) {
fmt.Printf("%s: SELF-SIGNED (as expected)\n", root)
} else {
fmt.Printf("%s: expected SELF-SIGNED, but was not detected as such\n", root)
failures++
}
}
if failures == 0 { // expiryString returns a YYYY-MM-DD date string to display for certificate
fmt.Println("selftest: PASS") // expiry. If an explicit exp string is provided, it is used. Otherwise, if a
return 0 // leaf certificate is available, its NotAfter is formatted. As a last resort,
} // it falls back to today's date (should not normally happen).
fmt.Fprintf(os.Stderr, "selftest: FAIL (%d failure(s))\n", failures) func expiryString(leaf *x509.Certificate, exp string) string {
return 1 if exp != "" {
return exp
}
if leaf != nil {
return leaf.NotAfter.Format("2006-01-02")
}
return time.Now().Format("2006-01-02")
}
// processCert verifies a single certificate file against the provided CA pool
// and prints the result in the required format, handling self-signed
// certificates specially.
func processCert(caPool *x509.CertPool, certPath string) {
ok, exp := verifyAgainstCA(caPool, certPath)
name := filepath.Base(certPath)
// Try to load the leaf cert for self-signed detection and expiry fallback
var leaf *x509.Certificate
if certs, err := loadCertsFromFile(certPath); err == nil && len(certs) > 0 {
leaf = certs[0]
}
// Prefer the SELF-SIGNED label if applicable
if isSelfSigned(leaf) {
fmt.Printf("%s: SELF-SIGNED\n", name)
return
}
if ok {
fmt.Printf("%s: OK (expires %s)\n", name, expiryString(leaf, exp))
return
}
fmt.Printf("%s: INVALID\n", name)
} }
func main() { func main() {
@@ -250,38 +319,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
for _, certPath := range os.Args[2:] { for _, certPath := range os.Args[2:] {
ok, exp := verifyAgainstCA(caPool, certPath) processCert(caPool, certPath)
name := filepath.Base(certPath) }
// Load the leaf once for self-signed detection and potential expiry fallback
var leaf *x509.Certificate
if certs, err := loadCertsFromFile(certPath); err == nil && len(certs) > 0 {
leaf = certs[0]
}
// If the certificate is self-signed, prefer the SELF-SIGNED label
if isSelfSigned(leaf) {
fmt.Printf("%s: SELF-SIGNED\n", name)
continue
}
if ok {
// Display with the requested format
// Example: file: OK (expires 2031-01-01)
// Ensure deterministic date formatting
// Note: no timezone displayed; date only as per example
// If exp ended up empty for some reason, recompute safely
if exp == "" {
if leaf != nil {
exp = leaf.NotAfter.Format("2006-01-02")
} else {
// fallback to the current date to avoid empty; though shouldn't happen
exp = time.Now().Format("2006-01-02")
}
}
fmt.Printf("%s: OK (expires %s)\n", name, exp)
} else {
fmt.Printf("%s: INVALID\n", name)
}
}
} }