initial commit [141.14.140.180,mike]

This commit is contained in:
2026-08-14 09:09:59 +02:00
commit 6a991a25a6
19 changed files with 6691 additions and 0 deletions
+138
View File
@@ -0,0 +1,138 @@
package main
import (
"crypto/tls"
"crypto/x509"
_ "embed"
"errors"
"fmt"
"net"
"os"
"strings"
)
// The Mozilla CA list as extracted by the curl project, refreshed with
//
// curl -o ca-bundle.pem https://curl.se/ca/cacert.pem
//
// It is not used unless the system store fails: on a machine old enough that
// its ca-certificates package predates Let's Encrypt's ISRG roots, every
// https:// forge is unreachable otherwise, and updating that package is often
// no longer possible there.
//
//go:embed ca-bundle.pem
var caBundle []byte
// How certificates are verified. Starts at the system store and falls back one
// step when that store turns out not to know the issuer.
type caMode int
const (
caSystem caMode = iota
caBundled
caFile
caNone
)
func (m caMode) String() string {
switch m {
case caBundled:
return "bundled CA list"
case caFile:
return "--cacert " + caCertPath()
case caNone:
return "no verification"
}
return "system CA store"
}
// caCurrent is the mode every request uses; the fallback in httpGet moves it
// forward at most once per run.
var caCurrent = caSystem
func bundledPool() *x509.CertPool {
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(caBundle) {
return nil
}
return pool
}
func filePool(path string) (*x509.CertPool, error) {
pem, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("cannot read --cacert %s: %w", path, err)
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("no certificates found in %s", path)
}
return pool, nil
}
// tlsConfig builds the config for the mode currently in force. The system
// store stays the default: it is the one the administrator controls.
func tlsConfig(mode caMode) (*tls.Config, error) {
switch mode {
case caBundled:
pool := bundledPool()
if pool == nil {
return nil, errors.New("the bundled CA list could not be parsed")
}
return &tls.Config{RootCAs: pool}, nil
case caFile:
pool, err := filePool(caCertPath())
if err != nil {
return nil, err
}
return &tls.Config{RootCAs: pool}, nil
case caNone:
return &tls.Config{InsecureSkipVerify: true}, nil
}
return &tls.Config{}, nil
}
func caCertPath() string {
if opt.cacert != "" {
return expandTilde(opt.cacert)
}
return expandTilde(os.Getenv("UPD_CACERT"))
}
// A certificate the local store cannot chain up to a root it knows. This is
// the failure the bundled list exists for; no other x509 problem (expired,
// wrong host name) would be fixed by more roots.
func isUnknownAuthority(err error) bool {
var unknown x509.UnknownAuthorityError
if errors.As(err, &unknown) {
return true
}
// Some paths only carry the verifier's verdict as text.
return strings.Contains(err.Error(), "certificate signed by unknown authority") ||
strings.Contains(err.Error(), "x509: failed to load system roots")
}
// Errors that will still be errors on the next attempt: retrying a rejected
// certificate, an unresolvable host or a handshake the two sides cannot agree
// on only makes the output longer.
func isPermanent(err error) bool {
var (
hostname x509.HostnameError
invalid x509.CertificateInvalidError
verify *tls.CertificateVerificationError
record tls.RecordHeaderError
dns *net.DNSError
)
switch {
case isUnknownAuthority(err),
errors.As(err, &hostname),
errors.As(err, &invalid),
errors.As(err, &verify),
errors.As(err, &record):
return true
case errors.As(err, &dns):
return !dns.IsTemporary
}
msg := err.Error()
return strings.Contains(msg, "tls: ") || strings.Contains(msg, "x509: ")
}