refactor: move tracex outside of engine/netx (#782)
* refactor: move tracex outside of engine/netx Consistently with https://github.com/ooni/probe/issues/2121 and https://github.com/ooni/probe/issues/2115, we can now move tracex outside of engine/netx. The main reason why this makes sense now is that the package is now changed significantly from the one that we imported from ooni/probe-engine. We have improved its implementation, which had not been touched significantly for quite some time, and converted it to unit testing. I will document tomorrow some extra work I'd like to do with this package but likely could not do $soon. * go fmt * regen tutorials
This commit is contained in:
parent
d397036073
commit
58adb68b2c
50 changed files with 34 additions and 34 deletions
98
internal/tracex/tls.go
Normal file
98
internal/tracex/tls.go
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package tracex
|
||||
|
||||
//
|
||||
// TLS
|
||||
//
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// TLSHandshakerSaver saves events occurring during the TLS handshake.
|
||||
type TLSHandshakerSaver struct {
|
||||
// TLSHandshaker is the underlying TLS handshaker.
|
||||
TLSHandshaker model.TLSHandshaker
|
||||
|
||||
// Saver is the saver in which to save events.
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// WrapTLSHandshaker wraps a model.TLSHandshaker with a SaverTLSHandshaker
|
||||
// that will save the TLS handshake results into this Saver.
|
||||
//
|
||||
// When this function is invoked on a nil Saver, it will directly return
|
||||
// the original TLSHandshaker without any wrapping.
|
||||
func (s *Saver) WrapTLSHandshaker(thx model.TLSHandshaker) model.TLSHandshaker {
|
||||
if s == nil {
|
||||
return thx
|
||||
}
|
||||
return &TLSHandshakerSaver{
|
||||
TLSHandshaker: thx,
|
||||
Saver: s,
|
||||
}
|
||||
}
|
||||
|
||||
// Handshake implements model.TLSHandshaker.Handshake
|
||||
func (h *TLSHandshakerSaver) Handshake(
|
||||
ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
|
||||
proto := conn.RemoteAddr().Network()
|
||||
remoteAddr := conn.RemoteAddr().String()
|
||||
start := time.Now()
|
||||
h.Saver.Write(&EventTLSHandshakeStart{&EventValue{
|
||||
Address: remoteAddr,
|
||||
NoTLSVerify: config.InsecureSkipVerify,
|
||||
Proto: proto,
|
||||
TLSNextProtos: config.NextProtos,
|
||||
TLSServerName: config.ServerName,
|
||||
Time: start,
|
||||
}})
|
||||
tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
|
||||
stop := time.Now()
|
||||
h.Saver.Write(&EventTLSHandshakeDone{&EventValue{
|
||||
Address: remoteAddr,
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NoTLSVerify: config.InsecureSkipVerify,
|
||||
Proto: proto,
|
||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||
TLSNextProtos: config.NextProtos,
|
||||
TLSPeerCerts: tlsPeerCerts(state, err),
|
||||
TLSServerName: config.ServerName,
|
||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||
Time: stop,
|
||||
}})
|
||||
return tlsconn, state, err
|
||||
}
|
||||
|
||||
var _ model.TLSHandshaker = &TLSHandshakerSaver{}
|
||||
|
||||
// tlsPeerCerts returns the certificates presented by the peer regardless
|
||||
// of whether the TLS handshake was successful
|
||||
func tlsPeerCerts(state tls.ConnectionState, err error) []*x509.Certificate {
|
||||
var x509HostnameError x509.HostnameError
|
||||
if errors.As(err, &x509HostnameError) {
|
||||
// Test case: https://wrong.host.badssl.com/
|
||||
return []*x509.Certificate{x509HostnameError.Certificate}
|
||||
}
|
||||
var x509UnknownAuthorityError x509.UnknownAuthorityError
|
||||
if errors.As(err, &x509UnknownAuthorityError) {
|
||||
// Test case: https://self-signed.badssl.com/. This error has
|
||||
// never been among the ones returned by MK.
|
||||
return []*x509.Certificate{x509UnknownAuthorityError.Cert}
|
||||
}
|
||||
var x509CertificateInvalidError x509.CertificateInvalidError
|
||||
if errors.As(err, &x509CertificateInvalidError) {
|
||||
// Test case: https://expired.badssl.com/
|
||||
return []*x509.Certificate{x509CertificateInvalidError.Cert}
|
||||
}
|
||||
return state.PeerCertificates
|
||||
}
|
||||
Loading…
Reference in a new issue