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