-# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
use constant {
VERS_TLS_1_4 => 0x0305,
- VERS_TLS_1_3_DRAFT => 0x7f16,
VERS_TLS_1_3 => 0x0304,
VERS_TLS_1_2 => 0x0303,
VERS_TLS_1_1 => 0x0302,
my $server = shift;
my $flight = shift;
my $packet = shift;
+ my $partial = "";
my @record_list = ();
my @message_list = ();
- my $data;
- my $content_type;
- my $version;
- my $len;
- my $len_real;
- my $decrypt_len;
my $recnum = 1;
while (length ($packet) > 0) {
- print " Record $recnum";
- if ($server) {
- print " (server -> client)\n";
- } else {
- print " (client -> server)\n";
- }
- #Get the record header
- if (length($packet) < TLS_RECORD_HEADER_LENGTH) {
- print "Partial data : ".length($packet)." bytes\n";
- $packet = "";
- } else {
- ($content_type, $version, $len) = unpack('CnnC*', $packet);
- $data = substr($packet, 5, $len);
-
- print " Content type: ".$record_type{$content_type}."\n";
- print " Version: $tls_version{$version}\n";
- print " Length: $len";
- if ($len == length($data)) {
- print "\n";
- $decrypt_len = $len_real = $len;
- } else {
- print " (expected), ".length($data)." (actual)\n";
- $decrypt_len = $len_real = length($data);
- }
+ print " Record $recnum ", $server ? "(server -> client)\n"
+ : "(client -> server)\n";
- my $record = TLSProxy::Record->new(
- $flight,
- $content_type,
- $version,
- $len,
- 0,
- $len_real,
- $decrypt_len,
- substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real),
- substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real)
- );
+ #Get the record header (unpack can't fail if $packet is too short)
+ my ($content_type, $version, $len) = unpack('Cnn', $packet);
+ if (length($packet) < TLS_RECORD_HEADER_LENGTH + ($len // 0)) {
+ print "Partial data : ".length($packet)." bytes\n";
+ $partial = $packet;
+ last;
+ }
+
+ my $data = substr($packet, TLS_RECORD_HEADER_LENGTH, $len);
+
+ print " Content type: ".$record_type{$content_type}."\n";
+ print " Version: $tls_version{$version}\n";
+ print " Length: $len\n";
+
+ my $record = TLSProxy::Record->new(
+ $flight,
+ $content_type,
+ $version,
+ $len,
+ 0,
+ $len, # len_real
+ $len, # decrypt_len
+ $data, # data
+ $data # decrypt_data
+ );
+
+ if ($content_type != RT_CCS
+ && (!TLSProxy::Proxy->is_tls13()
+ || $content_type != RT_ALERT)) {
if (($server && $server_encrypting)
|| (!$server && $client_encrypting)) {
if (!TLSProxy::Proxy->is_tls13() && $etm) {
$record->decrypt();
}
$record->encrypted(1);
- }
- if (TLSProxy::Proxy->is_tls13()) {
- print " Inner content type: "
- .$record_type{$record->content_type()}."\n";
+ if (TLSProxy::Proxy->is_tls13()) {
+ print " Inner content type: "
+ .$record_type{$record->content_type()}."\n";
+ }
}
+ }
- push @record_list, $record;
+ push @record_list, $record;
- #Now figure out what messages are contained within this record
- my @messages = TLSProxy::Message->get_messages($server, $record);
- push @message_list, @messages;
+ #Now figure out what messages are contained within this record
+ my @messages = TLSProxy::Message->get_messages($server, $record);
+ push @message_list, @messages;
- $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len_real);
- $recnum++;
- }
+ $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len);
+ $recnum++;
}
- return (\@record_list, \@message_list);
+ return (\@record_list, \@message_list, $partial);
}
sub clear
$decrypt_len,
$data,
$decrypt_data) = @_;
-
+
my $self = {
flight => $flight,
content_type => $content_type,
data => $data,
decrypt_data => $decrypt_data,
orig_decrypt_data => $decrypt_data,
+ sent => 0,
encrypted => 0,
outer_content_type => RT_APPLICATION_DATA
};
my $self = shift;
my $server = shift;
my $data;
- my $tls13_enc = 0;
+
+ #We only replay the records in the same direction
+ if ($self->{sent} || ($self->flight & 1) != $server) {
+ return "";
+ }
+ $self->{sent} = 1;
if ($self->sslv2) {
$data = pack('n', $self->len | 0x8000);
} else {
if (TLSProxy::Proxy->is_tls13() && $self->encrypted) {
$data = pack('Cnn', $self->outer_content_type, $self->version,
- $self->len + 1);
- $tls13_enc = 1;
+ $self->len);
} else {
$data = pack('Cnn', $self->content_type, $self->version,
$self->len);
}
$data .= $self->data;
- if ($tls13_enc) {
- $data .= pack('C', $self->content_type);
- }
-
return $data;
}
}
return $self->{outer_content_type};
}
+sub is_fatal_alert
+{
+ my $self = shift;
+ my $server = shift;
+
+ if (($self->{flight} & 1) == $server
+ && $self->{content_type} == TLSProxy::Record::RT_ALERT) {
+ my ($level, $alert) = unpack('CC', $self->decrypt_data);
+ return $alert if ($level == 2);
+ }
+ return 0;
+}
1;