linter fixes.

This commit is contained in:
2025-11-19 01:47:42 -08:00
parent b17fad4334
commit 7426988ae4
13 changed files with 75 additions and 48 deletions

View File

@@ -101,7 +101,7 @@ linters:
- loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap) - loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap)
- makezero # finds slice declarations with non-zero initial length - makezero # finds slice declarations with non-zero initial length
- mirror # reports wrong mirror patterns of bytes/strings usage - mirror # reports wrong mirror patterns of bytes/strings usage
- mnd # detects magic numbers # - mnd # detects magic numbers
- modernize # suggests simplifications to Go code, using modern language and library features - modernize # suggests simplifications to Go code, using modern language and library features
- musttag # enforces field tags in (un)marshaled structs - musttag # enforces field tags in (un)marshaled structs
- nakedret # finds naked returns in functions greater than a specified function length - nakedret # finds naked returns in functions greater than a specified function length

View File

@@ -158,7 +158,11 @@ func (p Profile) templateFromRequest(req *x509.CertificateRequest) (*x509.Certif
return certTemplate, nil return certTemplate, nil
} }
func (p Profile) SignRequest(parent *x509.Certificate, req *x509.CertificateRequest, priv crypto.PrivateKey) (*x509.Certificate, error) { func (p Profile) SignRequest(
parent *x509.Certificate,
req *x509.CertificateRequest,
priv crypto.PrivateKey,
) (*x509.Certificate, error) {
tpl, err := p.templateFromRequest(req) tpl, err := p.templateFromRequest(req)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create certificate template: %w", err) return nil, fmt.Errorf("failed to create certificate template: %w", err)

View File

@@ -8,14 +8,13 @@ import (
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"fmt" "fmt"
) )
var ( // var (
oidEd25519 = asn1.ObjectIdentifier{1, 3, 101, 110} // oidEd25519 = asn1.ObjectIdentifier{1, 3, 101, 110}
) //)
func GenerateKey(algorithm x509.PublicKeyAlgorithm, bitSize int) (crypto.PublicKey, crypto.PrivateKey, error) { func GenerateKey(algorithm x509.PublicKeyAlgorithm, bitSize int) (crypto.PublicKey, crypto.PrivateKey, error) {
var key crypto.PrivateKey var key crypto.PrivateKey
@@ -28,7 +27,12 @@ func GenerateKey(algorithm x509.PublicKeyAlgorithm, bitSize int) (crypto.PublicK
case x509.Ed25519: case x509.Ed25519:
key, err = rsa.GenerateKey(rand.Reader, bitSize) key, err = rsa.GenerateKey(rand.Reader, bitSize)
if err == nil { if err == nil {
pub = key.(*rsa.PrivateKey).Public() rsaPriv, ok := key.(*rsa.PrivateKey)
if !ok {
panic("failed to cast RSA private key to *rsa.PrivateKey")
}
pub = rsaPriv.Public()
} }
case x509.ECDSA: case x509.ECDSA:
var curve elliptic.Curve var curve elliptic.Curve
@@ -46,8 +50,17 @@ func GenerateKey(algorithm x509.PublicKeyAlgorithm, bitSize int) (crypto.PublicK
key, err = ecdsa.GenerateKey(curve, rand.Reader) key, err = ecdsa.GenerateKey(curve, rand.Reader)
if err == nil { if err == nil {
pub = key.(*ecdsa.PrivateKey).Public() ecPriv, ok := key.(*ecdsa.PrivateKey)
if !ok {
panic("failed to cast ECDSA private key to *ecdsa.PrivateKey")
}
pub = ecPriv.Public()
} }
case x509.DSA:
fallthrough
case x509.UnknownPublicKeyAlgorithm:
fallthrough
default: default:
err = errors.New("unsupported algorithm") err = errors.New("unsupported algorithm")
} }

View File

@@ -54,8 +54,6 @@ var extKeyUsages = map[x509.ExtKeyUsage]string{
x509.ExtKeyUsageMicrosoftKernelCodeSigning: "microsoft kernel code signing", x509.ExtKeyUsageMicrosoftKernelCodeSigning: "microsoft kernel code signing",
} }
func sigAlgoPK(a x509.SignatureAlgorithm) string { func sigAlgoPK(a x509.SignatureAlgorithm) string {
switch a { switch a {
case x509.MD2WithRSA, x509.MD5WithRSA, x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: case x509.MD2WithRSA, x509.MD5WithRSA, x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:

View File

@@ -1,6 +1,10 @@
package certlib package certlib_test
import "testing" import (
"testing"
"git.wntrmute.dev/kyle/goutils/certlib"
)
var ( var (
testCert1 = "testdata/cert1.pem" testCert1 = "testdata/cert1.pem"
@@ -16,25 +20,25 @@ type testCase struct {
} }
var testCases = []testCase{ var testCases = []testCase{
{"testdata/cert1.pem", "testdata/priv1.pem", true}, {testCert1, testPriv1, true},
{"testdata/cert2.pem", "testdata/priv2.pem", true}, {testCert2, testPriv2, true},
{"testdata/cert1.pem", "testdata/priv2.pem", false}, {testCert1, testPriv2, false},
{"testdata/cert2.pem", "testdata/priv1.pem", false}, {testCert2, testPriv1, false},
} }
func TestMatchKeys(t *testing.T) { func TestMatchKeys(t *testing.T) {
for i, tc := range testCases { for i, tc := range testCases {
cert, err := LoadCertificate(tc.cert) cert, err := certlib.LoadCertificate(tc.cert)
if err != nil { if err != nil {
t.Fatalf("failed to load cert %d: %v", i, err) t.Fatalf("failed to load cert %d: %v", i, err)
} }
priv, err := LoadPrivateKey(tc.key) priv, err := certlib.LoadPrivateKey(tc.key)
if err != nil { if err != nil {
t.Fatalf("failed to load key %d: %v", i, err) t.Fatalf("failed to load key %d: %v", i, err)
} }
ok, _ := MatchKeys(cert, priv) ok, _ := certlib.MatchKeys(cert, priv)
switch { switch {
case ok && !tc.match: case ok && !tc.match:
t.Fatalf("case %d: cert %s/key %s should not match", i, tc.cert, tc.key) t.Fatalf("case %d: cert %s/key %s should not match", i, tc.cert, tc.key)

View File

@@ -39,7 +39,7 @@ func main() {
revoke.HardFail = hardfail revoke.HardFail = hardfail
// Build a proxy-aware HTTP client for OCSP/CRL fetches // Build a proxy-aware HTTP client for OCSP/CRL fetches
if httpClient, err := dialer.NewHTTPClient(dialer.DialerOpts{Timeout: timeout}); err == nil { if httpClient, err := dialer.NewHTTPClient(dialer.Opts{Timeout: timeout}); err == nil {
revoke.HTTPClient = httpClient revoke.HTTPClient = httpClient
} }
@@ -105,7 +105,7 @@ func checkSite(hostport string) (string, error) {
defer cancel() defer cancel()
// Use proxy-aware TLS dialer // Use proxy-aware TLS dialer
conn, err := dialer.DialTLS(ctx, target.String(), dialer.DialerOpts{Timeout: timeout, TLSConfig: &tls.Config{ conn, err := dialer.DialTLS(ctx, target.String(), dialer.Opts{Timeout: timeout, TLSConfig: &tls.Config{
InsecureSkipVerify: true, // #nosec G402 -- CLI tool only verifies revocation InsecureSkipVerify: true, // #nosec G402 -- CLI tool only verifies revocation
ServerName: target.Host, ServerName: target.Host,
}}) }})

View File

@@ -25,7 +25,11 @@ func main() {
} }
// Use proxy-aware TLS dialer // Use proxy-aware TLS dialer
conn, err := dialer.DialTLS(context.Background(), server, dialer.DialerOpts{TLSConfig: &tls.Config{}}) // #nosec G402 conn, err := dialer.DialTLS(
context.Background(),
server,
dialer.Opts{TLSConfig: &tls.Config{}},
) // #nosec G402
die.If(err) die.If(err)
defer conn.Close() defer conn.Close()

View File

@@ -85,7 +85,7 @@ func main() {
continue continue
} }
// Use proxy-aware HTTP client with a reasonable timeout for connects/handshakes // Use proxy-aware HTTP client with a reasonable timeout for connects/handshakes
httpClient, err := dialer.NewHTTPClient(dialer.DialerOpts{Timeout: 30 * time.Second}) httpClient, err := dialer.NewHTTPClient(dialer.Opts{Timeout: 30 * time.Second})
if err != nil { if err != nil {
_, _ = lib.Warn(err, "building HTTP client for %s", remote) _, _ = lib.Warn(err, "building HTTP client for %s", remote)
continue continue

View File

@@ -43,7 +43,7 @@ func main() {
} }
var conn *tls.Conn var conn *tls.Conn
conn, err = dialer.DialTLS(context.Background(), site, dialer.DialerOpts{TLSConfig: tlsCfg}) conn, err = dialer.DialTLS(context.Background(), site, dialer.Opts{TLSConfig: tlsCfg})
die.If(err) die.If(err)
cs := conn.ConnectionState() cs := conn.ConnectionState()

View File

@@ -25,7 +25,7 @@ func main() {
conn, err := dialer.DialTLS( conn, err := dialer.DialTLS(
context.Background(), context.Background(),
hostPort.String(), hostPort.String(),
dialer.DialerOpts{TLSConfig: &tls.Config{InsecureSkipVerify: true}}, dialer.Opts{TLSConfig: &tls.Config{InsecureSkipVerify: true}},
) // #nosec G402 ) // #nosec G402
die.If(err) die.If(err)

View File

@@ -1,5 +1,5 @@
// Package lib contains reusable helpers. This file provides proxy-aware // Package dialer provides proxy-aware dialers for plain TCP and TLS
// dialers for plain TCP and TLS connections using environment variables. // connections using environment variables.
// //
// Supported proxy environment variables (checked case-insensitively): // Supported proxy environment variables (checked case-insensitively):
// - SOCKS5_PROXY (e.g., socks5://user:pass@host:1080) // - SOCKS5_PROXY (e.g., socks5://user:pass@host:1080)
@@ -66,7 +66,7 @@ func BaselineTLSConfig(skipVerify bool, secure bool) (*tls.Config, error) {
var debug = dbg.NewFromEnv() var debug = dbg.NewFromEnv()
// DialerOpts controls creation of proxy-aware dialers. // Opts controls creation of proxy-aware dialers.
// //
// Timeout controls the maximum amount of time spent establishing the // Timeout controls the maximum amount of time spent establishing the
// underlying TCP connection and any proxy handshake. If zero, a // underlying TCP connection and any proxy handshake. If zero, a
@@ -75,7 +75,7 @@ var debug = dbg.NewFromEnv()
// TLSConfig is used by the TLS dialer to configure the TLS handshake to // TLSConfig is used by the TLS dialer to configure the TLS handshake to
// the target endpoint. If TLSConfig.ServerName is empty, it will be set // the target endpoint. If TLSConfig.ServerName is empty, it will be set
// from the host portion of the address passed to DialContext. // from the host portion of the address passed to DialContext.
type DialerOpts struct { type Opts struct {
Timeout time.Duration Timeout time.Duration
TLSConfig *tls.Config TLSConfig *tls.Config
} }
@@ -88,7 +88,7 @@ type ContextDialer interface {
// DialTCP is a convenience helper that dials a TCP connection to address // DialTCP is a convenience helper that dials a TCP connection to address
// using a proxy-aware dialer derived from opts. It honors SOCKS5_PROXY, // using a proxy-aware dialer derived from opts. It honors SOCKS5_PROXY,
// HTTPS_PROXY, and HTTP_PROXY environment variables. // HTTPS_PROXY, and HTTP_PROXY environment variables.
func DialTCP(ctx context.Context, address string, opts DialerOpts) (net.Conn, error) { func DialTCP(ctx context.Context, address string, opts Opts) (net.Conn, error) {
d, err := NewNetDialer(opts) d, err := NewNetDialer(opts)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -100,7 +100,7 @@ func DialTCP(ctx context.Context, address string, opts DialerOpts) (net.Conn, er
// address using a proxy-aware dialer derived from opts. It returns a *tls.Conn. // address using a proxy-aware dialer derived from opts. It returns a *tls.Conn.
// It honors SOCKS5_PROXY, HTTPS_PROXY, and HTTP_PROXY environment variables and // It honors SOCKS5_PROXY, HTTPS_PROXY, and HTTP_PROXY environment variables and
// uses opts.TLSConfig for the handshake (filling ServerName from address if empty). // uses opts.TLSConfig for the handshake (filling ServerName from address if empty).
func DialTLS(ctx context.Context, address string, opts DialerOpts) (*tls.Conn, error) { func DialTLS(ctx context.Context, address string, opts Opts) (*tls.Conn, error) {
d, err := NewTLSDialer(opts) d, err := NewTLSDialer(opts)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -123,7 +123,7 @@ func DialTLS(ctx context.Context, address string, opts DialerOpts) (*tls.Conn, e
// proxies discovered from the environment (SOCKS5_PROXY, HTTPS_PROXY, HTTP_PROXY). // proxies discovered from the environment (SOCKS5_PROXY, HTTPS_PROXY, HTTP_PROXY).
// The returned dialer supports context cancellation for direct and HTTP(S) // The returned dialer supports context cancellation for direct and HTTP(S)
// proxies and applies the configured timeout to connection/proxy handshake. // proxies and applies the configured timeout to connection/proxy handshake.
func NewNetDialer(opts DialerOpts) (ContextDialer, error) { func NewNetDialer(opts Opts) (ContextDialer, error) {
if opts.Timeout <= 0 { if opts.Timeout <= 0 {
opts.Timeout = 30 * time.Second opts.Timeout = 30 * time.Second
} }
@@ -165,7 +165,7 @@ func NewNetDialer(opts DialerOpts) (ContextDialer, error) {
// //
// The returned dialer performs proxy negotiation (if any), then completes a // The returned dialer performs proxy negotiation (if any), then completes a
// TLS handshake to the target using opts.TLSConfig. // TLS handshake to the target using opts.TLSConfig.
func NewTLSDialer(opts DialerOpts) (ContextDialer, error) { func NewTLSDialer(opts Opts) (ContextDialer, error) {
if opts.Timeout <= 0 { if opts.Timeout <= 0 {
opts.Timeout = 30 * time.Second opts.Timeout = 30 * time.Second
} }
@@ -247,7 +247,7 @@ func getProxyURLFromEnv(name string) *url.URL {
// HTTPS_PROXY, and NO_PROXY/no_proxy. // HTTPS_PROXY, and NO_PROXY/no_proxy.
// - Connection and TLS handshake timeouts are derived from opts.Timeout. // - Connection and TLS handshake timeouts are derived from opts.Timeout.
// - For HTTPS targets, opts.TLSConfig is applied to the transport. // - For HTTPS targets, opts.TLSConfig is applied to the transport.
func NewHTTPClient(opts DialerOpts) (*http.Client, error) { func NewHTTPClient(opts Opts) (*http.Client, error) {
if opts.Timeout <= 0 { if opts.Timeout <= 0 {
opts.Timeout = 30 * time.Second opts.Timeout = 30 * time.Second
} }
@@ -422,7 +422,7 @@ func drainHeaders(br *bufio.Reader) error {
} }
// newSOCKS5Dialer builds a context-aware wrapper over the x/net/proxy dialer. // newSOCKS5Dialer builds a context-aware wrapper over the x/net/proxy dialer.
func newSOCKS5Dialer(u *url.URL, opts DialerOpts) (ContextDialer, error) { func newSOCKS5Dialer(u *url.URL, opts Opts) (ContextDialer, error) {
var auth *xproxy.Auth var auth *xproxy.Auth
if u.User != nil { if u.User != nil {
user := u.User.Username() user := u.User.Username()
@@ -468,8 +468,8 @@ func (s *socks5ContextDialer) DialContext(ctx context.Context, network, address
// tlsWrappingDialer performs a TLS handshake over an existing base dialer. // tlsWrappingDialer performs a TLS handshake over an existing base dialer.
type tlsWrappingDialer struct { type tlsWrappingDialer struct {
base ContextDialer base ContextDialer
tcfg *tls.Config tcfg *tls.Config
timeout time.Duration timeout time.Duration
} }

View File

@@ -67,7 +67,7 @@ func (sf *ServerFetcher) String() string {
} }
func (sf *ServerFetcher) GetChain() ([]*x509.Certificate, error) { func (sf *ServerFetcher) GetChain() ([]*x509.Certificate, error) {
opts := dialer.DialerOpts{ opts := dialer.Opts{
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
InsecureSkipVerify: sf.insecure, // #nosec G402 - no shit sherlock InsecureSkipVerify: sf.insecure, // #nosec G402 - no shit sherlock
RootCAs: sf.roots, RootCAs: sf.roots,

View File

@@ -3,6 +3,7 @@ package lib
import ( import (
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
@@ -118,6 +119,8 @@ func IsDigit(b byte) bool {
return b >= '0' && b <= '9' return b >= '0' && b <= '9'
} }
const signedaMask64 = 1<<63 - 1
// ParseDuration parses a duration string into a time.Duration. // ParseDuration parses a duration string into a time.Duration.
// It supports standard units (ns, us/µs, ms, s, m, h) plus extended units: // It supports standard units (ns, us/µs, ms, s, m, h) plus extended units:
// d (days, 24h), w (weeks, 7d), y (years, 365d). // d (days, 24h), w (weeks, 7d), y (years, 365d).
@@ -127,7 +130,7 @@ func IsDigit(b byte) bool {
func ParseDuration(s string) (time.Duration, error) { func ParseDuration(s string) (time.Duration, error) {
s = strings.ToLower(s) // Normalize to lowercase for case-insensitivity. s = strings.ToLower(s) // Normalize to lowercase for case-insensitivity.
if s == "" { if s == "" {
return 0, fmt.Errorf("empty duration string") return 0, errors.New("empty duration string")
} }
var total time.Duration var total time.Duration
@@ -165,23 +168,24 @@ func ParseDuration(s string) (time.Duration, error) {
var d time.Duration var d time.Duration
switch unit { switch unit {
case "ns": case "ns":
d = time.Nanosecond * time.Duration(num) d = time.Nanosecond * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "us", "µs": case "us", "µs":
d = time.Microsecond * time.Duration(num) d = time.Microsecond * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "ms": case "ms":
d = time.Millisecond * time.Duration(num) d = time.Millisecond * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "s": case "s":
d = time.Second * time.Duration(num) d = time.Second * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "m": case "m":
d = time.Minute * time.Duration(num) d = time.Minute * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "h": case "h":
d = time.Hour * time.Duration(num) d = time.Hour * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "d": case "d":
d = 24 * time.Hour * time.Duration(num) d = 24 * time.Hour * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "w": case "w":
d = 7 * 24 * time.Hour * time.Duration(num) d = 7 * 24 * time.Hour * time.Duration(num&signedaMask64) // #nosec G115 - masked off
case "y": case "y":
d = 365 * 24 * time.Hour * time.Duration(num) // Approximate, non-leap year. // Approximate, non-leap year.
d = 365 * 24 * time.Hour * time.Duration(num&signedaMask64) // #nosec G115 - masked off;
default: default:
return 0, fmt.Errorf("unknown unit %q at position %d", s[unitStart:i], unitStart) return 0, fmt.Errorf("unknown unit %q at position %d", s[unitStart:i], unitStart)
} }