Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 #!/usr/bin/perl
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 #--------------------------------------------------------------
8 # cgi script that parses request argument to appropriate
9 # open ssl or tstclntw options and starts ssl client.
10 #
12 use CGI qw/:standard/;
14 use subs qw(debug);
16 #--------------------------------------------------------------
17 # Prints out an error string and exits the script with an
18 # exitStatus.
19 # Param:
20 # str : an error string
21 # exitStat: an exit status of the program
22 #
23 sub svr_error {
24 my ($str, $exitStat) = @_;
26 if (!defined $str || $str eq "") {
27 $str = $ERR;
28 }
29 print "SERVER ERROR: $str\n";
30 if ($exitStat) {
31 print end_html if ($osDataArr{wservRun});
32 exit $exitStat;
33 }
34 }
36 #--------------------------------------------------------------
37 # Prints out a debug message
38 # Params:
39 # str: debug message
40 # inVal: additional value to print(optional)
41 #
42 sub debug {
43 my ($str, $inVal) = @_;
45 print "-- DEBUG: $str ($inVal)\n" if ($DEBUG == 1);
46 }
49 #--------------------------------------------------------------
50 # Initializes execution context depending on a webserver the
51 # script is running under.
52 #
53 sub init {
54 %osDataArr = (
55 loadSupportedCipthersFn => \&osSpecific,
56 cipherIsSupportedFn => \&verifyCipherSupport,
57 cipherListFn => \&convertCipher,
58 buildCipherTableFn => \&buildCipherTable,
59 execCmdFn => \&osSpecific,
60 );
62 $scriptName = $ENV{'SCRIPT_NAME'};
63 if (!defined $scriptName) {
64 $DEBUG=1;
65 debug "Debug is ON";
66 }
67 $DEBUG=1;
69 $svrSoft = $ENV{'SERVER_SOFTWARE'};
70 if (defined $svrSoft) {
71 $_ = $svrSoft;
72 /.*Microsoft.*/ && ($osDataArr{wserv} = "IIS");
73 /.*Apache.*/ && ($osDataArr{wserv} = "Apache");
74 $osDataArr{wservRun} = 1;
75 } else {
76 $osDataArr{wserv} = "Apache";
77 $osDataArr{wservRun} = 0;
78 }
79 }
81 #--------------------------------------------------------------
82 # Function-spigot to handle errors is OS specific functions are
83 # not implemented for a particular OS.
84 # Returns:
85 # always returns 0(failure)
86 #
87 sub osSpecific {
88 $ERR = "This function should be swapped to os specific function.";
89 return 0;
90 }
92 #--------------------------------------------------------------
93 # Sets os specific execution context values.
94 # Returns:
95 # 1 upon success, or 0 upon failure(if OS was not recognized)
96 #
97 sub setFunctRefs {
99 debug("Entering setFunctRefs function", $osDataArr{wserv});
101 if ($osDataArr{wserv} eq "Apache") {
102 $osDataArr{osConfigFile} = "apache_unix.cfg";
103 $osDataArr{suppCiphersCmd} = '$opensslb ciphers ALL:NULL';
104 $osDataArr{clientRunCmd} = '$opensslb s_client -host $in_host -port $in_port -cert $certDir/$in_cert.crt -key $certDir/$in_cert.key -CAfile $caCertFile $proto $ciphers -ign_eof < $reqFile';
105 $osDataArr{loadSupportedCipthersFn} = \&getSupportedCipherList_Unix;
106 $osDataArr{execCmdFn} = \&execClientCmd_Unix;
107 } elsif ($osDataArr{wserv} eq "IIS") {
108 $osDataArr{osConfigFile} = "iis_windows.cfg";
109 $osDataArr{suppCiphersCmd} = '$tstclntwb';
110 $osDataArr{clientRunCmd} = '$tstclntwb -h $in_host -p $in_port -n $in_cert $proto $ciphers < $reqFile';
111 $osDataArr{loadSupportedCipthersFn} = \&getSupportedCipherList_Win;
112 $osDataArr{execCmdFn} = \&execClientCmd_Win;
113 } else {
114 $ERR = "Unknown Web Server type.";
115 return 0;
116 }
117 return 1;
118 }
120 #--------------------------------------------------------------
121 # Parses data from HTTP request. Will print a form if request
122 # does not contain sufficient number of parameters.
123 # Returns:
124 # 1 if request has sufficient number of parameters
125 # 0 if not.
126 sub getReqData {
127 my $debug = param('debug');
128 $in_host = param('host');
129 $in_port = param('port');
130 $in_cert = param('cert');
131 $in_cipher = param('cipher');
133 if (!$osDataArr{wservRun}) {
134 $in_host="goa1";
135 $in_port="443";
136 $in_cert="TestUser511";
137 $in_cipher = "SSL3_RSA_WITH_NULL_SHA";
138 }
140 debug("Entering getReqData function", "$in_port:$in_host:$in_cert:$in_cipher");
142 if (defined $debug && $debug == "debug on") {
143 $DEBUG = 1;
144 }
146 if (!defined $in_host || $in_host eq "" ||
147 !defined $in_port || $in_port eq "" ||
148 !defined $in_cert || $in_cert eq "") {
149 if ($osDataArr{wservRun}) {
150 print h1('Command description form:'),
151 start_form(-method=>"get"),
152 "Host: ",textfield('host'),p,
153 "Port: ",textfield('port'),p,
154 "Cert: ",textfield('cert'),p,
155 "Cipher: ",textfield('cipher'),p,
156 checkbox_group(-name=>'debug',
157 -values=>['debug on ']),
158 submit,
159 end_form,
160 hr;
161 } else {
162 print "Printing html form to get client arguments\n";
163 }
164 $ERR = "the following parameters are required: host, port, cert";
165 return 0;
166 } else {
167 print "<pre>" if ($osDataArr{wservRun});
168 return 1;
169 }
170 }
173 #--------------------------------------------------------------
174 # Building cipher conversion table from file based on the OS.
175 # Params:
176 # tfile: cipher conversion file.
177 # sysName: system name
178 # tblPrt: returned pointer to a table.
179 sub buildCipherTable {
180 my ($tfile, $sysName, $tblPrt) = @_;
181 my @retArr = @$tblPrt;
182 my %table, %rtable;
183 my $strCount = 0;
185 debug("Entering getReqData function", "$tfile:$sysName:$tblPrt");
187 ($ERR = "No system name supplied" && return 0) if ($sysName =~ /^$/);
188 if (!open(TFILE, "$tfile")) {
189 $ERR = "Missing cipher conversion table file.";
190 return 0;
191 }
192 foreach (<TFILE>) {
193 chop;
194 /^#.*/ && next;
195 /^\s*$/ && next;
196 if ($strCount++ == 0) {
197 my @sysArr = split /\s+/;
198 $colCount = 0;
199 for (;$colCount <= $#sysArr;$colCount++) {
200 last if ($sysArr[$colCount] =~ /(.*:|^)$sysName.*/);
201 }
202 next;
203 }
204 my @ciphArr = split /\s+/, $_;
205 $table{$ciphArr[0]} = $ciphArr[$colCount];
206 $rtable{$ciphArr[$colCount]} = $ciphArr[0];
207 }
208 close(TFILE);
209 $cipherTablePtr[0] = \%table;
210 $cipherTablePtr[1] = \%rtable;
211 return 1
212 }
214 #--------------------------------------------------------------
215 # Client configuration function. Loads client configuration file.
216 # Initiates cipher table. Loads cipher list supported by ssl client.
217 #
218 sub configClient {
220 debug "Entering configClient function";
222 my $res = &setFunctRefs();
223 return $res if (!$res);
225 open(CFILE, $osDataArr{'osConfigFile'}) ||
226 ($ERR = "Missing configuration file." && return 0);
227 foreach (<CFILE>) {
228 /^#.*/ && next;
229 chop;
230 eval $_;
231 }
232 close(CFILE);
234 local @cipherTablePtr = ();
235 $osDataArr{'buildCipherTableFn'}->($cipherTableFile, $clientSys) || return 0;
236 $osDataArr{cipherTable} = $cipherTablePtr[0];
237 $osDataArr{rcipherTable} = $cipherTablePtr[1];
239 local $suppCiphersTablePrt;
240 &{$osDataArr{'loadSupportedCipthersFn'}} || return 0;
241 $osDataArr{suppCiphersTable} = $suppCiphersTablePrt;
242 }
244 #--------------------------------------------------------------
245 # Verifies that a particular cipher is supported.
246 # Params:
247 # checkCipher: cipher name
248 # Returns:
249 # 1 - cipher is supported(also echos the cipher).
250 # 0 - not supported.
251 #
252 sub verifyCipherSupport {
253 my ($checkCipher) = @_;
254 my @suppCiphersTable = @{$osDataArr{suppCiphersTable}};
256 debug("Entering verifyCipherSupport", $checkCipher);
257 foreach (@suppCiphersTable) {
258 return 1 if ($checkCipher eq $_);
259 }
260 $ERR = "cipher is not supported.";
261 return 0;
262 }
264 #--------------------------------------------------------------
265 # Converts long(?name of the type?) cipher name to
266 # openssl/tstclntw cipher name.
267 # Returns:
268 # 0 if cipher was not listed. 1 upon success.
269 #
270 sub convertCipher {
271 my ($cipher) = @_;
272 my @retList;
273 my $resStr;
274 my %cipherTable = %{$osDataArr{cipherTable}};
276 debug("Entering convertCipher", $cipher);
277 if (defined $cipher) {
278 my $cphr = $cipherTable{$cipher};
279 if (!defined $cphr) {
280 $ERR = "cipher is not listed.";
281 return 0;
282 }
283 &{$osDataArr{'cipherIsSupportedFn'}}($cphr) || return 0;
284 $ciphers = "$cphr";
285 return 1;
286 }
287 return 0;
288 }
290 #################################################################
291 # UNIX Apache Specific functions
292 #----------------------------------------------------------------
294 #--------------------------------------------------------------
295 # Executes ssl client command to get a list of ciphers supported
296 # by client.
297 #
298 sub getSupportedCipherList_Unix {
299 my @arr, @suppCiphersTable;
301 debug "Entering getSupportedCipherList_Unix function";
303 eval '$sLisrCmd = "'.$osDataArr{'suppCiphersCmd'}.'"';
304 if (!open (OUT, "$sLisrCmd|")) {
305 $ERR="Can not run command to verify supported cipher list.";
306 return 0;
307 }
308 @arr = <OUT>;
309 chop $arr[0];
310 @suppCiphersTable = split /:/, $arr[0];
311 debug("Supported ciphers", $arr[0]);
312 $suppCiphersTablePrt = \@suppCiphersTable;
313 close(OUT);
314 return 1;
315 }
317 #--------------------------------------------------------------
318 # Lunches ssl client command in response to a request.
319 #
320 #
321 sub execClientCmd_Unix {
322 my $proto;
323 local $ciphers;
325 debug "Entering execClientCmd_Unix";
326 if (defined $in_cipher && $in_cipher ne "") {
327 my @arr = split /_/, $in_cipher, 2;
328 $proto = "-".$arr[0];
329 $proto =~ tr /SLT/slt/;
330 $proto = "-tls1" if ($proto eq "-tls");
331 return 0 if (!&{$osDataArr{'cipherListFn'}}($in_cipher));
332 $ciphers = "-cipher $ciphers";
333 debug("Return from cipher conversion", "$ciphers");
334 }
336 eval '$command = "'.$osDataArr{'clientRunCmd'}.'"';
337 debug("Executing command", $command);
338 if (!open CMD_OUT, "$command 2>&1 |") {
339 $ERR = "can not launch client";
340 return 0;
341 }
343 my @cmdOutArr = <CMD_OUT>;
345 foreach (@cmdOutArr) {
346 print $_;
347 }
349 my $haveVerify = 0;
350 my $haveErrors = 0;
351 foreach (@cmdOutArr) {
352 chop;
353 if (/unknown option/) {
354 $haveErrors++;
355 svr_error "unknown option\n";
356 next;
357 }
358 if (/:no ciphers available/) {
359 $haveErrors++;
360 svr_error "no cipthers available\n";
361 next;
362 }
363 if (/verify error:/) {
364 $haveErrors++;
365 svr_error "unable to do verification\n";
366 next;
367 }
368 if (/alert certificate revoked:/) {
369 $haveErrors++;
370 svr_error "attempt to connect with revoked sertificate\n";
371 next;
372 }
373 if (/(error|ERROR)/) {
374 $haveErrors++;
375 svr_error "found errors in server log\n";
376 next;
377 }
378 /verify return:1/ && ($haveVerify = 1);
379 }
380 if ($haveVerify == 0) {
381 svr_error "no 'verify return:1' found in server log\n";
382 $haveErrors++;
383 }
385 if ($haveErrors > 0) {
386 $ERR = "Have $haveErrors server errors";
387 debug "Exiting execClientCmd_Unix";
388 return 0;
389 }
390 debug "Exiting execClientCmd_Unix";
391 return 1;
392 }
394 #################################################################
395 # Windows IIS Specific functions
396 #----------------------------------------------------------------
398 #--------------------------------------------------------------
399 # Executes ssl client command to get a list of ciphers supported
400 # by client.
401 #
402 sub getSupportedCipherList_Win {
403 my @arr, @suppCiphersTable;
405 debug "Entering getSupportedCipherList_Win function";
407 eval '$sLisrCmd = "'.$osDataArr{'suppCiphersCmd'}.'"';
408 if (!open (OUT, "$sLisrCmd|")) {
409 $ERR="Can not run command to verify supported cipher list.";
410 return 0;
411 }
412 my $startCipherList = 0;
413 foreach (<OUT>) {
414 chop;
415 if ($startCipherList) {
416 /^([a-zA-Z])\s+/ && push @suppCiphersTable, $1;
417 next;
418 }
419 /.*from list below.*/ && ($startCipherList = 1);
420 }
421 debug("Supported ciphers", join ':', @suppCiphersTable);
422 $suppCiphersTablePrt = \@suppCiphersTable;
423 close(OUT);
424 return 1;
425 }
427 #--------------------------------------------------------------
428 # Lunches ssl client command in response to a request.
429 #
430 #
431 sub execClientCmd_Win {
432 my $proto;
433 local $ciphers;
435 debug "Entering execClientCmd_Win";
436 if (defined $in_cipher && $in_cipher ne "") {
437 my @arr = split /_/, $in_cipher, 2;
438 $proto = "-2 -3 -T";
440 $proto =~ s/-T// if ($arr[0] eq "TLS");
441 $proto =~ s/-3// if ($arr[0] eq "SSL3");
442 $proto =~ s/-2// if ($arr[0] eq "SSL2");
443 return 0 if (!&{$osDataArr{'cipherListFn'}}($in_cipher));
444 $ciphers = "-c $ciphers";
445 debug("Return from cipher conversion", $ciphers);
446 }
448 eval '$command = "'.$osDataArr{'clientRunCmd'}.'"';
449 debug("Executing command", $command);
450 if (!open CMD_OUT, "$command 2>&1 |") {
451 $ERR = "can not launch client";
452 return 0;
453 }
455 my @cmdOutArr = <CMD_OUT>;
457 foreach (@cmdOutArr) {
458 print $_;
459 }
461 my $haveVerify = 0;
462 my $haveErrors = 0;
463 foreach (@cmdOutArr) {
464 chop;
465 if (/unknown option/) {
466 $haveErrors++;
467 svr_error "unknown option\n";
468 next;
469 }
470 if (/Error performing handshake/) {
471 $haveErrors++;
472 svr_error "Error performing handshake\n";
473 next;
474 }
475 if (/Error creating credentials/) {
476 $haveErrors++;
477 svr_error "Error creating credentials\n";
478 next;
479 }
480 if (/Error .* authenticating server credentials!/) {
481 $haveErrors++;
482 svr_error "Error authenticating server credentials\n";
483 next;
484 }
485 if (/(error|ERROR|Error)/) {
486 $haveErrors++;
487 svr_error "found errors in server log\n";
488 next;
489 }
490 }
492 if ($haveErrors > 0) {
493 $ERR = "Have $haveErrors server errors";
494 debug "Exiting execClientCmd_Win";
495 return 0;
496 }
497 debug "Exiting execClientCmd_Win";
498 return 1;
499 }
501 #################################################################
502 # Main line of execution
503 #----------------------------------------------------------------
504 &init;
506 if ($osDataArr{wservRun}) {
507 print header('text/html').
508 start_html('iopr client');
509 }
511 print "SCRIPT=OK\n";
513 if (!&getReqData) {
514 svr_error($ERR, 1);
515 }
517 if (!&configClient) {
518 svr_error($ERR, 1);
519 }
521 &{$osDataArr{'execCmdFn'}} || svr_error;
523 if ($osDataArr{wservRun}) {
524 print "</pre>";
525 print end_html;
526 }