mirror of
https://github.com/coalaura/up.git
synced 2025-07-17 21:44:35 +00:00
prefetch cert
This commit is contained in:
@ -135,6 +135,51 @@ 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 PreFetchServerCertificate(store *CertificateStore, addr string) error {
|
||||||
|
conn, err := tls.DialWithDialer(&net.Dialer{
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}, "tcp", addr, &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
state := conn.ConnectionState()
|
||||||
|
if len(state.PeerCertificates) == 0 {
|
||||||
|
return fmt.Errorf("no peer certificates")
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate := state.PeerCertificates[0]
|
||||||
|
|
||||||
|
if certificate.Subject.CommonName != "up" {
|
||||||
|
return errors.New("invalid certificate subject")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := state.ServerName
|
||||||
|
fingerprint := CertificateFingerprint(certificate)
|
||||||
|
|
||||||
|
if store.IsPinned(name, fingerprint) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Server fingerprint for %s: %s\n", name, fingerprint)
|
||||||
|
log.Print("Accept? [y/N]: ")
|
||||||
|
|
||||||
|
var confirm string
|
||||||
|
|
||||||
|
fmt.Scanln(&confirm)
|
||||||
|
|
||||||
|
if strings.ToLower(strings.TrimSpace(confirm)) != "y" {
|
||||||
|
return errors.New("certificate rejected")
|
||||||
|
}
|
||||||
|
|
||||||
|
return store.Pin(name, fingerprint)
|
||||||
|
}
|
||||||
|
|
||||||
func NewPinnedClient(store *CertificateStore) *http.Client {
|
func NewPinnedClient(store *CertificateStore) *http.Client {
|
||||||
config := &tls.Config{
|
config := &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
@ -154,22 +199,11 @@ func NewPinnedClient(store *CertificateStore) *http.Client {
|
|||||||
name := cs.ServerName
|
name := cs.ServerName
|
||||||
fingerprint := CertificateFingerprint(certificate)
|
fingerprint := CertificateFingerprint(certificate)
|
||||||
|
|
||||||
if store.IsPinned(name, fingerprint) {
|
if !store.IsPinned(name, fingerprint) {
|
||||||
return nil
|
return errors.New("unknown certificate")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Server fingerprint for %s: %s\n", name, fingerprint)
|
return nil
|
||||||
log.Print("Accept? [y/N]: ")
|
|
||||||
|
|
||||||
var confirm string
|
|
||||||
|
|
||||||
fmt.Scanln(&confirm)
|
|
||||||
|
|
||||||
if strings.ToLower(strings.TrimSpace(confirm)) != "y" {
|
|
||||||
return errors.New("certificate rejected")
|
|
||||||
}
|
|
||||||
|
|
||||||
return store.Pin(name, fingerprint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &http.Client{
|
return &http.Client{
|
||||||
|
@ -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...")
|
||||||
|
Reference in New Issue
Block a user