Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(engine): make netxlite.utlsConn public #1018

Merged
merged 1 commit into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 9 additions & 50 deletions internal/experiment/echcheck/utls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package echcheck
import (
"context"
"crypto/tls"
"net"

"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/ooni/probe-cli/v3/internal/runtimex"
utls "gitlab.com/yawning/utls.git"
"net"
)

type tlsHandshakerWithExtensions struct {
conn utlsConn
conn *netxlite.UTLSConn
extensions []utls.TLSExtension
dl model.DebugLogger
id *utls.ClientHelloID
Expand All @@ -31,60 +34,16 @@ func newHandshakerWithExtensions(extensions []utls.TLSExtension) func(dl model.D

func (t *tlsHandshakerWithExtensions) Handshake(ctx context.Context, conn net.Conn, tlsConfig *tls.Config) (
net.Conn, tls.ConnectionState, error) {
t.conn = newConnUTLSWithHelloID(conn, tlsConfig, t.id)
var err error
t.conn, err = netxlite.NewUTLSConn(conn, tlsConfig, t.id)
runtimex.Assert(err == nil, "unexpected error when creating UTLSConn")

if t.extensions != nil && len(t.extensions) != 0 {
t.conn.BuildHandshakeState()
t.conn.Extensions = append(t.conn.Extensions, t.extensions...)
}

err := t.conn.Handshake()
err = t.conn.Handshake()

return t.conn.NetConn(), t.conn.ConnectionState(), err
}

// TODO remove after https://github.com/ooni/probe/issues/2378
// utlsConn is a utls connection
type utlsConn struct {
*utls.UConn
nc net.Conn
}

// newConnUTLSWithHelloID creates a new connection with the given client hello ID.
func newConnUTLSWithHelloID(conn net.Conn, config *tls.Config, cid *utls.ClientHelloID) utlsConn {
uConfig := &utls.Config{
DynamicRecordSizingDisabled: config.DynamicRecordSizingDisabled,
InsecureSkipVerify: config.InsecureSkipVerify,
RootCAs: config.RootCAs,
NextProtos: config.NextProtos,
ServerName: config.ServerName,
}
tlsConn := utls.UClient(conn, uConfig, *cid)
oconn := utlsConn{
UConn: tlsConn,
nc: conn,
}
return oconn
}

func (c *utlsConn) ConnectionState() tls.ConnectionState {
uState := c.Conn.ConnectionState()
return tls.ConnectionState{
Version: uState.Version,
HandshakeComplete: uState.HandshakeComplete,
DidResume: uState.DidResume,
CipherSuite: uState.CipherSuite,
NegotiatedProtocol: uState.NegotiatedProtocol,
NegotiatedProtocolIsMutual: uState.NegotiatedProtocolIsMutual,
ServerName: uState.ServerName,
PeerCertificates: uState.PeerCertificates,
VerifiedChains: uState.VerifiedChains,
SignedCertificateTimestamps: uState.SignedCertificateTimestamps,
OCSPResponse: uState.OCSPResponse,
TLSUnique: uState.TLSUnique,
}
}

func (c *utlsConn) NetConn() net.Conn {
return c.nc
}
32 changes: 16 additions & 16 deletions internal/netxlite/utls.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ import (
// Passing a nil `id` will make this function panic.
func NewTLSHandshakerUTLS(logger model.DebugLogger, id *utls.ClientHelloID) model.TLSHandshaker {
return newTLSHandshaker(&tlsHandshakerConfigurable{
NewConn: newConnUTLS(id),
NewConn: newUTLSConnFactory(id),
}, logger)
}

// utlsConn implements TLSConn and uses a utls UConn as its underlying connection
type utlsConn struct {
// UTLSConn implements TLSConn and uses a utls UConn as its underlying connection
type UTLSConn struct {
// We include the real UConn
*utls.UConn

Expand All @@ -46,22 +46,22 @@ type utlsConn struct {
nc net.Conn
}

// Ensures that a utlsConn implements the TLSConn interface.
var _ TLSConn = &utlsConn{}
// Ensures that a UTLSConn implements the TLSConn interface.
var _ TLSConn = &UTLSConn{}

// newConnUTLS returns a NewConn function for creating utlsConn instances.
func newConnUTLS(clientHello *utls.ClientHelloID) func(conn net.Conn, config *tls.Config) (TLSConn, error) {
// newUTLSConnFactory returns a NewConn function for creating UTLSConn instances.
func newUTLSConnFactory(clientHello *utls.ClientHelloID) func(conn net.Conn, config *tls.Config) (TLSConn, error) {
return func(conn net.Conn, config *tls.Config) (TLSConn, error) {
return newConnUTLSWithHelloID(conn, config, clientHello)
return NewUTLSConn(conn, config, clientHello)
}
}

// errUTLSIncompatibleStdlibConfig indicates that the stdlib config you passed to
// newConnUTLSWithHelloID contains some fields we don't support.
// NewUTLSConn contains some fields we don't support.
var errUTLSIncompatibleStdlibConfig = errors.New("utls: incompatible stdlib config")

// newConnUTLSWithHelloID creates a new connection with the given client hello ID.
func newConnUTLSWithHelloID(conn net.Conn, config *tls.Config, cid *utls.ClientHelloID) (TLSConn, error) {
// NewUTLSConn creates a new connection with the given client hello ID.
func NewUTLSConn(conn net.Conn, config *tls.Config, cid *utls.ClientHelloID) (*UTLSConn, error) {
supportedFields := map[string]bool{
"DynamicRecordSizingDisabled": true,
"InsecureSkipVerify": true,
Expand Down Expand Up @@ -91,7 +91,7 @@ func newConnUTLSWithHelloID(conn net.Conn, config *tls.Config, cid *utls.ClientH
ServerName: config.ServerName,
}
tlsConn := utls.UClient(conn, uConfig, *cid)
oconn := &utlsConn{
oconn := &UTLSConn{
UConn: tlsConn,
testableHandshake: nil,
nc: conn,
Expand All @@ -104,7 +104,7 @@ func newConnUTLSWithHelloID(conn net.Conn, config *tls.Config, cid *utls.ClientH
// See https://github.com/ooni/probe/issues/1770 for more information.
var ErrUTLSHandshakePanic = errors.New("utls: handshake panic")

func (c *utlsConn) HandshakeContext(ctx context.Context) (err error) {
func (c *UTLSConn) HandshakeContext(ctx context.Context) (err error) {
errch := make(chan error, 1)
go func() {
defer func() {
Expand All @@ -123,14 +123,14 @@ func (c *utlsConn) HandshakeContext(ctx context.Context) (err error) {
return
}

func (c *utlsConn) handshakefn() func() error {
func (c *UTLSConn) handshakefn() func() error {
if c.testableHandshake != nil {
return c.testableHandshake
}
return c.UConn.Handshake
}

func (c *utlsConn) ConnectionState() tls.ConnectionState {
func (c *UTLSConn) ConnectionState() tls.ConnectionState {
uState := c.Conn.ConnectionState()
return tls.ConnectionState{
Version: uState.Version,
Expand All @@ -148,6 +148,6 @@ func (c *utlsConn) ConnectionState() tls.ConnectionState {
}
}

func (c *utlsConn) NetConn() net.Conn {
func (c *UTLSConn) NetConn() net.Conn {
return c.nc
}
12 changes: 6 additions & 6 deletions internal/netxlite/utls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestUTLSConn(t *testing.T) {
t.Run("Handshake", func(t *testing.T) {
t.Run("not interrupted with success", func(t *testing.T) {
ctx := context.Background()
conn := &utlsConn{
conn := &UTLSConn{
testableHandshake: func() error {
return nil
},
Expand All @@ -44,7 +44,7 @@ func TestUTLSConn(t *testing.T) {
t.Run("not interrupted with failure", func(t *testing.T) {
expected := errors.New("mocked error")
ctx := context.Background()
conn := &utlsConn{
conn := &UTLSConn{
testableHandshake: func() error {
return expected
},
Expand All @@ -61,7 +61,7 @@ func TestUTLSConn(t *testing.T) {
sigch := make(chan interface{})
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
conn := &utlsConn{
conn := &UTLSConn{
testableHandshake: func() error {
defer wg.Done()
<-sigch
Expand All @@ -80,7 +80,7 @@ func TestUTLSConn(t *testing.T) {
wg := sync.WaitGroup{}
wg.Add(1)
ctx := context.Background()
conn := &utlsConn{
conn := &UTLSConn{
testableHandshake: func() error {
defer wg.Done()
panic("mascetti")
Expand All @@ -95,7 +95,7 @@ func TestUTLSConn(t *testing.T) {
})

t.Run("NetConn", func(t *testing.T) {
factory := newConnUTLS(&utls.HelloChrome_70)
factory := newUTLSConnFactory(&utls.HelloChrome_70)
conn := &mocks.Conn{}
tconn, err := factory(conn, &tls.Config{})
if err != nil {
Expand Down Expand Up @@ -144,7 +144,7 @@ func Test_newConnUTLSWithHelloID(t *testing.T) {
t.Fatal(err)
}
defer conn.Close()
got, err := newConnUTLSWithHelloID(conn, tt.config, tt.cid)
got, err := NewUTLSConn(conn, tt.config, tt.cid)
if !errors.Is(err, tt.wantErr) {
t.Fatal("unexpected err", err)
}
Expand Down