1# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. 2# 3# Licensed under the OpenSSL license (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 8use strict; 9 10package TLSProxy::ServerHello; 11 12use vars '@ISA'; 13push @ISA, 'TLSProxy::Message'; 14 15sub new 16{ 17 my $class = shift; 18 my ($server, 19 $data, 20 $records, 21 $startoffset, 22 $message_frag_lens) = @_; 23 24 my $self = $class->SUPER::new( 25 $server, 26 TLSProxy::Message::MT_SERVER_HELLO, 27 $data, 28 $records, 29 $startoffset, 30 $message_frag_lens); 31 32 $self->{server_version} = 0; 33 $self->{random} = []; 34 $self->{session_id_len} = 0; 35 $self->{session} = ""; 36 $self->{ciphersuite} = 0; 37 $self->{comp_meth} = 0; 38 $self->{extension_data} = ""; 39 40 return $self; 41} 42 43sub parse 44{ 45 my $self = shift; 46 my $ptr = 2; 47 my ($server_version) = unpack('n', $self->data); 48 my $random = substr($self->data, $ptr, 32); 49 $ptr += 32; 50 my $session_id_len = unpack('C', substr($self->data, $ptr)); 51 $ptr++; 52 my $session = substr($self->data, $ptr, $session_id_len); 53 $ptr += $session_id_len; 54 my $ciphersuite = unpack('n', substr($self->data, $ptr)); 55 $ptr += 2; 56 my $comp_meth = unpack('C', substr($self->data, $ptr)); 57 $ptr++; 58 my $extensions_len = unpack('n', substr($self->data, $ptr)); 59 if (!defined $extensions_len) { 60 $extensions_len = 0; 61 } else { 62 $ptr += 2; 63 } 64 #For now we just deal with this as a block of data. In the future we will 65 #want to parse this 66 my $extension_data; 67 if ($extensions_len != 0) { 68 $extension_data = substr($self->data, $ptr); 69 70 if (length($extension_data) != $extensions_len) { 71 die "Invalid extension length\n"; 72 } 73 } else { 74 if (length($self->data) != $ptr) { 75 die "Invalid extension length\n"; 76 } 77 $extension_data = ""; 78 } 79 my %extensions = (); 80 while (length($extension_data) >= 4) { 81 my ($type, $size) = unpack("nn", $extension_data); 82 my $extdata = substr($extension_data, 4, $size); 83 $extension_data = substr($extension_data, 4 + $size); 84 $extensions{$type} = $extdata; 85 } 86 87 $self->server_version($server_version); 88 $self->random($random); 89 $self->session_id_len($session_id_len); 90 $self->session($session); 91 $self->ciphersuite($ciphersuite); 92 $self->comp_meth($comp_meth); 93 $self->extension_data(\%extensions); 94 95 $self->process_data(); 96 97 print " Server Version:".$server_version."\n"; 98 print " Session ID Len:".$session_id_len."\n"; 99 print " Ciphersuite:".$ciphersuite."\n"; 100 print " Compression Method:".$comp_meth."\n"; 101 print " Extensions Len:".$extensions_len."\n"; 102} 103 104#Perform any actions necessary based on the data we've seen 105sub process_data 106{ 107 my $self = shift; 108 109 TLSProxy::Message->ciphersuite($self->ciphersuite); 110} 111 112#Reconstruct the on-the-wire message data following changes 113sub set_message_contents 114{ 115 my $self = shift; 116 my $data; 117 my $extensions = ""; 118 119 $data = pack('n', $self->server_version); 120 $data .= $self->random; 121 $data .= pack('C', $self->session_id_len); 122 $data .= $self->session; 123 $data .= pack('n', $self->ciphersuite); 124 $data .= pack('C', $self->comp_meth); 125 126 foreach my $key (keys %{$self->extension_data}) { 127 my $extdata = ${$self->extension_data}{$key}; 128 $extensions .= pack("n", $key); 129 $extensions .= pack("n", length($extdata)); 130 $extensions .= $extdata; 131 if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) { 132 $extensions .= pack("n", $key); 133 $extensions .= pack("n", length($extdata)); 134 $extensions .= $extdata; 135 } 136 } 137 138 $data .= pack('n', length($extensions)); 139 $data .= $extensions; 140 $self->data($data); 141} 142 143#Read/write accessors 144sub server_version 145{ 146 my $self = shift; 147 if (@_) { 148 $self->{client_version} = shift; 149 } 150 return $self->{client_version}; 151} 152sub random 153{ 154 my $self = shift; 155 if (@_) { 156 $self->{random} = shift; 157 } 158 return $self->{random}; 159} 160sub session_id_len 161{ 162 my $self = shift; 163 if (@_) { 164 $self->{session_id_len} = shift; 165 } 166 return $self->{session_id_len}; 167} 168sub session 169{ 170 my $self = shift; 171 if (@_) { 172 $self->{session} = shift; 173 } 174 return $self->{session}; 175} 176sub ciphersuite 177{ 178 my $self = shift; 179 if (@_) { 180 $self->{ciphersuite} = shift; 181 } 182 return $self->{ciphersuite}; 183} 184sub comp_meth 185{ 186 my $self = shift; 187 if (@_) { 188 $self->{comp_meth} = shift; 189 } 190 return $self->{comp_meth}; 191} 192sub extension_data 193{ 194 my $self = shift; 195 if (@_) { 196 $self->{extension_data} = shift; 197 } 198 return $self->{extension_data}; 199} 200sub set_extension 201{ 202 my ($self, $ext_type, $ext_data) = @_; 203 $self->{extension_data}{$ext_type} = $ext_data; 204} 205sub delete_extension 206{ 207 my ($self, $ext_type) = @_; 208 delete $self->{extension_data}{$ext_type}; 209} 2101; 211