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