1
0
mirror of https://github.com/coalaura/up.git synced 2025-07-17 21:44:35 +00:00

prefetch cert

This commit is contained in:
Laura
2025-06-20 23:37:53 +02:00
parent 11c2deb097
commit 9e13dff54c
2 changed files with 52 additions and 14 deletions

View File

@ -135,23 +135,31 @@ func CertificateFingerprint(certificate *x509.Certificate) string {
return fmt.Sprintf("%s-%s", algo, hex.EncodeToString(sum[:])) return fmt.Sprintf("%s-%s", algo, hex.EncodeToString(sum[:]))
} }
func NewPinnedClient(store *CertificateStore) *http.Client { func PreFetchServerCertificate(store *CertificateStore, addr string) error {
config := &tls.Config{ conn, err := tls.DialWithDialer(&net.Dialer{
Timeout: 5 * time.Second,
}, "tcp", addr, &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
})
if err != nil {
return err
} }
config.VerifyConnection = func(cs tls.ConnectionState) error { defer conn.Close()
if len(cs.PeerCertificates) == 0 {
return errors.New("missing certificate") state := conn.ConnectionState()
if len(state.PeerCertificates) == 0 {
return fmt.Errorf("no peer certificates")
} }
certificate := cs.PeerCertificates[0] certificate := state.PeerCertificates[0]
if certificate.Subject.CommonName != "up" { if certificate.Subject.CommonName != "up" {
return errors.New("invalid certificate subject") return errors.New("invalid certificate subject")
} }
name := cs.ServerName name := state.ServerName
fingerprint := CertificateFingerprint(certificate) fingerprint := CertificateFingerprint(certificate)
if store.IsPinned(name, fingerprint) { if store.IsPinned(name, fingerprint) {
@ -172,6 +180,32 @@ func NewPinnedClient(store *CertificateStore) *http.Client {
return store.Pin(name, fingerprint) return store.Pin(name, fingerprint)
} }
func NewPinnedClient(store *CertificateStore) *http.Client {
config := &tls.Config{
InsecureSkipVerify: true,
}
config.VerifyConnection = func(cs tls.ConnectionState) error {
if len(cs.PeerCertificates) == 0 {
return errors.New("missing certificate")
}
certificate := cs.PeerCertificates[0]
if certificate.Subject.CommonName != "up" {
return errors.New("invalid certificate subject")
}
name := cs.ServerName
fingerprint := CertificateFingerprint(certificate)
if !store.IsPinned(name, fingerprint) {
return errors.New("unknown certificate")
}
return nil
}
return &http.Client{ return &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{
TLSClientConfig: config, TLSClientConfig: config,

View File

@ -141,6 +141,10 @@ func run(_ context.Context, cmd *cli.Command) error {
return fmt.Errorf("failed to load certificate store: %v", err) return fmt.Errorf("failed to load certificate store: %v", err)
} }
if err = PreFetchServerCertificate(store, hostname); err != nil {
return err
}
client := NewPinnedClient(store) client := NewPinnedClient(store)
log.Println("Requesting challenge...") log.Println("Requesting challenge...")