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