security/nss/tests/iopr/server_scr/client.cgi

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial