Home | History | Annotate | Line # | Download | only in TLSProxy
      1 # Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
      2 #
      3 # Licensed under the Apache License 2.0 (the "License").  You may not use
      4 # this file except in compliance with the License.  You can obtain a copy
      5 # in the file LICENSE in the source distribution or at
      6 # https://www.openssl.org/source/license.html
      7 
      8 use strict;
      9 
     10 package TLSProxy::ServerHello;
     11 
     12 use TLSProxy::Record;
     13 
     14 use vars '@ISA';
     15 push @ISA, 'TLSProxy::Message';
     16 
     17 my $hrrrandom = pack("C*", 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE,
     18                            0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2,
     19                            0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09,
     20                            0xE2, 0xC8, 0xA8, 0x33, 0x9C);
     21 
     22 sub new
     23 {
     24     my $class = shift;
     25     my ($isdtls,
     26         $server,
     27         $msgseq,
     28         $msgfrag,
     29         $msgfragoffs,
     30         $data,
     31         $records,
     32         $startoffset,
     33         $message_frag_lens) = @_;
     34 
     35     my $self = $class->SUPER::new(
     36         $isdtls,
     37         $server,
     38         TLSProxy::Message::MT_SERVER_HELLO,
     39         $msgseq,
     40         $msgfrag,
     41         $msgfragoffs,
     42         $data,
     43         $records,
     44         $startoffset,
     45         $message_frag_lens);
     46 
     47     $self->{server_version} = 0;
     48     $self->{random} = [];
     49     $self->{session_id_len} = 0;
     50     $self->{session} = "";
     51     $self->{ciphersuite} = 0;
     52     $self->{comp_meth} = 0;
     53     $self->{extension_data} = "";
     54 
     55     return $self;
     56 }
     57 
     58 sub parse
     59 {
     60     my $self = shift;
     61     my $ptr = 2;
     62     my ($server_version) = unpack('n', $self->data);
     63     my $neg_version = $server_version;
     64 
     65     my $random = substr($self->data, $ptr, 32);
     66     $ptr += 32;
     67     my $session_id_len = 0;
     68     my $session = "";
     69     $session_id_len = unpack('C', substr($self->data, $ptr));
     70     $ptr++;
     71     $session = substr($self->data, $ptr, $session_id_len);
     72     $ptr += $session_id_len;
     73 
     74     my $ciphersuite = unpack('n', substr($self->data, $ptr));
     75     $ptr += 2;
     76     my $comp_meth = 0;
     77     $comp_meth = unpack('C', substr($self->data, $ptr));
     78     $ptr++;
     79 
     80     my $extensions_len = unpack('n', substr($self->data, $ptr));
     81     if (!defined $extensions_len) {
     82         $extensions_len = 0;
     83     } else {
     84         $ptr += 2;
     85     }
     86     #For now we just deal with this as a block of data. In the future we will
     87     #want to parse this
     88     my $extension_data;
     89     if ($extensions_len != 0) {
     90         $extension_data = substr($self->data, $ptr);
     91 
     92         if (length($extension_data) != $extensions_len) {
     93             die "Invalid extension length\n";
     94         }
     95     } else {
     96         if (length($self->data) != $ptr) {
     97             die "Invalid extension length\n";
     98         }
     99         $extension_data = "";
    100     }
    101     my %extensions = ();
    102     while (length($extension_data) >= 4) {
    103         my ($type, $size) = unpack("nn", $extension_data);
    104         my $extdata = substr($extension_data, 4, $size);
    105         $extension_data = substr($extension_data, 4 + $size);
    106         $extensions{$type} = $extdata;
    107         if ($type == TLSProxy::Message::EXT_SUPPORTED_VERSIONS) {
    108             $neg_version = unpack('n', $extdata);
    109         }
    110     }
    111 
    112     if ($random eq $hrrrandom) {
    113         TLSProxy::Proxy->is_tls13(1);
    114     } elsif ($neg_version == TLSProxy::Record::VERS_TLS_1_3) {
    115         TLSProxy::Proxy->is_tls13(1);
    116 
    117         TLSProxy::Record->server_encrypting(1);
    118         TLSProxy::Record->client_encrypting(1);
    119     }
    120 
    121     $self->server_version($server_version);
    122     $self->random($random);
    123     $self->session_id_len($session_id_len);
    124     $self->session($session);
    125     $self->ciphersuite($ciphersuite);
    126     TLSProxy::Proxy->ciphersuite($ciphersuite);
    127     $self->comp_meth($comp_meth);
    128     $self->extension_data(\%extensions);
    129 
    130     $self->process_data();
    131 
    132 
    133     print "    Server Version:".$TLSProxy::Record::tls_version{$server_version}."\n";
    134     print "    Session ID Len:".$session_id_len."\n";
    135     print "    Ciphersuite:".$ciphersuite."\n";
    136     print "    Compression Method:".$comp_meth."\n";
    137     print "    Extensions Len:".$extensions_len."\n";
    138 }
    139 
    140 #Perform any actions necessary based on the data we've seen
    141 sub process_data
    142 {
    143     my $self = shift;
    144 
    145     TLSProxy::Message->ciphersuite($self->ciphersuite);
    146 }
    147 
    148 #Reconstruct the on-the-wire message data following changes
    149 sub set_message_contents
    150 {
    151     my $self = shift;
    152     my $data;
    153     my $extensions = "";
    154 
    155     $data = pack('n', $self->server_version);
    156     $data .= $self->random;
    157     $data .= pack('C', $self->session_id_len);
    158     $data .= $self->session;
    159     $data .= pack('n', $self->ciphersuite);
    160     $data .= pack('C', $self->comp_meth);
    161 
    162     foreach my $key (keys %{$self->extension_data}) {
    163         my $extdata = ${$self->extension_data}{$key};
    164         $extensions .= pack("n", $key);
    165         $extensions .= pack("n", length($extdata));
    166         $extensions .= $extdata;
    167         if ($key == $self->dupext) {
    168           $extensions .= pack("n", $key);
    169           $extensions .= pack("n", length($extdata));
    170           $extensions .= $extdata;
    171         }
    172     }
    173 
    174     $data .= pack('n', length($extensions));
    175     $data .= $extensions;
    176     $self->data($data);
    177 }
    178 
    179 #Read/write accessors
    180 sub server_version
    181 {
    182     my $self = shift;
    183     if (@_) {
    184       $self->{server_version} = shift;
    185     }
    186     return $self->{server_version};
    187 }
    188 sub random
    189 {
    190     my $self = shift;
    191     if (@_) {
    192       $self->{random} = shift;
    193     }
    194     return $self->{random};
    195 }
    196 sub session_id_len
    197 {
    198     my $self = shift;
    199     if (@_) {
    200       $self->{session_id_len} = shift;
    201     }
    202     return $self->{session_id_len};
    203 }
    204 sub session
    205 {
    206     my $self = shift;
    207     if (@_) {
    208       $self->{session} = shift;
    209     }
    210     return $self->{session};
    211 }
    212 sub ciphersuite
    213 {
    214     my $self = shift;
    215     if (@_) {
    216       $self->{ciphersuite} = shift;
    217     }
    218     return $self->{ciphersuite};
    219 }
    220 sub comp_meth
    221 {
    222     my $self = shift;
    223     if (@_) {
    224       $self->{comp_meth} = shift;
    225     }
    226     return $self->{comp_meth};
    227 }
    228 sub extension_data
    229 {
    230     my $self = shift;
    231     if (@_) {
    232       $self->{extension_data} = shift;
    233     }
    234     return $self->{extension_data};
    235 }
    236 sub set_extension
    237 {
    238     my ($self, $ext_type, $ext_data) = @_;
    239     $self->{extension_data}{$ext_type} = $ext_data;
    240 }
    241 sub delete_extension
    242 {
    243     my ($self, $ext_type) = @_;
    244     delete $self->{extension_data}{$ext_type};
    245 }
    246 1;
    247