security/nss/cmd/vfyserv/vfyserv.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /****************************************************************************
michael@0 6 * SSL client program that tests a server for proper operation of SSL2, *
michael@0 7 * SSL3, and TLS. Test propder certificate installation. *
michael@0 8 * *
michael@0 9 * This code was modified from the SSLSample code also kept in the NSS *
michael@0 10 * directory. *
michael@0 11 ****************************************************************************/
michael@0 12
michael@0 13 #include <stdio.h>
michael@0 14 #include <string.h>
michael@0 15
michael@0 16 #if defined(XP_UNIX)
michael@0 17 #include <unistd.h>
michael@0 18 #endif
michael@0 19
michael@0 20 #include "prerror.h"
michael@0 21
michael@0 22 #include "pk11func.h"
michael@0 23 #include "secmod.h"
michael@0 24 #include "secitem.h"
michael@0 25
michael@0 26
michael@0 27 #include <stdlib.h>
michael@0 28 #include <errno.h>
michael@0 29 #include <fcntl.h>
michael@0 30 #include <stdarg.h>
michael@0 31
michael@0 32 #include "nspr.h"
michael@0 33 #include "plgetopt.h"
michael@0 34 #include "prio.h"
michael@0 35 #include "prnetdb.h"
michael@0 36 #include "nss.h"
michael@0 37 #include "secutil.h"
michael@0 38 #include "ocsp.h"
michael@0 39
michael@0 40 #include "vfyserv.h"
michael@0 41
michael@0 42 #define RD_BUF_SIZE (60 * 1024)
michael@0 43
michael@0 44 extern int ssl2CipherSuites[];
michael@0 45 extern int ssl3CipherSuites[];
michael@0 46
michael@0 47 GlobalThreadMgr threadMGR;
michael@0 48 char *certNickname = NULL;
michael@0 49 char *hostName = NULL;
michael@0 50 secuPWData pwdata = { PW_NONE, 0 };
michael@0 51 unsigned short port = 0;
michael@0 52 PRBool dumpChain;
michael@0 53
michael@0 54 static void
michael@0 55 Usage(const char *progName)
michael@0 56 {
michael@0 57 PRFileDesc *pr_stderr;
michael@0 58
michael@0 59 pr_stderr = PR_STDERR;
michael@0 60
michael@0 61 PR_fprintf(pr_stderr, "Usage:\n"
michael@0 62 " %s [-c ] [-o] [-p port] [-d dbdir] [-w password] [-f pwfile]\n"
michael@0 63 " \t\t[-C cipher(s)] [-l <url> -t <nickname> ] hostname",
michael@0 64 progName);
michael@0 65 PR_fprintf (pr_stderr, "\nWhere:\n");
michael@0 66 PR_fprintf (pr_stderr,
michael@0 67 " %-13s dump server cert chain into files\n",
michael@0 68 "-c");
michael@0 69 PR_fprintf (pr_stderr,
michael@0 70 " %-13s perform server cert OCSP check\n",
michael@0 71 "-o");
michael@0 72 PR_fprintf (pr_stderr,
michael@0 73 " %-13s server port to be used\n",
michael@0 74 "-p");
michael@0 75 PR_fprintf (pr_stderr,
michael@0 76 " %-13s use security databases in \"dbdir\"\n",
michael@0 77 "-d dbdir");
michael@0 78 PR_fprintf (pr_stderr,
michael@0 79 " %-13s key database password\n",
michael@0 80 "-w password");
michael@0 81 PR_fprintf (pr_stderr,
michael@0 82 " %-13s token password file\n",
michael@0 83 "-f pwfile");
michael@0 84 PR_fprintf (pr_stderr,
michael@0 85 " %-13s communication cipher list\n",
michael@0 86 "-C cipher(s)");
michael@0 87 PR_fprintf (pr_stderr,
michael@0 88 " %-13s OCSP responder location. This location is used to\n"
michael@0 89 " %-13s check status of a server certificate. If not \n"
michael@0 90 " %-13s specified, location will be taken from the AIA\n"
michael@0 91 " %-13s server certificate extension.\n",
michael@0 92 "-l url", "", "", "");
michael@0 93 PR_fprintf (pr_stderr,
michael@0 94 " %-13s OCSP Trusted Responder Cert nickname\n\n",
michael@0 95 "-t nickname");
michael@0 96
michael@0 97 exit(1);
michael@0 98 }
michael@0 99
michael@0 100 PRFileDesc *
michael@0 101 setupSSLSocket(PRNetAddr *addr)
michael@0 102 {
michael@0 103 PRFileDesc *tcpSocket;
michael@0 104 PRFileDesc *sslSocket;
michael@0 105 PRSocketOptionData socketOption;
michael@0 106 PRStatus prStatus;
michael@0 107 SECStatus secStatus;
michael@0 108
michael@0 109
michael@0 110 tcpSocket = PR_NewTCPSocket();
michael@0 111 if (tcpSocket == NULL) {
michael@0 112 errWarn("PR_NewTCPSocket");
michael@0 113 }
michael@0 114
michael@0 115 /* Make the socket blocking. */
michael@0 116 socketOption.option = PR_SockOpt_Nonblocking;
michael@0 117 socketOption.value.non_blocking = PR_FALSE;
michael@0 118
michael@0 119 prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
michael@0 120 if (prStatus != PR_SUCCESS) {
michael@0 121 errWarn("PR_SetSocketOption");
michael@0 122 goto loser;
michael@0 123 }
michael@0 124
michael@0 125
michael@0 126 /* Import the socket into the SSL layer. */
michael@0 127 sslSocket = SSL_ImportFD(NULL, tcpSocket);
michael@0 128 if (!sslSocket) {
michael@0 129 errWarn("SSL_ImportFD");
michael@0 130 goto loser;
michael@0 131 }
michael@0 132
michael@0 133 /* Set configuration options. */
michael@0 134 secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
michael@0 135 if (secStatus != SECSuccess) {
michael@0 136 errWarn("SSL_OptionSet:SSL_SECURITY");
michael@0 137 goto loser;
michael@0 138 }
michael@0 139
michael@0 140 secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
michael@0 141 if (secStatus != SECSuccess) {
michael@0 142 errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
michael@0 143 goto loser;
michael@0 144 }
michael@0 145
michael@0 146 /* Set SSL callback routines. */
michael@0 147 secStatus = SSL_GetClientAuthDataHook(sslSocket,
michael@0 148 (SSLGetClientAuthData)myGetClientAuthData,
michael@0 149 (void *)certNickname);
michael@0 150 if (secStatus != SECSuccess) {
michael@0 151 errWarn("SSL_GetClientAuthDataHook");
michael@0 152 goto loser;
michael@0 153 }
michael@0 154
michael@0 155 secStatus = SSL_AuthCertificateHook(sslSocket,
michael@0 156 (SSLAuthCertificate)myAuthCertificate,
michael@0 157 (void *)CERT_GetDefaultCertDB());
michael@0 158 if (secStatus != SECSuccess) {
michael@0 159 errWarn("SSL_AuthCertificateHook");
michael@0 160 goto loser;
michael@0 161 }
michael@0 162
michael@0 163 secStatus = SSL_BadCertHook(sslSocket,
michael@0 164 (SSLBadCertHandler)myBadCertHandler, NULL);
michael@0 165 if (secStatus != SECSuccess) {
michael@0 166 errWarn("SSL_BadCertHook");
michael@0 167 goto loser;
michael@0 168 }
michael@0 169
michael@0 170 secStatus = SSL_HandshakeCallback(sslSocket,
michael@0 171 myHandshakeCallback,
michael@0 172 NULL);
michael@0 173 if (secStatus != SECSuccess) {
michael@0 174 errWarn("SSL_HandshakeCallback");
michael@0 175 goto loser;
michael@0 176 }
michael@0 177
michael@0 178 return sslSocket;
michael@0 179
michael@0 180 loser:
michael@0 181
michael@0 182 PR_Close(tcpSocket);
michael@0 183 return NULL;
michael@0 184 }
michael@0 185
michael@0 186
michael@0 187 const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" };
michael@0 188
michael@0 189 SECStatus
michael@0 190 handle_connection(PRFileDesc *sslSocket, int connection)
michael@0 191 {
michael@0 192 int countRead = 0;
michael@0 193 PRInt32 numBytes;
michael@0 194 char *readBuffer;
michael@0 195
michael@0 196 readBuffer = PORT_Alloc(RD_BUF_SIZE);
michael@0 197 if (!readBuffer) {
michael@0 198 exitErr("PORT_Alloc");
michael@0 199 }
michael@0 200
michael@0 201 /* compose the http request here. */
michael@0 202
michael@0 203 numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
michael@0 204 if (numBytes <= 0) {
michael@0 205 errWarn("PR_Write");
michael@0 206 PR_Free(readBuffer);
michael@0 207 readBuffer = NULL;
michael@0 208 return SECFailure;
michael@0 209 }
michael@0 210
michael@0 211 /* read until EOF */
michael@0 212 while (PR_TRUE) {
michael@0 213 numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
michael@0 214 if (numBytes == 0) {
michael@0 215 break; /* EOF */
michael@0 216 }
michael@0 217 if (numBytes < 0) {
michael@0 218 errWarn("PR_Read");
michael@0 219 break;
michael@0 220 }
michael@0 221 countRead += numBytes;
michael@0 222 }
michael@0 223
michael@0 224 printSecurityInfo(stderr, sslSocket);
michael@0 225
michael@0 226 PR_Free(readBuffer);
michael@0 227 readBuffer = NULL;
michael@0 228
michael@0 229 /* Caller closes the socket. */
michael@0 230
michael@0 231 fprintf(stderr,
michael@0 232 "***** Connection %d read %d bytes total.\n",
michael@0 233 connection, countRead);
michael@0 234
michael@0 235 return SECSuccess; /* success */
michael@0 236 }
michael@0 237
michael@0 238 #define BYTE(n,i) (((i)>>((n)*8))&0xff)
michael@0 239
michael@0 240 /* one copy of this function is launched in a separate thread for each
michael@0 241 ** connection to be made.
michael@0 242 */
michael@0 243 SECStatus
michael@0 244 do_connects(void *a, int connection)
michael@0 245 {
michael@0 246 PRNetAddr *addr = (PRNetAddr *)a;
michael@0 247 PRFileDesc *sslSocket;
michael@0 248 PRHostEnt hostEntry;
michael@0 249 char buffer[PR_NETDB_BUF_SIZE];
michael@0 250 PRStatus prStatus;
michael@0 251 PRIntn hostenum;
michael@0 252 PRInt32 ip;
michael@0 253 SECStatus secStatus;
michael@0 254
michael@0 255 /* Set up SSL secure socket. */
michael@0 256 sslSocket = setupSSLSocket(addr);
michael@0 257 if (sslSocket == NULL) {
michael@0 258 errWarn("setupSSLSocket");
michael@0 259 return SECFailure;
michael@0 260 }
michael@0 261
michael@0 262 secStatus = SSL_SetPKCS11PinArg(sslSocket, &pwdata);
michael@0 263 if (secStatus != SECSuccess) {
michael@0 264 errWarn("SSL_SetPKCS11PinArg");
michael@0 265 return secStatus;
michael@0 266 }
michael@0 267
michael@0 268 secStatus = SSL_SetURL(sslSocket, hostName);
michael@0 269 if (secStatus != SECSuccess) {
michael@0 270 errWarn("SSL_SetURL");
michael@0 271 return secStatus;
michael@0 272 }
michael@0 273
michael@0 274 /* Prepare and setup network connection. */
michael@0 275 prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
michael@0 276 if (prStatus != PR_SUCCESS) {
michael@0 277 errWarn("PR_GetHostByName");
michael@0 278 return SECFailure;
michael@0 279 }
michael@0 280
michael@0 281 hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
michael@0 282 if (hostenum == -1) {
michael@0 283 errWarn("PR_EnumerateHostEnt");
michael@0 284 return SECFailure;
michael@0 285 }
michael@0 286
michael@0 287 ip = PR_ntohl(addr->inet.ip);
michael@0 288 fprintf(stderr,
michael@0 289 "Connecting to host %s (addr %d.%d.%d.%d) on port %d\n",
michael@0 290 hostName, BYTE(3,ip), BYTE(2,ip), BYTE(1,ip),
michael@0 291 BYTE(0,ip), PR_ntohs(addr->inet.port));
michael@0 292
michael@0 293 prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
michael@0 294 if (prStatus != PR_SUCCESS) {
michael@0 295 errWarn("PR_Connect");
michael@0 296 return SECFailure;
michael@0 297 }
michael@0 298
michael@0 299 /* Established SSL connection, ready to send data. */
michael@0 300 #if 0
michael@0 301 secStatus = SSL_ForceHandshake(sslSocket);
michael@0 302 if (secStatus != SECSuccess) {
michael@0 303 errWarn("SSL_ForceHandshake");
michael@0 304 return secStatus;
michael@0 305 }
michael@0 306 #endif
michael@0 307
michael@0 308 secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
michael@0 309 if (secStatus != SECSuccess) {
michael@0 310 errWarn("SSL_ResetHandshake");
michael@0 311 prStatus = PR_Close(sslSocket);
michael@0 312 if (prStatus != PR_SUCCESS) {
michael@0 313 errWarn("PR_Close");
michael@0 314 }
michael@0 315 return secStatus;
michael@0 316 }
michael@0 317
michael@0 318 secStatus = handle_connection(sslSocket, connection);
michael@0 319 if (secStatus != SECSuccess) {
michael@0 320 /* error already printed out in handle_connection */
michael@0 321 /* errWarn("handle_connection"); */
michael@0 322 prStatus = PR_Close(sslSocket);
michael@0 323 if (prStatus != PR_SUCCESS) {
michael@0 324 errWarn("PR_Close");
michael@0 325 }
michael@0 326 return secStatus;
michael@0 327 }
michael@0 328
michael@0 329 PR_Close(sslSocket);
michael@0 330 return SECSuccess;
michael@0 331 }
michael@0 332
michael@0 333 void
michael@0 334 client_main(unsigned short port,
michael@0 335 int connections,
michael@0 336 const char * hostName)
michael@0 337 {
michael@0 338 int i;
michael@0 339 SECStatus secStatus;
michael@0 340 PRStatus prStatus;
michael@0 341 PRInt32 rv;
michael@0 342 PRNetAddr addr;
michael@0 343 PRHostEnt hostEntry;
michael@0 344 char buffer[PR_NETDB_BUF_SIZE];
michael@0 345
michael@0 346 /* Setup network connection. */
michael@0 347 prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
michael@0 348 if (prStatus != PR_SUCCESS) {
michael@0 349 exitErr("PR_GetHostByName");
michael@0 350 }
michael@0 351
michael@0 352 rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
michael@0 353 if (rv < 0) {
michael@0 354 exitErr("PR_EnumerateHostEnt");
michael@0 355 }
michael@0 356
michael@0 357 secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
michael@0 358 if (secStatus != SECSuccess) {
michael@0 359 exitErr("launch_thread");
michael@0 360 }
michael@0 361
michael@0 362 if (connections > 1) {
michael@0 363 /* wait for the first connection to terminate, then launch the rest. */
michael@0 364 reap_threads(&threadMGR);
michael@0 365 /* Start up the connections */
michael@0 366 for (i = 2; i <= connections; ++i) {
michael@0 367 secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
michael@0 368 if (secStatus != SECSuccess) {
michael@0 369 errWarn("launch_thread");
michael@0 370 }
michael@0 371 }
michael@0 372 }
michael@0 373
michael@0 374 reap_threads(&threadMGR);
michael@0 375 destroy_thread_data(&threadMGR);
michael@0 376 }
michael@0 377
michael@0 378 #define HEXCHAR_TO_INT(c, i) \
michael@0 379 if (((c) >= '0') && ((c) <= '9')) { \
michael@0 380 i = (c) - '0'; \
michael@0 381 } else if (((c) >= 'a') && ((c) <= 'f')) { \
michael@0 382 i = (c) - 'a' + 10; \
michael@0 383 } else if (((c) >= 'A') && ((c) <= 'F')) { \
michael@0 384 i = (c) - 'A' + 10; \
michael@0 385 } else { \
michael@0 386 Usage(progName); \
michael@0 387 }
michael@0 388
michael@0 389 int
michael@0 390 main(int argc, char **argv)
michael@0 391 {
michael@0 392 char * certDir = NULL;
michael@0 393 char * progName = NULL;
michael@0 394 int connections = 1;
michael@0 395 char * cipherString = NULL;
michael@0 396 char * respUrl = NULL;
michael@0 397 char * respCertName = NULL;
michael@0 398 SECStatus secStatus;
michael@0 399 PLOptState * optstate;
michael@0 400 PLOptStatus status;
michael@0 401 PRBool doOcspCheck = PR_FALSE;
michael@0 402
michael@0 403 /* Call the NSPR initialization routines */
michael@0 404 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
michael@0 405
michael@0 406 progName = PORT_Strdup(argv[0]);
michael@0 407
michael@0 408 hostName = NULL;
michael@0 409 optstate = PL_CreateOptState(argc, argv, "C:cd:f:l:n:p:ot:w:");
michael@0 410 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
michael@0 411 switch(optstate->option) {
michael@0 412 case 'C' : cipherString = PL_strdup(optstate->value); break;
michael@0 413 case 'c' : dumpChain = PR_TRUE; break;
michael@0 414 case 'd' : certDir = PL_strdup(optstate->value); break;
michael@0 415 case 'l' : respUrl = PL_strdup(optstate->value); break;
michael@0 416 case 'p' : port = PORT_Atoi(optstate->value); break;
michael@0 417 case 'o' : doOcspCheck = PR_TRUE; break;
michael@0 418 case 't' : respCertName = PL_strdup(optstate->value); break;
michael@0 419 case 'w':
michael@0 420 pwdata.source = PW_PLAINTEXT;
michael@0 421 pwdata.data = PORT_Strdup(optstate->value);
michael@0 422 break;
michael@0 423
michael@0 424 case 'f':
michael@0 425 pwdata.source = PW_FROMFILE;
michael@0 426 pwdata.data = PORT_Strdup(optstate->value);
michael@0 427 break;
michael@0 428 case '\0': hostName = PL_strdup(optstate->value); break;
michael@0 429 default : Usage(progName);
michael@0 430 }
michael@0 431 }
michael@0 432
michael@0 433 if (port == 0) {
michael@0 434 port = 443;
michael@0 435 }
michael@0 436
michael@0 437 if (port == 0 || hostName == NULL)
michael@0 438 Usage(progName);
michael@0 439
michael@0 440 if (doOcspCheck &&
michael@0 441 ((respCertName != NULL && respUrl == NULL) ||
michael@0 442 (respUrl != NULL && respCertName == NULL))) {
michael@0 443 SECU_PrintError (progName, "options -l <url> and -t "
michael@0 444 "<responder> must be used together");
michael@0 445 Usage(progName);
michael@0 446 }
michael@0 447
michael@0 448 PK11_SetPasswordFunc(SECU_GetModulePassword);
michael@0 449
michael@0 450 /* Initialize the NSS libraries. */
michael@0 451 if (certDir) {
michael@0 452 secStatus = NSS_Init(certDir);
michael@0 453 } else {
michael@0 454 secStatus = NSS_NoDB_Init(NULL);
michael@0 455
michael@0 456 /* load the builtins */
michael@0 457 SECMOD_AddNewModule("Builtins",
michael@0 458 DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
michael@0 459 }
michael@0 460 if (secStatus != SECSuccess) {
michael@0 461 exitErr("NSS_Init");
michael@0 462 }
michael@0 463 SECU_RegisterDynamicOids();
michael@0 464
michael@0 465 if (doOcspCheck == PR_TRUE) {
michael@0 466 SECStatus rv;
michael@0 467 CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
michael@0 468 if (handle == NULL) {
michael@0 469 SECU_PrintError (progName, "problem getting certdb handle");
michael@0 470 goto cleanup;
michael@0 471 }
michael@0 472
michael@0 473 rv = CERT_EnableOCSPChecking (handle);
michael@0 474 if (rv != SECSuccess) {
michael@0 475 SECU_PrintError (progName, "error enabling OCSP checking");
michael@0 476 goto cleanup;
michael@0 477 }
michael@0 478
michael@0 479 if (respUrl != NULL) {
michael@0 480 rv = CERT_SetOCSPDefaultResponder (handle, respUrl,
michael@0 481 respCertName);
michael@0 482 if (rv != SECSuccess) {
michael@0 483 SECU_PrintError (progName,
michael@0 484 "error setting default responder");
michael@0 485 goto cleanup;
michael@0 486 }
michael@0 487
michael@0 488 rv = CERT_EnableOCSPDefaultResponder (handle);
michael@0 489 if (rv != SECSuccess) {
michael@0 490 SECU_PrintError (progName,
michael@0 491 "error enabling default responder");
michael@0 492 goto cleanup;
michael@0 493 }
michael@0 494 }
michael@0 495 }
michael@0 496
michael@0 497 /* All cipher suites except RSA_NULL_MD5 are enabled by
michael@0 498 * Domestic Policy. */
michael@0 499 NSS_SetDomesticPolicy();
michael@0 500 SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE);
michael@0 501
michael@0 502 /* all the SSL2 and SSL3 cipher suites are enabled by default. */
michael@0 503 if (cipherString) {
michael@0 504 int ndx;
michael@0 505
michael@0 506 /* disable all the ciphers, then enable the ones we want. */
michael@0 507 disableAllSSLCiphers();
michael@0 508
michael@0 509 while (0 != (ndx = *cipherString++)) {
michael@0 510 int cipher;
michael@0 511
michael@0 512 if (ndx == ':') {
michael@0 513 int ctmp;
michael@0 514
michael@0 515 cipher = 0;
michael@0 516 HEXCHAR_TO_INT(*cipherString, ctmp)
michael@0 517 cipher |= (ctmp << 12);
michael@0 518 cipherString++;
michael@0 519 HEXCHAR_TO_INT(*cipherString, ctmp)
michael@0 520 cipher |= (ctmp << 8);
michael@0 521 cipherString++;
michael@0 522 HEXCHAR_TO_INT(*cipherString, ctmp)
michael@0 523 cipher |= (ctmp << 4);
michael@0 524 cipherString++;
michael@0 525 HEXCHAR_TO_INT(*cipherString, ctmp)
michael@0 526 cipher |= ctmp;
michael@0 527 cipherString++;
michael@0 528 } else {
michael@0 529 const int *cptr;
michael@0 530 if (! isalpha(ndx))
michael@0 531 Usage(progName);
michael@0 532 cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
michael@0 533 for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
michael@0 534 /* do nothing */;
michael@0 535 }
michael@0 536 if (cipher > 0) {
michael@0 537 SSL_CipherPrefSetDefault(cipher, PR_TRUE);
michael@0 538 } else {
michael@0 539 Usage(progName);
michael@0 540 }
michael@0 541 }
michael@0 542 }
michael@0 543
michael@0 544 client_main(port, connections, hostName);
michael@0 545
michael@0 546 cleanup:
michael@0 547 if (doOcspCheck) {
michael@0 548 CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
michael@0 549 CERT_DisableOCSPDefaultResponder(handle);
michael@0 550 CERT_DisableOCSPChecking (handle);
michael@0 551 }
michael@0 552
michael@0 553 if (NSS_Shutdown() != SECSuccess) {
michael@0 554 exit(1);
michael@0 555 }
michael@0 556
michael@0 557 PR_Cleanup();
michael@0 558 PORT_Free(progName);
michael@0 559 return 0;
michael@0 560 }
michael@0 561

mercurial