mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-17 23:56:56 +00:00
feat: dialer refactor to support modular dialing/checking/proxying
This commit is contained in:
committed by
Michal Horejsek
parent
8c2f88fe70
commit
0fd5ca3a24
77
pkg/pmapi/pin_checker.go
Normal file
77
pkg/pmapi/pin_checker.go
Normal file
@ -0,0 +1,77 @@
|
||||
package pmapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type PinChecker struct {
|
||||
trustedPins []string
|
||||
}
|
||||
|
||||
func NewPinChecker(trustedPins []string) PinChecker {
|
||||
return PinChecker{
|
||||
trustedPins: trustedPins,
|
||||
}
|
||||
}
|
||||
|
||||
// CheckCertificate returns whether the connection presents a known TLS certificate.
|
||||
func (p *PinChecker) CheckCertificate(conn net.Conn) error {
|
||||
connState := conn.(*tls.Conn).ConnectionState()
|
||||
|
||||
for _, peerCert := range connState.PeerCertificates {
|
||||
fingerprint := certFingerprint(peerCert)
|
||||
|
||||
for _, pin := range p.trustedPins {
|
||||
if pin == fingerprint {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ErrTLSMismatch
|
||||
}
|
||||
|
||||
func certFingerprint(cert *x509.Certificate) string {
|
||||
hash := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
|
||||
return fmt.Sprintf(`pin-sha256=%q`, base64.StdEncoding.EncodeToString(hash[:]))
|
||||
}
|
||||
|
||||
// ReportCertIssue reports a TLS key mismatch.
|
||||
func (p *PinChecker) ReportCertIssue(host, port, datetime string, connState tls.ConnectionState, appVersion string) {
|
||||
var certChain []string
|
||||
|
||||
if len(connState.VerifiedChains) > 0 {
|
||||
certChain = marshalCert7468(connState.VerifiedChains[len(connState.VerifiedChains)-1])
|
||||
} else {
|
||||
certChain = marshalCert7468(connState.PeerCertificates)
|
||||
}
|
||||
|
||||
report := NewTLSReport(host, port, connState.ServerName, certChain, p.trustedPins, appVersion)
|
||||
|
||||
go postCertIssueReport(report)
|
||||
}
|
||||
|
||||
func marshalCert7468(certs []*x509.Certificate) (pemCerts []string) {
|
||||
var buffer bytes.Buffer
|
||||
for _, cert := range certs {
|
||||
if err := pem.Encode(&buffer, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}); err != nil {
|
||||
logrus.WithField("pkg", "pmapi/tls-pinning").Errorf("encoding TLS cert: %v", err)
|
||||
}
|
||||
pemCerts = append(pemCerts, buffer.String())
|
||||
buffer.Reset()
|
||||
}
|
||||
|
||||
return pemCerts
|
||||
}
|
||||
Reference in New Issue
Block a user