2022-05-31 21:53:01 +02:00
|
|
|
package tracex
|
2021-06-08 11:24:13 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-05-31 21:53:01 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
2021-06-25 11:07:26 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
2021-06-08 11:24:13 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestSaverTLSHandshakerSuccessWithReadWrite(t *testing.T) {
|
|
|
|
// This is the most common use case for collecting reads, writes
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skip test in short mode")
|
|
|
|
}
|
|
|
|
nextprotos := []string{"h2"}
|
2022-05-31 21:53:01 +02:00
|
|
|
saver := &Saver{}
|
2021-09-06 14:12:30 +02:00
|
|
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
2021-06-08 11:24:13 +02:00
|
|
|
Config: &tls.Config{NextProtos: nextprotos},
|
2022-05-31 21:53:01 +02:00
|
|
|
Dialer: netxlite.NewDialerWithResolver(
|
|
|
|
model.DiscardLogger,
|
|
|
|
netxlite.NewResolverStdlib(model.DiscardLogger),
|
2022-06-01 08:31:20 +02:00
|
|
|
saver.NewReadWriteObserver(),
|
2022-05-31 21:53:01 +02:00
|
|
|
),
|
2022-06-01 07:44:54 +02:00
|
|
|
TLSHandshaker: saver.WrapTLSHandshaker(&netxlite.TLSHandshakerConfigurable{}),
|
2021-06-08 11:24:13 +02:00
|
|
|
}
|
|
|
|
// Implementation note: we don't close the connection here because it is
|
|
|
|
// very handy to have the last event being the end of the handshake
|
|
|
|
_, err := tlsdlr.DialTLSContext(context.Background(), "tcp", "www.google.com:443")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
ev := saver.Read()
|
|
|
|
if len(ev) < 4 {
|
|
|
|
// it's a bit tricky to be sure about the right number of
|
|
|
|
// events because network conditions may influence that
|
|
|
|
t.Fatal("unexpected number of events")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[0].Name() != "tls_handshake_start" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Name")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[0].Value().TLSServerName != "www.google.com" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSServerName")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if !reflect.DeepEqual(ev[0].Value().TLSNextProtos, nextprotos) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSNextProtos")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[0].Value().Time.After(time.Now()) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Time")
|
|
|
|
}
|
|
|
|
last := len(ev) - 1
|
|
|
|
for idx := 1; idx < last; idx++ {
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[idx].Value().Data == nil {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Data")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[idx].Value().Duration <= 0 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Duration")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[idx].Value().Err != nil {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Err")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[idx].Value().NumBytes <= 0 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected NumBytes")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
switch ev[idx].Name() {
|
2021-09-28 12:42:01 +02:00
|
|
|
case netxlite.ReadOperation, netxlite.WriteOperation:
|
2021-06-08 11:24:13 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unexpected Name")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[idx].Value().Time.Before(ev[idx-1].Value().Time) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Time")
|
|
|
|
}
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().Duration <= 0 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Duration")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().Err != nil {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Err")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Name() != "tls_handshake_done" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Name")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().TLSCipherSuite == "" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSCipherSuite")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().TLSNegotiatedProto != "h2" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSNegotiatedProto")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if !reflect.DeepEqual(ev[last].Value().TLSNextProtos, nextprotos) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSNextProtos")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().TLSPeerCerts == nil {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSPeerCerts")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().TLSServerName != "www.google.com" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSServerName")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().TLSVersion == "" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSVersion")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[last].Value().Time.Before(ev[last-1].Value().Time) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Time")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSaverTLSHandshakerSuccess(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skip test in short mode")
|
|
|
|
}
|
|
|
|
nextprotos := []string{"h2"}
|
2022-05-31 21:53:01 +02:00
|
|
|
saver := &Saver{}
|
2021-09-06 14:12:30 +02:00
|
|
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
2022-06-01 07:44:54 +02:00
|
|
|
Config: &tls.Config{NextProtos: nextprotos},
|
|
|
|
Dialer: &netxlite.DialerSystem{},
|
|
|
|
TLSHandshaker: saver.WrapTLSHandshaker(&netxlite.TLSHandshakerConfigurable{}),
|
2021-06-08 11:24:13 +02:00
|
|
|
}
|
|
|
|
conn, err := tlsdlr.DialTLSContext(context.Background(), "tcp", "www.google.com:443")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
conn.Close()
|
|
|
|
ev := saver.Read()
|
|
|
|
if len(ev) != 2 {
|
|
|
|
t.Fatal("unexpected number of events")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[0].Name() != "tls_handshake_start" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Name")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[0].Value().TLSServerName != "www.google.com" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSServerName")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if !reflect.DeepEqual(ev[0].Value().TLSNextProtos, nextprotos) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSNextProtos")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[0].Value().Time.After(time.Now()) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Time")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().Duration <= 0 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Duration")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().Err != nil {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Err")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Name() != "tls_handshake_done" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Name")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().TLSCipherSuite == "" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSCipherSuite")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().TLSNegotiatedProto != "h2" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSNegotiatedProto")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if !reflect.DeepEqual(ev[1].Value().TLSNextProtos, nextprotos) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSNextProtos")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().TLSPeerCerts == nil {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSPeerCerts")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().TLSServerName != "www.google.com" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSServerName")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().TLSVersion == "" {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected TLSVersion")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev[1].Value().Time.Before(ev[0].Value().Time) {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("unexpected Time")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSaverTLSHandshakerHostnameError(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skip test in short mode")
|
|
|
|
}
|
2022-05-31 21:53:01 +02:00
|
|
|
saver := &Saver{}
|
2021-09-06 14:12:30 +02:00
|
|
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
2022-06-01 07:44:54 +02:00
|
|
|
Dialer: &netxlite.DialerSystem{},
|
|
|
|
TLSHandshaker: saver.WrapTLSHandshaker(&netxlite.TLSHandshakerConfigurable{}),
|
2021-06-08 11:24:13 +02:00
|
|
|
}
|
|
|
|
conn, err := tlsdlr.DialTLSContext(
|
|
|
|
context.Background(), "tcp", "wrong.host.badssl.com:443")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected an error here")
|
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn here")
|
|
|
|
}
|
|
|
|
for _, ev := range saver.Read() {
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Name() != "tls_handshake_done" {
|
2021-06-08 11:24:13 +02:00
|
|
|
continue
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Value().NoTLSVerify == true {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected NoTLSVerify to be false")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected at least a certificate here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSaverTLSHandshakerInvalidCertError(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skip test in short mode")
|
|
|
|
}
|
2022-05-31 21:53:01 +02:00
|
|
|
saver := &Saver{}
|
2021-09-06 14:12:30 +02:00
|
|
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
2022-06-01 07:44:54 +02:00
|
|
|
Dialer: &netxlite.DialerSystem{},
|
|
|
|
TLSHandshaker: saver.WrapTLSHandshaker(&netxlite.TLSHandshakerConfigurable{}),
|
2021-06-08 11:24:13 +02:00
|
|
|
}
|
|
|
|
conn, err := tlsdlr.DialTLSContext(
|
|
|
|
context.Background(), "tcp", "expired.badssl.com:443")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected an error here")
|
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn here")
|
|
|
|
}
|
|
|
|
for _, ev := range saver.Read() {
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Name() != "tls_handshake_done" {
|
2021-06-08 11:24:13 +02:00
|
|
|
continue
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Value().NoTLSVerify == true {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected NoTLSVerify to be false")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected at least a certificate here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSaverTLSHandshakerAuthorityError(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skip test in short mode")
|
|
|
|
}
|
2022-05-31 21:53:01 +02:00
|
|
|
saver := &Saver{}
|
2021-09-06 14:12:30 +02:00
|
|
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
2022-06-01 07:44:54 +02:00
|
|
|
Dialer: &netxlite.DialerSystem{},
|
|
|
|
TLSHandshaker: saver.WrapTLSHandshaker(&netxlite.TLSHandshakerConfigurable{}),
|
2021-06-08 11:24:13 +02:00
|
|
|
}
|
|
|
|
conn, err := tlsdlr.DialTLSContext(
|
|
|
|
context.Background(), "tcp", "self-signed.badssl.com:443")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected an error here")
|
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn here")
|
|
|
|
}
|
|
|
|
for _, ev := range saver.Read() {
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Name() != "tls_handshake_done" {
|
2021-06-08 11:24:13 +02:00
|
|
|
continue
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Value().NoTLSVerify == true {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected NoTLSVerify to be false")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected at least a certificate here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSaverTLSHandshakerNoTLSVerify(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skip test in short mode")
|
|
|
|
}
|
2022-05-31 21:53:01 +02:00
|
|
|
saver := &Saver{}
|
2021-09-06 14:12:30 +02:00
|
|
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
2022-06-01 07:44:54 +02:00
|
|
|
Config: &tls.Config{InsecureSkipVerify: true},
|
|
|
|
Dialer: &netxlite.DialerSystem{},
|
|
|
|
TLSHandshaker: saver.WrapTLSHandshaker(&netxlite.TLSHandshakerConfigurable{}),
|
2021-06-08 11:24:13 +02:00
|
|
|
}
|
|
|
|
conn, err := tlsdlr.DialTLSContext(
|
|
|
|
context.Background(), "tcp", "self-signed.badssl.com:443")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if conn == nil {
|
|
|
|
t.Fatal("expected non-nil conn here")
|
|
|
|
}
|
|
|
|
conn.Close()
|
|
|
|
for _, ev := range saver.Read() {
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Name() != "tls_handshake_done" {
|
2021-06-08 11:24:13 +02:00
|
|
|
continue
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if ev.Value().NoTLSVerify != true {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected NoTLSVerify to be true")
|
|
|
|
}
|
2022-06-01 14:32:16 +02:00
|
|
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
2021-06-08 11:24:13 +02:00
|
|
|
t.Fatal("expected at least a certificate here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|