1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/vfyserv/vfyutil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,633 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "vfyserv.h" 1.9 +#include "secerr.h" 1.10 +#include "sslerr.h" 1.11 +#include "nspr.h" 1.12 +#include "secutil.h" 1.13 + 1.14 + 1.15 +extern PRBool dumpChain; 1.16 +extern void dumpCertChain(CERTCertificate *, SECCertUsage); 1.17 + 1.18 +/* Declare SSL cipher suites. */ 1.19 + 1.20 +int ssl2CipherSuites[] = { 1.21 + SSL_EN_RC4_128_WITH_MD5, /* A */ 1.22 + SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */ 1.23 + SSL_EN_RC2_128_CBC_WITH_MD5, /* C */ 1.24 + SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */ 1.25 + SSL_EN_DES_64_CBC_WITH_MD5, /* E */ 1.26 + SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */ 1.27 + 0 1.28 +}; 1.29 + 1.30 +int ssl3CipherSuites[] = { 1.31 + -1, /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */ 1.32 + -1, /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, * b */ 1.33 + TLS_RSA_WITH_RC4_128_MD5, /* c */ 1.34 + TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* d */ 1.35 + TLS_RSA_WITH_DES_CBC_SHA, /* e */ 1.36 + TLS_RSA_EXPORT_WITH_RC4_40_MD5, /* f */ 1.37 + TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */ 1.38 + -1, /* SSL_FORTEZZA_DMS_WITH_NULL_SHA, * h */ 1.39 + TLS_RSA_WITH_NULL_MD5, /* i */ 1.40 + SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */ 1.41 + SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */ 1.42 + TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */ 1.43 + TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */ 1.44 + TLS_RSA_WITH_RC4_128_SHA, /* n */ 1.45 + TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */ 1.46 + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */ 1.47 + TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */ 1.48 + TLS_DHE_RSA_WITH_DES_CBC_SHA, /* r */ 1.49 + TLS_DHE_DSS_WITH_DES_CBC_SHA, /* s */ 1.50 + TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */ 1.51 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */ 1.52 + TLS_RSA_WITH_AES_128_CBC_SHA, /* v */ 1.53 + TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */ 1.54 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */ 1.55 + TLS_RSA_WITH_AES_256_CBC_SHA, /* y */ 1.56 + TLS_RSA_WITH_NULL_SHA, /* z */ 1.57 + 0 1.58 +}; 1.59 + 1.60 +/************************************************************************** 1.61 +** 1.62 +** SSL callback routines. 1.63 +** 1.64 +**************************************************************************/ 1.65 + 1.66 +/* Function: char * myPasswd() 1.67 + * 1.68 + * Purpose: This function is our custom password handler that is called by 1.69 + * SSL when retreiving private certs and keys from the database. Returns a 1.70 + * pointer to a string that with a password for the database. Password pointer 1.71 + * should point to dynamically allocated memory that will be freed later. 1.72 + */ 1.73 +char * 1.74 +myPasswd(PK11SlotInfo *info, PRBool retry, void *arg) 1.75 +{ 1.76 + char * passwd = NULL; 1.77 + 1.78 + if ( (!retry) && arg ) { 1.79 + passwd = PORT_Strdup((char *)arg); 1.80 + } 1.81 + return passwd; 1.82 +} 1.83 + 1.84 +/* Function: SECStatus myAuthCertificate() 1.85 + * 1.86 + * Purpose: This function is our custom certificate authentication handler. 1.87 + * 1.88 + * Note: This implementation is essentially the same as the default 1.89 + * SSL_AuthCertificate(). 1.90 + */ 1.91 +SECStatus 1.92 +myAuthCertificate(void *arg, PRFileDesc *socket, 1.93 + PRBool checksig, PRBool isServer) 1.94 +{ 1.95 + 1.96 + SECCertificateUsage certUsage; 1.97 + CERTCertificate * cert; 1.98 + void * pinArg; 1.99 + char * hostName; 1.100 + SECStatus secStatus; 1.101 + 1.102 + if (!arg || !socket) { 1.103 + errWarn("myAuthCertificate"); 1.104 + return SECFailure; 1.105 + } 1.106 + 1.107 + /* Define how the cert is being used based upon the isServer flag. */ 1.108 + 1.109 + certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer; 1.110 + 1.111 + cert = SSL_PeerCertificate(socket); 1.112 + 1.113 + pinArg = SSL_RevealPinArg(socket); 1.114 + 1.115 + if (dumpChain == PR_TRUE) { 1.116 + dumpCertChain(cert, certUsage); 1.117 + } 1.118 + 1.119 + secStatus = CERT_VerifyCertificateNow((CERTCertDBHandle *)arg, 1.120 + cert, 1.121 + checksig, 1.122 + certUsage, 1.123 + pinArg, 1.124 + NULL); 1.125 + 1.126 + /* If this is a server, we're finished. */ 1.127 + if (isServer || secStatus != SECSuccess) { 1.128 + SECU_printCertProblems(stderr, (CERTCertDBHandle *)arg, cert, 1.129 + checksig, certUsage, pinArg, PR_FALSE); 1.130 + CERT_DestroyCertificate(cert); 1.131 + return secStatus; 1.132 + } 1.133 + 1.134 + /* Certificate is OK. Since this is the client side of an SSL 1.135 + * connection, we need to verify that the name field in the cert 1.136 + * matches the desired hostname. This is our defense against 1.137 + * man-in-the-middle attacks. 1.138 + */ 1.139 + 1.140 + /* SSL_RevealURL returns a hostName, not an URL. */ 1.141 + hostName = SSL_RevealURL(socket); 1.142 + 1.143 + if (hostName && hostName[0]) { 1.144 + secStatus = CERT_VerifyCertName(cert, hostName); 1.145 + } else { 1.146 + PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0); 1.147 + secStatus = SECFailure; 1.148 + } 1.149 + 1.150 + if (hostName) 1.151 + PR_Free(hostName); 1.152 + 1.153 + CERT_DestroyCertificate(cert); 1.154 + return secStatus; 1.155 +} 1.156 + 1.157 +/* Function: SECStatus myBadCertHandler() 1.158 + * 1.159 + * Purpose: This callback is called when the incoming certificate is not 1.160 + * valid. We define a certain set of parameters that still cause the 1.161 + * certificate to be "valid" for this session, and return SECSuccess to cause 1.162 + * the server to continue processing the request when any of these conditions 1.163 + * are met. Otherwise, SECFailure is return and the server rejects the 1.164 + * request. 1.165 + */ 1.166 +SECStatus 1.167 +myBadCertHandler(void *arg, PRFileDesc *socket) 1.168 +{ 1.169 + 1.170 + SECStatus secStatus = SECFailure; 1.171 + PRErrorCode err; 1.172 + 1.173 + /* log invalid cert here */ 1.174 + 1.175 + if (!arg) { 1.176 + return secStatus; 1.177 + } 1.178 + 1.179 + *(PRErrorCode *)arg = err = PORT_GetError(); 1.180 + 1.181 + /* If any of the cases in the switch are met, then we will proceed */ 1.182 + /* with the processing of the request anyway. Otherwise, the default */ 1.183 + /* case will be reached and we will reject the request. */ 1.184 + 1.185 + switch (err) { 1.186 + case SEC_ERROR_INVALID_AVA: 1.187 + case SEC_ERROR_INVALID_TIME: 1.188 + case SEC_ERROR_BAD_SIGNATURE: 1.189 + case SEC_ERROR_EXPIRED_CERTIFICATE: 1.190 + case SEC_ERROR_UNKNOWN_ISSUER: 1.191 + case SEC_ERROR_UNTRUSTED_CERT: 1.192 + case SEC_ERROR_CERT_VALID: 1.193 + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 1.194 + case SEC_ERROR_CRL_EXPIRED: 1.195 + case SEC_ERROR_CRL_BAD_SIGNATURE: 1.196 + case SEC_ERROR_EXTENSION_VALUE_INVALID: 1.197 + case SEC_ERROR_CA_CERT_INVALID: 1.198 + case SEC_ERROR_CERT_USAGES_INVALID: 1.199 + case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: 1.200 + secStatus = SECSuccess; 1.201 + break; 1.202 + default: 1.203 + secStatus = SECFailure; 1.204 + break; 1.205 + } 1.206 + 1.207 + fprintf(stderr, "Bad certificate: %d, %s\n", err, SECU_Strerror(err)); 1.208 + 1.209 + return secStatus; 1.210 +} 1.211 + 1.212 +/* Function: SECStatus ownGetClientAuthData() 1.213 + * 1.214 + * Purpose: This callback is used by SSL to pull client certificate 1.215 + * information upon server request. 1.216 + */ 1.217 +SECStatus 1.218 +myGetClientAuthData(void *arg, 1.219 + PRFileDesc *socket, 1.220 + struct CERTDistNamesStr *caNames, 1.221 + struct CERTCertificateStr **pRetCert, 1.222 + struct SECKEYPrivateKeyStr **pRetKey) 1.223 +{ 1.224 + 1.225 + CERTCertificate * cert; 1.226 + SECKEYPrivateKey * privKey; 1.227 + char * chosenNickName = (char *)arg; 1.228 + void * proto_win = NULL; 1.229 + SECStatus secStatus = SECFailure; 1.230 + 1.231 + proto_win = SSL_RevealPinArg(socket); 1.232 + 1.233 + if (chosenNickName) { 1.234 + cert = PK11_FindCertFromNickname(chosenNickName, proto_win); 1.235 + if (cert) { 1.236 + privKey = PK11_FindKeyByAnyCert(cert, proto_win); 1.237 + if (privKey) { 1.238 + secStatus = SECSuccess; 1.239 + } else { 1.240 + CERT_DestroyCertificate(cert); 1.241 + } 1.242 + } 1.243 + } else { /* no nickname given, automatically find the right cert */ 1.244 + CERTCertNicknames *names; 1.245 + int i; 1.246 + 1.247 + names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(), 1.248 + SEC_CERT_NICKNAMES_USER, proto_win); 1.249 + 1.250 + if (names != NULL) { 1.251 + for(i = 0; i < names->numnicknames; i++ ) { 1.252 + 1.253 + cert = PK11_FindCertFromNickname(names->nicknames[i], 1.254 + proto_win); 1.255 + if (!cert) { 1.256 + continue; 1.257 + } 1.258 + 1.259 + /* Only check unexpired certs */ 1.260 + if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE) 1.261 + != secCertTimeValid ) { 1.262 + CERT_DestroyCertificate(cert); 1.263 + continue; 1.264 + } 1.265 + 1.266 + secStatus = NSS_CmpCertChainWCANames(cert, caNames); 1.267 + if (secStatus == SECSuccess) { 1.268 + privKey = PK11_FindKeyByAnyCert(cert, proto_win); 1.269 + if (privKey) { 1.270 + break; 1.271 + } 1.272 + secStatus = SECFailure; 1.273 + } 1.274 + CERT_DestroyCertificate(cert); 1.275 + } /* for loop */ 1.276 + CERT_FreeNicknames(names); 1.277 + } 1.278 + } 1.279 + 1.280 + if (secStatus == SECSuccess) { 1.281 + *pRetCert = cert; 1.282 + *pRetKey = privKey; 1.283 + } 1.284 + 1.285 + return secStatus; 1.286 +} 1.287 + 1.288 +/* Function: void myHandshakeCallback() 1.289 + * 1.290 + * Purpose: Called by SSL to inform application that the handshake is 1.291 + * complete. This function is mostly used on the server side of an SSL 1.292 + * connection, although it is provided for a client as well. 1.293 + * Useful when a non-blocking SSL_ReHandshake or SSL_ResetHandshake 1.294 + * is used to initiate a handshake. 1.295 + * 1.296 + * A typical scenario would be: 1.297 + * 1.298 + * 1. Server accepts an SSL connection from the client without client auth. 1.299 + * 2. Client sends a request. 1.300 + * 3. Server determines that to service request it needs to authenticate the 1.301 + * client and initiates another handshake requesting client auth. 1.302 + * 4. While handshake is in progress, server can do other work or spin waiting 1.303 + * for the handshake to complete. 1.304 + * 5. Server is notified that handshake has been successfully completed by 1.305 + * the custom handshake callback function and it can service the client's 1.306 + * request. 1.307 + * 1.308 + * Note: This function is not implemented in this sample, as we are using 1.309 + * blocking sockets. 1.310 + */ 1.311 +void 1.312 +myHandshakeCallback(PRFileDesc *socket, void *arg) 1.313 +{ 1.314 + fprintf(stderr,"Handshake Complete: SERVER CONFIGURED CORRECTLY\n"); 1.315 +} 1.316 + 1.317 + 1.318 +/************************************************************************** 1.319 +** 1.320 +** Routines for disabling SSL ciphers. 1.321 +** 1.322 +**************************************************************************/ 1.323 + 1.324 +void 1.325 +disableAllSSLCiphers(void) 1.326 +{ 1.327 + const PRUint16 *cipherSuites = SSL_ImplementedCiphers; 1.328 + int i = SSL_NumImplementedCiphers; 1.329 + SECStatus rv; 1.330 + 1.331 + /* disable all the SSL3 cipher suites */ 1.332 + while (--i >= 0) { 1.333 + PRUint16 suite = cipherSuites[i]; 1.334 + rv = SSL_CipherPrefSetDefault(suite, PR_FALSE); 1.335 + if (rv != SECSuccess) { 1.336 + fprintf(stderr, 1.337 + "SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n", 1.338 + suite, i); 1.339 + errWarn("SSL_CipherPrefSetDefault"); 1.340 + exit(2); 1.341 + } 1.342 + } 1.343 +} 1.344 + 1.345 +/************************************************************************** 1.346 +** 1.347 +** Error and information routines. 1.348 +** 1.349 +**************************************************************************/ 1.350 + 1.351 +void 1.352 +errWarn(char *function) 1.353 +{ 1.354 + PRErrorCode errorNumber = PR_GetError(); 1.355 + const char * errorString = SECU_Strerror(errorNumber); 1.356 + 1.357 + fprintf(stderr, "Error in function %s: %d\n - %s\n", 1.358 + function, errorNumber, errorString); 1.359 +} 1.360 + 1.361 +void 1.362 +exitErr(char *function) 1.363 +{ 1.364 + errWarn(function); 1.365 + /* Exit gracefully. */ 1.366 + /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/ 1.367 + (void) NSS_Shutdown(); 1.368 + PR_Cleanup(); 1.369 + exit(1); 1.370 +} 1.371 + 1.372 +void 1.373 +printSecurityInfo(FILE *outfile, PRFileDesc *fd) 1.374 +{ 1.375 + char * cp; /* bulk cipher name */ 1.376 + char * ip; /* cert issuer DN */ 1.377 + char * sp; /* cert subject DN */ 1.378 + int op; /* High, Low, Off */ 1.379 + int kp0; /* total key bits */ 1.380 + int kp1; /* secret key bits */ 1.381 + int result; 1.382 + SSL3Statistics * ssl3stats = SSL_GetStatistics(); 1.383 + 1.384 + if (!outfile) { 1.385 + outfile = stdout; 1.386 + } 1.387 + 1.388 + result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp); 1.389 + if (result != SECSuccess) 1.390 + return; 1.391 + fprintf(outfile, 1.392 + " bulk cipher %s, %d secret key bits, %d key bits, status: %d\n" 1.393 + " subject DN:\n %s\n" 1.394 + " issuer DN:\n %s\n", cp, kp1, kp0, op, sp, ip); 1.395 + PR_Free(cp); 1.396 + PR_Free(ip); 1.397 + PR_Free(sp); 1.398 + 1.399 + fprintf(outfile, 1.400 + " %ld cache hits; %ld cache misses, %ld cache not reusable\n", 1.401 + ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses, 1.402 + ssl3stats->hch_sid_cache_not_ok); 1.403 + 1.404 +} 1.405 + 1.406 + 1.407 +/************************************************************************** 1.408 +** Begin thread management routines and data. 1.409 +**************************************************************************/ 1.410 + 1.411 +void 1.412 +thread_wrapper(void * arg) 1.413 +{ 1.414 + GlobalThreadMgr *threadMGR = (GlobalThreadMgr *)arg; 1.415 + perThread *slot = &threadMGR->threads[threadMGR->index]; 1.416 + 1.417 + /* wait for parent to finish launching us before proceeding. */ 1.418 + PR_Lock(threadMGR->threadLock); 1.419 + PR_Unlock(threadMGR->threadLock); 1.420 + 1.421 + slot->rv = (* slot->startFunc)(slot->a, slot->b); 1.422 + 1.423 + PR_Lock(threadMGR->threadLock); 1.424 + slot->running = rs_zombie; 1.425 + 1.426 + /* notify the thread exit handler. */ 1.427 + PR_NotifyCondVar(threadMGR->threadEndQ); 1.428 + 1.429 + PR_Unlock(threadMGR->threadLock); 1.430 +} 1.431 + 1.432 +SECStatus 1.433 +launch_thread(GlobalThreadMgr *threadMGR, 1.434 + startFn *startFunc, 1.435 + void *a, 1.436 + int b) 1.437 +{ 1.438 + perThread *slot; 1.439 + int i; 1.440 + 1.441 + if (!threadMGR->threadStartQ) { 1.442 + threadMGR->threadLock = PR_NewLock(); 1.443 + threadMGR->threadStartQ = PR_NewCondVar(threadMGR->threadLock); 1.444 + threadMGR->threadEndQ = PR_NewCondVar(threadMGR->threadLock); 1.445 + } 1.446 + PR_Lock(threadMGR->threadLock); 1.447 + while (threadMGR->numRunning >= MAX_THREADS) { 1.448 + PR_WaitCondVar(threadMGR->threadStartQ, PR_INTERVAL_NO_TIMEOUT); 1.449 + } 1.450 + for (i = 0; i < threadMGR->numUsed; ++i) { 1.451 + slot = &threadMGR->threads[i]; 1.452 + if (slot->running == rs_idle) 1.453 + break; 1.454 + } 1.455 + if (i >= threadMGR->numUsed) { 1.456 + if (i >= MAX_THREADS) { 1.457 + /* something's really wrong here. */ 1.458 + PORT_Assert(i < MAX_THREADS); 1.459 + PR_Unlock(threadMGR->threadLock); 1.460 + return SECFailure; 1.461 + } 1.462 + ++(threadMGR->numUsed); 1.463 + PORT_Assert(threadMGR->numUsed == i + 1); 1.464 + slot = &threadMGR->threads[i]; 1.465 + } 1.466 + 1.467 + slot->a = a; 1.468 + slot->b = b; 1.469 + slot->startFunc = startFunc; 1.470 + 1.471 + threadMGR->index = i; 1.472 + 1.473 + slot->prThread = PR_CreateThread(PR_USER_THREAD, 1.474 + thread_wrapper, threadMGR, 1.475 + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, 1.476 + PR_JOINABLE_THREAD, 0); 1.477 + 1.478 + if (slot->prThread == NULL) { 1.479 + PR_Unlock(threadMGR->threadLock); 1.480 + printf("Failed to launch thread!\n"); 1.481 + return SECFailure; 1.482 + } 1.483 + 1.484 + slot->inUse = 1; 1.485 + slot->running = 1; 1.486 + ++(threadMGR->numRunning); 1.487 + PR_Unlock(threadMGR->threadLock); 1.488 + 1.489 + return SECSuccess; 1.490 +} 1.491 + 1.492 +SECStatus 1.493 +reap_threads(GlobalThreadMgr *threadMGR) 1.494 +{ 1.495 + perThread * slot; 1.496 + int i; 1.497 + 1.498 + if (!threadMGR->threadLock) 1.499 + return SECSuccess; 1.500 + PR_Lock(threadMGR->threadLock); 1.501 + while (threadMGR->numRunning > 0) { 1.502 + PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT); 1.503 + for (i = 0; i < threadMGR->numUsed; ++i) { 1.504 + slot = &threadMGR->threads[i]; 1.505 + if (slot->running == rs_zombie) { 1.506 + /* Handle cleanup of thread here. */ 1.507 + 1.508 + /* Now make sure the thread has ended OK. */ 1.509 + PR_JoinThread(slot->prThread); 1.510 + slot->running = rs_idle; 1.511 + --threadMGR->numRunning; 1.512 + 1.513 + /* notify the thread launcher. */ 1.514 + PR_NotifyCondVar(threadMGR->threadStartQ); 1.515 + } 1.516 + } 1.517 + } 1.518 + 1.519 + /* Safety Sam sez: make sure count is right. */ 1.520 + for (i = 0; i < threadMGR->numUsed; ++i) { 1.521 + slot = &threadMGR->threads[i]; 1.522 + if (slot->running != rs_idle) { 1.523 + fprintf(stderr, "Thread in slot %d is in state %d!\n", 1.524 + i, slot->running); 1.525 + } 1.526 + } 1.527 + PR_Unlock(threadMGR->threadLock); 1.528 + return SECSuccess; 1.529 +} 1.530 + 1.531 +void 1.532 +destroy_thread_data(GlobalThreadMgr *threadMGR) 1.533 +{ 1.534 + PORT_Memset(threadMGR->threads, 0, sizeof(threadMGR->threads)); 1.535 + 1.536 + if (threadMGR->threadEndQ) { 1.537 + PR_DestroyCondVar(threadMGR->threadEndQ); 1.538 + threadMGR->threadEndQ = NULL; 1.539 + } 1.540 + if (threadMGR->threadStartQ) { 1.541 + PR_DestroyCondVar(threadMGR->threadStartQ); 1.542 + threadMGR->threadStartQ = NULL; 1.543 + } 1.544 + if (threadMGR->threadLock) { 1.545 + PR_DestroyLock(threadMGR->threadLock); 1.546 + threadMGR->threadLock = NULL; 1.547 + } 1.548 +} 1.549 + 1.550 +/************************************************************************** 1.551 +** End thread management routines. 1.552 +**************************************************************************/ 1.553 + 1.554 +void 1.555 +lockedVars_Init( lockedVars * lv) 1.556 +{ 1.557 + lv->count = 0; 1.558 + lv->waiters = 0; 1.559 + lv->lock = PR_NewLock(); 1.560 + lv->condVar = PR_NewCondVar(lv->lock); 1.561 +} 1.562 + 1.563 +void 1.564 +lockedVars_Destroy( lockedVars * lv) 1.565 +{ 1.566 + PR_DestroyCondVar(lv->condVar); 1.567 + lv->condVar = NULL; 1.568 + 1.569 + PR_DestroyLock(lv->lock); 1.570 + lv->lock = NULL; 1.571 +} 1.572 + 1.573 +void 1.574 +lockedVars_WaitForDone(lockedVars * lv) 1.575 +{ 1.576 + PR_Lock(lv->lock); 1.577 + while (lv->count > 0) { 1.578 + PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT); 1.579 + } 1.580 + PR_Unlock(lv->lock); 1.581 +} 1.582 + 1.583 +int /* returns count */ 1.584 +lockedVars_AddToCount(lockedVars * lv, int addend) 1.585 +{ 1.586 + int rv; 1.587 + 1.588 + PR_Lock(lv->lock); 1.589 + rv = lv->count += addend; 1.590 + if (rv <= 0) { 1.591 + PR_NotifyCondVar(lv->condVar); 1.592 + } 1.593 + PR_Unlock(lv->lock); 1.594 + return rv; 1.595 +} 1.596 + 1.597 + 1.598 +/* 1.599 + * Dump cert chain in to cert.* files. This function is will 1.600 + * create collisions while dumping cert chains if called from 1.601 + * multiple treads. But it should not be a problem since we 1.602 + * consider vfyserv to be single threaded(see bug 353477). 1.603 + */ 1.604 + 1.605 +void 1.606 +dumpCertChain(CERTCertificate *cert, SECCertUsage usage) 1.607 +{ 1.608 + CERTCertificateList *certList; 1.609 + int count = 0; 1.610 + 1.611 + certList = CERT_CertChainFromCert(cert, usage, PR_TRUE); 1.612 + if (certList == NULL) { 1.613 + errWarn("CERT_CertChainFromCert"); 1.614 + return; 1.615 + } 1.616 + 1.617 + for(count = 0; count < (unsigned int)certList->len; count++) { 1.618 + char certFileName[16]; 1.619 + PRFileDesc *cfd; 1.620 + 1.621 + PR_snprintf(certFileName, sizeof certFileName, "cert.%03d", 1.622 + count); 1.623 + cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 1.624 + 0664); 1.625 + if (!cfd) { 1.626 + PR_fprintf(PR_STDOUT, 1.627 + "Error: couldn't save cert der in file '%s'\n", 1.628 + certFileName); 1.629 + } else { 1.630 + PR_Write(cfd, certList->certs[count].data, certList->certs[count].len); 1.631 + PR_Close(cfd); 1.632 + PR_fprintf(PR_STDOUT, "Cert file %s was created.\n", certFileName); 1.633 + } 1.634 + } 1.635 + CERT_DestroyCertificateList(certList); 1.636 +}