refactor: merge tlsx into netxlite (#403)
Part of https://github.com/ooni/probe/issues/1505
This commit is contained in:
@@ -37,7 +37,6 @@ import (
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -110,7 +109,7 @@ type tlsHandshaker interface {
|
||||
net.Conn, tls.ConnectionState, error)
|
||||
}
|
||||
|
||||
var defaultCertPool *x509.CertPool = tlsx.NewDefaultCertPool()
|
||||
var defaultCertPool *x509.CertPool = netxlite.NewDefaultCertPool()
|
||||
|
||||
// NewResolver creates a new resolver from the specified config
|
||||
func NewResolver(config Config) Resolver {
|
||||
@@ -312,7 +311,7 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
|
||||
return c, err
|
||||
}
|
||||
config.TLSConfig = &tls.Config{ServerName: SNIOverride}
|
||||
if err := tlsx.ConfigureTLSVersion(config.TLSConfig, TLSVersion); err != nil {
|
||||
if err := netxlite.ConfigureTLSVersion(config.TLSConfig, TLSVersion); err != nil {
|
||||
return c, err
|
||||
}
|
||||
switch resolverURL.Scheme {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -848,7 +847,7 @@ func TestNewDNSClientBadUDPEndpoint(t *testing.T) {
|
||||
func TestNewDNSCLientWithInvalidTLSVersion(t *testing.T) {
|
||||
_, err := netx.NewDNSClientWithOverrides(
|
||||
netx.Config{}, "dot://8.8.8.8", "", "", "TLSv999")
|
||||
if !errors.Is(err, tlsx.ErrInvalidTLSVersion) {
|
||||
if !errors.Is(err, netxlite.ErrInvalidTLSVersion) {
|
||||
t.Fatalf("not the error we expected: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// HandshakeSaver saves events occurring during the handshake
|
||||
@@ -50,12 +50,12 @@ func (h HandshakeSaver) DialContext(ctx context.Context, network string,
|
||||
Duration: stop.Sub(start),
|
||||
Name: "quic_handshake_done",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
TLSCipherSuite: tlsx.CipherSuiteString(state.CipherSuite),
|
||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSPeerCerts: trace.PeerCerts(state, err),
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
TLSVersion: tlsx.VersionString(state.Version),
|
||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||
Time: stop,
|
||||
})
|
||||
return sess, nil
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// SaverTLSHandshaker saves events occurring during the handshake
|
||||
@@ -35,12 +35,12 @@ func (h SaverTLSHandshaker) Handshake(
|
||||
Err: err,
|
||||
Name: "tls_handshake_done",
|
||||
NoTLSVerify: config.InsecureSkipVerify,
|
||||
TLSCipherSuite: tlsx.CipherSuiteString(state.CipherSuite),
|
||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||
TLSNextProtos: config.NextProtos,
|
||||
TLSPeerCerts: trace.PeerCerts(state, err),
|
||||
TLSServerName: config.ServerName,
|
||||
TLSVersion: tlsx.VersionString(state.Version),
|
||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||
Time: stop,
|
||||
})
|
||||
return tlsconn, state, err
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,86 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Forked from github.com/certifi/gocertifi <https://git.io/JJjmG>.
|
||||
//
|
||||
// This script should not be invoked directly, rather it should be
|
||||
// executed by running go generate ./... from toplevel dir.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/iox"
|
||||
)
|
||||
|
||||
var tmpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
|
||||
// {{ .Timestamp }}
|
||||
// {{ .URL }}
|
||||
|
||||
package tlsx
|
||||
|
||||
//go:generate go run generate.go "{{ .URL }}"
|
||||
|
||||
const pemcerts string = ` + "`" + `
|
||||
{{ .Bundle }}
|
||||
` + "`" + `
|
||||
`))
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 || !strings.HasPrefix(os.Args[1], "https://") {
|
||||
log.Fatal("usage: go run generate.go <url>")
|
||||
}
|
||||
url := os.Args[1]
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
log.Fatal("expected 200, got", resp.StatusCode)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bundle, err := iox.ReadAllContext(context.Background(), resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
pool := x509.NewCertPool()
|
||||
if !pool.AppendCertsFromPEM(bundle) {
|
||||
log.Fatalf("can't parse certificates from %s", url)
|
||||
}
|
||||
|
||||
fp, err := os.Create("certifi.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = tmpl.Execute(fp, struct {
|
||||
Timestamp time.Time
|
||||
URL string
|
||||
Bundle string
|
||||
}{
|
||||
Timestamp: time.Now(),
|
||||
URL: url,
|
||||
Bundle: string(bundle),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := fp.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
// Package tlsx contains TLS extensions
|
||||
package tlsx
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
tlsVersionString = map[uint16]string{
|
||||
tls.VersionSSL30: "SSLv3",
|
||||
tls.VersionTLS10: "TLSv1",
|
||||
tls.VersionTLS11: "TLSv1.1",
|
||||
tls.VersionTLS12: "TLSv1.2",
|
||||
tls.VersionTLS13: "TLSv1.3",
|
||||
0: "", // guarantee correct behaviour
|
||||
}
|
||||
|
||||
tlsCipherSuiteString = map[uint16]string{
|
||||
tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256",
|
||||
tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384",
|
||||
tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
|
||||
0: "", // guarantee correct behaviour
|
||||
}
|
||||
)
|
||||
|
||||
// VersionString returns a TLS version string.
|
||||
func VersionString(value uint16) string {
|
||||
if str, found := tlsVersionString[value]; found {
|
||||
return str
|
||||
}
|
||||
return fmt.Sprintf("TLS_VERSION_UNKNOWN_%d", value)
|
||||
}
|
||||
|
||||
// CipherSuiteString returns the TLS cipher suite as a string.
|
||||
func CipherSuiteString(value uint16) string {
|
||||
if str, found := tlsCipherSuiteString[value]; found {
|
||||
return str
|
||||
}
|
||||
return fmt.Sprintf("TLS_CIPHER_SUITE_UNKNOWN_%d", value)
|
||||
}
|
||||
|
||||
// NewDefaultCertPool returns a copy of the default x509
|
||||
// certificate pool that we bundle from Mozilla.
|
||||
func NewDefaultCertPool() *x509.CertPool {
|
||||
pool := x509.NewCertPool()
|
||||
// Assumption: AppendCertsFromPEM cannot fail because we
|
||||
// run this function already in the generate.go file
|
||||
pool.AppendCertsFromPEM([]byte(pemcerts))
|
||||
return pool
|
||||
}
|
||||
|
||||
// ErrInvalidTLSVersion indicates that you passed us a string
|
||||
// that does not represent a valid TLS version.
|
||||
var ErrInvalidTLSVersion = errors.New("invalid TLS version")
|
||||
|
||||
// ConfigureTLSVersion configures the correct TLS version into
|
||||
// the specified *tls.Config or returns an error.
|
||||
func ConfigureTLSVersion(config *tls.Config, version string) error {
|
||||
switch version {
|
||||
case "TLSv1.3":
|
||||
config.MinVersion = tls.VersionTLS13
|
||||
config.MaxVersion = tls.VersionTLS13
|
||||
case "TLSv1.2":
|
||||
config.MinVersion = tls.VersionTLS12
|
||||
config.MaxVersion = tls.VersionTLS12
|
||||
case "TLSv1.1":
|
||||
config.MinVersion = tls.VersionTLS11
|
||||
config.MaxVersion = tls.VersionTLS11
|
||||
case "TLSv1.0", "TLSv1":
|
||||
config.MinVersion = tls.VersionTLS10
|
||||
config.MaxVersion = tls.VersionTLS10
|
||||
case "":
|
||||
// nothing
|
||||
default:
|
||||
return ErrInvalidTLSVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package tlsx
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVersionString(t *testing.T) {
|
||||
if VersionString(tls.VersionTLS13) != "TLSv1.3" {
|
||||
t.Fatal("not working for existing version")
|
||||
}
|
||||
if VersionString(1) != "TLS_VERSION_UNKNOWN_1" {
|
||||
t.Fatal("not working for nonexisting version")
|
||||
}
|
||||
if VersionString(0) != "" {
|
||||
t.Fatal("not working for zero version")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCipherSuite(t *testing.T) {
|
||||
if CipherSuiteString(tls.TLS_AES_128_GCM_SHA256) != "TLS_AES_128_GCM_SHA256" {
|
||||
t.Fatal("not working for existing cipher suite")
|
||||
}
|
||||
if CipherSuiteString(1) != "TLS_CIPHER_SUITE_UNKNOWN_1" {
|
||||
t.Fatal("not working for nonexisting cipher suite")
|
||||
}
|
||||
if CipherSuiteString(0) != "" {
|
||||
t.Fatal("not working for zero cipher suite")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDefaultCertPoolWorks(t *testing.T) {
|
||||
pool := NewDefaultCertPool()
|
||||
if pool == nil {
|
||||
t.Fatal("expected non-nil value here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigureTLSVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
version string
|
||||
wantErr error
|
||||
versionMin int
|
||||
versionMax int
|
||||
}{{
|
||||
name: "with TLSv1.3",
|
||||
version: "TLSv1.3",
|
||||
wantErr: nil,
|
||||
versionMin: tls.VersionTLS13,
|
||||
versionMax: tls.VersionTLS13,
|
||||
}, {
|
||||
name: "with TLSv1.2",
|
||||
version: "TLSv1.2",
|
||||
wantErr: nil,
|
||||
versionMin: tls.VersionTLS12,
|
||||
versionMax: tls.VersionTLS12,
|
||||
}, {
|
||||
name: "with TLSv1.1",
|
||||
version: "TLSv1.1",
|
||||
wantErr: nil,
|
||||
versionMin: tls.VersionTLS11,
|
||||
versionMax: tls.VersionTLS11,
|
||||
}, {
|
||||
name: "with TLSv1.0",
|
||||
version: "TLSv1.0",
|
||||
wantErr: nil,
|
||||
versionMin: tls.VersionTLS10,
|
||||
versionMax: tls.VersionTLS10,
|
||||
}, {
|
||||
name: "with TLSv1",
|
||||
version: "TLSv1",
|
||||
wantErr: nil,
|
||||
versionMin: tls.VersionTLS10,
|
||||
versionMax: tls.VersionTLS10,
|
||||
}, {
|
||||
name: "with default",
|
||||
version: "",
|
||||
wantErr: nil,
|
||||
versionMin: 0,
|
||||
versionMax: 0,
|
||||
}, {
|
||||
name: "with invalid version",
|
||||
version: "TLSv999",
|
||||
wantErr: ErrInvalidTLSVersion,
|
||||
versionMin: 0,
|
||||
versionMax: 0,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
conf := new(tls.Config)
|
||||
err := ConfigureTLSVersion(conf, tt.version)
|
||||
if !errors.Is(err, tt.wantErr) {
|
||||
t.Fatalf("not the error we expected: %+v", err)
|
||||
}
|
||||
if conf.MinVersion != uint16(tt.versionMin) {
|
||||
t.Fatalf("not the min version we expected: %+v", conf.MinVersion)
|
||||
}
|
||||
if conf.MaxVersion != uint16(tt.versionMax) {
|
||||
t.Fatalf("not the max version we expected: %+v", conf.MaxVersion)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user