diff options
author | Frederik Wedel-Heinen <frederik.wedel-heinen@dencrypt.dk> | 2024-01-11 14:18:07 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2024-02-09 08:11:23 +0000 |
commit | a1c72cc20dd4620a69142cfc65fd17daef8d28ee (patch) | |
tree | 0ac3c746f4b0e57162a6d493787189cc130f5e2f /util | |
parent | 01690a7ff36c4d18c48b301cdf375c954105a1d9 (diff) |
Support DTLS in TLS::Proxy.
Fixes #23199
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23319)
Diffstat (limited to 'util')
-rw-r--r-- | util/perl/TLSProxy/Certificate.pm | 10 | ||||
-rw-r--r-- | util/perl/TLSProxy/CertificateRequest.pm | 10 | ||||
-rw-r--r-- | util/perl/TLSProxy/CertificateVerify.pm | 10 | ||||
-rw-r--r-- | util/perl/TLSProxy/ClientHello.pm | 54 | ||||
-rw-r--r-- | util/perl/TLSProxy/EncryptedExtensions.pm | 10 | ||||
-rw-r--r-- | util/perl/TLSProxy/HelloVerifyRequest.pm | 115 | ||||
-rw-r--r-- | util/perl/TLSProxy/Message.pm | 187 | ||||
-rw-r--r-- | util/perl/TLSProxy/NewSessionTicket.pm | 56 | ||||
-rw-r--r-- | util/perl/TLSProxy/Proxy.pm | 132 | ||||
-rw-r--r-- | util/perl/TLSProxy/Record.pm | 184 | ||||
-rw-r--r-- | util/perl/TLSProxy/ServerHello.pm | 14 | ||||
-rw-r--r-- | util/perl/TLSProxy/ServerKeyExchange.pm | 10 |
12 files changed, 694 insertions, 98 deletions
diff --git a/util/perl/TLSProxy/Certificate.pm b/util/perl/TLSProxy/Certificate.pm index 03f6619954..a32bc2c97b 100644 --- a/util/perl/TLSProxy/Certificate.pm +++ b/util/perl/TLSProxy/Certificate.pm @@ -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, diff --git a/util/perl/TLSProxy/CertificateRequest.pm b/util/perl/TLSProxy/CertificateRequest.pm index 193bea168a..0191df68f9 100644 --- a/util/perl/TLSProxy/CertificateRequest.pm +++ b/util/perl/TLSProxy/CertificateRequest.pm @@ -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, diff --git a/util/perl/TLSProxy/CertificateVerify.pm b/util/perl/TLSProxy/CertificateVerify.pm index fe45001405..9592272991 100644 --- a/util/perl/TLSProxy/CertificateVerify.pm +++ b/util/perl/TLSProxy/CertificateVerify.pm @@ -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, diff --git a/util/perl/TLSProxy/ClientHello.pm b/util/perl/TLSProxy/ClientHello.pm index c49bc23671..5a5f5fd34d 100644 --- a/util/perl/TLSProxy/ClientHello.pm +++ b/util/perl/TLSProxy/ClientHello.pm @@ -9,30 +9,43 @@ use strict; package TLSProxy::ClientHello; +use TLSProxy::Record; + use vars '@ISA'; 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, - 1, + TLSProxy::Message::MT_CLIENT_HELLO, + $msgseq, + $msgfrag, + $msgfragoffs, $data, $records, $startoffset, $message_frag_lens); + $self->{isdtls} = $isdtls; $self->{client_version} = 0; $self->{random} = []; $self->{session_id_len} = 0; $self->{session} = ""; + $self->{legacy_cookie_len} = 0; #DTLS only + $self->{legacy_cookie} = ""; #DTLS only $self->{ciphersuite_len} = 0; $self->{ciphersuites} = []; $self->{comp_meth_len} = 0; @@ -54,6 +67,14 @@ sub parse $ptr++; my $session = substr($self->data, $ptr, $session_id_len); $ptr += $session_id_len; + my $legacy_cookie_len = 0; + my $legacy_cookie = ""; + if($self->{isdtls}) { + $legacy_cookie_len = unpack('C', substr($self->data, $ptr)); + $ptr++; + $legacy_cookie = substr($self->data, $ptr, $legacy_cookie_len); + $ptr += $legacy_cookie_len; + } my $ciphersuite_len = unpack('n', substr($self->data, $ptr)); $ptr += 2; my @ciphersuites = unpack('n*', substr($self->data, $ptr, @@ -84,6 +105,8 @@ sub parse $self->random($random); $self->session_id_len($session_id_len); $self->session($session); + $self->legacy_cookie_len($legacy_cookie_len); + $self->legacy_cookie($legacy_cookie); $self->ciphersuite_len($ciphersuite_len); $self->ciphersuites(\@ciphersuites); $self->comp_meth_len($comp_meth_len); @@ -93,8 +116,11 @@ sub parse $self->process_extensions(); - print " Client Version:".$client_version."\n"; + print " Client Version:".$TLSProxy::Record::tls_version{$client_version}."\n"; print " Session ID Len:".$session_id_len."\n"; + if($self->{isdtls}) { + print " Legacy Cookie Len:".$legacy_cookie_len."\n"; + } print " Ciphersuite len:".$ciphersuite_len."\n"; print " Compression Method Len:".$comp_meth_len."\n"; print " Extensions Len:".$extensions_len."\n"; @@ -138,6 +164,12 @@ sub set_message_contents $data .= $self->random; $data .= pack('C', $self->session_id_len); $data .= $self->session; + if($self->{isdtls}){ + $data .= pack('C', $self->legacy_cookie_len); + if($self->legacy_cookie_len > 0) { + $data .= $self->legacy_cookie; + } + } $data .= pack('n', $self->ciphersuite_len); $data .= pack("n*", @{$self->ciphersuites}); $data .= pack('C', $self->comp_meth_len); @@ -197,6 +229,22 @@ sub session } return $self->{session}; } +sub legacy_cookie_len +{ + my $self = shift; + if (@_) { + $self->{legacy_cookie_len} = shift; + } + return $self->{legacy_cookie_len}; +} +sub legacy_cookie +{ + my $self = shift; + if (@_) { + $self->{legacy_cookie} = shift; + } + return $self->{legacy_cookie}; +} sub ciphersuite_len { my $self = shift; diff --git a/util/perl/TLSProxy/EncryptedExtensions.pm b/util/perl/TLSProxy/EncryptedExtensions.pm index 4fd445b41e..5f867101d9 100644 --- a/util/perl/TLSProxy/EncryptedExtensions.pm +++ b/util/perl/TLSProxy/EncryptedExtensions.pm @@ -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_ENCRYPTED_EXTENSIONS, + $msgseq, + $msgfrag, + $msgfragoffs, $data, $records, $startoffset, diff --git a/util/perl/TLSProxy/HelloVerifyRequest.pm b/util/perl/TLSProxy/HelloVerifyRequest.pm new file mode 100644 index 0000000000..40162d08ef --- /dev/null +++ b/util/perl/TLSProxy/HelloVerifyRequest.pm @@ -0,0 +1,115 @@ +# Copyright 2016-2018 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; + +package TLSProxy::HelloVerifyRequest; + +use TLSProxy::Record; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + + +sub new +{ + my $class = shift; + my ($isdtls, + $server, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $isdtls, + $server, + TLSProxy::Message::MT_HELLO_VERIFY_REQUEST, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{server_version} = 0; + $self->{cookie_len} = 0; + $self->{cookie} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + + my ($server_version) = unpack('n', $self->data); + my $ptr = 2; + my $cookie_len = unpack('C', substr($self->data, $ptr)); + $ptr++; + my $cookie = substr($self->data, $ptr, $cookie_len); + + $self->server_version($server_version); + $self->cookie_len($cookie_len); + $self->cookie($cookie); + + $self->process_data(); + + print " Server Version:".$TLSProxy::Record::tls_version{$server_version}."\n"; + print " Cookie Len:".$cookie_len."\n"; +} + +#Perform any actions necessary based on the data we've seen +sub process_data +{ + my $self = shift; + #Intentional no-op +} + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + + $data = pack('n', $self->server_version); + $data .= pack('C', $self->cookie_len); + $data .= $self->cookie; + + $self->data($data); +} + +#Read/write accessors +sub server_version +{ + my $self = shift; + if (@_) { + $self->{server_version} = shift; + } + return $self->{server_version}; +} +sub cookie_len +{ + my $self = shift; + if (@_) { + $self->{cookie_len} = shift; + } + return $self->{cookie_len}; +} +sub cookie +{ + my $self = shift; + if (@_) { + $self->{cookie} = shift; + } + return $self->{cookie}; +} +1; diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index ce22187569..c5e822e90d 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -11,6 +11,7 @@ package TLSProxy::Message; use TLSProxy::Alert; +use constant DTLS_MESSAGE_HEADER_LENGTH => 12; use constant TLS_MESSAGE_HEADER_LENGTH => 4; #Message types @@ -18,6 +19,7 @@ use constant { MT_HELLO_REQUEST => 0, MT_CLIENT_HELLO => 1, MT_SERVER_HELLO => 2, + MT_HELLO_VERIFY_REQUEST => 3, MT_NEW_SESSION_TICKET => 4, MT_ENCRYPTED_EXTENSIONS => 8, MT_CERTIFICATE => 11, @@ -42,7 +44,9 @@ use constant { use constant { AL_DESC_CLOSE_NOTIFY => 0, AL_DESC_UNEXPECTED_MESSAGE => 10, + AL_DESC_BAD_RECORD_MAC => 20, AL_DESC_ILLEGAL_PARAMETER => 47, + AL_DESC_PROTOCOL_VERSION => 70, AL_DESC_NO_RENEGOTIATION => 100 }; @@ -50,6 +54,7 @@ my %message_type = ( MT_HELLO_REQUEST, "HelloRequest", MT_CLIENT_HELLO, "ClientHello", MT_SERVER_HELLO, "ServerHello", + MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest", MT_NEW_SESSION_TICKET, "NewSessionTicket", MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions", MT_CERTIFICATE, "Certificate", @@ -172,6 +177,7 @@ sub get_messages my $class = shift; my $serverin = shift; my $record = shift; + my $isdtls = shift; my @messages = (); my $message; @@ -216,8 +222,14 @@ sub get_messages $recoffset = $messlen - length($payload); $payload .= substr($record->decrypt_data, 0, $recoffset); push @message_frag_lens, $recoffset; - $message = create_message($server, $mt, $payload, - $startoffset); + if ($isdtls) { + # We must set $msgseq, $msgfrag, $msgfragoffs + die "Internal error: cannot handle partial dtls messages\n" + } + $message = create_message($server, $mt, + #$msgseq, $msgfrag, $msgfragoffs, + 0, 0, 0, + $payload, $startoffset, $isdtls); push @messages, $message; $payload = ""; @@ -232,21 +244,36 @@ sub get_messages while ($record->decrypt_len > $recoffset) { #We are at the start of a new message - if ($record->decrypt_len - $recoffset < 4) { + my $msgheaderlen = $isdtls ? DTLS_MESSAGE_HEADER_LENGTH + : TLS_MESSAGE_HEADER_LENGTH; + if ($record->decrypt_len - $recoffset < $msgheaderlen) { #Whilst technically probably valid we can't cope with this die "End of record in the middle of a message header\n"; } @message_rec_list = ($record); my $lenhi; my $lenlo; - ($mt, $lenhi, $lenlo) = unpack('CnC', - substr($record->decrypt_data, - $recoffset)); + my $msgseq; + my $msgfrag; + my $msgfragoffs; + if ($isdtls) { + my $msgfraghi; + my $msgfraglo; + my $msgfragoffshi; + my $msgfragoffslo; + ($mt, $lenhi, $lenlo, $msgseq, $msgfraghi, $msgfraglo, $msgfragoffshi, $msgfragoffslo) = + unpack('CnCnnCnC', substr($record->decrypt_data, $recoffset)); + $msgfrag = ($msgfraghi << 8) | $msgfraglo; + $msgfragoffs = ($msgfragoffshi << 8) | $msgfragoffslo; + } else { + ($mt, $lenhi, $lenlo) = + unpack('CnC', substr($record->decrypt_data, $recoffset)); + } $messlen = ($lenhi << 8) | $lenlo; - print " Message type: $message_type{$mt}\n"; + print " Message type: $message_type{$mt}($mt)\n"; print " Message Length: $messlen\n"; $startoffset = $recoffset; - $recoffset += 4; + $recoffset += $msgheaderlen; $payload = ""; if ($recoffset <= $record->decrypt_len) { @@ -257,8 +284,9 @@ sub get_messages $messlen); $recoffset += $messlen; push @message_frag_lens, $messlen; - $message = create_message($server, $mt, $payload, - $startoffset); + $message = create_message($server, $mt, $msgseq, + $msgfrag, $msgfragoffs, + $payload, $startoffset, $isdtls); push @messages, $message; $payload = ""; @@ -307,14 +335,18 @@ sub get_messages #construct it sub create_message { - my ($server, $mt, $data, $startoffset) = @_; + my ($server, $mt, $msgseq, $msgfrag, $msgfragoffs, $data, $startoffset, $isdtls) = @_; my $message; #We only support ClientHello in this version...needs to be extended for #others if ($mt == MT_CLIENT_HELLO) { $message = TLSProxy::ClientHello->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -323,7 +355,24 @@ sub create_message $message->parse(); } elsif ($mt == MT_SERVER_HELLO) { $message = TLSProxy::ServerHello->new( + $isdtls, + $server, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_HELLO_VERIFY_REQUEST) { + $message = TLSProxy::HelloVerifyRequest->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -332,7 +381,11 @@ sub create_message $message->parse(); } elsif ($mt == MT_ENCRYPTED_EXTENSIONS) { $message = TLSProxy::EncryptedExtensions->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -341,7 +394,11 @@ sub create_message $message->parse(); } elsif ($mt == MT_CERTIFICATE) { $message = TLSProxy::Certificate->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -350,7 +407,11 @@ sub create_message $message->parse(); } elsif ($mt == MT_CERTIFICATE_REQUEST) { $message = TLSProxy::CertificateRequest->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -359,7 +420,11 @@ sub create_message $message->parse(); } elsif ($mt == MT_CERTIFICATE_VERIFY) { $message = TLSProxy::CertificateVerify->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -368,7 +433,11 @@ sub create_message $message->parse(); } elsif ($mt == MT_SERVER_KEY_EXCHANGE) { $message = TLSProxy::ServerKeyExchange->new( + $isdtls, $server, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -376,19 +445,36 @@ sub create_message ); $message->parse(); } elsif ($mt == MT_NEW_SESSION_TICKET) { - $message = TLSProxy::NewSessionTicket->new( - $server, - $data, - [@message_rec_list], - $startoffset, - [@message_frag_lens] - ); + if ($isdtls) { + $message = TLSProxy::NewSessionTicket->new_dtls( + $server, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + } else { + $message = TLSProxy::NewSessionTicket->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + } $message->parse(); } else { #Unknown message type $message = TLSProxy::Message->new( + $isdtls, $server, $mt, + $msgseq, + $msgfrag, + $msgfragoffs, $data, [@message_rec_list], $startoffset, @@ -423,18 +509,26 @@ sub alert sub new { my $class = shift; - my ($server, + my ($isdtls, + $server, $mt, + $msgseq, + $msgfrag, + $msgfragoffs, $data, $records, $startoffset, $message_frag_lens) = @_; my $self = { + isdtls => $isdtls, server => $server, data => $data, records => $records, mt => $mt, + msgseq => $msgseq, + msgfrag => $msgfrag, + msgfragoffs => $msgfragoffs, startoffset => $startoffset, message_frag_lens => $message_frag_lens, dupext => -1 @@ -463,12 +557,21 @@ sub repack $self->set_message_contents(); - my $lenhi; - my $lenlo; + my $lenlo = length($self->data) & 0xff; + my $lenhi = length($self->data) >> 8; - $lenlo = length($self->data) & 0xff; - $lenhi = length($self->data) >> 8; - $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data; + if ($self->{isdtls}) { + my $msgfraghi = $self->msgfrag >> 8; + my $msgfraglo = $self->msgfrag & 0xff; + my $msgfragoffshi = $self->msgfragoffs >> 8; + my $msgfragoffslo = $self->msgfragoffs & 0xff; + + $msgdata = pack('CnCnnCnC', $self->mt, $lenhi, $lenlo, $self->msgseq, + $msgfraghi, $msgfraglo, + $msgfragoffshi, $msgfragoffslo).$self->data; + } else { + $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data; + } if ($numrecs == 0) { #The message is fully contained within one record @@ -476,13 +579,14 @@ sub repack my $recdata = $rec->decrypt_data; my $old_length; + my $msg_header_len = $self->{isdtls} ? DTLS_MESSAGE_HEADER_LENGTH + : TLS_MESSAGE_HEADER_LENGTH; # We use empty message_frag_lens to indicates that pre-repacking, # the message wasn't present. The first fragment length doesn't include # the TLS header, so we need to check and compute the right length. if (@{$self->message_frag_lens}) { - $old_length = ${$self->message_frag_lens}[0] + - TLS_MESSAGE_HEADER_LENGTH; + $old_length = ${$self->message_frag_lens}[0] + $msg_header_len; } else { $old_length = 0; } @@ -529,8 +633,7 @@ sub repack $rec->len(length($rec->data)); #Update the fragment len in case we changed it above - ${$self->message_frag_lens}[0] = length($msgdata) - - TLS_MESSAGE_HEADER_LENGTH; + ${$self->message_frag_lens}[0] = length($msgdata) - $msg_header_len; return; } @@ -578,6 +681,30 @@ sub mt } return $self->{mt}; } +sub msgseq +{ + my $self = shift; + if (@_) { + $self->{msgseq} = shift; + } + return $self->{msgseq}; +} +sub msgfrag +{ + my $self = shift; + if (@_) { + $self->{msgfrag} = shift; + } + return $self->{msgfrag}; +} +sub msgfragoffs +{ + my $self = shift; + if (@_) { + $self->{msgfragoffs} = shift; + } + return $self->{msgfragoffs}; +} sub data { my $self = shift; @@ -613,7 +740,9 @@ sub message_frag_lens sub encoded_length { my $self = shift; - return TLS_MESSAGE_HEADER_LENGTH + length($self->data); + my $msg_header_len = $self->{isdtls} ? DTLS_MESSAGE_HEADER_LENGTH + : TLS_MESSAGE_HEADER_LENGTH; + return $msg_header_len + length($self->data); } sub dupext { diff --git a/util/perl/TLSProxy/NewSessionTicket.pm b/util/perl/TLSProxy/NewSessionTicket.pm index 1c532ff7be..748efb8aa8 100644 --- a/util/perl/TLSProxy/NewSessionTicket.pm +++ b/util/perl/TLSProxy/NewSessionTicket.pm @@ -12,18 +12,74 @@ package TLSProxy::NewSessionTicket; use vars '@ISA'; push @ISA, 'TLSProxy::Message'; +sub new_dtls +{ + my $class = shift; + + my ($server, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + return $class->init( + 1, + $server, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + $records, + $startoffset, + $message_frag_lens + ) +} + sub new { my $class = shift; + my ($server, $data, $records, $startoffset, $message_frag_lens) = @_; + return $class->init( + 0, + $server, + 0, # msgseq + 0, # msgfrag + 0, # $msgfragoffs + $data, + $records, + $startoffset, + $message_frag_lens + ) +} + +sub init{ + my $class = shift; + my ($isdtls, + $server, + $msgseq, + $msgfrag, + $msgfragoffs, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + my $self = $class->SUPER::new( + $isdtls, $server, TLSProxy::Message::MT_NEW_SESSION_TICKET, + $msgseq, + $msgfrag, + $msgfragoffs, $data, $records, $startoffset, diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm index 3de10eccb9..0084328a5f 100644 --- a/util/perl/TLSProxy/Proxy.pm +++ b/util/perl/TLSProxy/Proxy.pm @@ -17,6 +17,7 @@ use TLSProxy::Record; use TLSProxy::Message; use TLSProxy::ClientHello; use TLSProxy::ServerHello; +use TLSProxy::HelloVerifyRequest; use TLSProxy::EncryptedExtensions; use TLSProxy::Certificate; use TLSProxy::CertificateRequest; @@ -71,17 +72,37 @@ BEGIN my $is_tls13 = 0; my $ciphersuite = undef; -sub new -{ +sub new { + my $class = shift; + my ($filter, + $execute, + $cert, + $debug) = @_; + return init($class, $filter, $execute, $cert, $debug, 0); +} + +sub new_dtls { my $class = shift; my ($filter, $execute, $cert, $debug) = @_; + return init($class, $filter, $execute, $cert, $debug, 1); +} + +sub init +{ + my $class = shift; + my ($filter, + $execute, + $cert, + $debug, + $isdtls) = @_; my $self = { #Public read/write proxy_addr => $have_IPv6 ? "[::1]" : "127.0.0.1", + client_addr => $have_IPv6 ? "[::1]" : "127.0.0.1", filter => $filter, serverflags => "", clientflags => "", @@ -90,7 +111,9 @@ sub new sessionfile => undef, #Public read + isdtls => $isdtls, proxy_port => 0, + client_port => 49152 + int(rand(65535 - 49152)), server_port => 0, serverpid => 0, clientpid => 0, @@ -108,29 +131,6 @@ sub new message_list => [], }; - # Create the Proxy socket - my $proxaddr = $self->{proxy_addr}; - $proxaddr =~ s/[\[\]]//g; # Remove [ and ] - my @proxyargs = ( - LocalHost => $proxaddr, - LocalPort => 0, - Proto => "tcp", - Listen => SOMAXCONN, - ); - - if (my $sock = $IP_factory->(@proxyargs)) { - $self->{proxy_sock} = $sock; - $self->{proxy_port} = $sock->sockport(); - $self->{proxy_addr} = $sock->sockhost(); - $self->{proxy_addr} =~ s/(.*:.*)/[$1]/; - print "Proxy started on port ", - "$self->{proxy_addr}:$self->{proxy_port}\n"; - # use same address for s_server - $self->{server_addr} = $self->{proxy_addr}; - } else { - warn "Failed creating proxy socket (".$proxaddr.",0): $!\n"; - } - return bless $self, $class; } @@ -200,7 +200,7 @@ sub connect_to_server my $sock = $IP_factory->(PeerAddr => $servaddr, PeerPort => $self->{server_port}, - Proto => 'tcp'); + Proto => $self->{isdtls} ? 'udp' : 'tcp'); if (!defined($sock)) { my $err = $!; kill(3, $self->{real_serverpid}); @@ -215,12 +215,51 @@ sub start my ($self) = shift; my $pid; + + # Create the Proxy socket + my $proxaddr = $self->{proxy_addr}; + $proxaddr =~ s/[\[\]]//g; # Remove [ and ] + my $clientaddr = $self->{client_addr}; + $clientaddr =~ s/[\[\]]//g; # Remove [ and ] + + my @proxyargs; + + if ($self->{isdtls}) { + @proxyargs = ( + LocalHost => $proxaddr, + LocalPort => 0, + PeerHost => $clientaddr, + PeerPort => $self->{client_port}, + Proto => "udp", + ); + } else { + @proxyargs = ( + LocalHost => $proxaddr, + LocalPort => 0, + Proto => "tcp", + Listen => SOMAXCONN, + ); + } + + if (my $sock = $IP_factory->(@proxyargs)) { + $self->{proxy_sock} = $sock; + $self->{proxy_port} = $sock->sockport(); + $self->{proxy_addr} = $sock->sockhost(); + $self->{proxy_addr} =~ s/(.*:.*)/[$1]/; + print "Proxy started on port ", + "$self->{proxy_addr}:$self->{proxy_port}\n"; + # use same address for s_server + $self->{server_addr} = $self->{proxy_addr}; + } else { + warn "Failed creating proxy socket (".$proxaddr.",0): $!\n"; + } + if ($self->{proxy_sock} == 0) { return 0; } my $execcmd = $self->execute - ." s_server -max_protocol TLSv1.3 -no_comp -rev -engine ossltest" + ." s_server -no_comp -engine ossltest -state" #In TLSv1.3 we issue two session tickets. The default session id #callback gets confused because the ossltest engine causes the same #session id to be created twice due to the changed random number @@ -230,6 +269,14 @@ sub start ." -accept $self->{server_addr}:0" ." -cert ".$self->cert." -cert2 ".$self->cert ." -naccept ".$self->serverconnects; + if ($self->{isdtls}) { + $execcmd .= " -dtls -max_protocol DTLSv1.2" + |