Skip to content

Commit

Permalink
Support DTLS in TLS::Proxy.
Browse files Browse the repository at this point in the history
Fixes openssl#23199

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from openssl#23319)
  • Loading branch information
fwh-dc authored and mattcaswell committed Feb 9, 2024
1 parent 01690a7 commit a1c72cc
Show file tree
Hide file tree
Showing 16 changed files with 857 additions and 106 deletions.
153 changes: 153 additions & 0 deletions test/recipes/70-test_dtlsrecords.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#! /usr/bin/env perl
# Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use feature 'state';

use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
use OpenSSL::Test::Utils;
use TLSProxy::Proxy;
use TLSProxy::Message;

my $test_name = "test_dtlsrecords";
setup($test_name);

plan skip_all => "TLSProxy isn't usable on $^O"
if $^O =~ /^(VMS)$/;

plan skip_all => "$test_name needs the dynamic engine feature enabled"
if disabled("engine") || disabled("dynamic-engine");

plan skip_all => "$test_name needs the sock feature enabled"
if disabled("sock");

plan skip_all => "$test_name needs DTLSv1.2 enabled"
if disabled("dtls1_2");

my $proxy = TLSProxy::Proxy->new_dtls(
undef,
cmdstr(app(["openssl"]), display => 1),
srctop_file("apps", "server.pem"),
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
);

plan tests => 4;

my $fatal_alert = 0; # set by filters at expected fatal alerts
my $inject_recs_num = 0; # used by add_empty_recs_filter
my $proxy_start_success = 0;

#Test 1: Injecting out of context empty records should succeed
my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
$inject_recs_num = 1;
$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
$proxy->clientflags("-max_protocol DTLSv1.2");
$proxy->filter(\&add_empty_recs_filter);
$proxy_start_success = $proxy->start();
ok($proxy_start_success && TLSProxy::Message->success(), "Out of context empty records test");

#Test 2: Injecting in context empty records should succeed
$proxy->clear();
$content_type = TLSProxy::Record::RT_HANDSHAKE;
$inject_recs_num = 1;
$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
$proxy->clientflags("-max_protocol DTLSv1.2");
$proxy->filter(\&add_empty_recs_filter);
$proxy_start_success = $proxy->start();
ok($proxy_start_success && TLSProxy::Message->success(), "In context empty records test");

#Unrecognised record type tests

#Test 3: Sending an unrecognised record type in DTLSv1.2 should fail
$fatal_alert = 0;
$proxy->clear();
$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
$proxy->clientflags("-max_protocol DTLSv1.2");
$proxy->filter(\&add_unknown_record_type);
ok($proxy->start() == 0, "Unrecognised record type in DTLS1.2");

SKIP: {
skip "DTLSv1 disabled", 1 if disabled("dtls1");

#Test 4: Sending an unrecognised record type in DTLSv1 should fail
$fatal_alert = 0;
$proxy->clear();
$proxy->clientflags("-min_protocol DTLSv1 -max_protocol DTLSv1 -cipher DEFAULT:\@SECLEVEL=0");
$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
$proxy->filter(\&add_unknown_record_type);
ok($proxy->start() == 0, "Unrecognised record type in DTLSv1");
}

sub add_empty_recs_filter
{
my $proxy = shift;
my $records = $proxy->record_list;

# We're only interested in the initial ClientHello
if ($proxy->flight != 0) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

for (my $i = 0; $i < $inject_recs_num; $i++) {
my $record = TLSProxy::Record->new_dtls(
0,
$content_type,
TLSProxy::Record::VERS_TLS_1_2,
0,
0,
0,
0,
0,
0,
"",
""
);
push @{$records}, $record;
}
}

sub add_unknown_record_type
{
my $proxy = shift;
my $records = $proxy->record_list;
state $added_record;

# We'll change a record after the initial version neg has taken place
if ($proxy->flight == 0) {
$added_record = 0;
return;
} elsif ($proxy->flight != 1 || $added_record) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

my $record = TLSProxy::Record->new_dtls(
1,
TLSProxy::Record::RT_UNKNOWN,
@{$records}[-1]->version(),
@{$records}[-1]->epoch(),
@{$records}[-1]->seq() +1,
1,
0,
1,
1,
"X",
"X"
);

#Find ServerHello record and insert after that
my $i;
for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
next;
}
$i++;

splice @{$proxy->record_list}, $i, 0, $record;
$added_record = 1;
}
2 changes: 1 addition & 1 deletion test/recipes/70-test_sslcbcpadding.t
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,6 @@ sub add_maximal_padding_filter
} elsif ($sent_corrupted_payload) {
# Check for bad_record_mac from client
my $last_record = @{$proxy->record_list}[-1];
$fatal_alert = 1 if $last_record->is_fatal_alert(0) == 20;
$fatal_alert = 1 if $last_record->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_BAD_RECORD_MAC;
}
}
13 changes: 7 additions & 6 deletions test/recipes/70-test_sslrecords.t
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use feature 'state';
use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
use OpenSSL::Test::Utils;
use TLSProxy::Proxy;
use TLSProxy::Message;

my $test_name = "test_sslrecords";
setup($test_name);
Expand Down Expand Up @@ -273,7 +274,7 @@ sub add_empty_recs_filter

# We're only interested in the initial ClientHello
if ($proxy->flight != 0) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

Expand Down Expand Up @@ -301,7 +302,7 @@ sub add_frag_alert_filter

# We're only interested in the initial ClientHello
if ($proxy->flight != 0) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

Expand Down Expand Up @@ -507,7 +508,7 @@ sub add_unknown_record_type
$added_record = 0;
return;
} elsif ($proxy->flight != 1 || $added_record) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

Expand Down Expand Up @@ -541,7 +542,7 @@ sub change_version

# We'll change a version after the initial version neg has taken place
if ($proxy->flight != 1) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 70;
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_PROTOCOL_VERSION;
return;
}

Expand Down Expand Up @@ -578,7 +579,7 @@ sub change_outer_record_type

# We'll change a record after the initial version neg has taken place
if ($proxy->flight != 1) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

Expand All @@ -601,7 +602,7 @@ sub not_on_record_boundary

#Find server's first flight
if ($proxy->flight != 1) {
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}

Expand Down
3 changes: 2 additions & 1 deletion test/recipes/70-test_tls13hrr.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use strict;
use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
use OpenSSL::Test::Utils;
use TLSProxy::Proxy;
use TLSProxy::Message;

my $test_name = "test_tls13hrr";
setup($test_name);
Expand Down Expand Up @@ -122,7 +123,7 @@ sub hrr_filter
# and the unexpected_message alert from client
if ($proxy->flight == 4) {
$fatal_alert = 1
if @{$proxy->record_list}[-1]->is_fatal_alert(0) == 10;
if @{$proxy->record_list}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
return;
}
if ($proxy->flight != 3) {
Expand Down
10 changes: 9 additions & 1 deletion util/perl/TLSProxy/Certificate.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ push @ISA, 'TLSProxy::Message';
sub new
{
my $class = shift;
my ($server,
my ($isdtls,
$server,
$msgseq,
$msgfrag,
$msgfragoffs,
$data,
$records,
$startoffset,
$message_frag_lens) = @_;

my $self = $class->SUPER::new(
$isdtls,
$server,
TLSProxy::Message::MT_CERTIFICATE,
$msgseq,
$msgfrag,
$msgfragoffs,
$data,
$records,
$startoffset,
Expand Down
10 changes: 9 additions & 1 deletion util/perl/TLSProxy/CertificateRequest.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ push @ISA, 'TLSProxy::Message';
sub new
{
my $class = shift;
my ($server,
my ($isdtls,
$server,
$msgseq,
$msgfrag,
$msgfragoffs,
$data,
$records,
$startoffset,
$message_frag_lens) = @_;

my $self = $class->SUPER::new(
$isdtls,
$server,
TLSProxy::Message::MT_CERTIFICATE_REQUEST,
$msgseq,
$msgfrag,
$msgfragoffs,
$data,
$records,
$startoffset,
Expand Down
10 changes: 9 additions & 1 deletion util/perl/TLSProxy/CertificateVerify.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ push @ISA, 'TLSProxy::Message';
sub new
{
my $class = shift;
my ($server,
my ($isdtls,
$server,
$msgseq,
$msgfrag,
$msgfragoffs,
$data,
$records,
$startoffset,
$message_frag_lens) = @_;

my $self = $class->SUPER::new(
$isdtls,
$server,
TLSProxy::Message::MT_CERTIFICATE_VERIFY,
$msgseq,
$msgfrag,
$msgfragoffs,
$data,
$records,
$startoffset,
Expand Down
Loading

0 comments on commit a1c72cc

Please sign in to comment.