security/nss/lib/certhigh/certhigh.c

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

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

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

michael@0 1 /* 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 #include "nspr.h"
michael@0 5 #include "secerr.h"
michael@0 6 #include "secasn1.h"
michael@0 7 #include "seccomon.h"
michael@0 8 #include "pk11func.h"
michael@0 9 #include "certdb.h"
michael@0 10 #include "certt.h"
michael@0 11 #include "cert.h"
michael@0 12 #include "certxutl.h"
michael@0 13
michael@0 14 #include "nsspki.h"
michael@0 15 #include "pki.h"
michael@0 16 #include "pkit.h"
michael@0 17 #include "pkitm.h"
michael@0 18 #include "pki3hack.h"
michael@0 19
michael@0 20
michael@0 21 PRBool
michael@0 22 CERT_MatchNickname(char *name1, char *name2) {
michael@0 23 char *nickname1= NULL;
michael@0 24 char *nickname2 = NULL;
michael@0 25 char *token1;
michael@0 26 char *token2;
michael@0 27 char *token = NULL;
michael@0 28 int len;
michael@0 29
michael@0 30 /* first deal with the straight comparison */
michael@0 31 if (PORT_Strcmp(name1, name2) == 0) {
michael@0 32 return PR_TRUE;
michael@0 33 }
michael@0 34 /* we need to handle the case where one name has an explicit token and the other
michael@0 35 * doesn't */
michael@0 36 token1 = PORT_Strchr(name1,':');
michael@0 37 token2 = PORT_Strchr(name2,':');
michael@0 38 if ((token1 && token2) || (!token1 && !token2)) {
michael@0 39 /* either both token names are specified or neither are, not match */
michael@0 40 return PR_FALSE;
michael@0 41 }
michael@0 42 if (token1) {
michael@0 43 token=name1;
michael@0 44 nickname1=token1;
michael@0 45 nickname2=name2;
michael@0 46 } else {
michael@0 47 token=name2;
michael@0 48 nickname1=token2;
michael@0 49 nickname2=name1;
michael@0 50 }
michael@0 51 len = nickname1-token;
michael@0 52 nickname1++;
michael@0 53 if (PORT_Strcmp(nickname1,nickname2) != 0) {
michael@0 54 return PR_FALSE;
michael@0 55 }
michael@0 56 /* compare the other token with the internal slot here */
michael@0 57 return PR_TRUE;
michael@0 58 }
michael@0 59
michael@0 60 /*
michael@0 61 * Find all user certificates that match the given criteria.
michael@0 62 *
michael@0 63 * "handle" - database to search
michael@0 64 * "usage" - certificate usage to match
michael@0 65 * "oneCertPerName" - if set then only return the "best" cert per
michael@0 66 * name
michael@0 67 * "validOnly" - only return certs that are curently valid
michael@0 68 * "proto_win" - window handle passed to pkcs11
michael@0 69 */
michael@0 70 CERTCertList *
michael@0 71 CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
michael@0 72 SECCertUsage usage,
michael@0 73 PRBool oneCertPerName,
michael@0 74 PRBool validOnly,
michael@0 75 void *proto_win)
michael@0 76 {
michael@0 77 CERTCertNicknames *nicknames = NULL;
michael@0 78 char **nnptr;
michael@0 79 int nn;
michael@0 80 CERTCertificate *cert = NULL;
michael@0 81 CERTCertList *certList = NULL;
michael@0 82 SECStatus rv;
michael@0 83 PRTime time;
michael@0 84 CERTCertListNode *node = NULL;
michael@0 85 CERTCertListNode *freenode = NULL;
michael@0 86 int n;
michael@0 87
michael@0 88 time = PR_Now();
michael@0 89
michael@0 90 nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
michael@0 91 proto_win);
michael@0 92
michael@0 93 if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) {
michael@0 94 goto loser;
michael@0 95 }
michael@0 96
michael@0 97 nnptr = nicknames->nicknames;
michael@0 98 nn = nicknames->numnicknames;
michael@0 99
michael@0 100 while ( nn > 0 ) {
michael@0 101 cert = NULL;
michael@0 102 /* use the pk11 call so that we pick up any certs on tokens,
michael@0 103 * which may require login
michael@0 104 */
michael@0 105 if ( proto_win != NULL ) {
michael@0 106 cert = PK11_FindCertFromNickname(*nnptr,proto_win);
michael@0 107 }
michael@0 108
michael@0 109 /* Sigh, It turns out if the cert is already in the temp db, because
michael@0 110 * it's in the perm db, then the nickname lookup doesn't work.
michael@0 111 * since we already have the cert here, though, than we can just call
michael@0 112 * CERT_CreateSubjectCertList directly. For those cases where we didn't
michael@0 113 * find the cert in pkcs #11 (because we didn't have a password arg,
michael@0 114 * or because the nickname is for a peer, server, or CA cert, then we
michael@0 115 * go look the cert up.
michael@0 116 */
michael@0 117 if (cert == NULL) {
michael@0 118 cert = CERT_FindCertByNickname(handle,*nnptr);
michael@0 119 }
michael@0 120
michael@0 121 if ( cert != NULL ) {
michael@0 122 /* collect certs for this nickname, sorting them into the list */
michael@0 123 certList = CERT_CreateSubjectCertList(certList, handle,
michael@0 124 &cert->derSubject, time, validOnly);
michael@0 125
michael@0 126 CERT_FilterCertListForUserCerts(certList);
michael@0 127
michael@0 128 /* drop the extra reference */
michael@0 129 CERT_DestroyCertificate(cert);
michael@0 130 }
michael@0 131
michael@0 132 nnptr++;
michael@0 133 nn--;
michael@0 134 }
michael@0 135
michael@0 136 /* remove certs with incorrect usage */
michael@0 137 rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
michael@0 138
michael@0 139 if ( rv != SECSuccess ) {
michael@0 140 goto loser;
michael@0 141 }
michael@0 142
michael@0 143 /* remove any extra certs for each name */
michael@0 144 if ( oneCertPerName ) {
michael@0 145 PRBool *flags;
michael@0 146
michael@0 147 nn = nicknames->numnicknames;
michael@0 148 nnptr = nicknames->nicknames;
michael@0 149
michael@0 150 flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
michael@0 151 if ( flags == NULL ) {
michael@0 152 goto loser;
michael@0 153 }
michael@0 154
michael@0 155 node = CERT_LIST_HEAD(certList);
michael@0 156
michael@0 157 /* treverse all certs in the list */
michael@0 158 while ( !CERT_LIST_END(node, certList) ) {
michael@0 159
michael@0 160 /* find matching nickname index */
michael@0 161 for ( n = 0; n < nn; n++ ) {
michael@0 162 if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) {
michael@0 163 /* We found a match. If this is the first one, then
michael@0 164 * set the flag and move on to the next cert. If this
michael@0 165 * is not the first one then delete it from the list.
michael@0 166 */
michael@0 167 if ( flags[n] ) {
michael@0 168 /* We have already seen a cert with this nickname,
michael@0 169 * so delete this one.
michael@0 170 */
michael@0 171 freenode = node;
michael@0 172 node = CERT_LIST_NEXT(node);
michael@0 173 CERT_RemoveCertListNode(freenode);
michael@0 174 } else {
michael@0 175 /* keep the first cert for each nickname, but set the
michael@0 176 * flag so we know to delete any others with the same
michael@0 177 * nickname.
michael@0 178 */
michael@0 179 flags[n] = PR_TRUE;
michael@0 180 node = CERT_LIST_NEXT(node);
michael@0 181 }
michael@0 182 break;
michael@0 183 }
michael@0 184 }
michael@0 185 if ( n == nn ) {
michael@0 186 /* if we get here it means that we didn't find a matching
michael@0 187 * nickname, which should not happen.
michael@0 188 */
michael@0 189 PORT_Assert(0);
michael@0 190 node = CERT_LIST_NEXT(node);
michael@0 191 }
michael@0 192 }
michael@0 193 PORT_Free(flags);
michael@0 194 }
michael@0 195
michael@0 196 goto done;
michael@0 197
michael@0 198 loser:
michael@0 199 if ( certList != NULL ) {
michael@0 200 CERT_DestroyCertList(certList);
michael@0 201 certList = NULL;
michael@0 202 }
michael@0 203
michael@0 204 done:
michael@0 205 if ( nicknames != NULL ) {
michael@0 206 CERT_FreeNicknames(nicknames);
michael@0 207 }
michael@0 208
michael@0 209 return(certList);
michael@0 210 }
michael@0 211
michael@0 212 /*
michael@0 213 * Find a user certificate that matchs the given criteria.
michael@0 214 *
michael@0 215 * "handle" - database to search
michael@0 216 * "nickname" - nickname to match
michael@0 217 * "usage" - certificate usage to match
michael@0 218 * "validOnly" - only return certs that are curently valid
michael@0 219 * "proto_win" - window handle passed to pkcs11
michael@0 220 */
michael@0 221 CERTCertificate *
michael@0 222 CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
michael@0 223 const char *nickname,
michael@0 224 SECCertUsage usage,
michael@0 225 PRBool validOnly,
michael@0 226 void *proto_win)
michael@0 227 {
michael@0 228 CERTCertificate *cert = NULL;
michael@0 229 CERTCertList *certList = NULL;
michael@0 230 SECStatus rv;
michael@0 231 PRTime time;
michael@0 232
michael@0 233 time = PR_Now();
michael@0 234
michael@0 235 /* use the pk11 call so that we pick up any certs on tokens,
michael@0 236 * which may require login
michael@0 237 */
michael@0 238 /* XXX - why is this restricted? */
michael@0 239 if ( proto_win != NULL ) {
michael@0 240 cert = PK11_FindCertFromNickname(nickname,proto_win);
michael@0 241 }
michael@0 242
michael@0 243
michael@0 244 /* sigh, There are still problems find smart cards from the temp
michael@0 245 * db. This will get smart cards working again. The real fix
michael@0 246 * is to make sure we can search the temp db by their token nickname.
michael@0 247 */
michael@0 248 if (cert == NULL) {
michael@0 249 cert = CERT_FindCertByNickname(handle,nickname);
michael@0 250 }
michael@0 251
michael@0 252 if ( cert != NULL ) {
michael@0 253 unsigned int requiredKeyUsage;
michael@0 254 unsigned int requiredCertType;
michael@0 255
michael@0 256 rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
michael@0 257 &requiredKeyUsage, &requiredCertType);
michael@0 258 if ( rv != SECSuccess ) {
michael@0 259 /* drop the extra reference */
michael@0 260 CERT_DestroyCertificate(cert);
michael@0 261 cert = NULL;
michael@0 262 goto loser;
michael@0 263 }
michael@0 264 /* If we already found the right cert, just return it */
michael@0 265 if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE)
michael@0 266 == secCertTimeValid) &&
michael@0 267 (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
michael@0 268 (cert->nsCertType & requiredCertType) &&
michael@0 269 CERT_IsUserCert(cert) ) {
michael@0 270 return(cert);
michael@0 271 }
michael@0 272
michael@0 273 /* collect certs for this nickname, sorting them into the list */
michael@0 274 certList = CERT_CreateSubjectCertList(certList, handle,
michael@0 275 &cert->derSubject, time, validOnly);
michael@0 276
michael@0 277 CERT_FilterCertListForUserCerts(certList);
michael@0 278
michael@0 279 /* drop the extra reference */
michael@0 280 CERT_DestroyCertificate(cert);
michael@0 281 cert = NULL;
michael@0 282 }
michael@0 283
michael@0 284 if ( certList == NULL ) {
michael@0 285 goto loser;
michael@0 286 }
michael@0 287
michael@0 288 /* remove certs with incorrect usage */
michael@0 289 rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
michael@0 290
michael@0 291 if ( rv != SECSuccess ) {
michael@0 292 goto loser;
michael@0 293 }
michael@0 294
michael@0 295 if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) {
michael@0 296 cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
michael@0 297 }
michael@0 298
michael@0 299 loser:
michael@0 300 if ( certList != NULL ) {
michael@0 301 CERT_DestroyCertList(certList);
michael@0 302 }
michael@0 303
michael@0 304 return(cert);
michael@0 305 }
michael@0 306
michael@0 307 CERTCertList *
michael@0 308 CERT_MatchUserCert(CERTCertDBHandle *handle,
michael@0 309 SECCertUsage usage,
michael@0 310 int nCANames, char **caNames,
michael@0 311 void *proto_win)
michael@0 312 {
michael@0 313 CERTCertList *certList = NULL;
michael@0 314 SECStatus rv;
michael@0 315
michael@0 316 certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
michael@0 317 proto_win);
michael@0 318 if ( certList == NULL ) {
michael@0 319 goto loser;
michael@0 320 }
michael@0 321
michael@0 322 rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
michael@0 323 if ( rv != SECSuccess ) {
michael@0 324 goto loser;
michael@0 325 }
michael@0 326
michael@0 327 goto done;
michael@0 328
michael@0 329 loser:
michael@0 330 if ( certList != NULL ) {
michael@0 331 CERT_DestroyCertList(certList);
michael@0 332 certList = NULL;
michael@0 333 }
michael@0 334
michael@0 335 done:
michael@0 336
michael@0 337 return(certList);
michael@0 338 }
michael@0 339
michael@0 340
michael@0 341 typedef struct stringNode {
michael@0 342 struct stringNode *next;
michael@0 343 char *string;
michael@0 344 } stringNode;
michael@0 345
michael@0 346 static PRStatus
michael@0 347 CollectNicknames( NSSCertificate *c, void *data)
michael@0 348 {
michael@0 349 CERTCertNicknames *names;
michael@0 350 PRBool saveit = PR_FALSE;
michael@0 351 stringNode *node;
michael@0 352 int len;
michael@0 353 #ifdef notdef
michael@0 354 NSSTrustDomain *td;
michael@0 355 NSSTrust *trust;
michael@0 356 #endif
michael@0 357 char *stanNickname;
michael@0 358 char *nickname = NULL;
michael@0 359
michael@0 360 names = (CERTCertNicknames *)data;
michael@0 361
michael@0 362 stanNickname = nssCertificate_GetNickname(c,NULL);
michael@0 363
michael@0 364 if ( stanNickname ) {
michael@0 365 nss_ZFreeIf(stanNickname);
michael@0 366 stanNickname = NULL;
michael@0 367 if (names->what == SEC_CERT_NICKNAMES_USER) {
michael@0 368 saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
michael@0 369 }
michael@0 370 #ifdef notdef
michael@0 371 else {
michael@0 372 td = NSSCertificate_GetTrustDomain(c);
michael@0 373 if (!td) {
michael@0 374 return PR_SUCCESS;
michael@0 375 }
michael@0 376 trust = nssTrustDomain_FindTrustForCertificate(td,c);
michael@0 377
michael@0 378 switch(names->what) {
michael@0 379 case SEC_CERT_NICKNAMES_ALL:
michael@0 380 if ((trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
michael@0 381 (trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
michael@0 382 (trust->objectSigningFlags &
michael@0 383 (CERTDB_VALID_CA|CERTDB_VALID_PEER))) {
michael@0 384 saveit = PR_TRUE;
michael@0 385 }
michael@0 386
michael@0 387 break;
michael@0 388 case SEC_CERT_NICKNAMES_SERVER:
michael@0 389 if ( trust->sslFlags & CERTDB_VALID_PEER ) {
michael@0 390 saveit = PR_TRUE;
michael@0 391 }
michael@0 392
michael@0 393 break;
michael@0 394 case SEC_CERT_NICKNAMES_CA:
michael@0 395 if (((trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)||
michael@0 396 ((trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA) ||
michael@0 397 ((trust->objectSigningFlags & CERTDB_VALID_CA )
michael@0 398 == CERTDB_VALID_CA)) {
michael@0 399 saveit = PR_TRUE;
michael@0 400 }
michael@0 401 break;
michael@0 402 }
michael@0 403 }
michael@0 404 #endif
michael@0 405 }
michael@0 406
michael@0 407 /* traverse the list of collected nicknames and make sure we don't make
michael@0 408 * a duplicate
michael@0 409 */
michael@0 410 if ( saveit ) {
michael@0 411 nickname = STAN_GetCERTCertificateName(NULL, c);
michael@0 412 /* nickname can only be NULL here if we are having memory
michael@0 413 * alloc problems */
michael@0 414 if (nickname == NULL) {
michael@0 415 return PR_FAILURE;
michael@0 416 }
michael@0 417 node = (stringNode *)names->head;
michael@0 418 while ( node != NULL ) {
michael@0 419 if ( PORT_Strcmp(nickname, node->string) == 0 ) {
michael@0 420 /* if the string matches, then don't save this one */
michael@0 421 saveit = PR_FALSE;
michael@0 422 break;
michael@0 423 }
michael@0 424 node = node->next;
michael@0 425 }
michael@0 426 }
michael@0 427
michael@0 428 if ( saveit ) {
michael@0 429
michael@0 430 /* allocate the node */
michael@0 431 node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
michael@0 432 if ( node == NULL ) {
michael@0 433 PORT_Free(nickname);
michael@0 434 return PR_FAILURE;
michael@0 435 }
michael@0 436
michael@0 437 /* copy the string */
michael@0 438 len = PORT_Strlen(nickname) + 1;
michael@0 439 node->string = (char*)PORT_ArenaAlloc(names->arena, len);
michael@0 440 if ( node->string == NULL ) {
michael@0 441 PORT_Free(nickname);
michael@0 442 return PR_FAILURE;
michael@0 443 }
michael@0 444 PORT_Memcpy(node->string, nickname, len);
michael@0 445
michael@0 446 /* link it into the list */
michael@0 447 node->next = (stringNode *)names->head;
michael@0 448 names->head = (void *)node;
michael@0 449
michael@0 450 /* bump the count */
michael@0 451 names->numnicknames++;
michael@0 452 }
michael@0 453
michael@0 454 if (nickname) PORT_Free(nickname);
michael@0 455 return(PR_SUCCESS);
michael@0 456 }
michael@0 457
michael@0 458 CERTCertNicknames *
michael@0 459 CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
michael@0 460 {
michael@0 461 PLArenaPool *arena;
michael@0 462 CERTCertNicknames *names;
michael@0 463 int i;
michael@0 464 stringNode *node;
michael@0 465
michael@0 466 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 467 if ( arena == NULL ) {
michael@0 468 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 469 return(NULL);
michael@0 470 }
michael@0 471
michael@0 472 names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
michael@0 473 if ( names == NULL ) {
michael@0 474 goto loser;
michael@0 475 }
michael@0 476
michael@0 477 names->arena = arena;
michael@0 478 names->head = NULL;
michael@0 479 names->numnicknames = 0;
michael@0 480 names->nicknames = NULL;
michael@0 481 names->what = what;
michael@0 482 names->totallen = 0;
michael@0 483
michael@0 484 /* make sure we are logged in */
michael@0 485 (void) pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx);
michael@0 486
michael@0 487 NSSTrustDomain_TraverseCertificates(handle,
michael@0 488 CollectNicknames, (void *)names);
michael@0 489 if ( names->numnicknames ) {
michael@0 490 names->nicknames = (char**)PORT_ArenaAlloc(arena,
michael@0 491 names->numnicknames * sizeof(char *));
michael@0 492
michael@0 493 if ( names->nicknames == NULL ) {
michael@0 494 goto loser;
michael@0 495 }
michael@0 496
michael@0 497 node = (stringNode *)names->head;
michael@0 498
michael@0 499 for ( i = 0; i < names->numnicknames; i++ ) {
michael@0 500 PORT_Assert(node != NULL);
michael@0 501
michael@0 502 names->nicknames[i] = node->string;
michael@0 503 names->totallen += PORT_Strlen(node->string);
michael@0 504 node = node->next;
michael@0 505 }
michael@0 506
michael@0 507 PORT_Assert(node == NULL);
michael@0 508 }
michael@0 509
michael@0 510 return(names);
michael@0 511
michael@0 512 loser:
michael@0 513 PORT_FreeArena(arena, PR_FALSE);
michael@0 514 return(NULL);
michael@0 515 }
michael@0 516
michael@0 517 void
michael@0 518 CERT_FreeNicknames(CERTCertNicknames *nicknames)
michael@0 519 {
michael@0 520 PORT_FreeArena(nicknames->arena, PR_FALSE);
michael@0 521
michael@0 522 return;
michael@0 523 }
michael@0 524
michael@0 525 /* [ FROM pcertdb.c ] */
michael@0 526
michael@0 527 typedef struct dnameNode {
michael@0 528 struct dnameNode *next;
michael@0 529 SECItem name;
michael@0 530 } dnameNode;
michael@0 531
michael@0 532 void
michael@0 533 CERT_FreeDistNames(CERTDistNames *names)
michael@0 534 {
michael@0 535 PORT_FreeArena(names->arena, PR_FALSE);
michael@0 536
michael@0 537 return;
michael@0 538 }
michael@0 539
michael@0 540 static SECStatus
michael@0 541 CollectDistNames( CERTCertificate *cert, SECItem *k, void *data)
michael@0 542 {
michael@0 543 CERTDistNames *names;
michael@0 544 PRBool saveit = PR_FALSE;
michael@0 545 CERTCertTrust trust;
michael@0 546 dnameNode *node;
michael@0 547 int len;
michael@0 548
michael@0 549 names = (CERTDistNames *)data;
michael@0 550
michael@0 551 if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) {
michael@0 552 /* only collect names of CAs trusted for issuing SSL clients */
michael@0 553 if ( trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA ) {
michael@0 554 saveit = PR_TRUE;
michael@0 555 }
michael@0 556 }
michael@0 557
michael@0 558 if ( saveit ) {
michael@0 559 /* allocate the node */
michael@0 560 node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
michael@0 561 if ( node == NULL ) {
michael@0 562 return(SECFailure);
michael@0 563 }
michael@0 564
michael@0 565 /* copy the name */
michael@0 566 node->name.len = len = cert->derSubject.len;
michael@0 567 node->name.type = siBuffer;
michael@0 568 node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len);
michael@0 569 if ( node->name.data == NULL ) {
michael@0 570 return(SECFailure);
michael@0 571 }
michael@0 572 PORT_Memcpy(node->name.data, cert->derSubject.data, len);
michael@0 573
michael@0 574 /* link it into the list */
michael@0 575 node->next = (dnameNode *)names->head;
michael@0 576 names->head = (void *)node;
michael@0 577
michael@0 578 /* bump the count */
michael@0 579 names->nnames++;
michael@0 580 }
michael@0 581
michael@0 582 return(SECSuccess);
michael@0 583 }
michael@0 584
michael@0 585 /*
michael@0 586 * Return all of the CAs that are "trusted" for SSL.
michael@0 587 */
michael@0 588 CERTDistNames *
michael@0 589 CERT_DupDistNames(CERTDistNames *orig)
michael@0 590 {
michael@0 591 PLArenaPool *arena;
michael@0 592 CERTDistNames *names;
michael@0 593 int i;
michael@0 594 SECStatus rv;
michael@0 595
michael@0 596 /* allocate an arena to use */
michael@0 597 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 598 if (arena == NULL) {
michael@0 599 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 600 return(NULL);
michael@0 601 }
michael@0 602
michael@0 603 /* allocate the header structure */
michael@0 604 names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
michael@0 605 if (names == NULL) {
michael@0 606 goto loser;
michael@0 607 }
michael@0 608
michael@0 609 /* initialize the header struct */
michael@0 610 names->arena = arena;
michael@0 611 names->head = NULL;
michael@0 612 names->nnames = orig->nnames;
michael@0 613 names->names = NULL;
michael@0 614
michael@0 615 /* construct the array from the list */
michael@0 616 if (orig->nnames) {
michael@0 617 names->names = (SECItem*)PORT_ArenaNewArray(arena, SECItem,
michael@0 618 orig->nnames);
michael@0 619 if (names->names == NULL) {
michael@0 620 goto loser;
michael@0 621 }
michael@0 622 for (i = 0; i < orig->nnames; i++) {
michael@0 623 rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]);
michael@0 624 if (rv != SECSuccess) {
michael@0 625 goto loser;
michael@0 626 }
michael@0 627 }
michael@0 628 }
michael@0 629 return(names);
michael@0 630
michael@0 631 loser:
michael@0 632 PORT_FreeArena(arena, PR_FALSE);
michael@0 633 return(NULL);
michael@0 634 }
michael@0 635
michael@0 636 CERTDistNames *
michael@0 637 CERT_GetSSLCACerts(CERTCertDBHandle *handle)
michael@0 638 {
michael@0 639 PLArenaPool *arena;
michael@0 640 CERTDistNames *names;
michael@0 641 int i;
michael@0 642 SECStatus rv;
michael@0 643 dnameNode *node;
michael@0 644
michael@0 645 /* allocate an arena to use */
michael@0 646 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 647 if ( arena == NULL ) {
michael@0 648 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 649 return(NULL);
michael@0 650 }
michael@0 651
michael@0 652 /* allocate the header structure */
michael@0 653 names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
michael@0 654 if ( names == NULL ) {
michael@0 655 goto loser;
michael@0 656 }
michael@0 657
michael@0 658 /* initialize the header struct */
michael@0 659 names->arena = arena;
michael@0 660 names->head = NULL;
michael@0 661 names->nnames = 0;
michael@0 662 names->names = NULL;
michael@0 663
michael@0 664 /* collect the names from the database */
michael@0 665 rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
michael@0 666 if ( rv ) {
michael@0 667 goto loser;
michael@0 668 }
michael@0 669
michael@0 670 /* construct the array from the list */
michael@0 671 if ( names->nnames ) {
michael@0 672 names->names = (SECItem*)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
michael@0 673
michael@0 674 if ( names->names == NULL ) {
michael@0 675 goto loser;
michael@0 676 }
michael@0 677
michael@0 678 node = (dnameNode *)names->head;
michael@0 679
michael@0 680 for ( i = 0; i < names->nnames; i++ ) {
michael@0 681 PORT_Assert(node != NULL);
michael@0 682
michael@0 683 names->names[i] = node->name;
michael@0 684 node = node->next;
michael@0 685 }
michael@0 686
michael@0 687 PORT_Assert(node == NULL);
michael@0 688 }
michael@0 689
michael@0 690 return(names);
michael@0 691
michael@0 692 loser:
michael@0 693 PORT_FreeArena(arena, PR_FALSE);
michael@0 694 return(NULL);
michael@0 695 }
michael@0 696
michael@0 697 CERTDistNames *
michael@0 698 CERT_DistNamesFromCertList(CERTCertList *certList)
michael@0 699 {
michael@0 700 CERTDistNames * dnames = NULL;
michael@0 701 PLArenaPool * arena;
michael@0 702 CERTCertListNode *node = NULL;
michael@0 703 SECItem * names = NULL;
michael@0 704 int listLen = 0, i = 0;
michael@0 705
michael@0 706 if (certList == NULL) {
michael@0 707 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 708 return NULL;
michael@0 709 }
michael@0 710
michael@0 711 node = CERT_LIST_HEAD(certList);
michael@0 712 while ( ! CERT_LIST_END(node, certList) ) {
michael@0 713 listLen += 1;
michael@0 714 node = CERT_LIST_NEXT(node);
michael@0 715 }
michael@0 716
michael@0 717 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 718 if (arena == NULL) goto loser;
michael@0 719 dnames = PORT_ArenaZNew(arena, CERTDistNames);
michael@0 720 if (dnames == NULL) goto loser;
michael@0 721
michael@0 722 dnames->arena = arena;
michael@0 723 dnames->nnames = listLen;
michael@0 724 dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen);
michael@0 725 if (names == NULL) goto loser;
michael@0 726
michael@0 727 node = CERT_LIST_HEAD(certList);
michael@0 728 while ( ! CERT_LIST_END(node, certList) ) {
michael@0 729 CERTCertificate *cert = node->cert;
michael@0 730 SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject);
michael@0 731 if (rv == SECFailure) {
michael@0 732 goto loser;
michael@0 733 }
michael@0 734 node = CERT_LIST_NEXT(node);
michael@0 735 }
michael@0 736 return dnames;
michael@0 737 loser:
michael@0 738 if (arena) {
michael@0 739 PORT_FreeArena(arena, PR_FALSE);
michael@0 740 }
michael@0 741 return NULL;
michael@0 742 }
michael@0 743
michael@0 744 CERTDistNames *
michael@0 745 CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
michael@0 746 int nnames)
michael@0 747 {
michael@0 748 CERTDistNames *dnames = NULL;
michael@0 749 PLArenaPool *arena;
michael@0 750 int i, rv;
michael@0 751 SECItem *names = NULL;
michael@0 752 CERTCertificate *cert = NULL;
michael@0 753
michael@0 754 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 755 if (arena == NULL) goto loser;
michael@0 756 dnames = PORT_ArenaZNew(arena, CERTDistNames);
michael@0 757 if (dnames == NULL) goto loser;
michael@0 758
michael@0 759 dnames->arena = arena;
michael@0 760 dnames->nnames = nnames;
michael@0 761 dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames);
michael@0 762 if (names == NULL) goto loser;
michael@0 763
michael@0 764 for (i = 0; i < nnames; i++) {
michael@0 765 cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
michael@0 766 if (cert == NULL) goto loser;
michael@0 767 rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
michael@0 768 if (rv == SECFailure) goto loser;
michael@0 769 CERT_DestroyCertificate(cert);
michael@0 770 }
michael@0 771 return dnames;
michael@0 772
michael@0 773 loser:
michael@0 774 if (cert != NULL)
michael@0 775 CERT_DestroyCertificate(cert);
michael@0 776 if (arena != NULL)
michael@0 777 PORT_FreeArena(arena, PR_FALSE);
michael@0 778 return NULL;
michael@0 779 }
michael@0 780
michael@0 781 /* [ from pcertdb.c - calls Ascii to Name ] */
michael@0 782 /*
michael@0 783 * Lookup a certificate in the database by name
michael@0 784 */
michael@0 785 CERTCertificate *
michael@0 786 CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
michael@0 787 {
michael@0 788 CERTName *name;
michael@0 789 SECItem *nameItem;
michael@0 790 CERTCertificate *cert = NULL;
michael@0 791 PLArenaPool *arena = NULL;
michael@0 792
michael@0 793 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 794
michael@0 795 if ( arena == NULL ) {
michael@0 796 goto loser;
michael@0 797 }
michael@0 798
michael@0 799 name = CERT_AsciiToName(nameStr);
michael@0 800
michael@0 801 if ( name ) {
michael@0 802 nameItem = SEC_ASN1EncodeItem (arena, NULL, (void *)name,
michael@0 803 CERT_NameTemplate);
michael@0 804 if ( nameItem != NULL ) {
michael@0 805 cert = CERT_FindCertByName(handle, nameItem);
michael@0 806 }
michael@0 807 CERT_DestroyName(name);
michael@0 808 }
michael@0 809
michael@0 810 loser:
michael@0 811 if ( arena ) {
michael@0 812 PORT_FreeArena(arena, PR_FALSE);
michael@0 813 }
michael@0 814
michael@0 815 return(cert);
michael@0 816 }
michael@0 817
michael@0 818 /* From certv3.c */
michael@0 819
michael@0 820 CERTCrlDistributionPoints *
michael@0 821 CERT_FindCRLDistributionPoints (CERTCertificate *cert)
michael@0 822 {
michael@0 823 SECItem encodedExtenValue;
michael@0 824 SECStatus rv;
michael@0 825 CERTCrlDistributionPoints *dps;
michael@0 826
michael@0 827 encodedExtenValue.data = NULL;
michael@0 828 encodedExtenValue.len = 0;
michael@0 829
michael@0 830 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
michael@0 831 &encodedExtenValue);
michael@0 832 if ( rv != SECSuccess ) {
michael@0 833 return (NULL);
michael@0 834 }
michael@0 835
michael@0 836 dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue);
michael@0 837
michael@0 838 PORT_Free(encodedExtenValue.data);
michael@0 839
michael@0 840 return dps;
michael@0 841 }
michael@0 842
michael@0 843 /* From crl.c */
michael@0 844 CERTSignedCrl * CERT_ImportCRL
michael@0 845 (CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
michael@0 846 {
michael@0 847 CERTSignedCrl* retCrl = NULL;
michael@0 848 PK11SlotInfo* slot = PK11_GetInternalKeySlot();
michael@0 849 retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
michael@0 850 CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
michael@0 851 PK11_FreeSlot(slot);
michael@0 852
michael@0 853 return retCrl;
michael@0 854 }
michael@0 855
michael@0 856 /* From certdb.c */
michael@0 857 static SECStatus
michael@0 858 cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
michael@0 859 {
michael@0 860 SECStatus rv;
michael@0 861 SECItem *derCert;
michael@0 862 CERTCertificate *cert = NULL;
michael@0 863 CERTCertificate *newcert = NULL;
michael@0 864 CERTCertDBHandle *handle;
michael@0 865 CERTCertTrust trust;
michael@0 866 PRBool isca;
michael@0 867 char *nickname;
michael@0 868 unsigned int certtype;
michael@0 869
michael@0 870 handle = CERT_GetDefaultCertDB();
michael@0 871
michael@0 872 while (numcerts--) {
michael@0 873 derCert = certs;
michael@0 874 certs++;
michael@0 875
michael@0 876 /* decode my certificate */
michael@0 877 /* This use is ok -- only looks at decoded parts, calls NewTemp later */
michael@0 878 newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
michael@0 879 if ( newcert == NULL ) {
michael@0 880 goto loser;
michael@0 881 }
michael@0 882
michael@0 883 if (!trusted) {
michael@0 884 /* make sure that cert is valid */
michael@0 885 rv = CERT_CertTimesValid(newcert);
michael@0 886 if ( rv == SECFailure ) {
michael@0 887 goto endloop;
michael@0 888 }
michael@0 889 }
michael@0 890
michael@0 891 /* does it have the CA extension */
michael@0 892
michael@0 893 /*
michael@0 894 * Make sure that if this is an intermediate CA in the chain that
michael@0 895 * it was given permission by its signer to be a CA.
michael@0 896 */
michael@0 897 isca = CERT_IsCACert(newcert, &certtype);
michael@0 898
michael@0 899 if ( !isca ) {
michael@0 900 if (!trusted) {
michael@0 901 goto endloop;
michael@0 902 }
michael@0 903 trust.sslFlags = CERTDB_VALID_CA;
michael@0 904 trust.emailFlags = CERTDB_VALID_CA;
michael@0 905 trust.objectSigningFlags = CERTDB_VALID_CA;
michael@0 906 } else {
michael@0 907 /* SSL ca's must have the ssl bit set */
michael@0 908 if ( ( certUsage == certUsageSSLCA ) &&
michael@0 909 (( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA )) {
michael@0 910 goto endloop;
michael@0 911 }
michael@0 912
michael@0 913 /* it passed all of the tests, so lets add it to the database */
michael@0 914 /* mark it as a CA */
michael@0 915 PORT_Memset((void *)&trust, 0, sizeof(trust));
michael@0 916 switch ( certUsage ) {
michael@0 917 case certUsageSSLCA:
michael@0 918 trust.sslFlags = CERTDB_VALID_CA;
michael@0 919 break;
michael@0 920 case certUsageUserCertImport:
michael@0 921 if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
michael@0 922 trust.sslFlags = CERTDB_VALID_CA;
michael@0 923 }
michael@0 924 if ((certtype & NS_CERT_TYPE_EMAIL_CA)
michael@0 925 == NS_CERT_TYPE_EMAIL_CA ) {
michael@0 926 trust.emailFlags = CERTDB_VALID_CA;
michael@0 927 }
michael@0 928 if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) ==
michael@0 929 NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
michael@0 930 trust.objectSigningFlags = CERTDB_VALID_CA;
michael@0 931 }
michael@0 932 break;
michael@0 933 default:
michael@0 934 PORT_Assert(0);
michael@0 935 break;
michael@0 936 }
michael@0 937 }
michael@0 938
michael@0 939 cert = CERT_NewTempCertificate(handle, derCert, NULL,
michael@0 940 PR_FALSE, PR_FALSE);
michael@0 941 if ( cert == NULL ) {
michael@0 942 goto loser;
michael@0 943 }
michael@0 944
michael@0 945 /* if the cert is temp, make it perm; otherwise we're done */
michael@0 946 if (cert->istemp) {
michael@0 947 /* get a default nickname for it */
michael@0 948 nickname = CERT_MakeCANickname(cert);
michael@0 949
michael@0 950 rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
michael@0 951
michael@0 952 /* free the nickname */
michael@0 953 if ( nickname ) {
michael@0 954 PORT_Free(nickname);
michael@0 955 }
michael@0 956 } else {
michael@0 957 rv = SECSuccess;
michael@0 958 }
michael@0 959
michael@0 960 CERT_DestroyCertificate(cert);
michael@0 961 cert = NULL;
michael@0 962
michael@0 963 if ( rv != SECSuccess ) {
michael@0 964 goto loser;
michael@0 965 }
michael@0 966
michael@0 967 endloop:
michael@0 968 if ( newcert ) {
michael@0 969 CERT_DestroyCertificate(newcert);
michael@0 970 newcert = NULL;
michael@0 971 }
michael@0 972
michael@0 973 }
michael@0 974
michael@0 975 rv = SECSuccess;
michael@0 976 goto done;
michael@0 977 loser:
michael@0 978 rv = SECFailure;
michael@0 979 done:
michael@0 980
michael@0 981 if ( newcert ) {
michael@0 982 CERT_DestroyCertificate(newcert);
michael@0 983 newcert = NULL;
michael@0 984 }
michael@0 985
michael@0 986 if ( cert ) {
michael@0 987 CERT_DestroyCertificate(cert);
michael@0 988 cert = NULL;
michael@0 989 }
michael@0 990
michael@0 991 return(rv);
michael@0 992 }
michael@0 993
michael@0 994 SECStatus
michael@0 995 CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
michael@0 996 {
michael@0 997 return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
michael@0 998 }
michael@0 999
michael@0 1000 SECStatus
michael@0 1001 CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage) {
michael@0 1002 return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
michael@0 1003 }
michael@0 1004
michael@0 1005 /* Moved from certdb.c */
michael@0 1006 /*
michael@0 1007 ** CERT_CertChainFromCert
michael@0 1008 **
michael@0 1009 ** Construct a CERTCertificateList consisting of the given certificate and all
michael@0 1010 ** of the issuer certs until we either get to a self-signed cert or can't find
michael@0 1011 ** an issuer. Since we don't know how many certs are in the chain we have to
michael@0 1012 ** build a linked list first as we count them.
michael@0 1013 */
michael@0 1014
michael@0 1015 typedef struct certNode {
michael@0 1016 struct certNode *next;
michael@0 1017 CERTCertificate *cert;
michael@0 1018 } certNode;
michael@0 1019
michael@0 1020 CERTCertificateList *
michael@0 1021 CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
michael@0 1022 PRBool includeRoot)
michael@0 1023 {
michael@0 1024 CERTCertificateList *chain = NULL;
michael@0 1025 NSSCertificate **stanChain;
michael@0 1026 NSSCertificate *stanCert;
michael@0 1027 PLArenaPool *arena;
michael@0 1028 NSSUsage nssUsage;
michael@0 1029 int i, len;
michael@0 1030 NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
michael@0 1031 NSSCryptoContext *cc = STAN_GetDefaultCryptoContext();
michael@0 1032
michael@0 1033 stanCert = STAN_GetNSSCertificate(cert);
michael@0 1034 if (!stanCert) {
michael@0 1035 /* error code is set */
michael@0 1036 return NULL;
michael@0 1037 }
michael@0 1038 nssUsage.anyUsage = PR_FALSE;
michael@0 1039 nssUsage.nss3usage = usage;
michael@0 1040 nssUsage.nss3lookingForCA = PR_FALSE;
michael@0 1041 stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL,
michael@0 1042 CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc);
michael@0 1043 if (!stanChain) {
michael@0 1044 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
michael@0 1045 return NULL;
michael@0 1046 }
michael@0 1047
michael@0 1048 len = 0;
michael@0 1049 stanCert = stanChain[0];
michael@0 1050 while (stanCert) {
michael@0 1051 stanCert = stanChain[++len];
michael@0 1052 }
michael@0 1053
michael@0 1054 arena = PORT_NewArena(4096);
michael@0 1055 if (arena == NULL) {
michael@0 1056 goto loser;
michael@0 1057 }
michael@0 1058
michael@0 1059 chain = (CERTCertificateList *)PORT_ArenaAlloc(arena,
michael@0 1060 sizeof(CERTCertificateList));
michael@0 1061 if (!chain) goto loser;
michael@0 1062 chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
michael@0 1063 if (!chain->certs) goto loser;
michael@0 1064 i = 0;
michael@0 1065 stanCert = stanChain[i];
michael@0 1066 while (stanCert) {
michael@0 1067 SECItem derCert;
michael@0 1068 CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
michael@0 1069 if (!cCert) {
michael@0 1070 goto loser;
michael@0 1071 }
michael@0 1072 derCert.len = (unsigned int)stanCert->encoding.size;
michael@0 1073 derCert.data = (unsigned char *)stanCert->encoding.data;
michael@0 1074 derCert.type = siBuffer;
michael@0 1075 SECITEM_CopyItem(arena, &chain->certs[i], &derCert);
michael@0 1076 stanCert = stanChain[++i];
michael@0 1077 if (!stanCert && !cCert->isRoot) {
michael@0 1078 /* reached the end of the chain, but the final cert is
michael@0 1079 * not a root. Don't discard it.
michael@0 1080 */
michael@0 1081 includeRoot = PR_TRUE;
michael@0 1082 }
michael@0 1083 CERT_DestroyCertificate(cCert);
michael@0 1084 }
michael@0 1085 if ( !includeRoot && len > 1) {
michael@0 1086 chain->len = len - 1;
michael@0 1087 } else {
michael@0 1088 chain->len = len;
michael@0 1089 }
michael@0 1090
michael@0 1091 chain->arena = arena;
michael@0 1092 nss_ZFreeIf(stanChain);
michael@0 1093 return chain;
michael@0 1094 loser:
michael@0 1095 i = 0;
michael@0 1096 stanCert = stanChain[i];
michael@0 1097 while (stanCert) {
michael@0 1098 CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
michael@0 1099 if (cCert) {
michael@0 1100 CERT_DestroyCertificate(cCert);
michael@0 1101 }
michael@0 1102 stanCert = stanChain[++i];
michael@0 1103 }
michael@0 1104 nss_ZFreeIf(stanChain);
michael@0 1105 if (arena) {
michael@0 1106 PORT_FreeArena(arena, PR_FALSE);
michael@0 1107 }
michael@0 1108 return NULL;
michael@0 1109 }
michael@0 1110
michael@0 1111 /* Builds a CERTCertificateList holding just one DER-encoded cert, namely
michael@0 1112 ** the one for the cert passed as an argument.
michael@0 1113 */
michael@0 1114 CERTCertificateList *
michael@0 1115 CERT_CertListFromCert(CERTCertificate *cert)
michael@0 1116 {
michael@0 1117 CERTCertificateList *chain = NULL;
michael@0 1118 int rv;
michael@0 1119 PLArenaPool *arena;
michael@0 1120
michael@0 1121 /* arena for SecCertificateList */
michael@0 1122 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 1123 if (arena == NULL) goto no_memory;
michael@0 1124
michael@0 1125 /* build the CERTCertificateList */
michael@0 1126 chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
michael@0 1127 if (chain == NULL) goto no_memory;
michael@0 1128 chain->certs = (SECItem*)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
michael@0 1129 if (chain->certs == NULL) goto no_memory;
michael@0 1130 rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
michael@0 1131 if (rv < 0) goto loser;
michael@0 1132 chain->len = 1;
michael@0 1133 chain->arena = arena;
michael@0 1134
michael@0 1135 return chain;
michael@0 1136
michael@0 1137 no_memory:
michael@0 1138 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 1139 loser:
michael@0 1140 if (arena != NULL) {
michael@0 1141 PORT_FreeArena(arena, PR_FALSE);
michael@0 1142 }
michael@0 1143 return NULL;
michael@0 1144 }
michael@0 1145
michael@0 1146 CERTCertificateList *
michael@0 1147 CERT_DupCertList(const CERTCertificateList * oldList)
michael@0 1148 {
michael@0 1149 CERTCertificateList *newList = NULL;
michael@0 1150 PLArenaPool *arena = NULL;
michael@0 1151 SECItem *newItem;
michael@0 1152 SECItem *oldItem;
michael@0 1153 int len = oldList->len;
michael@0 1154 int rv;
michael@0 1155
michael@0 1156 /* arena for SecCertificateList */
michael@0 1157 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 1158 if (arena == NULL)
michael@0 1159 goto no_memory;
michael@0 1160
michael@0 1161 /* now build the CERTCertificateList */
michael@0 1162 newList = PORT_ArenaNew(arena, CERTCertificateList);
michael@0 1163 if (newList == NULL)
michael@0 1164 goto no_memory;
michael@0 1165 newList->arena = arena;
michael@0 1166 newItem = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
michael@0 1167 if (newItem == NULL)
michael@0 1168 goto no_memory;
michael@0 1169 newList->certs = newItem;
michael@0 1170 newList->len = len;
michael@0 1171
michael@0 1172 for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
michael@0 1173 rv = SECITEM_CopyItem(arena, newItem, oldItem);
michael@0 1174 if (rv < 0)
michael@0 1175 goto loser;
michael@0 1176 }
michael@0 1177 return newList;
michael@0 1178
michael@0 1179 no_memory:
michael@0 1180 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 1181 loser:
michael@0 1182 if (arena != NULL) {
michael@0 1183 PORT_FreeArena(arena, PR_FALSE);
michael@0 1184 }
michael@0 1185 return NULL;
michael@0 1186 }
michael@0 1187
michael@0 1188 void
michael@0 1189 CERT_DestroyCertificateList(CERTCertificateList *list)
michael@0 1190 {
michael@0 1191 PORT_FreeArena(list->arena, PR_FALSE);
michael@0 1192 }
michael@0 1193

mercurial