1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/certhigh/certhigh.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1193 @@ 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 +#include "nspr.h" 1.8 +#include "secerr.h" 1.9 +#include "secasn1.h" 1.10 +#include "seccomon.h" 1.11 +#include "pk11func.h" 1.12 +#include "certdb.h" 1.13 +#include "certt.h" 1.14 +#include "cert.h" 1.15 +#include "certxutl.h" 1.16 + 1.17 +#include "nsspki.h" 1.18 +#include "pki.h" 1.19 +#include "pkit.h" 1.20 +#include "pkitm.h" 1.21 +#include "pki3hack.h" 1.22 + 1.23 + 1.24 +PRBool 1.25 +CERT_MatchNickname(char *name1, char *name2) { 1.26 + char *nickname1= NULL; 1.27 + char *nickname2 = NULL; 1.28 + char *token1; 1.29 + char *token2; 1.30 + char *token = NULL; 1.31 + int len; 1.32 + 1.33 + /* first deal with the straight comparison */ 1.34 + if (PORT_Strcmp(name1, name2) == 0) { 1.35 + return PR_TRUE; 1.36 + } 1.37 + /* we need to handle the case where one name has an explicit token and the other 1.38 + * doesn't */ 1.39 + token1 = PORT_Strchr(name1,':'); 1.40 + token2 = PORT_Strchr(name2,':'); 1.41 + if ((token1 && token2) || (!token1 && !token2)) { 1.42 + /* either both token names are specified or neither are, not match */ 1.43 + return PR_FALSE; 1.44 + } 1.45 + if (token1) { 1.46 + token=name1; 1.47 + nickname1=token1; 1.48 + nickname2=name2; 1.49 + } else { 1.50 + token=name2; 1.51 + nickname1=token2; 1.52 + nickname2=name1; 1.53 + } 1.54 + len = nickname1-token; 1.55 + nickname1++; 1.56 + if (PORT_Strcmp(nickname1,nickname2) != 0) { 1.57 + return PR_FALSE; 1.58 + } 1.59 + /* compare the other token with the internal slot here */ 1.60 + return PR_TRUE; 1.61 +} 1.62 + 1.63 +/* 1.64 + * Find all user certificates that match the given criteria. 1.65 + * 1.66 + * "handle" - database to search 1.67 + * "usage" - certificate usage to match 1.68 + * "oneCertPerName" - if set then only return the "best" cert per 1.69 + * name 1.70 + * "validOnly" - only return certs that are curently valid 1.71 + * "proto_win" - window handle passed to pkcs11 1.72 + */ 1.73 +CERTCertList * 1.74 +CERT_FindUserCertsByUsage(CERTCertDBHandle *handle, 1.75 + SECCertUsage usage, 1.76 + PRBool oneCertPerName, 1.77 + PRBool validOnly, 1.78 + void *proto_win) 1.79 +{ 1.80 + CERTCertNicknames *nicknames = NULL; 1.81 + char **nnptr; 1.82 + int nn; 1.83 + CERTCertificate *cert = NULL; 1.84 + CERTCertList *certList = NULL; 1.85 + SECStatus rv; 1.86 + PRTime time; 1.87 + CERTCertListNode *node = NULL; 1.88 + CERTCertListNode *freenode = NULL; 1.89 + int n; 1.90 + 1.91 + time = PR_Now(); 1.92 + 1.93 + nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER, 1.94 + proto_win); 1.95 + 1.96 + if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) { 1.97 + goto loser; 1.98 + } 1.99 + 1.100 + nnptr = nicknames->nicknames; 1.101 + nn = nicknames->numnicknames; 1.102 + 1.103 + while ( nn > 0 ) { 1.104 + cert = NULL; 1.105 + /* use the pk11 call so that we pick up any certs on tokens, 1.106 + * which may require login 1.107 + */ 1.108 + if ( proto_win != NULL ) { 1.109 + cert = PK11_FindCertFromNickname(*nnptr,proto_win); 1.110 + } 1.111 + 1.112 + /* Sigh, It turns out if the cert is already in the temp db, because 1.113 + * it's in the perm db, then the nickname lookup doesn't work. 1.114 + * since we already have the cert here, though, than we can just call 1.115 + * CERT_CreateSubjectCertList directly. For those cases where we didn't 1.116 + * find the cert in pkcs #11 (because we didn't have a password arg, 1.117 + * or because the nickname is for a peer, server, or CA cert, then we 1.118 + * go look the cert up. 1.119 + */ 1.120 + if (cert == NULL) { 1.121 + cert = CERT_FindCertByNickname(handle,*nnptr); 1.122 + } 1.123 + 1.124 + if ( cert != NULL ) { 1.125 + /* collect certs for this nickname, sorting them into the list */ 1.126 + certList = CERT_CreateSubjectCertList(certList, handle, 1.127 + &cert->derSubject, time, validOnly); 1.128 + 1.129 + CERT_FilterCertListForUserCerts(certList); 1.130 + 1.131 + /* drop the extra reference */ 1.132 + CERT_DestroyCertificate(cert); 1.133 + } 1.134 + 1.135 + nnptr++; 1.136 + nn--; 1.137 + } 1.138 + 1.139 + /* remove certs with incorrect usage */ 1.140 + rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE); 1.141 + 1.142 + if ( rv != SECSuccess ) { 1.143 + goto loser; 1.144 + } 1.145 + 1.146 + /* remove any extra certs for each name */ 1.147 + if ( oneCertPerName ) { 1.148 + PRBool *flags; 1.149 + 1.150 + nn = nicknames->numnicknames; 1.151 + nnptr = nicknames->nicknames; 1.152 + 1.153 + flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn); 1.154 + if ( flags == NULL ) { 1.155 + goto loser; 1.156 + } 1.157 + 1.158 + node = CERT_LIST_HEAD(certList); 1.159 + 1.160 + /* treverse all certs in the list */ 1.161 + while ( !CERT_LIST_END(node, certList) ) { 1.162 + 1.163 + /* find matching nickname index */ 1.164 + for ( n = 0; n < nn; n++ ) { 1.165 + if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) { 1.166 + /* We found a match. If this is the first one, then 1.167 + * set the flag and move on to the next cert. If this 1.168 + * is not the first one then delete it from the list. 1.169 + */ 1.170 + if ( flags[n] ) { 1.171 + /* We have already seen a cert with this nickname, 1.172 + * so delete this one. 1.173 + */ 1.174 + freenode = node; 1.175 + node = CERT_LIST_NEXT(node); 1.176 + CERT_RemoveCertListNode(freenode); 1.177 + } else { 1.178 + /* keep the first cert for each nickname, but set the 1.179 + * flag so we know to delete any others with the same 1.180 + * nickname. 1.181 + */ 1.182 + flags[n] = PR_TRUE; 1.183 + node = CERT_LIST_NEXT(node); 1.184 + } 1.185 + break; 1.186 + } 1.187 + } 1.188 + if ( n == nn ) { 1.189 + /* if we get here it means that we didn't find a matching 1.190 + * nickname, which should not happen. 1.191 + */ 1.192 + PORT_Assert(0); 1.193 + node = CERT_LIST_NEXT(node); 1.194 + } 1.195 + } 1.196 + PORT_Free(flags); 1.197 + } 1.198 + 1.199 + goto done; 1.200 + 1.201 +loser: 1.202 + if ( certList != NULL ) { 1.203 + CERT_DestroyCertList(certList); 1.204 + certList = NULL; 1.205 + } 1.206 + 1.207 +done: 1.208 + if ( nicknames != NULL ) { 1.209 + CERT_FreeNicknames(nicknames); 1.210 + } 1.211 + 1.212 + return(certList); 1.213 +} 1.214 + 1.215 +/* 1.216 + * Find a user certificate that matchs the given criteria. 1.217 + * 1.218 + * "handle" - database to search 1.219 + * "nickname" - nickname to match 1.220 + * "usage" - certificate usage to match 1.221 + * "validOnly" - only return certs that are curently valid 1.222 + * "proto_win" - window handle passed to pkcs11 1.223 + */ 1.224 +CERTCertificate * 1.225 +CERT_FindUserCertByUsage(CERTCertDBHandle *handle, 1.226 + const char *nickname, 1.227 + SECCertUsage usage, 1.228 + PRBool validOnly, 1.229 + void *proto_win) 1.230 +{ 1.231 + CERTCertificate *cert = NULL; 1.232 + CERTCertList *certList = NULL; 1.233 + SECStatus rv; 1.234 + PRTime time; 1.235 + 1.236 + time = PR_Now(); 1.237 + 1.238 + /* use the pk11 call so that we pick up any certs on tokens, 1.239 + * which may require login 1.240 + */ 1.241 + /* XXX - why is this restricted? */ 1.242 + if ( proto_win != NULL ) { 1.243 + cert = PK11_FindCertFromNickname(nickname,proto_win); 1.244 + } 1.245 + 1.246 + 1.247 + /* sigh, There are still problems find smart cards from the temp 1.248 + * db. This will get smart cards working again. The real fix 1.249 + * is to make sure we can search the temp db by their token nickname. 1.250 + */ 1.251 + if (cert == NULL) { 1.252 + cert = CERT_FindCertByNickname(handle,nickname); 1.253 + } 1.254 + 1.255 + if ( cert != NULL ) { 1.256 + unsigned int requiredKeyUsage; 1.257 + unsigned int requiredCertType; 1.258 + 1.259 + rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE, 1.260 + &requiredKeyUsage, &requiredCertType); 1.261 + if ( rv != SECSuccess ) { 1.262 + /* drop the extra reference */ 1.263 + CERT_DestroyCertificate(cert); 1.264 + cert = NULL; 1.265 + goto loser; 1.266 + } 1.267 + /* If we already found the right cert, just return it */ 1.268 + if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE) 1.269 + == secCertTimeValid) && 1.270 + (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) && 1.271 + (cert->nsCertType & requiredCertType) && 1.272 + CERT_IsUserCert(cert) ) { 1.273 + return(cert); 1.274 + } 1.275 + 1.276 + /* collect certs for this nickname, sorting them into the list */ 1.277 + certList = CERT_CreateSubjectCertList(certList, handle, 1.278 + &cert->derSubject, time, validOnly); 1.279 + 1.280 + CERT_FilterCertListForUserCerts(certList); 1.281 + 1.282 + /* drop the extra reference */ 1.283 + CERT_DestroyCertificate(cert); 1.284 + cert = NULL; 1.285 + } 1.286 + 1.287 + if ( certList == NULL ) { 1.288 + goto loser; 1.289 + } 1.290 + 1.291 + /* remove certs with incorrect usage */ 1.292 + rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE); 1.293 + 1.294 + if ( rv != SECSuccess ) { 1.295 + goto loser; 1.296 + } 1.297 + 1.298 + if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) { 1.299 + cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert); 1.300 + } 1.301 + 1.302 +loser: 1.303 + if ( certList != NULL ) { 1.304 + CERT_DestroyCertList(certList); 1.305 + } 1.306 + 1.307 + return(cert); 1.308 +} 1.309 + 1.310 +CERTCertList * 1.311 +CERT_MatchUserCert(CERTCertDBHandle *handle, 1.312 + SECCertUsage usage, 1.313 + int nCANames, char **caNames, 1.314 + void *proto_win) 1.315 +{ 1.316 + CERTCertList *certList = NULL; 1.317 + SECStatus rv; 1.318 + 1.319 + certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE, 1.320 + proto_win); 1.321 + if ( certList == NULL ) { 1.322 + goto loser; 1.323 + } 1.324 + 1.325 + rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage); 1.326 + if ( rv != SECSuccess ) { 1.327 + goto loser; 1.328 + } 1.329 + 1.330 + goto done; 1.331 + 1.332 +loser: 1.333 + if ( certList != NULL ) { 1.334 + CERT_DestroyCertList(certList); 1.335 + certList = NULL; 1.336 + } 1.337 + 1.338 +done: 1.339 + 1.340 + return(certList); 1.341 +} 1.342 + 1.343 + 1.344 +typedef struct stringNode { 1.345 + struct stringNode *next; 1.346 + char *string; 1.347 +} stringNode; 1.348 + 1.349 +static PRStatus 1.350 +CollectNicknames( NSSCertificate *c, void *data) 1.351 +{ 1.352 + CERTCertNicknames *names; 1.353 + PRBool saveit = PR_FALSE; 1.354 + stringNode *node; 1.355 + int len; 1.356 +#ifdef notdef 1.357 + NSSTrustDomain *td; 1.358 + NSSTrust *trust; 1.359 +#endif 1.360 + char *stanNickname; 1.361 + char *nickname = NULL; 1.362 + 1.363 + names = (CERTCertNicknames *)data; 1.364 + 1.365 + stanNickname = nssCertificate_GetNickname(c,NULL); 1.366 + 1.367 + if ( stanNickname ) { 1.368 + nss_ZFreeIf(stanNickname); 1.369 + stanNickname = NULL; 1.370 + if (names->what == SEC_CERT_NICKNAMES_USER) { 1.371 + saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL); 1.372 + } 1.373 +#ifdef notdef 1.374 + else { 1.375 + td = NSSCertificate_GetTrustDomain(c); 1.376 + if (!td) { 1.377 + return PR_SUCCESS; 1.378 + } 1.379 + trust = nssTrustDomain_FindTrustForCertificate(td,c); 1.380 + 1.381 + switch(names->what) { 1.382 + case SEC_CERT_NICKNAMES_ALL: 1.383 + if ((trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) || 1.384 + (trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) || 1.385 + (trust->objectSigningFlags & 1.386 + (CERTDB_VALID_CA|CERTDB_VALID_PEER))) { 1.387 + saveit = PR_TRUE; 1.388 + } 1.389 + 1.390 + break; 1.391 + case SEC_CERT_NICKNAMES_SERVER: 1.392 + if ( trust->sslFlags & CERTDB_VALID_PEER ) { 1.393 + saveit = PR_TRUE; 1.394 + } 1.395 + 1.396 + break; 1.397 + case SEC_CERT_NICKNAMES_CA: 1.398 + if (((trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)|| 1.399 + ((trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA) || 1.400 + ((trust->objectSigningFlags & CERTDB_VALID_CA ) 1.401 + == CERTDB_VALID_CA)) { 1.402 + saveit = PR_TRUE; 1.403 + } 1.404 + break; 1.405 + } 1.406 + } 1.407 +#endif 1.408 + } 1.409 + 1.410 + /* traverse the list of collected nicknames and make sure we don't make 1.411 + * a duplicate 1.412 + */ 1.413 + if ( saveit ) { 1.414 + nickname = STAN_GetCERTCertificateName(NULL, c); 1.415 + /* nickname can only be NULL here if we are having memory 1.416 + * alloc problems */ 1.417 + if (nickname == NULL) { 1.418 + return PR_FAILURE; 1.419 + } 1.420 + node = (stringNode *)names->head; 1.421 + while ( node != NULL ) { 1.422 + if ( PORT_Strcmp(nickname, node->string) == 0 ) { 1.423 + /* if the string matches, then don't save this one */ 1.424 + saveit = PR_FALSE; 1.425 + break; 1.426 + } 1.427 + node = node->next; 1.428 + } 1.429 + } 1.430 + 1.431 + if ( saveit ) { 1.432 + 1.433 + /* allocate the node */ 1.434 + node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode)); 1.435 + if ( node == NULL ) { 1.436 + PORT_Free(nickname); 1.437 + return PR_FAILURE; 1.438 + } 1.439 + 1.440 + /* copy the string */ 1.441 + len = PORT_Strlen(nickname) + 1; 1.442 + node->string = (char*)PORT_ArenaAlloc(names->arena, len); 1.443 + if ( node->string == NULL ) { 1.444 + PORT_Free(nickname); 1.445 + return PR_FAILURE; 1.446 + } 1.447 + PORT_Memcpy(node->string, nickname, len); 1.448 + 1.449 + /* link it into the list */ 1.450 + node->next = (stringNode *)names->head; 1.451 + names->head = (void *)node; 1.452 + 1.453 + /* bump the count */ 1.454 + names->numnicknames++; 1.455 + } 1.456 + 1.457 + if (nickname) PORT_Free(nickname); 1.458 + return(PR_SUCCESS); 1.459 +} 1.460 + 1.461 +CERTCertNicknames * 1.462 +CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx) 1.463 +{ 1.464 + PLArenaPool *arena; 1.465 + CERTCertNicknames *names; 1.466 + int i; 1.467 + stringNode *node; 1.468 + 1.469 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.470 + if ( arena == NULL ) { 1.471 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.472 + return(NULL); 1.473 + } 1.474 + 1.475 + names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); 1.476 + if ( names == NULL ) { 1.477 + goto loser; 1.478 + } 1.479 + 1.480 + names->arena = arena; 1.481 + names->head = NULL; 1.482 + names->numnicknames = 0; 1.483 + names->nicknames = NULL; 1.484 + names->what = what; 1.485 + names->totallen = 0; 1.486 + 1.487 + /* make sure we are logged in */ 1.488 + (void) pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx); 1.489 + 1.490 + NSSTrustDomain_TraverseCertificates(handle, 1.491 + CollectNicknames, (void *)names); 1.492 + if ( names->numnicknames ) { 1.493 + names->nicknames = (char**)PORT_ArenaAlloc(arena, 1.494 + names->numnicknames * sizeof(char *)); 1.495 + 1.496 + if ( names->nicknames == NULL ) { 1.497 + goto loser; 1.498 + } 1.499 + 1.500 + node = (stringNode *)names->head; 1.501 + 1.502 + for ( i = 0; i < names->numnicknames; i++ ) { 1.503 + PORT_Assert(node != NULL); 1.504 + 1.505 + names->nicknames[i] = node->string; 1.506 + names->totallen += PORT_Strlen(node->string); 1.507 + node = node->next; 1.508 + } 1.509 + 1.510 + PORT_Assert(node == NULL); 1.511 + } 1.512 + 1.513 + return(names); 1.514 + 1.515 +loser: 1.516 + PORT_FreeArena(arena, PR_FALSE); 1.517 + return(NULL); 1.518 +} 1.519 + 1.520 +void 1.521 +CERT_FreeNicknames(CERTCertNicknames *nicknames) 1.522 +{ 1.523 + PORT_FreeArena(nicknames->arena, PR_FALSE); 1.524 + 1.525 + return; 1.526 +} 1.527 + 1.528 +/* [ FROM pcertdb.c ] */ 1.529 + 1.530 +typedef struct dnameNode { 1.531 + struct dnameNode *next; 1.532 + SECItem name; 1.533 +} dnameNode; 1.534 + 1.535 +void 1.536 +CERT_FreeDistNames(CERTDistNames *names) 1.537 +{ 1.538 + PORT_FreeArena(names->arena, PR_FALSE); 1.539 + 1.540 + return; 1.541 +} 1.542 + 1.543 +static SECStatus 1.544 +CollectDistNames( CERTCertificate *cert, SECItem *k, void *data) 1.545 +{ 1.546 + CERTDistNames *names; 1.547 + PRBool saveit = PR_FALSE; 1.548 + CERTCertTrust trust; 1.549 + dnameNode *node; 1.550 + int len; 1.551 + 1.552 + names = (CERTDistNames *)data; 1.553 + 1.554 + if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) { 1.555 + /* only collect names of CAs trusted for issuing SSL clients */ 1.556 + if ( trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA ) { 1.557 + saveit = PR_TRUE; 1.558 + } 1.559 + } 1.560 + 1.561 + if ( saveit ) { 1.562 + /* allocate the node */ 1.563 + node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode)); 1.564 + if ( node == NULL ) { 1.565 + return(SECFailure); 1.566 + } 1.567 + 1.568 + /* copy the name */ 1.569 + node->name.len = len = cert->derSubject.len; 1.570 + node->name.type = siBuffer; 1.571 + node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len); 1.572 + if ( node->name.data == NULL ) { 1.573 + return(SECFailure); 1.574 + } 1.575 + PORT_Memcpy(node->name.data, cert->derSubject.data, len); 1.576 + 1.577 + /* link it into the list */ 1.578 + node->next = (dnameNode *)names->head; 1.579 + names->head = (void *)node; 1.580 + 1.581 + /* bump the count */ 1.582 + names->nnames++; 1.583 + } 1.584 + 1.585 + return(SECSuccess); 1.586 +} 1.587 + 1.588 +/* 1.589 + * Return all of the CAs that are "trusted" for SSL. 1.590 + */ 1.591 +CERTDistNames * 1.592 +CERT_DupDistNames(CERTDistNames *orig) 1.593 +{ 1.594 + PLArenaPool *arena; 1.595 + CERTDistNames *names; 1.596 + int i; 1.597 + SECStatus rv; 1.598 + 1.599 + /* allocate an arena to use */ 1.600 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.601 + if (arena == NULL) { 1.602 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.603 + return(NULL); 1.604 + } 1.605 + 1.606 + /* allocate the header structure */ 1.607 + names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames)); 1.608 + if (names == NULL) { 1.609 + goto loser; 1.610 + } 1.611 + 1.612 + /* initialize the header struct */ 1.613 + names->arena = arena; 1.614 + names->head = NULL; 1.615 + names->nnames = orig->nnames; 1.616 + names->names = NULL; 1.617 + 1.618 + /* construct the array from the list */ 1.619 + if (orig->nnames) { 1.620 + names->names = (SECItem*)PORT_ArenaNewArray(arena, SECItem, 1.621 + orig->nnames); 1.622 + if (names->names == NULL) { 1.623 + goto loser; 1.624 + } 1.625 + for (i = 0; i < orig->nnames; i++) { 1.626 + rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]); 1.627 + if (rv != SECSuccess) { 1.628 + goto loser; 1.629 + } 1.630 + } 1.631 + } 1.632 + return(names); 1.633 + 1.634 +loser: 1.635 + PORT_FreeArena(arena, PR_FALSE); 1.636 + return(NULL); 1.637 +} 1.638 + 1.639 +CERTDistNames * 1.640 +CERT_GetSSLCACerts(CERTCertDBHandle *handle) 1.641 +{ 1.642 + PLArenaPool *arena; 1.643 + CERTDistNames *names; 1.644 + int i; 1.645 + SECStatus rv; 1.646 + dnameNode *node; 1.647 + 1.648 + /* allocate an arena to use */ 1.649 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.650 + if ( arena == NULL ) { 1.651 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.652 + return(NULL); 1.653 + } 1.654 + 1.655 + /* allocate the header structure */ 1.656 + names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames)); 1.657 + if ( names == NULL ) { 1.658 + goto loser; 1.659 + } 1.660 + 1.661 + /* initialize the header struct */ 1.662 + names->arena = arena; 1.663 + names->head = NULL; 1.664 + names->nnames = 0; 1.665 + names->names = NULL; 1.666 + 1.667 + /* collect the names from the database */ 1.668 + rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL); 1.669 + if ( rv ) { 1.670 + goto loser; 1.671 + } 1.672 + 1.673 + /* construct the array from the list */ 1.674 + if ( names->nnames ) { 1.675 + names->names = (SECItem*)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem)); 1.676 + 1.677 + if ( names->names == NULL ) { 1.678 + goto loser; 1.679 + } 1.680 + 1.681 + node = (dnameNode *)names->head; 1.682 + 1.683 + for ( i = 0; i < names->nnames; i++ ) { 1.684 + PORT_Assert(node != NULL); 1.685 + 1.686 + names->names[i] = node->name; 1.687 + node = node->next; 1.688 + } 1.689 + 1.690 + PORT_Assert(node == NULL); 1.691 + } 1.692 + 1.693 + return(names); 1.694 + 1.695 +loser: 1.696 + PORT_FreeArena(arena, PR_FALSE); 1.697 + return(NULL); 1.698 +} 1.699 + 1.700 +CERTDistNames * 1.701 +CERT_DistNamesFromCertList(CERTCertList *certList) 1.702 +{ 1.703 + CERTDistNames * dnames = NULL; 1.704 + PLArenaPool * arena; 1.705 + CERTCertListNode *node = NULL; 1.706 + SECItem * names = NULL; 1.707 + int listLen = 0, i = 0; 1.708 + 1.709 + if (certList == NULL) { 1.710 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.711 + return NULL; 1.712 + } 1.713 + 1.714 + node = CERT_LIST_HEAD(certList); 1.715 + while ( ! CERT_LIST_END(node, certList) ) { 1.716 + listLen += 1; 1.717 + node = CERT_LIST_NEXT(node); 1.718 + } 1.719 + 1.720 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.721 + if (arena == NULL) goto loser; 1.722 + dnames = PORT_ArenaZNew(arena, CERTDistNames); 1.723 + if (dnames == NULL) goto loser; 1.724 + 1.725 + dnames->arena = arena; 1.726 + dnames->nnames = listLen; 1.727 + dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen); 1.728 + if (names == NULL) goto loser; 1.729 + 1.730 + node = CERT_LIST_HEAD(certList); 1.731 + while ( ! CERT_LIST_END(node, certList) ) { 1.732 + CERTCertificate *cert = node->cert; 1.733 + SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject); 1.734 + if (rv == SECFailure) { 1.735 + goto loser; 1.736 + } 1.737 + node = CERT_LIST_NEXT(node); 1.738 + } 1.739 + return dnames; 1.740 +loser: 1.741 + if (arena) { 1.742 + PORT_FreeArena(arena, PR_FALSE); 1.743 + } 1.744 + return NULL; 1.745 +} 1.746 + 1.747 +CERTDistNames * 1.748 +CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames, 1.749 + int nnames) 1.750 +{ 1.751 + CERTDistNames *dnames = NULL; 1.752 + PLArenaPool *arena; 1.753 + int i, rv; 1.754 + SECItem *names = NULL; 1.755 + CERTCertificate *cert = NULL; 1.756 + 1.757 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.758 + if (arena == NULL) goto loser; 1.759 + dnames = PORT_ArenaZNew(arena, CERTDistNames); 1.760 + if (dnames == NULL) goto loser; 1.761 + 1.762 + dnames->arena = arena; 1.763 + dnames->nnames = nnames; 1.764 + dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames); 1.765 + if (names == NULL) goto loser; 1.766 + 1.767 + for (i = 0; i < nnames; i++) { 1.768 + cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]); 1.769 + if (cert == NULL) goto loser; 1.770 + rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject); 1.771 + if (rv == SECFailure) goto loser; 1.772 + CERT_DestroyCertificate(cert); 1.773 + } 1.774 + return dnames; 1.775 + 1.776 +loser: 1.777 + if (cert != NULL) 1.778 + CERT_DestroyCertificate(cert); 1.779 + if (arena != NULL) 1.780 + PORT_FreeArena(arena, PR_FALSE); 1.781 + return NULL; 1.782 +} 1.783 + 1.784 +/* [ from pcertdb.c - calls Ascii to Name ] */ 1.785 +/* 1.786 + * Lookup a certificate in the database by name 1.787 + */ 1.788 +CERTCertificate * 1.789 +CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr) 1.790 +{ 1.791 + CERTName *name; 1.792 + SECItem *nameItem; 1.793 + CERTCertificate *cert = NULL; 1.794 + PLArenaPool *arena = NULL; 1.795 + 1.796 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.797 + 1.798 + if ( arena == NULL ) { 1.799 + goto loser; 1.800 + } 1.801 + 1.802 + name = CERT_AsciiToName(nameStr); 1.803 + 1.804 + if ( name ) { 1.805 + nameItem = SEC_ASN1EncodeItem (arena, NULL, (void *)name, 1.806 + CERT_NameTemplate); 1.807 + if ( nameItem != NULL ) { 1.808 + cert = CERT_FindCertByName(handle, nameItem); 1.809 + } 1.810 + CERT_DestroyName(name); 1.811 + } 1.812 + 1.813 +loser: 1.814 + if ( arena ) { 1.815 + PORT_FreeArena(arena, PR_FALSE); 1.816 + } 1.817 + 1.818 + return(cert); 1.819 +} 1.820 + 1.821 +/* From certv3.c */ 1.822 + 1.823 +CERTCrlDistributionPoints * 1.824 +CERT_FindCRLDistributionPoints (CERTCertificate *cert) 1.825 +{ 1.826 + SECItem encodedExtenValue; 1.827 + SECStatus rv; 1.828 + CERTCrlDistributionPoints *dps; 1.829 + 1.830 + encodedExtenValue.data = NULL; 1.831 + encodedExtenValue.len = 0; 1.832 + 1.833 + rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS, 1.834 + &encodedExtenValue); 1.835 + if ( rv != SECSuccess ) { 1.836 + return (NULL); 1.837 + } 1.838 + 1.839 + dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue); 1.840 + 1.841 + PORT_Free(encodedExtenValue.data); 1.842 + 1.843 + return dps; 1.844 +} 1.845 + 1.846 +/* From crl.c */ 1.847 +CERTSignedCrl * CERT_ImportCRL 1.848 + (CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx) 1.849 +{ 1.850 + CERTSignedCrl* retCrl = NULL; 1.851 + PK11SlotInfo* slot = PK11_GetInternalKeySlot(); 1.852 + retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx, 1.853 + CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS); 1.854 + PK11_FreeSlot(slot); 1.855 + 1.856 + return retCrl; 1.857 +} 1.858 + 1.859 +/* From certdb.c */ 1.860 +static SECStatus 1.861 +cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted) 1.862 +{ 1.863 + SECStatus rv; 1.864 + SECItem *derCert; 1.865 + CERTCertificate *cert = NULL; 1.866 + CERTCertificate *newcert = NULL; 1.867 + CERTCertDBHandle *handle; 1.868 + CERTCertTrust trust; 1.869 + PRBool isca; 1.870 + char *nickname; 1.871 + unsigned int certtype; 1.872 + 1.873 + handle = CERT_GetDefaultCertDB(); 1.874 + 1.875 + while (numcerts--) { 1.876 + derCert = certs; 1.877 + certs++; 1.878 + 1.879 + /* decode my certificate */ 1.880 + /* This use is ok -- only looks at decoded parts, calls NewTemp later */ 1.881 + newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); 1.882 + if ( newcert == NULL ) { 1.883 + goto loser; 1.884 + } 1.885 + 1.886 + if (!trusted) { 1.887 + /* make sure that cert is valid */ 1.888 + rv = CERT_CertTimesValid(newcert); 1.889 + if ( rv == SECFailure ) { 1.890 + goto endloop; 1.891 + } 1.892 + } 1.893 + 1.894 + /* does it have the CA extension */ 1.895 + 1.896 + /* 1.897 + * Make sure that if this is an intermediate CA in the chain that 1.898 + * it was given permission by its signer to be a CA. 1.899 + */ 1.900 + isca = CERT_IsCACert(newcert, &certtype); 1.901 + 1.902 + if ( !isca ) { 1.903 + if (!trusted) { 1.904 + goto endloop; 1.905 + } 1.906 + trust.sslFlags = CERTDB_VALID_CA; 1.907 + trust.emailFlags = CERTDB_VALID_CA; 1.908 + trust.objectSigningFlags = CERTDB_VALID_CA; 1.909 + } else { 1.910 + /* SSL ca's must have the ssl bit set */ 1.911 + if ( ( certUsage == certUsageSSLCA ) && 1.912 + (( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA )) { 1.913 + goto endloop; 1.914 + } 1.915 + 1.916 + /* it passed all of the tests, so lets add it to the database */ 1.917 + /* mark it as a CA */ 1.918 + PORT_Memset((void *)&trust, 0, sizeof(trust)); 1.919 + switch ( certUsage ) { 1.920 + case certUsageSSLCA: 1.921 + trust.sslFlags = CERTDB_VALID_CA; 1.922 + break; 1.923 + case certUsageUserCertImport: 1.924 + if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) { 1.925 + trust.sslFlags = CERTDB_VALID_CA; 1.926 + } 1.927 + if ((certtype & NS_CERT_TYPE_EMAIL_CA) 1.928 + == NS_CERT_TYPE_EMAIL_CA ) { 1.929 + trust.emailFlags = CERTDB_VALID_CA; 1.930 + } 1.931 + if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) == 1.932 + NS_CERT_TYPE_OBJECT_SIGNING_CA ) { 1.933 + trust.objectSigningFlags = CERTDB_VALID_CA; 1.934 + } 1.935 + break; 1.936 + default: 1.937 + PORT_Assert(0); 1.938 + break; 1.939 + } 1.940 + } 1.941 + 1.942 + cert = CERT_NewTempCertificate(handle, derCert, NULL, 1.943 + PR_FALSE, PR_FALSE); 1.944 + if ( cert == NULL ) { 1.945 + goto loser; 1.946 + } 1.947 + 1.948 + /* if the cert is temp, make it perm; otherwise we're done */ 1.949 + if (cert->istemp) { 1.950 + /* get a default nickname for it */ 1.951 + nickname = CERT_MakeCANickname(cert); 1.952 + 1.953 + rv = CERT_AddTempCertToPerm(cert, nickname, &trust); 1.954 + 1.955 + /* free the nickname */ 1.956 + if ( nickname ) { 1.957 + PORT_Free(nickname); 1.958 + } 1.959 + } else { 1.960 + rv = SECSuccess; 1.961 + } 1.962 + 1.963 + CERT_DestroyCertificate(cert); 1.964 + cert = NULL; 1.965 + 1.966 + if ( rv != SECSuccess ) { 1.967 + goto loser; 1.968 + } 1.969 + 1.970 +endloop: 1.971 + if ( newcert ) { 1.972 + CERT_DestroyCertificate(newcert); 1.973 + newcert = NULL; 1.974 + } 1.975 + 1.976 + } 1.977 + 1.978 + rv = SECSuccess; 1.979 + goto done; 1.980 +loser: 1.981 + rv = SECFailure; 1.982 +done: 1.983 + 1.984 + if ( newcert ) { 1.985 + CERT_DestroyCertificate(newcert); 1.986 + newcert = NULL; 1.987 + } 1.988 + 1.989 + if ( cert ) { 1.990 + CERT_DestroyCertificate(cert); 1.991 + cert = NULL; 1.992 + } 1.993 + 1.994 + return(rv); 1.995 +} 1.996 + 1.997 +SECStatus 1.998 +CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage) 1.999 +{ 1.1000 + return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE); 1.1001 +} 1.1002 + 1.1003 +SECStatus 1.1004 +CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage) { 1.1005 + return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE); 1.1006 +} 1.1007 + 1.1008 +/* Moved from certdb.c */ 1.1009 +/* 1.1010 +** CERT_CertChainFromCert 1.1011 +** 1.1012 +** Construct a CERTCertificateList consisting of the given certificate and all 1.1013 +** of the issuer certs until we either get to a self-signed cert or can't find 1.1014 +** an issuer. Since we don't know how many certs are in the chain we have to 1.1015 +** build a linked list first as we count them. 1.1016 +*/ 1.1017 + 1.1018 +typedef struct certNode { 1.1019 + struct certNode *next; 1.1020 + CERTCertificate *cert; 1.1021 +} certNode; 1.1022 + 1.1023 +CERTCertificateList * 1.1024 +CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, 1.1025 + PRBool includeRoot) 1.1026 +{ 1.1027 + CERTCertificateList *chain = NULL; 1.1028 + NSSCertificate **stanChain; 1.1029 + NSSCertificate *stanCert; 1.1030 + PLArenaPool *arena; 1.1031 + NSSUsage nssUsage; 1.1032 + int i, len; 1.1033 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.1034 + NSSCryptoContext *cc = STAN_GetDefaultCryptoContext(); 1.1035 + 1.1036 + stanCert = STAN_GetNSSCertificate(cert); 1.1037 + if (!stanCert) { 1.1038 + /* error code is set */ 1.1039 + return NULL; 1.1040 + } 1.1041 + nssUsage.anyUsage = PR_FALSE; 1.1042 + nssUsage.nss3usage = usage; 1.1043 + nssUsage.nss3lookingForCA = PR_FALSE; 1.1044 + stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL, 1.1045 + CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc); 1.1046 + if (!stanChain) { 1.1047 + PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 1.1048 + return NULL; 1.1049 + } 1.1050 + 1.1051 + len = 0; 1.1052 + stanCert = stanChain[0]; 1.1053 + while (stanCert) { 1.1054 + stanCert = stanChain[++len]; 1.1055 + } 1.1056 + 1.1057 + arena = PORT_NewArena(4096); 1.1058 + if (arena == NULL) { 1.1059 + goto loser; 1.1060 + } 1.1061 + 1.1062 + chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, 1.1063 + sizeof(CERTCertificateList)); 1.1064 + if (!chain) goto loser; 1.1065 + chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem)); 1.1066 + if (!chain->certs) goto loser; 1.1067 + i = 0; 1.1068 + stanCert = stanChain[i]; 1.1069 + while (stanCert) { 1.1070 + SECItem derCert; 1.1071 + CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); 1.1072 + if (!cCert) { 1.1073 + goto loser; 1.1074 + } 1.1075 + derCert.len = (unsigned int)stanCert->encoding.size; 1.1076 + derCert.data = (unsigned char *)stanCert->encoding.data; 1.1077 + derCert.type = siBuffer; 1.1078 + SECITEM_CopyItem(arena, &chain->certs[i], &derCert); 1.1079 + stanCert = stanChain[++i]; 1.1080 + if (!stanCert && !cCert->isRoot) { 1.1081 + /* reached the end of the chain, but the final cert is 1.1082 + * not a root. Don't discard it. 1.1083 + */ 1.1084 + includeRoot = PR_TRUE; 1.1085 + } 1.1086 + CERT_DestroyCertificate(cCert); 1.1087 + } 1.1088 + if ( !includeRoot && len > 1) { 1.1089 + chain->len = len - 1; 1.1090 + } else { 1.1091 + chain->len = len; 1.1092 + } 1.1093 + 1.1094 + chain->arena = arena; 1.1095 + nss_ZFreeIf(stanChain); 1.1096 + return chain; 1.1097 +loser: 1.1098 + i = 0; 1.1099 + stanCert = stanChain[i]; 1.1100 + while (stanCert) { 1.1101 + CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); 1.1102 + if (cCert) { 1.1103 + CERT_DestroyCertificate(cCert); 1.1104 + } 1.1105 + stanCert = stanChain[++i]; 1.1106 + } 1.1107 + nss_ZFreeIf(stanChain); 1.1108 + if (arena) { 1.1109 + PORT_FreeArena(arena, PR_FALSE); 1.1110 + } 1.1111 + return NULL; 1.1112 +} 1.1113 + 1.1114 +/* Builds a CERTCertificateList holding just one DER-encoded cert, namely 1.1115 +** the one for the cert passed as an argument. 1.1116 +*/ 1.1117 +CERTCertificateList * 1.1118 +CERT_CertListFromCert(CERTCertificate *cert) 1.1119 +{ 1.1120 + CERTCertificateList *chain = NULL; 1.1121 + int rv; 1.1122 + PLArenaPool *arena; 1.1123 + 1.1124 + /* arena for SecCertificateList */ 1.1125 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1126 + if (arena == NULL) goto no_memory; 1.1127 + 1.1128 + /* build the CERTCertificateList */ 1.1129 + chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList)); 1.1130 + if (chain == NULL) goto no_memory; 1.1131 + chain->certs = (SECItem*)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem)); 1.1132 + if (chain->certs == NULL) goto no_memory; 1.1133 + rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert)); 1.1134 + if (rv < 0) goto loser; 1.1135 + chain->len = 1; 1.1136 + chain->arena = arena; 1.1137 + 1.1138 + return chain; 1.1139 + 1.1140 +no_memory: 1.1141 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1142 +loser: 1.1143 + if (arena != NULL) { 1.1144 + PORT_FreeArena(arena, PR_FALSE); 1.1145 + } 1.1146 + return NULL; 1.1147 +} 1.1148 + 1.1149 +CERTCertificateList * 1.1150 +CERT_DupCertList(const CERTCertificateList * oldList) 1.1151 +{ 1.1152 + CERTCertificateList *newList = NULL; 1.1153 + PLArenaPool *arena = NULL; 1.1154 + SECItem *newItem; 1.1155 + SECItem *oldItem; 1.1156 + int len = oldList->len; 1.1157 + int rv; 1.1158 + 1.1159 + /* arena for SecCertificateList */ 1.1160 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1161 + if (arena == NULL) 1.1162 + goto no_memory; 1.1163 + 1.1164 + /* now build the CERTCertificateList */ 1.1165 + newList = PORT_ArenaNew(arena, CERTCertificateList); 1.1166 + if (newList == NULL) 1.1167 + goto no_memory; 1.1168 + newList->arena = arena; 1.1169 + newItem = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem)); 1.1170 + if (newItem == NULL) 1.1171 + goto no_memory; 1.1172 + newList->certs = newItem; 1.1173 + newList->len = len; 1.1174 + 1.1175 + for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) { 1.1176 + rv = SECITEM_CopyItem(arena, newItem, oldItem); 1.1177 + if (rv < 0) 1.1178 + goto loser; 1.1179 + } 1.1180 + return newList; 1.1181 + 1.1182 +no_memory: 1.1183 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1184 +loser: 1.1185 + if (arena != NULL) { 1.1186 + PORT_FreeArena(arena, PR_FALSE); 1.1187 + } 1.1188 + return NULL; 1.1189 +} 1.1190 + 1.1191 +void 1.1192 +CERT_DestroyCertificateList(CERTCertificateList *list) 1.1193 +{ 1.1194 + PORT_FreeArena(list->arena, PR_FALSE); 1.1195 +} 1.1196 +