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