Update copyright year
[openssl.git] / util / perl / TLSProxy / Record.pm
index c5583082daadda89029378aab03959d1d7236d26..841467b8e02f4b0549cdffa5cb9434c1a107bdfc 100644 (file)
@@ -1,4 +1,4 @@
-# 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
@@ -36,7 +36,6 @@ my %record_type = (
 
 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,
@@ -61,54 +60,45 @@ sub get_records
     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) {
@@ -117,25 +107,25 @@ sub get_records
                     $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
@@ -183,7 +173,7 @@ sub new
         $decrypt_len,
         $data,
         $decrypt_data) = @_;
-    
+
     my $self = {
         flight => $flight,
         content_type => $content_type,
@@ -195,6 +185,7 @@ sub new
         data => $data,
         decrypt_data => $decrypt_data,
         orig_decrypt_data => $decrypt_data,
+        sent => 0,
         encrypted => 0,
         outer_content_type => RT_APPLICATION_DATA
     };
@@ -284,15 +275,19 @@ sub reconstruct_record
     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);
@@ -301,10 +296,6 @@ sub reconstruct_record
     }
     $data .= $self->data;
 
-    if ($tls13_enc) {
-        $data .= pack('C', $self->content_type);
-    }
-
     return $data;
 }
 
@@ -395,4 +386,16 @@ sub outer_content_type
     }
     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;