cmd: continuing linter fixes

This commit is contained in:
2025-11-16 02:54:02 -08:00
parent 0f77bd49dc
commit 3ad562b6fa
29 changed files with 319 additions and 175 deletions

View File

@@ -242,6 +242,10 @@ linters:
check-type-assertions: true
exclude-functions:
- (*git.wntrmute.dev/kyle/goutils/sbuf.Buffer).Write
- git.wntrmute.dev/kyle/goutils/lib.Warn
- git.wntrmute.dev/kyle/goutils/lib.Warnx
- git.wntrmute.dev/kyle/goutils/lib.Err
- git.wntrmute.dev/kyle/goutils/lib.Errx
exhaustive:
# Program elements to check for exhaustiveness.
@@ -333,6 +337,12 @@ linters:
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#no-unused-link
- no-unused-link
gosec:
excludes:
- G104 # handled by errcheck
- G301
- G306
govet:
# Enable all analyzers.
# Default: false
@@ -368,6 +378,12 @@ linters:
- os.WriteFile
- prometheus.ExponentialBuckets.*
- prometheus.LinearBuckets
ignored-numbers:
- 1
- 2
- 3
- 4
- 8
nakedret:
# Make an issue if func has more lines of code than this setting, and it has naked returns.
@@ -436,6 +452,8 @@ linters:
# Omit embedded fields from selector expression.
# https://staticcheck.dev/docs/checks/#QF1008
- -QF1008
# We often explicitly enable old/deprecated ciphers for research.
- -SA1019
usetesting:
# Enable/disable `os.TempDir()` detections.

View File

@@ -458,8 +458,6 @@ func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) {
}
if procType, ok := keyDER.Headers["Proc-Type"]; ok && strings.Contains(procType, "ENCRYPTED") {
if password != nil {
// nolintlint requires rationale:
//nolint:staticcheck // legacy RFC1423 PEM encryption supported for backward compatibility when caller supplies a password
return x509.DecryptPEMBlock(keyDER, password)
}
return nil, certerr.DecodeError(certerr.ErrorSourcePrivateKey, certerr.ErrEncryptedPrivateKey)

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"crypto/tls"
"encoding/pem"
"flag"
@@ -22,22 +23,26 @@ func main() {
server += ":443"
}
var chain string
conn, err := tls.Dial("tcp", server, nil)
d := &tls.Dialer{Config: &tls.Config{}} // #nosec G402
nc, err := d.DialContext(context.Background(), "tcp", server)
die.If(err)
conn, ok := nc.(*tls.Conn)
if !ok {
die.With("invalid TLS connection (not a *tls.Conn)")
}
defer conn.Close()
details := conn.ConnectionState()
var chainSb30 strings.Builder
var chain strings.Builder
for _, cert := range details.PeerCertificates {
p := pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
chainSb30.WriteString(string(pem.EncodeToMemory(&p)))
chain.Write(pem.EncodeToMemory(&p))
}
chain += chainSb30.String()
fmt.Fprintln(os.Stdout, chain)
fmt.Fprintln(os.Stdout, chain.String())
}
}

View File

@@ -3,6 +3,7 @@ package main
import (
"bytes"
"context"
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
@@ -246,18 +247,34 @@ func displayAllCerts(in []byte, leafOnly bool) {
func displayAllCertsWeb(uri string, leafOnly bool) {
ci := getConnInfo(uri)
conn, err := tls.Dial("tcp", ci.Addr, permissiveConfig())
d := &tls.Dialer{Config: permissiveConfig()}
nc, err := d.DialContext(context.Background(), "tcp", ci.Addr)
if err != nil {
_, _ = lib.Warn(err, "couldn't connect to %s", ci.Addr)
return
}
conn, ok := nc.(*tls.Conn)
if !ok {
_, _ = lib.Warnx("invalid TLS connection (not a *tls.Conn)")
return
}
defer conn.Close()
state := conn.ConnectionState()
conn.Close()
if err = conn.Close(); err != nil {
_, _ = lib.Warn(err, "couldn't close TLS connection")
}
conn, err = tls.Dial("tcp", ci.Addr, verifyConfig(ci.Host))
d = &tls.Dialer{Config: verifyConfig(ci.Host)}
nc, err = d.DialContext(context.Background(), "tcp", ci.Addr)
if err == nil {
conn, ok = nc.(*tls.Conn)
if !ok {
_, _ = lib.Warnx("invalid TLS connection (not a *tls.Conn)")
return
}
err = conn.VerifyHostname(ci.Host)
if err == nil {
state = conn.ConnectionState()
@@ -293,6 +310,32 @@ func displayAllCertsWeb(uri string, leafOnly bool) {
}
}
func shouldReadStdin(argc int, argv []string) bool {
if argc == 0 {
return true
}
if argc == 1 && argv[0] == "-" {
return true
}
return false
}
func readStdin(leafOnly bool) {
certs, err := io.ReadAll(os.Stdin)
if err != nil {
_, _ = lib.Warn(err, "couldn't read certificates from standard input")
os.Exit(1)
}
// This is needed for getting certs from JSON/jq.
certs = bytes.TrimSpace(certs)
certs = bytes.ReplaceAll(certs, []byte(`\n`), []byte{0xa})
certs = bytes.Trim(certs, `"`)
displayAllCerts(certs, leafOnly)
}
func main() {
var leafOnly bool
flag.BoolVar(&showHash, "d", false, "show hashes of raw DER contents")
@@ -300,32 +343,23 @@ func main() {
flag.BoolVar(&leafOnly, "l", false, "only show the leaf certificate")
flag.Parse()
if flag.NArg() == 0 || (flag.NArg() == 1 && flag.Arg(0) == "-") {
certs, err := io.ReadAll(os.Stdin)
if err != nil {
_, _ = lib.Warn(err, "couldn't read certificates from standard input")
os.Exit(1)
}
if shouldReadStdin(flag.NArg(), flag.Args()) {
readStdin(leafOnly)
return
}
// This is needed for getting certs from JSON/jq.
certs = bytes.TrimSpace(certs)
certs = bytes.ReplaceAll(certs, []byte(`\n`), []byte{0xa})
certs = bytes.Trim(certs, `"`)
displayAllCerts(certs, leafOnly)
} else {
for _, filename := range flag.Args() {
fmt.Fprintf(os.Stdout, "--%s ---%s", filename, "\n")
if strings.HasPrefix(filename, "https://") {
displayAllCertsWeb(filename, leafOnly)
} else {
in, err := os.ReadFile(filename)
if err != nil {
_, _ = lib.Warn(err, "couldn't read certificate")
continue
}
displayAllCerts(in, leafOnly)
for _, filename := range flag.Args() {
fmt.Fprintf(os.Stdout, "--%s ---%s", filename, "\n")
if strings.HasPrefix(filename, "https://") {
displayAllCertsWeb(filename, leafOnly)
} else {
in, err := os.ReadFile(filename)
if err != nil {
_, _ = lib.Warn(err, "couldn't read certificate")
continue
}
displayAllCerts(in, leafOnly)
}
}
}

View File

@@ -13,6 +13,11 @@ import (
// following two lifted from CFSSL, (replace-regexp "\(.+\): \(.+\),"
// "\2: \1,")
const (
sSHA256 = "SHA256"
sSHA512 = "SHA512"
)
var keyUsage = map[x509.KeyUsage]string{
x509.KeyUsageDigitalSignature: "digital signature",
x509.KeyUsageContentCommitment: "content committment",
@@ -70,19 +75,19 @@ func sigAlgoHash(a x509.SignatureAlgorithm) string {
case x509.SHA1WithRSA, x509.ECDSAWithSHA1, x509.DSAWithSHA1:
return "SHA1"
case x509.SHA256WithRSA, x509.ECDSAWithSHA256, x509.DSAWithSHA256:
return "SHA256"
return sSHA256
case x509.SHA256WithRSAPSS:
return "SHA256"
return sSHA256
case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
return "SHA384"
case x509.SHA384WithRSAPSS:
return "SHA384"
case x509.SHA512WithRSA, x509.ECDSAWithSHA512:
return "SHA512"
return sSHA512
case x509.SHA512WithRSAPSS:
return "SHA512"
return sSHA512
case x509.PureEd25519:
return "SHA512"
return sSHA512
case x509.UnknownSignatureAlgorithm:
return "unknown hash algorithm"
default:
@@ -144,14 +149,14 @@ func dumpHex(in []byte) string {
func permissiveConfig() *tls.Config {
return &tls.Config{
InsecureSkipVerify: true,
}
} // #nosec G402
}
// verifyConfig returns a config that will verify the connection.
func verifyConfig(hostname string) *tls.Config {
return &tls.Config{
ServerName: hostname,
}
} // #nosec G402
}
type connInfo struct {

View File

@@ -2,6 +2,7 @@ package main
import (
"bufio"
"context"
"errors"
"flag"
"fmt"
@@ -57,7 +58,7 @@ var modes = ssh.TerminalModes{
}
func sshAgent() ssh.AuthMethod {
a, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
a, err := (&net.Dialer{}).DialContext(context.Background(), "unix", os.Getenv("SSH_AUTH_SOCK"))
if err == nil {
return ssh.PublicKeysCallback(agent.NewClient(a).Signers)
}
@@ -116,7 +117,7 @@ func exec(wg *sync.WaitGroup, user, host string, commands []string) {
}
shutdown = append(shutdown, session.Close)
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
if err = session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
logError(host, err, "request for pty failed")
return

View File

@@ -26,7 +26,7 @@ func setupFile(hdr *tar.Header, file *os.File) error {
if verbose {
fmt.Printf("\tchmod %0#o\n", hdr.Mode)
}
err := file.Chmod(os.FileMode(hdr.Mode))
err := file.Chmod(os.FileMode(hdr.Mode & 0xFFFFFFFF)) // #nosec G115
if err != nil {
return err
}
@@ -55,7 +55,9 @@ func processFile(tfr *tar.Reader, hdr *tar.Header, top string) error {
if verbose {
fmt.Println(hdr.Name)
}
filePath := filepath.Clean(filepath.Join(top, hdr.Name))
switch hdr.Typeflag {
case tar.TypeReg:
file, err := os.Create(filePath)
@@ -109,7 +111,7 @@ func processFile(tfr *tar.Reader, hdr *tar.Header, top string) error {
return err
}
case tar.TypeDir:
err := os.MkdirAll(filePath, os.FileMode(hdr.Mode))
err := os.MkdirAll(filePath, os.FileMode(hdr.Mode&0xFFFFFFFF)) // #nosec G115
if err != nil {
return err
}
@@ -261,8 +263,9 @@ func main() {
die.If(err)
tfr := tar.NewReader(r)
var hdr *tar.Header
for {
hdr, err := tfr.Next()
hdr, err = tfr.Next()
if errors.Is(err, io.EOF) {
break
}

View File

@@ -47,7 +47,7 @@ func main() {
Bytes: out,
}
err = os.WriteFile(fileName+".pub", pem.EncodeToMemory(p), 0o644)
err = os.WriteFile(fileName+".pub", pem.EncodeToMemory(p), 0o644) // #nosec G306
die.If(err)
fmt.Fprintf(os.Stdout, "[+] wrote %s.\n", fileName+".pub")
}

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"flag"
"fmt"
"io"
@@ -152,7 +153,7 @@ func rsync(syncDir, target, excludeFile string, verboseRsync bool) error {
return err
}
cmd := exec.Command(path, args...)
cmd := exec.CommandContext(context.Background(), path, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
@@ -218,7 +219,7 @@ func main() {
if excludeFile != "" {
defer func() {
log.Infof("removing exclude file %s", excludeFile)
if err := os.Remove(excludeFile); err != nil {
if rmErr := os.Remove(excludeFile); rmErr != nil {
log.Warningf("failed to remove temp file %s", excludeFile)
}
}()

View File

@@ -30,7 +30,7 @@ func openImage(imageFile string) (*os.File, []byte, error) {
return nil, nil, err
}
if _, err := f.Seek(0, 0); err != nil {
if _, err = f.Seek(0, 0); err != nil {
return nil, nil, err
}
@@ -103,12 +103,12 @@ func main() {
die.If(err)
if !bytes.Equal(deviceHash, hash) {
fmt.Fprintln(os.Stderr, "Hash mismatch:")
fmt.Fprintf(os.Stderr, "\t%s: %s\n", imageFile, hash)
fmt.Fprintf(os.Stderr, "\t%s: %s\n", devicePath, deviceHash)
os.Exit(1)
buf := &bytes.Buffer{}
fmt.Fprintln(buf, "Hash mismatch:")
fmt.Fprintf(buf, "\t%s: %s\n", imageFile, hash)
fmt.Fprintf(buf, "\t%s: %s\n", devicePath, deviceHash)
die.With(buf.String())
}
debug.Println("OK")
os.Exit(0)
}

View File

@@ -1,6 +1,7 @@
package main
import (
"errors"
"flag"
"fmt"
"io"
@@ -37,10 +38,11 @@ func dumpFile(path string, indentLevel int) error {
defer file.Close()
fmt.Printf("%svar buffer = []byte{\n", indent.String())
var n int
for {
buf := make([]byte, 8)
n, err := file.Read(buf)
if err == io.EOF {
n, err = file.Read(buf)
if errors.Is(err, io.EOF) {
if n > 0 {
fmt.Printf("%s", indent.String())
printBytes(buf[:n])

View File

@@ -26,7 +26,7 @@ func main() {
path = flag.Arg(0)
}
fillByte := uint8(*fill)
fillByte := uint8(*fill & 0xff) // #nosec G115 clearing out of bounds bits
buf := make([]byte, pageSize)
for i := range pageSize {

View File

@@ -72,9 +72,7 @@ func main() {
if end < start {
fmt.Fprintln(os.Stderr, "[!] end < start, swapping values")
tmp := end
end = start
start = tmp
start, end = end, start
}
var fmtStr string

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"flag"
"fmt"
"log"
@@ -8,7 +9,8 @@ import (
)
func lookupHost(host string) error {
cname, err := net.LookupCNAME(host)
r := &net.Resolver{}
cname, err := r.LookupCNAME(context.Background(), host)
if err != nil {
return err
}
@@ -18,7 +20,7 @@ func lookupHost(host string) error {
host = cname
}
addrs, err := net.LookupHost(host)
addrs, err := r.LookupHost(context.Background(), host)
if err != nil {
return err
}

View File

@@ -11,7 +11,10 @@ based on whether the source filename ends in ".gz".
Flags:
-l level Compression level (0-9). Only meaninful when
compressing a file.
compressing a file.
-u Do not restrict the size during decompression. As
a safeguard against gzip bombs, the maximum size
allowed is 32 * the compressed file size.

View File

@@ -40,26 +40,42 @@ func compress(path, target string, level int) error {
return nil
}
func uncompress(path, target string) error {
func uncompress(path, target string, unrestrict bool) error {
sourceFile, err := os.Open(path)
if err != nil {
return fmt.Errorf("opening file for read: %w", err)
}
defer sourceFile.Close()
fi, err := sourceFile.Stat()
if err != nil {
return fmt.Errorf("reading file stats: %w", err)
}
maxDecompressionSize := fi.Size() * 32
gzipUncompressor, err := gzip.NewReader(sourceFile)
if err != nil {
return fmt.Errorf("reading gzip headers: %w", err)
}
defer gzipUncompressor.Close()
var reader io.Reader = &io.LimitedReader{
R: gzipUncompressor,
N: maxDecompressionSize,
}
if unrestrict {
reader = gzipUncompressor
}
destFile, err := os.Create(target)
if err != nil {
return fmt.Errorf("opening file for write: %w", err)
}
defer destFile.Close()
_, err = io.Copy(destFile, gzipUncompressor)
_, err = io.Copy(destFile, reader)
if err != nil {
return fmt.Errorf("uncompressing file: %w", err)
}
@@ -87,8 +103,8 @@ func isDir(path string) bool {
file, err := os.Open(path)
if err == nil {
defer file.Close()
stat, err := file.Stat()
if err != nil {
stat, err2 := file.Stat()
if err2 != nil {
return false
}
@@ -132,8 +148,11 @@ func main() {
var level int
var path string
var target = "."
var err error
var unrestrict bool
flag.IntVar(&level, "l", flate.DefaultCompression, "compression level")
flag.BoolVar(&unrestrict, "u", false, "do not restrict decompression")
flag.Parse()
if flag.NArg() < 1 || flag.NArg() > 2 {
@@ -147,30 +166,31 @@ func main() {
}
if strings.HasSuffix(path, gzipExt) {
target, err := pathForUncompressing(path, target)
target, err = pathForUncompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
err = uncompress(path, target)
err = uncompress(path, target, unrestrict)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
} else {
target, err := pathForCompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
return
}
err = compress(path, target, level)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
target, err = pathForCompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
err = compress(path, target, level)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
}

View File

@@ -32,7 +32,7 @@ func main() {
if p == nil {
lib.Errx(lib.ExitFailure, "%s isn't a PEM-encoded file", flag.Arg(0))
}
if _, err := os.Stdout.Write(p.Bytes); err != nil {
if _, err = os.Stdout.Write(p.Bytes); err != nil {
lib.Err(lib.ExitFailure, err, "writing body")
}
}

View File

@@ -27,7 +27,8 @@ func main() {
break
}
cert, err := x509.ParseCertificate(p.Bytes)
var cert *x509.Certificate
cert, err = x509.ParseCertificate(p.Bytes)
if err != nil {
fmt.Fprintf(os.Stderr, "[!] %s: %v\n", fileName, err)
break

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"flag"
"fmt"
"io"
@@ -76,7 +77,13 @@ func main() {
continue
}
resp, err := http.Get(remote)
req, reqErr := http.NewRequestWithContext(context.Background(), http.MethodGet, remote, nil)
if reqErr != nil {
_, _ = lib.Warn(reqErr, "building request for %s", remote)
continue
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
_, _ = lib.Warn(err, "fetching %s", remote)
continue

View File

@@ -18,7 +18,7 @@ func rollDie(count, sides int) []int {
var rolls []int
for range count {
roll := rand.IntN(sides) + 1
roll := rand.IntN(sides) + 1 // #nosec G404
sum += roll
rolls = append(rolls, roll)
}

View File

@@ -75,13 +75,14 @@ func walkFile(path string, _ os.FileInfo, err error) error {
for _, importSpec := range f.Imports {
importPath := strings.Trim(importSpec.Path.Value, `"`)
if stdLibRegexp.MatchString(importPath) {
switch {
case stdLibRegexp.MatchString(importPath):
debug.Println("standard lib:", importPath)
continue
} else if strings.HasPrefix(importPath, project) {
case strings.HasPrefix(importPath, project):
debug.Println("internal import:", importPath)
continue
} else if strings.HasPrefix(importPath, "golang.org/") {
case strings.HasPrefix(importPath, "golang.org/"):
debug.Println("extended lib:", importPath)
continue
}

View File

@@ -5,7 +5,7 @@ import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/sha1"
"crypto/sha1" // #nosec G505
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
@@ -20,6 +20,11 @@ import (
"git.wntrmute.dev/kyle/goutils/lib"
)
const (
keyTypeRSA = "RSA"
keyTypeECDSA = "ECDSA"
)
func usage(w io.Writer) {
fmt.Fprintf(w, `ski: print subject key info for PEM-encoded files
@@ -94,10 +99,10 @@ func parseKey(data []byte) ([]byte, string) {
switch p := privInterface.(type) {
case *rsa.PrivateKey:
priv = p
kt = "RSA"
kt = keyTypeRSA
case *ecdsa.PrivateKey:
priv = p
kt = "ECDSA"
kt = keyTypeECDSA
default:
die.With("unknown private key type %T", privInterface)
}
@@ -116,9 +121,9 @@ func parseCertificate(data []byte) ([]byte, string) {
var kt string
switch pub.(type) {
case *rsa.PublicKey:
kt = "RSA"
kt = keyTypeRSA
case *ecdsa.PublicKey:
kt = "ECDSA"
kt = keyTypeECDSA
default:
die.With("unknown public key type %T", pub)
}
@@ -136,9 +141,9 @@ func parseCSR(data []byte) ([]byte, string) {
var kt string
switch pub.(type) {
case *rsa.PublicKey:
kt = "RSA"
kt = keyTypeRSA
case *ecdsa.PublicKey:
kt = "ECDSA"
kt = keyTypeECDSA
default:
die.With("unknown public key type %T", pub)
}
@@ -186,7 +191,7 @@ func main() {
continue
}
pubHash := sha1.Sum(subPKI.SubjectPublicKey.Bytes)
pubHash := sha1.Sum(subPKI.SubjectPublicKey.Bytes) // #nosec G401 this is the standard
pubHashString := dumpHex(pubHash[:])
if ski == "" {
ski = pubHashString

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"flag"
"io"
"net"
@@ -10,7 +11,7 @@ import (
)
func proxy(conn net.Conn, inside string) error {
proxyConn, err := net.Dial("tcp", inside)
proxyConn, err := (&net.Dialer{}).DialContext(context.Background(), "tcp", inside)
if err != nil {
return err
}
@@ -31,18 +32,20 @@ func main() {
flag.StringVar(&inside, "p", "4000", "inside port")
flag.Parse()
l, err := net.Listen("tcp", "0.0.0.0:"+outside)
lc := &net.ListenConfig{}
l, err := lc.Listen(context.Background(), "tcp", "0.0.0.0:"+outside)
die.If(err)
for {
conn, err := l.Accept()
var conn net.Conn
conn, err = l.Accept()
if err != nil {
_, _ = lib.Warn(err, "accept failed")
continue
}
go func() {
if err := proxy(conn, "127.0.0.1:"+inside); err != nil {
if err = proxy(conn, "127.0.0.1:"+inside); err != nil {
_, _ = lib.Warn(err, "proxy error")
}
}()

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"crypto/rand"
"crypto/tls"
"crypto/x509"
@@ -15,7 +16,7 @@ import (
)
func main() {
cfg := &tls.Config{}
cfg := &tls.Config{} // #nosec G402
var sysRoot, listenAddr, certFile, keyFile string
var verify bool
@@ -46,7 +47,8 @@ func main() {
}
cfg.Certificates = append(cfg.Certificates, cert)
if sysRoot != "" {
pemList, err := os.ReadFile(sysRoot)
var pemList []byte
pemList, err = os.ReadFile(sysRoot)
die.If(err)
roots := x509.NewCertPool()
@@ -58,14 +60,16 @@ func main() {
cfg.RootCAs = roots
}
l, err := net.Listen("tcp", listenAddr)
lc := &net.ListenConfig{}
l, err := lc.Listen(context.Background(), "tcp", listenAddr)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
for {
conn, err := l.Accept()
var conn net.Conn
conn, err = l.Accept()
if err != nil {
fmt.Println(err.Error())
continue
@@ -79,7 +83,7 @@ func handleConn(conn net.Conn, cfg *tls.Config) {
defer conn.Close()
raddr := conn.RemoteAddr()
tconn := tls.Server(conn, cfg)
if err := tconn.Handshake(); err != nil {
if err := tconn.HandshakeContext(context.Background()); err != nil {
fmt.Printf("[+] %v: failed to complete handshake: %v\n", raddr, err)
return
}

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/pem"
@@ -13,7 +14,7 @@ import (
)
func main() {
var cfg = &tls.Config{}
var cfg = &tls.Config{} // #nosec G402
var sysRoot, serverName string
flag.StringVar(&sysRoot, "ca", "", "provide an alternate CA bundle")
@@ -43,10 +44,13 @@ func main() {
if err != nil {
site += ":443"
}
conn, err := tls.Dial("tcp", site, cfg)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
d := &tls.Dialer{Config: cfg}
nc, err := d.DialContext(context.Background(), "tcp", site)
die.If(err)
conn, ok := nc.(*tls.Conn)
if !ok {
die.With("invalid TLS connection (not a *tls.Conn)")
}
cs := conn.ConnectionState()
@@ -62,6 +66,7 @@ func main() {
err = os.WriteFile(site+".pem", chain, 0644)
die.If(err)
fmt.Printf("[+] wrote %s.pem.\n", site)
}
}

View File

@@ -1,10 +1,14 @@
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"git.wntrmute.dev/kyle/goutils/certlib/hosts"
"git.wntrmute.dev/kyle/goutils/die"
)
func main() {
@@ -13,16 +17,23 @@ func main() {
os.Exit(1)
}
hostPort := os.Args[1]
conn, err := tls.Dial("tcp", hostPort, &tls.Config{
InsecureSkipVerify: true,
})
hostPort, err := hosts.ParseHost(os.Args[1])
die.If(err)
if err != nil {
fmt.Printf("Failed to connect to the TLS server: %v\n", err)
os.Exit(1)
d := &tls.Dialer{Config: &tls.Config{
InsecureSkipVerify: true,
}} // #nosec G402
nc, err := d.DialContext(context.Background(), "tcp", hostPort.String())
die.If(err)
conn, ok := nc.(*tls.Conn)
if !ok {
die.With("invalid TLS connection (not a *tls.Conn)")
}
defer conn.Close()
state := conn.ConnectionState()
printConnectionDetails(state)
}

View File

@@ -253,15 +253,16 @@ func main() {
showTime(time.Now())
os.Exit(0)
case 1:
if flag.Arg(0) == "-" {
switch {
case flag.Arg(0) == "-":
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
times = append(times, s.Text())
}
} else if flag.Arg(0) == "help" {
case flag.Arg(0) == "help":
usageExamples()
} else {
default:
times = flag.Args()
}
default:

View File

@@ -11,9 +11,8 @@ import (
type empty struct{}
func errorf(format string, args ...any) {
format += "\n"
fmt.Fprintf(os.Stderr, format, args...)
func errorf(path string, err error) {
fmt.Fprintf(os.Stderr, "%s FAILED: %s\n", path, err)
}
func usage(w io.Writer) {
@@ -45,14 +44,14 @@ func main() {
path := "stdin"
in, err := io.ReadAll(os.Stdin)
if err != nil {
errorf("%s FAILED: %s", path, err)
errorf(path, err)
os.Exit(1)
}
var e empty
err = yaml.Unmarshal(in, &e)
if err != nil {
errorf("%s FAILED: %s", path, err)
errorf(path, err)
os.Exit(1)
}
@@ -66,14 +65,14 @@ func main() {
for _, path := range flag.Args() {
in, err := os.ReadFile(path)
if err != nil {
errorf("%s FAILED: %s", path, err)
errorf(path, err)
continue
}
var e empty
err = yaml.Unmarshal(in, &e)
if err != nil {
errorf("%s FAILED: %s", path, err)
errorf(path, err)
continue
}

View File

@@ -14,16 +14,16 @@ import (
"os"
"path/filepath"
"regexp"
"git.wntrmute.dev/kyle/goutils/lib"
)
const defaultDirectory = ".git/objects"
func errorf(format string, a ...any) {
fmt.Fprintf(os.Stderr, format, a...)
if format[len(format)-1] != '\n' {
fmt.Fprintf(os.Stderr, "\n")
}
}
// maxDecompressedSize limits how many bytes we will decompress from a zlib
// stream to mitigate decompression bombs (gosec G110).
// Increase this if you expect larger objects.
const maxDecompressedSize int64 = 64 << 30 // 64 GiB
func isDir(path string) bool {
fi, err := os.Stat(path)
@@ -48,17 +48,21 @@ func loadFile(path string) ([]byte, error) {
}
defer zread.Close()
_, err = io.Copy(buf, zread)
if err != nil {
// Protect against decompression bombs by limiting how much we read.
lr := io.LimitReader(zread, maxDecompressedSize+1)
if _, err = buf.ReadFrom(lr); err != nil {
return nil, err
}
if int64(buf.Len()) > maxDecompressedSize {
return nil, fmt.Errorf("decompressed size exceeds limit (%d bytes)", maxDecompressedSize)
}
return buf.Bytes(), nil
}
func showFile(path string) {
fileData, err := loadFile(path)
if err != nil {
errorf("%v", err)
lib.Warn(err, "failed to load %s", path)
return
}
@@ -68,39 +72,71 @@ func showFile(path string) {
func searchFile(path string, search *regexp.Regexp) error {
file, err := os.Open(path)
if err != nil {
errorf("%v", err)
lib.Warn(err, "failed to open %s", path)
return err
}
defer file.Close()
zread, err := zlib.NewReader(file)
if err != nil {
errorf("%v", err)
lib.Warn(err, "failed to decompress %s", path)
return err
}
defer zread.Close()
zbuf := bufio.NewReader(zread)
if search.MatchReader(zbuf) {
fileData, err := loadFile(path)
if err != nil {
errorf("%v", err)
return err
}
fmt.Printf("%s:\n%s\n", path, fileData)
// Limit how much we scan to avoid DoS via huge decompression.
lr := io.LimitReader(zread, maxDecompressedSize+1)
zbuf := bufio.NewReader(lr)
if !search.MatchReader(zbuf) {
return nil
}
fileData, err := loadFile(path)
if err != nil {
lib.Warn(err, "failed to load %s", path)
return err
}
fmt.Printf("%s:\n%s\n", path, fileData)
return nil
}
func buildWalker(searchExpr *regexp.Regexp) filepath.WalkFunc {
return func(path string, info os.FileInfo, _ error) error {
if info.Mode().IsRegular() {
return searchFile(path, searchExpr)
if !info.Mode().IsRegular() {
return nil
}
return nil
return searchFile(path, searchExpr)
}
}
// runSearch compiles the search expression and processes the provided paths.
// It returns an error for fatal conditions; per-file errors are logged.
func runSearch(expr string) error {
search, err := regexp.Compile(expr)
if err != nil {
return fmt.Errorf("invalid regexp: %w", err)
}
pathList := flag.Args()
if len(pathList) == 0 {
pathList = []string{defaultDirectory}
}
for _, path := range pathList {
if isDir(path) {
if err2 := filepath.Walk(path, buildWalker(search)); err2 != nil {
return err2
}
continue
}
if err2 := searchFile(path, search); err2 != nil {
// Non-fatal: keep going, but report it.
lib.Warn(err2, "non-fatal error while searching files")
}
}
return nil
}
func main() {
flSearch := flag.String("s", "", "search string (should be an RE2 regular expression)")
flag.Parse()
@@ -109,29 +145,10 @@ func main() {
for _, path := range flag.Args() {
showFile(path)
}
} else {
search, err := regexp.Compile(*flSearch)
if err != nil {
errorf("Bad regexp: %v", err)
return
}
return
}
pathList := flag.Args()
if len(pathList) == 0 {
pathList = []string{defaultDirectory}
}
for _, path := range pathList {
if isDir(path) {
if err := filepath.Walk(path, buildWalker(search)); err != nil {
errorf("%v", err)
return
}
} else {
if err := searchFile(path, search); err != nil {
errorf("%v", err)
}
}
}
if err := runSearch(*flSearch); err != nil {
lib.Err(lib.ExitFailure, err, "failed to run search")
}
}