| 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  |  | 
|     5 /* |  | 
|     6  * Hacks to integrate NSS 3.4 and NSS 4.0 certificates. |  | 
|     7  */ |  | 
|     8  |  | 
|     9 #ifndef NSSPKI_H |  | 
|    10 #include "nsspki.h" |  | 
|    11 #endif /* NSSPKI_H */ |  | 
|    12  |  | 
|    13 #ifndef PKI_H |  | 
|    14 #include "pki.h" |  | 
|    15 #endif /* PKI_H */ |  | 
|    16  |  | 
|    17 #ifndef PKIM_H |  | 
|    18 #include "pkim.h" |  | 
|    19 #endif /* PKIM_H */ |  | 
|    20  |  | 
|    21 #ifndef DEV_H |  | 
|    22 #include "dev.h" |  | 
|    23 #endif /* DEV_H */ |  | 
|    24  |  | 
|    25 #ifndef DEVNSS3HACK_H |  | 
|    26 #include "dev3hack.h" |  | 
|    27 #endif /* DEVNSS3HACK_H */ |  | 
|    28  |  | 
|    29 #ifndef PKINSS3HACK_H |  | 
|    30 #include "pki3hack.h" |  | 
|    31 #endif /* PKINSS3HACK_H */ |  | 
|    32  |  | 
|    33 #include "secitem.h" |  | 
|    34 #include "certdb.h" |  | 
|    35 #include "certt.h" |  | 
|    36 #include "cert.h" |  | 
|    37 #include "certi.h" |  | 
|    38 #include "pk11func.h" |  | 
|    39 #include "pkistore.h" |  | 
|    40 #include "secmod.h" |  | 
|    41 #include "nssrwlk.h" |  | 
|    42  |  | 
|    43 NSSTrustDomain *g_default_trust_domain = NULL; |  | 
|    44  |  | 
|    45 NSSCryptoContext *g_default_crypto_context = NULL; |  | 
|    46  |  | 
|    47 NSSTrustDomain * |  | 
|    48 STAN_GetDefaultTrustDomain() |  | 
|    49 { |  | 
|    50     return g_default_trust_domain; |  | 
|    51 } |  | 
|    52  |  | 
|    53 NSSCryptoContext * |  | 
|    54 STAN_GetDefaultCryptoContext() |  | 
|    55 { |  | 
|    56     return g_default_crypto_context; |  | 
|    57 } |  | 
|    58  |  | 
|    59 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; |  | 
|    60 extern const NSSError NSS_ERROR_INTERNAL_ERROR; |  | 
|    61  |  | 
|    62 NSS_IMPLEMENT PRStatus |  | 
|    63 STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot) |  | 
|    64 { |  | 
|    65     NSSToken *token; |  | 
|    66     if (!td) { |  | 
|    67         td = g_default_trust_domain; |  | 
|    68         if (!td) { |  | 
|    69             /* we're called while still initting. slot will get added |  | 
|    70              * appropriately through normal init processes */ |  | 
|    71             return PR_SUCCESS; |  | 
|    72         } |  | 
|    73     } |  | 
|    74     token = nssToken_CreateFromPK11SlotInfo(td, slot); |  | 
|    75     PK11Slot_SetNSSToken(slot, token); |  | 
|    76     /* Don't add nonexistent token to TD's token list */ |  | 
|    77     if (token) { |  | 
|    78         NSSRWLock_LockWrite(td->tokensLock); |  | 
|    79         nssList_Add(td->tokenList, token); |  | 
|    80         NSSRWLock_UnlockWrite(td->tokensLock); |  | 
|    81     } |  | 
|    82     return PR_SUCCESS; |  | 
|    83 } |  | 
|    84  |  | 
|    85 NSS_IMPLEMENT PRStatus |  | 
|    86 STAN_ResetTokenInterator(NSSTrustDomain *td) |  | 
|    87 { |  | 
|    88     if (!td) { |  | 
|    89         td = g_default_trust_domain; |  | 
|    90         if (!td) { |  | 
|    91             /* we're called while still initting. slot will get added |  | 
|    92              * appropriately through normal init processes */ |  | 
|    93             return PR_SUCCESS; |  | 
|    94         } |  | 
|    95     } |  | 
|    96     NSSRWLock_LockWrite(td->tokensLock); |  | 
|    97     nssListIterator_Destroy(td->tokens); |  | 
|    98     td->tokens = nssList_CreateIterator(td->tokenList); |  | 
|    99     NSSRWLock_UnlockWrite(td->tokensLock); |  | 
|   100     return PR_SUCCESS; |  | 
|   101 } |  | 
|   102  |  | 
|   103 NSS_IMPLEMENT PRStatus |  | 
|   104 STAN_LoadDefaultNSS3TrustDomain ( |  | 
|   105   void |  | 
|   106 ) |  | 
|   107 { |  | 
|   108     NSSTrustDomain *td; |  | 
|   109     SECMODModuleList *mlp; |  | 
|   110     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); |  | 
|   111     int i; |  | 
|   112  |  | 
|   113     if (g_default_trust_domain || g_default_crypto_context) { |  | 
|   114         /* Stan is already initialized or a previous shutdown failed. */ |  | 
|   115         nss_SetError(NSS_ERROR_ALREADY_INITIALIZED); |  | 
|   116         return PR_FAILURE; |  | 
|   117     } |  | 
|   118     td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL); |  | 
|   119     if (!td) { |  | 
|   120         return PR_FAILURE; |  | 
|   121     } |  | 
|   122     /* |  | 
|   123      * Deadlock warning: we should never acquire the moduleLock while |  | 
|   124      * we hold the tokensLock. We can use the NSSRWLock Rank feature to |  | 
|   125      * guarrentee this. tokensLock have a higher rank than module lock. |  | 
|   126      */ |  | 
|   127     td->tokenList = nssList_Create(td->arena, PR_TRUE); |  | 
|   128     if (!td->tokenList) { |  | 
|   129         goto loser; |  | 
|   130     } |  | 
|   131     SECMOD_GetReadLock(moduleLock); |  | 
|   132     NSSRWLock_LockWrite(td->tokensLock); |  | 
|   133     for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) { |  | 
|   134         for (i=0; i < mlp->module->slotCount; i++) { |  | 
|   135             STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]); |  | 
|   136         } |  | 
|   137     } |  | 
|   138     td->tokens = nssList_CreateIterator(td->tokenList); |  | 
|   139     NSSRWLock_UnlockWrite(td->tokensLock); |  | 
|   140     SECMOD_ReleaseReadLock(moduleLock); |  | 
|   141     if (!td->tokens) { |  | 
|   142         goto loser; |  | 
|   143     } |  | 
|   144     g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL); |  | 
|   145     if (!g_default_crypto_context) { |  | 
|   146         goto loser; |  | 
|   147     } |  | 
|   148     g_default_trust_domain = td; |  | 
|   149     return PR_SUCCESS; |  | 
|   150  |  | 
|   151   loser: |  | 
|   152     NSSTrustDomain_Destroy(td); |  | 
|   153     return PR_FAILURE; |  | 
|   154 } |  | 
|   155  |  | 
|   156 /* |  | 
|   157  * must be called holding the ModuleListLock (either read or write). |  | 
|   158  */ |  | 
|   159 NSS_IMPLEMENT SECStatus |  | 
|   160 STAN_AddModuleToDefaultTrustDomain ( |  | 
|   161   SECMODModule *module |  | 
|   162 ) |  | 
|   163 { |  | 
|   164     NSSTrustDomain *td; |  | 
|   165     int i; |  | 
|   166     td = STAN_GetDefaultTrustDomain(); |  | 
|   167     for (i=0; i<module->slotCount; i++) { |  | 
|   168         STAN_InitTokenForSlotInfo(td, module->slots[i]); |  | 
|   169     } |  | 
|   170     STAN_ResetTokenInterator(td); |  | 
|   171     return SECSuccess; |  | 
|   172 } |  | 
|   173  |  | 
|   174 /* |  | 
|   175  * must be called holding the ModuleListLock (either read or write). |  | 
|   176  */ |  | 
|   177 NSS_IMPLEMENT SECStatus |  | 
|   178 STAN_RemoveModuleFromDefaultTrustDomain ( |  | 
|   179   SECMODModule *module |  | 
|   180 ) |  | 
|   181 { |  | 
|   182     NSSToken *token; |  | 
|   183     NSSTrustDomain *td; |  | 
|   184     int i; |  | 
|   185     td = STAN_GetDefaultTrustDomain(); |  | 
|   186     NSSRWLock_LockWrite(td->tokensLock); |  | 
|   187     for (i=0; i<module->slotCount; i++) { |  | 
|   188         token = PK11Slot_GetNSSToken(module->slots[i]); |  | 
|   189         if (token) { |  | 
|   190             nssToken_NotifyCertsNotVisible(token); |  | 
|   191             nssList_Remove(td->tokenList, token); |  | 
|   192             PK11Slot_SetNSSToken(module->slots[i], NULL); |  | 
|   193             nssToken_Destroy(token); |  | 
|   194         } |  | 
|   195     } |  | 
|   196     nssListIterator_Destroy(td->tokens); |  | 
|   197     td->tokens = nssList_CreateIterator(td->tokenList); |  | 
|   198     NSSRWLock_UnlockWrite(td->tokensLock); |  | 
|   199     return SECSuccess; |  | 
|   200 } |  | 
|   201  |  | 
|   202 NSS_IMPLEMENT PRStatus |  | 
|   203 STAN_Shutdown() |  | 
|   204 { |  | 
|   205     PRStatus status = PR_SUCCESS; |  | 
|   206     if (g_default_trust_domain) { |  | 
|   207         if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) { |  | 
|   208             g_default_trust_domain = NULL; |  | 
|   209         } else { |  | 
|   210             status = PR_FAILURE; |  | 
|   211         } |  | 
|   212     } |  | 
|   213     if (g_default_crypto_context) { |  | 
|   214         if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) { |  | 
|   215             g_default_crypto_context = NULL; |  | 
|   216         } else { |  | 
|   217             status = PR_FAILURE; |  | 
|   218         } |  | 
|   219     } |  | 
|   220     return status; |  | 
|   221 } |  | 
|   222  |  | 
|   223 /* this function should not be a hack; it will be needed in 4.0 (rename) */ |  | 
|   224 NSS_IMPLEMENT NSSItem * |  | 
|   225 STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der) |  | 
|   226 { |  | 
|   227     NSSItem *rvKey; |  | 
|   228     SECItem secDER; |  | 
|   229     SECItem secKey = { 0 }; |  | 
|   230     SECStatus secrv; |  | 
|   231     PLArenaPool *arena; |  | 
|   232  |  | 
|   233     SECITEM_FROM_NSSITEM(&secDER, der); |  | 
|   234  |  | 
|   235     /* nss3 call uses nss3 arena's */ |  | 
|   236     arena = PORT_NewArena(256); |  | 
|   237     if (!arena) { |  | 
|   238         return NULL; |  | 
|   239     } |  | 
|   240     secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey); |  | 
|   241     if (secrv != SECSuccess) { |  | 
|   242         PORT_FreeArena(arena, PR_FALSE); |  | 
|   243         return NULL; |  | 
|   244     } |  | 
|   245     rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data); |  | 
|   246     PORT_FreeArena(arena,PR_FALSE); |  | 
|   247     return rvKey; |  | 
|   248 } |  | 
|   249  |  | 
|   250 NSS_IMPLEMENT PRStatus |  | 
|   251 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, |  | 
|   252                                      NSSDER *issuer, NSSDER *serial) |  | 
|   253 { |  | 
|   254     SECItem derCert   = { 0 }; |  | 
|   255     SECItem derIssuer = { 0 }; |  | 
|   256     SECItem derSerial = { 0 }; |  | 
|   257     SECStatus secrv; |  | 
|   258     derCert.data = (unsigned char *)der->data; |  | 
|   259     derCert.len = der->size; |  | 
|   260     secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer); |  | 
|   261     if (secrv != SECSuccess) { |  | 
|   262         return PR_FAILURE; |  | 
|   263     } |  | 
|   264     secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial); |  | 
|   265     if (secrv != SECSuccess) { |  | 
|   266         PORT_Free(derSerial.data); |  | 
|   267         return PR_FAILURE; |  | 
|   268     } |  | 
|   269     issuer->data = derIssuer.data; |  | 
|   270     issuer->size = derIssuer.len; |  | 
|   271     serial->data = derSerial.data; |  | 
|   272     serial->size = derSerial.len; |  | 
|   273     return PR_SUCCESS; |  | 
|   274 } |  | 
|   275  |  | 
|   276 static NSSItem * |  | 
|   277 nss3certificate_getIdentifier(nssDecodedCert *dc) |  | 
|   278 { |  | 
|   279     NSSItem *rvID; |  | 
|   280     CERTCertificate *c = (CERTCertificate *)dc->data; |  | 
|   281     rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data); |  | 
|   282     return rvID; |  | 
|   283 } |  | 
|   284  |  | 
|   285 static void * |  | 
|   286 nss3certificate_getIssuerIdentifier(nssDecodedCert *dc) |  | 
|   287 { |  | 
|   288     CERTCertificate *c = (CERTCertificate *)dc->data; |  | 
|   289     return (void *)c->authKeyID; |  | 
|   290 } |  | 
|   291  |  | 
|   292 static nssCertIDMatch |  | 
|   293 nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id) |  | 
|   294 { |  | 
|   295     CERTCertificate *c = (CERTCertificate *)dc->data; |  | 
|   296     CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id; |  | 
|   297     SECItem skid; |  | 
|   298     nssCertIDMatch match = nssCertIDMatch_Unknown; |  | 
|   299  |  | 
|   300     /* keyIdentifier */ |  | 
|   301     if (authKeyID->keyID.len > 0 && |  | 
|   302         CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) { |  | 
|   303         PRBool skiEqual; |  | 
|   304         skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid); |  | 
|   305         PORT_Free(skid.data); |  | 
|   306         if (skiEqual) { |  | 
|   307             /* change the state to positive match, but keep going */ |  | 
|   308             match = nssCertIDMatch_Yes; |  | 
|   309         } else { |  | 
|   310             /* exit immediately on failure */ |  | 
|   311             return nssCertIDMatch_No; |  | 
|   312         } |  | 
|   313     } |  | 
|   314  |  | 
|   315     /* issuer/serial (treated as pair) */ |  | 
|   316     if (authKeyID->authCertIssuer) { |  | 
|   317         SECItem *caName = NULL; |  | 
|   318         SECItem *caSN = &authKeyID->authCertSerialNumber; |  | 
|   319  |  | 
|   320         caName = (SECItem *)CERT_GetGeneralNameByType( |  | 
|   321                                                 authKeyID->authCertIssuer, |  | 
|   322                                                 certDirectoryName, PR_TRUE); |  | 
|   323         if (caName != NULL && |  | 
|   324             SECITEM_ItemsAreEqual(&c->derIssuer, caName) && |  | 
|   325             SECITEM_ItemsAreEqual(&c->serialNumber, caSN))  |  | 
|   326         { |  | 
|   327             match = nssCertIDMatch_Yes; |  | 
|   328         } else { |  | 
|   329             match = nssCertIDMatch_Unknown; |  | 
|   330         } |  | 
|   331     } |  | 
|   332     return match; |  | 
|   333 } |  | 
|   334  |  | 
|   335 static PRBool |  | 
|   336 nss3certificate_isValidIssuer(nssDecodedCert *dc) |  | 
|   337 { |  | 
|   338     CERTCertificate *c = (CERTCertificate *)dc->data; |  | 
|   339     unsigned int ignore; |  | 
|   340     return CERT_IsCACert(c, &ignore); |  | 
|   341 } |  | 
|   342  |  | 
|   343 static NSSUsage * |  | 
|   344 nss3certificate_getUsage(nssDecodedCert *dc) |  | 
|   345 { |  | 
|   346     /* CERTCertificate *c = (CERTCertificate *)dc->data; */ |  | 
|   347     return NULL; |  | 
|   348 } |  | 
|   349  |  | 
|   350 static PRBool  |  | 
|   351 nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time) |  | 
|   352 { |  | 
|   353     SECCertTimeValidity validity; |  | 
|   354     CERTCertificate *c = (CERTCertificate *)dc->data; |  | 
|   355     validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE); |  | 
|   356     if (validity == secCertTimeValid) { |  | 
|   357         return PR_TRUE; |  | 
|   358     } |  | 
|   359     return PR_FALSE; |  | 
|   360 } |  | 
|   361  |  | 
|   362 static PRBool  |  | 
|   363 nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc) |  | 
|   364 { |  | 
|   365     /* I know this isn't right, but this is glue code anyway */ |  | 
|   366     if (cmpdc->type == dc->type) { |  | 
|   367         CERTCertificate *certa = (CERTCertificate *)dc->data; |  | 
|   368         CERTCertificate *certb = (CERTCertificate *)cmpdc->data; |  | 
|   369         return CERT_IsNewer(certa, certb); |  | 
|   370     } |  | 
|   371     return PR_FALSE; |  | 
|   372 } |  | 
|   373  |  | 
|   374 /* CERT_FilterCertListByUsage */ |  | 
|   375 static PRBool |  | 
|   376 nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage) |  | 
|   377 { |  | 
|   378     CERTCertificate *cc; |  | 
|   379     unsigned int requiredKeyUsage = 0; |  | 
|   380     unsigned int requiredCertType = 0; |  | 
|   381     SECStatus secrv; |  | 
|   382     PRBool match; |  | 
|   383     PRBool ca; |  | 
|   384  |  | 
|   385     /* This is for NSS 3.3 functions that do not specify a usage */ |  | 
|   386     if (usage->anyUsage) { |  | 
|   387         return PR_TRUE; |  | 
|   388     } |  | 
|   389     ca = usage->nss3lookingForCA; |  | 
|   390     secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca, |  | 
|   391                                              &requiredKeyUsage, |  | 
|   392                                              &requiredCertType); |  | 
|   393     if (secrv != SECSuccess) { |  | 
|   394         return PR_FALSE; |  | 
|   395     } |  | 
|   396     cc = (CERTCertificate *)dc->data; |  | 
|   397     secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage); |  | 
|   398     match = (PRBool)(secrv == SECSuccess); |  | 
|   399     if (match) { |  | 
|   400         unsigned int certType = 0; |  | 
|   401         if (ca) { |  | 
|   402             (void)CERT_IsCACert(cc, &certType); |  | 
|   403         } else { |  | 
|   404             certType = cc->nsCertType; |  | 
|   405         } |  | 
|   406         if (!(certType & requiredCertType)) { |  | 
|   407             match = PR_FALSE; |  | 
|   408         } |  | 
|   409     } |  | 
|   410     return match; |  | 
|   411 } |  | 
|   412  |  | 
|   413 static PRBool |  | 
|   414 nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage) |  | 
|   415 { |  | 
|   416     CERTCertificate *cc; |  | 
|   417     PRBool ca; |  | 
|   418     SECStatus secrv; |  | 
|   419     unsigned int requiredFlags; |  | 
|   420     unsigned int trustFlags; |  | 
|   421     SECTrustType trustType; |  | 
|   422     CERTCertTrust trust; |  | 
|   423  |  | 
|   424     /* This is for NSS 3.3 functions that do not specify a usage */ |  | 
|   425     if (usage->anyUsage) { |  | 
|   426         return PR_FALSE;  /* XXX is this right? */ |  | 
|   427     } |  | 
|   428     cc = (CERTCertificate *)dc->data; |  | 
|   429     ca = usage->nss3lookingForCA; |  | 
|   430     if (!ca) { |  | 
|   431         PRBool trusted; |  | 
|   432         unsigned int failedFlags; |  | 
|   433         secrv = cert_CheckLeafTrust(cc, usage->nss3usage, |  | 
|   434                                     &failedFlags, &trusted); |  | 
|   435         return secrv == SECSuccess && trusted; |  | 
|   436     } |  | 
|   437     secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags, |  | 
|   438                                           &trustType); |  | 
|   439     if (secrv != SECSuccess) { |  | 
|   440         return PR_FALSE; |  | 
|   441     } |  | 
|   442     secrv = CERT_GetCertTrust(cc, &trust); |  | 
|   443     if (secrv != SECSuccess) { |  | 
|   444         return PR_FALSE; |  | 
|   445     } |  | 
|   446     if (trustType == trustTypeNone) { |  | 
|   447         /* normally trustTypeNone usages accept any of the given trust bits |  | 
|   448          * being on as acceptable. */ |  | 
|   449         trustFlags = trust.sslFlags | trust.emailFlags | |  | 
|   450                      trust.objectSigningFlags; |  | 
|   451     } else { |  | 
|   452         trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); |  | 
|   453     } |  | 
|   454     return (trustFlags & requiredFlags) == requiredFlags; |  | 
|   455 } |  | 
|   456  |  | 
|   457 static NSSASCII7 * |  | 
|   458 nss3certificate_getEmailAddress(nssDecodedCert *dc) |  | 
|   459 { |  | 
|   460     CERTCertificate *cc = (CERTCertificate *)dc->data; |  | 
|   461     return (cc && cc->emailAddr && cc->emailAddr[0]) |  | 
|   462             ? (NSSASCII7 *)cc->emailAddr : NULL; |  | 
|   463 } |  | 
|   464  |  | 
|   465 static PRStatus |  | 
|   466 nss3certificate_getDERSerialNumber(nssDecodedCert *dc,  |  | 
|   467                                    NSSDER *serial, NSSArena *arena) |  | 
|   468 { |  | 
|   469     CERTCertificate *cc = (CERTCertificate *)dc->data; |  | 
|   470     SECItem derSerial = { 0 }; |  | 
|   471     SECStatus secrv; |  | 
|   472     secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); |  | 
|   473     if (secrv == SECSuccess) { |  | 
|   474         (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data); |  | 
|   475         PORT_Free(derSerial.data); |  | 
|   476         return PR_SUCCESS; |  | 
|   477     } |  | 
|   478     return PR_FAILURE; |  | 
|   479 } |  | 
|   480  |  | 
|   481 /* Returns NULL if "encoding" cannot be decoded. */ |  | 
|   482 NSS_IMPLEMENT nssDecodedCert * |  | 
|   483 nssDecodedPKIXCertificate_Create ( |  | 
|   484   NSSArena *arenaOpt, |  | 
|   485   NSSDER *encoding |  | 
|   486 ) |  | 
|   487 { |  | 
|   488     nssDecodedCert  *rvDC = NULL; |  | 
|   489     CERTCertificate *cert; |  | 
|   490     SECItem          secDER; |  | 
|   491  |  | 
|   492     SECITEM_FROM_NSSITEM(&secDER, encoding); |  | 
|   493     cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL); |  | 
|   494     if (cert) { |  | 
|   495         rvDC = nss_ZNEW(arenaOpt, nssDecodedCert); |  | 
|   496         if (rvDC) { |  | 
|   497             rvDC->type                = NSSCertificateType_PKIX; |  | 
|   498             rvDC->data                = (void *)cert; |  | 
|   499             rvDC->getIdentifier       = nss3certificate_getIdentifier; |  | 
|   500             rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier; |  | 
|   501             rvDC->matchIdentifier     = nss3certificate_matchIdentifier; |  | 
|   502             rvDC->isValidIssuer       = nss3certificate_isValidIssuer; |  | 
|   503             rvDC->getUsage            = nss3certificate_getUsage; |  | 
|   504             rvDC->isValidAtTime       = nss3certificate_isValidAtTime; |  | 
|   505             rvDC->isNewerThan         = nss3certificate_isNewerThan; |  | 
|   506             rvDC->matchUsage          = nss3certificate_matchUsage; |  | 
|   507             rvDC->isTrustedForUsage   = nss3certificate_isTrustedForUsage; |  | 
|   508             rvDC->getEmailAddress     = nss3certificate_getEmailAddress; |  | 
|   509             rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber; |  | 
|   510         } else { |  | 
|   511             CERT_DestroyCertificate(cert); |  | 
|   512         } |  | 
|   513     } |  | 
|   514     return rvDC; |  | 
|   515 } |  | 
|   516  |  | 
|   517 static nssDecodedCert * |  | 
|   518 create_decoded_pkix_cert_from_nss3cert ( |  | 
|   519   NSSArena *arenaOpt, |  | 
|   520   CERTCertificate *cc |  | 
|   521 ) |  | 
|   522 { |  | 
|   523     nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert); |  | 
|   524     if (rvDC) { |  | 
|   525         rvDC->type                = NSSCertificateType_PKIX; |  | 
|   526         rvDC->data                = (void *)cc; |  | 
|   527         rvDC->getIdentifier       = nss3certificate_getIdentifier; |  | 
|   528         rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier; |  | 
|   529         rvDC->matchIdentifier     = nss3certificate_matchIdentifier; |  | 
|   530         rvDC->isValidIssuer       = nss3certificate_isValidIssuer; |  | 
|   531         rvDC->getUsage            = nss3certificate_getUsage; |  | 
|   532         rvDC->isValidAtTime       = nss3certificate_isValidAtTime; |  | 
|   533         rvDC->isNewerThan         = nss3certificate_isNewerThan; |  | 
|   534         rvDC->matchUsage          = nss3certificate_matchUsage; |  | 
|   535         rvDC->isTrustedForUsage   = nss3certificate_isTrustedForUsage; |  | 
|   536         rvDC->getEmailAddress     = nss3certificate_getEmailAddress; |  | 
|   537         rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber; |  | 
|   538     } |  | 
|   539     return rvDC; |  | 
|   540 } |  | 
|   541  |  | 
|   542 NSS_IMPLEMENT PRStatus |  | 
|   543 nssDecodedPKIXCertificate_Destroy ( |  | 
|   544   nssDecodedCert *dc |  | 
|   545 ) |  | 
|   546 { |  | 
|   547     CERTCertificate *cert = (CERTCertificate *)dc->data; |  | 
|   548  |  | 
|   549     /* The decoder may only be half initialized (the case where we find we  |  | 
|   550      * could not decode the certificate). In this case, there is not cert to |  | 
|   551      * free, just free the dc structure. */ |  | 
|   552     if (cert) { |  | 
|   553         PRBool freeSlot = cert->ownSlot; |  | 
|   554         PK11SlotInfo *slot = cert->slot; |  | 
|   555         PLArenaPool *arena  = cert->arena; |  | 
|   556         /* zero cert before freeing. Any stale references to this cert |  | 
|   557          * after this point will probably cause an exception.  */ |  | 
|   558         PORT_Memset(cert, 0, sizeof *cert); |  | 
|   559         /* free the arena that contains the cert. */ |  | 
|   560         PORT_FreeArena(arena, PR_FALSE); |  | 
|   561         if (slot && freeSlot) { |  | 
|   562             PK11_FreeSlot(slot); |  | 
|   563         } |  | 
|   564     } |  | 
|   565     nss_ZFreeIf(dc); |  | 
|   566     return PR_SUCCESS; |  | 
|   567 } |  | 
|   568  |  | 
|   569 /* see pk11cert.c:pk11_HandleTrustObject */ |  | 
|   570 static unsigned int |  | 
|   571 get_nss3trust_from_nss4trust(nssTrustLevel t) |  | 
|   572 { |  | 
|   573     unsigned int rt = 0; |  | 
|   574     if (t == nssTrustLevel_Trusted) { |  | 
|   575         rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED; |  | 
|   576     } |  | 
|   577     if (t == nssTrustLevel_TrustedDelegator) { |  | 
|   578         rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA; |  | 
|   579     } |  | 
|   580     if (t == nssTrustLevel_NotTrusted) { |  | 
|   581         rt |= CERTDB_TERMINAL_RECORD; |  | 
|   582     } |  | 
|   583     if (t == nssTrustLevel_ValidDelegator) { |  | 
|   584         rt |= CERTDB_VALID_CA; |  | 
|   585     } |  | 
|   586     return rt; |  | 
|   587 } |  | 
|   588  |  | 
|   589 static CERTCertTrust * |  | 
|   590 cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena) |  | 
|   591 { |  | 
|   592     CERTCertTrust *rvTrust; |  | 
|   593     unsigned int client; |  | 
|   594     if (!t) { |  | 
|   595         return NULL; |  | 
|   596     } |  | 
|   597     rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust)); |  | 
|   598     if (!rvTrust) return NULL; |  | 
|   599     rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth); |  | 
|   600     client = get_nss3trust_from_nss4trust(t->clientAuth); |  | 
|   601     if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) { |  | 
|   602         client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA); |  | 
|   603         rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA; |  | 
|   604     } |  | 
|   605     rvTrust->sslFlags |= client; |  | 
|   606     rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection); |  | 
|   607     rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning); |  | 
|   608     return rvTrust; |  | 
|   609 } |  | 
|   610  |  | 
|   611 CERTCertTrust *  |  | 
|   612 nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc) |  | 
|   613 { |  | 
|   614     CERTCertTrust *rvTrust = NULL; |  | 
|   615     NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); |  | 
|   616     NSSTrust *t; |  | 
|   617     t = nssTrustDomain_FindTrustForCertificate(td, c); |  | 
|   618     if (t) { |  | 
|   619         rvTrust = cert_trust_from_stan_trust(t, cc->arena); |  | 
|   620         if (!rvTrust) { |  | 
|   621             nssTrust_Destroy(t); |  | 
|   622             return NULL; |  | 
|   623         } |  | 
|   624         nssTrust_Destroy(t); |  | 
|   625     } else { |  | 
|   626         rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); |  | 
|   627         if (!rvTrust) { |  | 
|   628             return NULL; |  | 
|   629         } |  | 
|   630         memset(rvTrust, 0, sizeof(*rvTrust)); |  | 
|   631     } |  | 
|   632     if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) { |  | 
|   633         rvTrust->sslFlags |= CERTDB_USER; |  | 
|   634         rvTrust->emailFlags |= CERTDB_USER; |  | 
|   635         rvTrust->objectSigningFlags |= CERTDB_USER; |  | 
|   636     } |  | 
|   637     return rvTrust; |  | 
|   638 } |  | 
|   639  |  | 
|   640 static nssCryptokiInstance * |  | 
|   641 get_cert_instance(NSSCertificate *c) |  | 
|   642 { |  | 
|   643     nssCryptokiObject *instance, **ci; |  | 
|   644     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); |  | 
|   645     if (!instances) { |  | 
|   646         return NULL; |  | 
|   647     } |  | 
|   648     instance = NULL; |  | 
|   649     for (ci = instances; *ci; ci++) { |  | 
|   650         if (!instance) { |  | 
|   651             instance = nssCryptokiObject_Clone(*ci); |  | 
|   652         } else { |  | 
|   653             /* This only really works for two instances...  But 3.4 can't |  | 
|   654              * handle more anyway.  The logic is, if there are multiple |  | 
|   655              * instances, prefer the one that is not internal (e.g., on |  | 
|   656              * a hardware device. |  | 
|   657              */ |  | 
|   658             if (PK11_IsInternal(instance->token->pk11slot)) { |  | 
|   659                 nssCryptokiObject_Destroy(instance); |  | 
|   660                 instance = nssCryptokiObject_Clone(*ci); |  | 
|   661             } |  | 
|   662         } |  | 
|   663     } |  | 
|   664     nssCryptokiObjectArray_Destroy(instances); |  | 
|   665     return instance; |  | 
|   666 } |  | 
|   667  |  | 
|   668 char *  |  | 
|   669 STAN_GetCERTCertificateNameForInstance ( |  | 
|   670   PLArenaPool *arenaOpt, |  | 
|   671   NSSCertificate *c, |  | 
|   672   nssCryptokiInstance *instance |  | 
|   673 ) |  | 
|   674 { |  | 
|   675     NSSCryptoContext *context = c->object.cryptoContext; |  | 
|   676     PRStatus nssrv; |  | 
|   677     int nicklen, tokenlen, len; |  | 
|   678     NSSUTF8 *tokenName = NULL; |  | 
|   679     NSSUTF8 *stanNick = NULL; |  | 
|   680     char *nickname = NULL; |  | 
|   681     char *nick; |  | 
|   682  |  | 
|   683     if (instance) { |  | 
|   684         stanNick = instance->label; |  | 
|   685     } else if (context) { |  | 
|   686         stanNick = c->object.tempName; |  | 
|   687     } |  | 
|   688     if (stanNick) { |  | 
|   689         /* fill other fields needed by NSS3 functions using CERTCertificate */ |  | 
|   690         if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||  |  | 
|   691                          PORT_Strchr(stanNick, ':') != NULL) ) { |  | 
|   692             tokenName = nssToken_GetName(instance->token); |  | 
|   693             tokenlen = nssUTF8_Size(tokenName, &nssrv); |  | 
|   694         } else { |  | 
|   695         /* don't use token name for internal slot; 3.3 didn't */ |  | 
|   696             tokenlen = 0; |  | 
|   697         } |  | 
|   698         nicklen = nssUTF8_Size(stanNick, &nssrv); |  | 
|   699         len = tokenlen + nicklen; |  | 
|   700         if (arenaOpt) { |  | 
|   701             nickname = PORT_ArenaAlloc(arenaOpt, len); |  | 
|   702         } else { |  | 
|   703             nickname = PORT_Alloc(len); |  | 
|   704         } |  | 
|   705         nick = nickname; |  | 
|   706         if (tokenName) { |  | 
|   707             memcpy(nick, tokenName, tokenlen-1); |  | 
|   708             nick += tokenlen-1; |  | 
|   709             *nick++ = ':'; |  | 
|   710         } |  | 
|   711         memcpy(nick, stanNick, nicklen-1); |  | 
|   712         nickname[len-1] = '\0'; |  | 
|   713     } |  | 
|   714     return nickname; |  | 
|   715 } |  | 
|   716  |  | 
|   717 char *  |  | 
|   718 STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c) |  | 
|   719 { |  | 
|   720     char * result; |  | 
|   721     nssCryptokiInstance *instance = get_cert_instance(c); |  | 
|   722     /* It's OK to call this function, even if instance is NULL */ |  | 
|   723     result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance); |  | 
|   724     if (instance) |  | 
|   725         nssCryptokiObject_Destroy(instance); |  | 
|   726     return result; |  | 
|   727 } |  | 
|   728  |  | 
|   729 static void |  | 
|   730 fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced
      ) |  | 
|   731 { |  | 
|   732     CERTCertTrust* trust = NULL; |  | 
|   733     NSSTrust *nssTrust; |  | 
|   734     NSSCryptoContext *context = c->object.cryptoContext; |  | 
|   735     nssCryptokiInstance *instance; |  | 
|   736     NSSUTF8 *stanNick = NULL; |  | 
|   737  |  | 
|   738     /* We are holding the base class object's lock on entry of this function |  | 
|   739      * This lock protects writes to fields of the CERTCertificate . |  | 
|   740      * It is also needed by some functions to compute values such as trust. |  | 
|   741      */ |  | 
|   742     instance = get_cert_instance(c); |  | 
|   743  |  | 
|   744     if (instance) { |  | 
|   745         stanNick = instance->label; |  | 
|   746     } else if (context) { |  | 
|   747         stanNick = c->object.tempName; |  | 
|   748     } |  | 
|   749     /* fill other fields needed by NSS3 functions using CERTCertificate */ |  | 
|   750     if ((!cc->nickname && stanNick) || forced) { |  | 
|   751         PRStatus nssrv; |  | 
|   752         int nicklen, tokenlen, len; |  | 
|   753         NSSUTF8 *tokenName = NULL; |  | 
|   754         char *nick; |  | 
|   755         if (instance &&  |  | 
|   756              (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||  |  | 
|   757               (stanNick && PORT_Strchr(stanNick, ':') != NULL))) { |  | 
|   758             tokenName = nssToken_GetName(instance->token); |  | 
|   759             tokenlen = nssUTF8_Size(tokenName, &nssrv); |  | 
|   760         } else { |  | 
|   761             /* don't use token name for internal slot; 3.3 didn't */ |  | 
|   762             tokenlen = 0; |  | 
|   763         } |  | 
|   764         if (stanNick) { |  | 
|   765             nicklen = nssUTF8_Size(stanNick, &nssrv); |  | 
|   766             len = tokenlen + nicklen; |  | 
|   767             nick = PORT_ArenaAlloc(cc->arena, len); |  | 
|   768             if (tokenName) { |  | 
|   769                 memcpy(nick, tokenName, tokenlen-1); |  | 
|   770                 nick[tokenlen-1] = ':'; |  | 
|   771                 memcpy(nick+tokenlen, stanNick, nicklen-1); |  | 
|   772             } else { |  | 
|   773                 memcpy(nick, stanNick, nicklen-1); |  | 
|   774             } |  | 
|   775             nick[len-1] = '\0'; |  | 
|   776             cc->nickname = nick; |  | 
|   777         } else { |  | 
|   778             cc->nickname = NULL; |  | 
|   779         } |  | 
|   780     } |  | 
|   781     if (context) { |  | 
|   782         /* trust */ |  | 
|   783         nssTrust = nssCryptoContext_FindTrustForCertificate(context, c); |  | 
|   784         if (!nssTrust) { |  | 
|   785             /* chicken and egg issue: |  | 
|   786              * |  | 
|   787              * c->issuer and c->serial are empty at this point, but |  | 
|   788              * nssTrustDomain_FindTrustForCertificate use them to look up |  | 
|   789              * up the trust object, so we point them to cc->derIssuer and |  | 
|   790              * cc->serialNumber. |  | 
|   791              * |  | 
|   792              * Our caller will fill these in with proper arena copies when we |  | 
|   793              * return. */ |  | 
|   794             c->issuer.data = cc->derIssuer.data; |  | 
|   795             c->issuer.size = cc->derIssuer.len; |  | 
|   796             c->serial.data = cc->serialNumber.data; |  | 
|   797             c->serial.size = cc->serialNumber.len; |  | 
|   798             nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c); |  | 
|   799         } |  | 
|   800         if (nssTrust) { |  | 
|   801             trust = cert_trust_from_stan_trust(nssTrust, cc->arena); |  | 
|   802             if (trust) { |  | 
|   803                 /* we should destroy cc->trust before replacing it, but it's |  | 
|   804                    allocated in cc->arena, so memory growth will occur on each |  | 
|   805                    refresh */ |  | 
|   806                 CERT_LockCertTrust(cc); |  | 
|   807                 cc->trust = trust; |  | 
|   808                 CERT_UnlockCertTrust(cc); |  | 
|   809             } |  | 
|   810             nssTrust_Destroy(nssTrust); |  | 
|   811         } |  | 
|   812     } else if (instance) { |  | 
|   813         /* slot */ |  | 
|   814         if (cc->slot != instance->token->pk11slot) { |  | 
|   815             if (cc->slot) { |  | 
|   816                 PK11_FreeSlot(cc->slot); |  | 
|   817             } |  | 
|   818             cc->slot = PK11_ReferenceSlot(instance->token->pk11slot); |  | 
|   819         } |  | 
|   820         cc->ownSlot = PR_TRUE; |  | 
|   821         /* pkcs11ID */ |  | 
|   822         cc->pkcs11ID = instance->handle; |  | 
|   823         /* trust */ |  | 
|   824         trust = nssTrust_GetCERTCertTrustForCert(c, cc); |  | 
|   825         if (trust) { |  | 
|   826             /* we should destroy cc->trust before replacing it, but it's |  | 
|   827                allocated in cc->arena, so memory growth will occur on each |  | 
|   828                refresh */ |  | 
|   829             CERT_LockCertTrust(cc); |  | 
|   830             cc->trust = trust; |  | 
|   831             CERT_UnlockCertTrust(cc); |  | 
|   832         } |  | 
|   833     }  |  | 
|   834     if (instance) { |  | 
|   835         nssCryptokiObject_Destroy(instance); |  | 
|   836     } |  | 
|   837     /* database handle is now the trust domain */ |  | 
|   838     cc->dbhandle = c->object.trustDomain; |  | 
|   839     /* subjectList ? */ |  | 
|   840     /* istemp and isperm are supported in NSS 3.4 */ |  | 
|   841     cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */ |  | 
|   842     cc->isperm = PR_TRUE;  /* by default */ |  | 
|   843     /* pointer back */ |  | 
|   844     cc->nssCertificate = c; |  | 
|   845     if (trust) { |  | 
|   846         /* force the cert type to be recomputed to include trust info */ |  | 
|   847         PRUint32 nsCertType = cert_ComputeCertType(cc); |  | 
|   848  |  | 
|   849         /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */ |  | 
|   850         PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32)); |  | 
|   851         PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType); |  | 
|   852     } |  | 
|   853 } |  | 
|   854  |  | 
|   855 static CERTCertificate * |  | 
|   856 stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate) |  | 
|   857 { |  | 
|   858     nssDecodedCert *dc = NULL; |  | 
|   859     CERTCertificate *cc = NULL; |  | 
|   860     CERTCertTrust certTrust; |  | 
|   861  |  | 
|   862     /* make sure object does not go away until we finish */ |  | 
|   863     nssPKIObject_AddRef(&c->object); |  | 
|   864     nssPKIObject_Lock(&c->object); |  | 
|   865  |  | 
|   866     dc = c->decoding; |  | 
|   867     if (!dc) { |  | 
|   868         dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding); |  | 
|   869         if (!dc) { |  | 
|   870             goto loser; |  | 
|   871         } |  | 
|   872         cc = (CERTCertificate *)dc->data; |  | 
|   873         PORT_Assert(cc); /* software error */ |  | 
|   874         if (!cc) { |  | 
|   875             nssDecodedPKIXCertificate_Destroy(dc); |  | 
|   876             nss_SetError(NSS_ERROR_INTERNAL_ERROR); |  | 
|   877             goto loser; |  | 
|   878         } |  | 
|   879         PORT_Assert(!c->decoding);  |  | 
|   880         if (!c->decoding) { |  | 
|   881             c->decoding = dc; |  | 
|   882         } else {  |  | 
|   883             /* this should never happen. Fail. */ |  | 
|   884             nssDecodedPKIXCertificate_Destroy(dc); |  | 
|   885             nss_SetError(NSS_ERROR_INTERNAL_ERROR); |  | 
|   886             goto loser; |  | 
|   887         } |  | 
|   888     } |  | 
|   889     cc = (CERTCertificate *)dc->data; |  | 
|   890     PORT_Assert(cc); |  | 
|   891     if (!cc) { |  | 
|   892         nss_SetError(NSS_ERROR_INTERNAL_ERROR); |  | 
|   893         goto loser; |  | 
|   894     } |  | 
|   895     if (!cc->nssCertificate || forceUpdate) { |  | 
|   896         fill_CERTCertificateFields(c, cc, forceUpdate); |  | 
|   897     } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess && |  | 
|   898                !c->object.cryptoContext) { |  | 
|   899         /* if it's a perm cert, it might have been stored before the |  | 
|   900          * trust, so look for the trust again.  But a temp cert can be |  | 
|   901          * ignored. |  | 
|   902          */ |  | 
|   903         CERTCertTrust* trust = NULL; |  | 
|   904         trust = nssTrust_GetCERTCertTrustForCert(c, cc); |  | 
|   905  |  | 
|   906         CERT_LockCertTrust(cc); |  | 
|   907         cc->trust = trust; |  | 
|   908         CERT_UnlockCertTrust(cc); |  | 
|   909     } |  | 
|   910  |  | 
|   911   loser: |  | 
|   912     nssPKIObject_Unlock(&c->object); |  | 
|   913     nssPKIObject_Destroy(&c->object); |  | 
|   914     return cc; |  | 
|   915 } |  | 
|   916  |  | 
|   917 NSS_IMPLEMENT CERTCertificate * |  | 
|   918 STAN_ForceCERTCertificateUpdate(NSSCertificate *c) |  | 
|   919 { |  | 
|   920     if (c->decoding) { |  | 
|   921         return stan_GetCERTCertificate(c, PR_TRUE); |  | 
|   922     } |  | 
|   923     return NULL; |  | 
|   924 } |  | 
|   925  |  | 
|   926 NSS_IMPLEMENT CERTCertificate * |  | 
|   927 STAN_GetCERTCertificate(NSSCertificate *c) |  | 
|   928 { |  | 
|   929     return stan_GetCERTCertificate(c, PR_FALSE); |  | 
|   930 } |  | 
|   931 /* |  | 
|   932  * many callers of STAN_GetCERTCertificate() intend that |  | 
|   933  * the CERTCertificate returned inherits the reference to the  |  | 
|   934  * NSSCertificate. For these callers it's convenient to have  |  | 
|   935  * this function 'own' the reference and either return a valid  |  | 
|   936  * CERTCertificate structure which inherits the reference or  |  | 
|   937  * destroy the reference to NSSCertificate and returns NULL. |  | 
|   938  */ |  | 
|   939 NSS_IMPLEMENT CERTCertificate * |  | 
|   940 STAN_GetCERTCertificateOrRelease(NSSCertificate *c) |  | 
|   941 { |  | 
|   942     CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE); |  | 
|   943     if (!nss3cert) { |  | 
|   944         nssCertificate_Destroy(c); |  | 
|   945     } |  | 
|   946     return nss3cert; |  | 
|   947 } |  | 
|   948  |  | 
|   949 static nssTrustLevel |  | 
|   950 get_stan_trust(unsigned int t, PRBool isClientAuth)  |  | 
|   951 { |  | 
|   952     if (isClientAuth) { |  | 
|   953         if (t & CERTDB_TRUSTED_CLIENT_CA) { |  | 
|   954             return nssTrustLevel_TrustedDelegator; |  | 
|   955         } |  | 
|   956     } else { |  | 
|   957         if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) { |  | 
|   958             return nssTrustLevel_TrustedDelegator; |  | 
|   959         } |  | 
|   960     } |  | 
|   961     if (t & CERTDB_TRUSTED) { |  | 
|   962         return nssTrustLevel_Trusted; |  | 
|   963     } |  | 
|   964     if (t & CERTDB_TERMINAL_RECORD) { |  | 
|   965         return nssTrustLevel_NotTrusted; |  | 
|   966     } |  | 
|   967     if (t & CERTDB_VALID_CA) { |  | 
|   968         return nssTrustLevel_ValidDelegator; |  | 
|   969     } |  | 
|   970     return nssTrustLevel_MustVerify; |  | 
|   971 } |  | 
|   972  |  | 
|   973 NSS_EXTERN NSSCertificate * |  | 
|   974 STAN_GetNSSCertificate(CERTCertificate *cc) |  | 
|   975 { |  | 
|   976     NSSCertificate *c; |  | 
|   977     nssCryptokiInstance *instance; |  | 
|   978     nssPKIObject *pkiob; |  | 
|   979     NSSArena *arena; |  | 
|   980     c = cc->nssCertificate; |  | 
|   981     if (c) { |  | 
|   982         return c; |  | 
|   983     } |  | 
|   984     /* i don't think this should happen.  but if it can, need to create |  | 
|   985      * NSSCertificate from CERTCertificate values here.  */ |  | 
|   986     /* Yup, it can happen. */ |  | 
|   987     arena = NSSArena_Create(); |  | 
|   988     if (!arena) { |  | 
|   989         return NULL; |  | 
|   990     } |  | 
|   991     c = nss_ZNEW(arena, NSSCertificate); |  | 
|   992     if (!c) { |  | 
|   993         nssArena_Destroy(arena); |  | 
|   994         return NULL; |  | 
|   995     } |  | 
|   996     NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert); |  | 
|   997     c->type = NSSCertificateType_PKIX; |  | 
|   998     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor); |  | 
|   999     if (!pkiob) { |  | 
|  1000         nssArena_Destroy(arena); |  | 
|  1001         return NULL; |  | 
|  1002     } |  | 
|  1003     c->object = *pkiob; |  | 
|  1004     nssItem_Create(arena, |  | 
|  1005                    &c->issuer, cc->derIssuer.len, cc->derIssuer.data); |  | 
|  1006     nssItem_Create(arena, |  | 
|  1007                    &c->subject, cc->derSubject.len, cc->derSubject.data); |  | 
|  1008     if (PR_TRUE) { |  | 
|  1009         /* CERTCertificate stores serial numbers decoded.  I need the DER |  | 
|  1010         * here.  sigh. |  | 
|  1011         */ |  | 
|  1012         SECItem derSerial; |  | 
|  1013         SECStatus secrv; |  | 
|  1014         secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); |  | 
|  1015         if (secrv == SECFailure) { |  | 
|  1016             nssArena_Destroy(arena); |  | 
|  1017             return NULL; |  | 
|  1018         } |  | 
|  1019         nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data); |  | 
|  1020         PORT_Free(derSerial.data); |  | 
|  1021     } |  | 
|  1022     if (cc->emailAddr && cc->emailAddr[0]) { |  | 
|  1023         c->email = nssUTF8_Create(arena, |  | 
|  1024                                   nssStringType_PrintableString, |  | 
|  1025                                   (NSSUTF8 *)cc->emailAddr, |  | 
|  1026                                   PORT_Strlen(cc->emailAddr)); |  | 
|  1027     } |  | 
|  1028     if (cc->slot) { |  | 
|  1029         instance = nss_ZNEW(arena, nssCryptokiInstance); |  | 
|  1030         if (!instance) { |  | 
|  1031             nssArena_Destroy(arena); |  | 
|  1032             return NULL; |  | 
|  1033         } |  | 
|  1034         instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot)); |  | 
|  1035         instance->handle = cc->pkcs11ID; |  | 
|  1036         instance->isTokenObject = PR_TRUE; |  | 
|  1037         if (cc->nickname) { |  | 
|  1038             instance->label = nssUTF8_Create(arena, |  | 
|  1039                                              nssStringType_UTF8String, |  | 
|  1040                                              (NSSUTF8 *)cc->nickname, |  | 
|  1041                                              PORT_Strlen(cc->nickname)); |  | 
|  1042         } |  | 
|  1043         nssPKIObject_AddInstance(&c->object, instance); |  | 
|  1044     } |  | 
|  1045     c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc); |  | 
|  1046     cc->nssCertificate = c; |  | 
|  1047     return c; |  | 
|  1048 } |  | 
|  1049  |  | 
|  1050 static NSSToken* |  | 
|  1051 stan_GetTrustToken ( |  | 
|  1052   NSSCertificate *c |  | 
|  1053 ) |  | 
|  1054 { |  | 
|  1055     NSSToken *ttok = NULL; |  | 
|  1056     NSSToken *rtok = NULL; |  | 
|  1057     NSSToken *tok = NULL; |  | 
|  1058     nssCryptokiObject **ip; |  | 
|  1059     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); |  | 
|  1060     if (!instances) { |  | 
|  1061         return PR_FALSE; |  | 
|  1062     } |  | 
|  1063     for (ip = instances; *ip; ip++) { |  | 
|  1064         nssCryptokiObject *instance = *ip; |  | 
|  1065         nssCryptokiObject *to =  |  | 
|  1066                 nssToken_FindTrustForCertificate(instance->token, NULL, |  | 
|  1067                 &c->encoding, &c->issuer, &c->serial,  |  | 
|  1068                 nssTokenSearchType_TokenOnly); |  | 
|  1069         NSSToken *ctok = instance->token; |  | 
|  1070         PRBool ro = PK11_IsReadOnly(ctok->pk11slot); |  | 
|  1071  |  | 
|  1072         if (to) { |  | 
|  1073             nssCryptokiObject_Destroy(to); |  | 
|  1074             ttok = ctok; |  | 
|  1075             if (!ro) { |  | 
|  1076                 break; |  | 
|  1077             } |  | 
|  1078         } else { |  | 
|  1079             if (!rtok && ro) { |  | 
|  1080                 rtok = ctok; |  | 
|  1081             }  |  | 
|  1082             if (!tok && !ro) { |  | 
|  1083                 tok = ctok; |  | 
|  1084             } |  | 
|  1085         } |  | 
|  1086     } |  | 
|  1087     nssCryptokiObjectArray_Destroy(instances); |  | 
|  1088     return ttok ? ttok : (tok ? tok : rtok); |  | 
|  1089 } |  | 
|  1090  |  | 
|  1091 NSS_EXTERN PRStatus |  | 
|  1092 STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) |  | 
|  1093 { |  | 
|  1094     PRStatus nssrv; |  | 
|  1095     NSSCertificate *c = STAN_GetNSSCertificate(cc); |  | 
|  1096     NSSToken *tok; |  | 
|  1097     NSSTrustDomain *td; |  | 
|  1098     NSSTrust *nssTrust; |  | 
|  1099     NSSArena *arena; |  | 
|  1100     CERTCertTrust *oldTrust; |  | 
|  1101     CERTCertTrust *newTrust; |  | 
|  1102     nssListIterator *tokens; |  | 
|  1103     PRBool moving_object; |  | 
|  1104     nssCryptokiObject *newInstance; |  | 
|  1105     nssPKIObject *pkiob; |  | 
|  1106  |  | 
|  1107     if (c == NULL) { |  | 
|  1108         return PR_FAILURE; |  | 
|  1109     } |  | 
|  1110     oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc); |  | 
|  1111     if (oldTrust) { |  | 
|  1112         if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) { |  | 
|  1113             /* ... and the new trust is no different, done) */ |  | 
|  1114             return PR_SUCCESS; |  | 
|  1115         } else { |  | 
|  1116             /* take over memory already allocated in cc's arena */ |  | 
|  1117             newTrust = oldTrust; |  | 
|  1118         } |  | 
|  1119     } else { |  | 
|  1120         newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); |  | 
|  1121     } |  | 
|  1122     memcpy(newTrust, trust, sizeof(CERTCertTrust)); |  | 
|  1123     CERT_LockCertTrust(cc); |  | 
|  1124     cc->trust = newTrust; |  | 
|  1125     CERT_UnlockCertTrust(cc); |  | 
|  1126     /* Set the NSSCerticate's trust */ |  | 
|  1127     arena = nssArena_Create(); |  | 
|  1128     if (!arena) return PR_FAILURE; |  | 
|  1129     nssTrust = nss_ZNEW(arena, NSSTrust); |  | 
|  1130     if (!nssTrust) { |  | 
|  1131         nssArena_Destroy(arena); |  | 
|  1132         return PR_FAILURE; |  | 
|  1133     } |  | 
|  1134     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock); |  | 
|  1135     if (!pkiob) { |  | 
|  1136         nssArena_Destroy(arena); |  | 
|  1137         return PR_FAILURE; |  | 
|  1138     } |  | 
|  1139     nssTrust->object = *pkiob; |  | 
|  1140     nssTrust->certificate = c; |  | 
|  1141     nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE); |  | 
|  1142     nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE); |  | 
|  1143     nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE); |  | 
|  1144     nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE); |  | 
|  1145     nssTrust->stepUpApproved =  |  | 
|  1146                     (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA); |  | 
|  1147     if (c->object.cryptoContext != NULL) { |  | 
|  1148         /* The cert is in a context, set the trust there */ |  | 
|  1149         NSSCryptoContext *cc = c->object.cryptoContext; |  | 
|  1150         nssrv = nssCryptoContext_ImportTrust(cc, nssTrust); |  | 
|  1151         if (nssrv != PR_SUCCESS) { |  | 
|  1152             goto done; |  | 
|  1153         } |  | 
|  1154         if (c->object.numInstances == 0) { |  | 
|  1155             /* The context is the only instance, finished */ |  | 
|  1156             goto done; |  | 
|  1157         } |  | 
|  1158     } |  | 
|  1159     td = STAN_GetDefaultTrustDomain(); |  | 
|  1160     tok = stan_GetTrustToken(c); |  | 
|  1161     moving_object = PR_FALSE; |  | 
|  1162     if (tok && PK11_IsReadOnly(tok->pk11slot))  { |  | 
|  1163         NSSRWLock_LockRead(td->tokensLock); |  | 
|  1164         tokens = nssList_CreateIterator(td->tokenList); |  | 
|  1165         if (!tokens) { |  | 
|  1166             nssrv = PR_FAILURE; |  | 
|  1167             NSSRWLock_UnlockRead(td->tokensLock); |  | 
|  1168             goto done; |  | 
|  1169         } |  | 
|  1170         for (tok  = (NSSToken *)nssListIterator_Start(tokens); |  | 
|  1171              tok != (NSSToken *)NULL; |  | 
|  1172              tok  = (NSSToken *)nssListIterator_Next(tokens)) |  | 
|  1173         { |  | 
|  1174             if (!PK11_IsReadOnly(tok->pk11slot)) break; |  | 
|  1175         } |  | 
|  1176         nssListIterator_Finish(tokens); |  | 
|  1177         nssListIterator_Destroy(tokens); |  | 
|  1178         NSSRWLock_UnlockRead(td->tokensLock); |  | 
|  1179         moving_object = PR_TRUE; |  | 
|  1180     }  |  | 
|  1181     if (tok) { |  | 
|  1182         if (moving_object) { |  | 
|  1183             /* this is kind of hacky.  the softoken needs the cert |  | 
|  1184              * object in order to store trust.  forcing it to be perm |  | 
|  1185              */ |  | 
|  1186             NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); |  | 
|  1187             NSSASCII7 *email = NULL; |  | 
|  1188  |  | 
|  1189             if (PK11_IsInternal(tok->pk11slot)) { |  | 
|  1190                 email = c->email; |  | 
|  1191             } |  | 
|  1192             newInstance = nssToken_ImportCertificate(tok, NULL, |  | 
|  1193                                                      NSSCertificateType_PKIX, |  | 
|  1194                                                      &c->id, |  | 
|  1195                                                      nickname, |  | 
|  1196                                                      &c->encoding, |  | 
|  1197                                                      &c->issuer, |  | 
|  1198                                                      &c->subject, |  | 
|  1199                                                      &c->serial, |  | 
|  1200                                                      email, |  | 
|  1201                                                      PR_TRUE); |  | 
|  1202             nss_ZFreeIf(nickname); |  | 
|  1203             nickname = NULL; |  | 
|  1204             if (!newInstance) { |  | 
|  1205                 nssrv = PR_FAILURE; |  | 
|  1206                 goto done; |  | 
|  1207             } |  | 
|  1208             nssPKIObject_AddInstance(&c->object, newInstance); |  | 
|  1209         } |  | 
|  1210         newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, |  | 
|  1211                                            &c->issuer, &c->serial, |  | 
|  1212                                            nssTrust->serverAuth, |  | 
|  1213                                            nssTrust->clientAuth, |  | 
|  1214                                            nssTrust->codeSigning, |  | 
|  1215                                            nssTrust->emailProtection, |  | 
|  1216                                            nssTrust->stepUpApproved, PR_TRUE); |  | 
|  1217         /* If the selected token can't handle trust, dump the trust on  |  | 
|  1218          * the internal token */ |  | 
|  1219         if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) { |  | 
|  1220             PK11SlotInfo *slot = PK11_GetInternalKeySlot(); |  | 
|  1221             NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); |  | 
|  1222             NSSASCII7 *email = c->email; |  | 
|  1223             tok = PK11Slot_GetNSSToken(slot); |  | 
|  1224             PK11_FreeSlot(slot); |  | 
|  1225          |  | 
|  1226             newInstance = nssToken_ImportCertificate(tok, NULL, |  | 
|  1227                                                      NSSCertificateType_PKIX, |  | 
|  1228                                                      &c->id, |  | 
|  1229                                                      nickname, |  | 
|  1230                                                      &c->encoding, |  | 
|  1231                                                      &c->issuer, |  | 
|  1232                                                      &c->subject, |  | 
|  1233                                                      &c->serial, |  | 
|  1234                                                      email, |  | 
|  1235                                                      PR_TRUE); |  | 
|  1236             nss_ZFreeIf(nickname); |  | 
|  1237             nickname = NULL; |  | 
|  1238             if (!newInstance) { |  | 
|  1239                 nssrv = PR_FAILURE; |  | 
|  1240                 goto done; |  | 
|  1241             } |  | 
|  1242             nssPKIObject_AddInstance(&c->object, newInstance); |  | 
|  1243             newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, |  | 
|  1244                                            &c->issuer, &c->serial, |  | 
|  1245                                            nssTrust->serverAuth, |  | 
|  1246                                            nssTrust->clientAuth, |  | 
|  1247                                            nssTrust->codeSigning, |  | 
|  1248                                            nssTrust->emailProtection, |  | 
|  1249                                            nssTrust->stepUpApproved, PR_TRUE); |  | 
|  1250         } |  | 
|  1251         if (newInstance) { |  | 
|  1252             nssCryptokiObject_Destroy(newInstance); |  | 
|  1253             nssrv = PR_SUCCESS; |  | 
|  1254         } else { |  | 
|  1255             nssrv = PR_FAILURE; |  | 
|  1256         } |  | 
|  1257     } else { |  | 
|  1258         nssrv = PR_FAILURE; |  | 
|  1259     } |  | 
|  1260 done: |  | 
|  1261     (void)nssTrust_Destroy(nssTrust); |  | 
|  1262     return nssrv; |  | 
|  1263 } |  | 
|  1264  |  | 
|  1265 /* |  | 
|  1266 ** Delete trust objects matching the given slot. |  | 
|  1267 ** Returns error if a device fails to delete. |  | 
|  1268 ** |  | 
|  1269 ** This function has the side effect of moving the |  | 
|  1270 ** surviving entries to the front of the object list |  | 
|  1271 ** and nullifying the rest. |  | 
|  1272 */ |  | 
|  1273 static PRStatus |  | 
|  1274 DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject) |  | 
|  1275 { |  | 
|  1276     int numNotDestroyed = 0;     /* the ones skipped plus the failures */ |  | 
|  1277     int failureCount = 0;        /* actual deletion failures by devices */ |  | 
|  1278     unsigned int index; |  | 
|  1279  |  | 
|  1280     nssPKIObject_AddRef(tObject); |  | 
|  1281     nssPKIObject_Lock(tObject); |  | 
|  1282     /* Keep going even if a module fails to delete. */ |  | 
|  1283     for (index = 0; index < tObject->numInstances; index++) { |  | 
|  1284         nssCryptokiObject *instance = tObject->instances[index]; |  | 
|  1285         if (!instance) { |  | 
|  1286             continue; |  | 
|  1287         } |  | 
|  1288  |  | 
|  1289         /* ReadOnly and not matched treated the same */ |  | 
|  1290         if (PK11_IsReadOnly(instance->token->pk11slot) || |  | 
|  1291             pk11slot != instance->token->pk11slot) { |  | 
|  1292             tObject->instances[numNotDestroyed++] = instance; |  | 
|  1293             continue; |  | 
|  1294         } |  | 
|  1295  |  | 
|  1296         /* Here we have found a matching one */ |  | 
|  1297         tObject->instances[index] = NULL; |  | 
|  1298         if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) { |  | 
|  1299             nssCryptokiObject_Destroy(instance); |  | 
|  1300         } else { |  | 
|  1301             tObject->instances[numNotDestroyed++] = instance; |  | 
|  1302             failureCount++; |  | 
|  1303         } |  | 
|  1304  |  | 
|  1305     } |  | 
|  1306     if (numNotDestroyed == 0) { |  | 
|  1307         nss_ZFreeIf(tObject->instances); |  | 
|  1308         tObject->numInstances = 0; |  | 
|  1309     } else { |  | 
|  1310         tObject->numInstances = numNotDestroyed; |  | 
|  1311     } |  | 
|  1312  |  | 
|  1313     nssPKIObject_Unlock(tObject); |  | 
|  1314     nssPKIObject_Destroy(tObject); |  | 
|  1315  |  | 
|  1316     return failureCount == 0 ? PR_SUCCESS : PR_FAILURE; |  | 
|  1317 } |  | 
|  1318  |  | 
|  1319 /* |  | 
|  1320 ** Delete trust objects matching the slot of the given certificate. |  | 
|  1321 ** Returns an error if any device fails to delete.  |  | 
|  1322 */ |  | 
|  1323 NSS_EXTERN PRStatus |  | 
|  1324 STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c) |  | 
|  1325 { |  | 
|  1326     PRStatus nssrv = PR_SUCCESS; |  | 
|  1327  |  | 
|  1328     NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); |  | 
|  1329     NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); |  | 
|  1330     /* caller made sure nssTrust isn't NULL */ |  | 
|  1331     nssPKIObject *tobject = &nssTrust->object; |  | 
|  1332     nssPKIObject *cobject = &c->object; |  | 
|  1333     unsigned int i; |  | 
|  1334  |  | 
|  1335     /* Iterate through the cert and trust object instances looking for |  | 
|  1336      * those with matching pk11 slots to delete. Even if some device |  | 
|  1337      * can't delete we keep going. Keeping a status variable for the |  | 
|  1338      * loop so that once it's failed the other gets set. |  | 
|  1339      */ |  | 
|  1340     NSSRWLock_LockRead(td->tokensLock); |  | 
|  1341     nssPKIObject_AddRef(cobject); |  | 
|  1342     nssPKIObject_Lock(cobject); |  | 
|  1343     for (i = 0; i < cobject->numInstances; i++) { |  | 
|  1344         nssCryptokiObject *cInstance = cobject->instances[i]; |  | 
|  1345         if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) { |  | 
|  1346                 PRStatus status; |  | 
|  1347             if (!tobject->numInstances || !tobject->instances) continue; |  | 
|  1348             status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tob
      ject); |  | 
|  1349             if (status == PR_FAILURE) { |  | 
|  1350                 /* set the outer one but keep going */ |  | 
|  1351                 nssrv = PR_FAILURE; |  | 
|  1352             } |  | 
|  1353         } |  | 
|  1354     } |  | 
|  1355     nssPKIObject_Unlock(cobject); |  | 
|  1356     nssPKIObject_Destroy(cobject); |  | 
|  1357     NSSRWLock_UnlockRead(td->tokensLock); |  | 
|  1358     return nssrv; |  | 
|  1359 } |  | 
|  1360  |  | 
|  1361 /* CERT_TraversePermCertsForSubject */ |  | 
|  1362 NSS_IMPLEMENT PRStatus |  | 
|  1363 nssTrustDomain_TraverseCertificatesBySubject ( |  | 
|  1364   NSSTrustDomain *td, |  | 
|  1365   NSSDER *subject, |  | 
|  1366   PRStatus (*callback)(NSSCertificate *c, void *arg), |  | 
|  1367   void *arg |  | 
|  1368 ) |  | 
|  1369 { |  | 
|  1370     PRStatus nssrv = PR_SUCCESS; |  | 
|  1371     NSSArena *tmpArena; |  | 
|  1372     NSSCertificate **subjectCerts; |  | 
|  1373     NSSCertificate *c; |  | 
|  1374     PRIntn i; |  | 
|  1375     tmpArena = NSSArena_Create(); |  | 
|  1376     if (!tmpArena) { |  | 
|  1377         return PR_FAILURE; |  | 
|  1378     } |  | 
|  1379     subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL, |  | 
|  1380                                                             0, tmpArena); |  | 
|  1381     if (subjectCerts) { |  | 
|  1382         for (i=0, c = subjectCerts[i]; c; i++) { |  | 
|  1383             nssrv = callback(c, arg); |  | 
|  1384             if (nssrv != PR_SUCCESS) break; |  | 
|  1385         } |  | 
|  1386     } |  | 
|  1387     nssArena_Destroy(tmpArena); |  | 
|  1388     return nssrv; |  | 
|  1389 } |  | 
|  1390  |  | 
|  1391 /* CERT_TraversePermCertsForNickname */ |  | 
|  1392 NSS_IMPLEMENT PRStatus |  | 
|  1393 nssTrustDomain_TraverseCertificatesByNickname ( |  | 
|  1394   NSSTrustDomain *td, |  | 
|  1395   NSSUTF8 *nickname, |  | 
|  1396   PRStatus (*callback)(NSSCertificate *c, void *arg), |  | 
|  1397   void *arg |  | 
|  1398 ) |  | 
|  1399 { |  | 
|  1400     PRStatus nssrv = PR_SUCCESS; |  | 
|  1401     NSSArena *tmpArena; |  | 
|  1402     NSSCertificate **nickCerts; |  | 
|  1403     NSSCertificate *c; |  | 
|  1404     PRIntn i; |  | 
|  1405     tmpArena = NSSArena_Create(); |  | 
|  1406     if (!tmpArena) { |  | 
|  1407         return PR_FAILURE; |  | 
|  1408     } |  | 
|  1409     nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL, |  | 
|  1410                                                           0, tmpArena); |  | 
|  1411     if (nickCerts) { |  | 
|  1412         for (i=0, c = nickCerts[i]; c; i++) { |  | 
|  1413             nssrv = callback(c, arg); |  | 
|  1414             if (nssrv != PR_SUCCESS) break; |  | 
|  1415         } |  | 
|  1416     } |  | 
|  1417     nssArena_Destroy(tmpArena); |  | 
|  1418     return nssrv; |  | 
|  1419 } |  | 
|  1420  |  | 
|  1421 static void cert_dump_iter(const void *k, void *v, void *a) |  | 
|  1422 { |  | 
|  1423     NSSCertificate *c = (NSSCertificate *)k; |  | 
|  1424     CERTCertificate *cert = STAN_GetCERTCertificate(c); |  | 
|  1425     printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName); |  | 
|  1426 } |  | 
|  1427  |  | 
|  1428 void |  | 
|  1429 nss_DumpCertificateCacheInfo() |  | 
|  1430 { |  | 
|  1431     NSSTrustDomain *td; |  | 
|  1432     NSSCryptoContext *cc; |  | 
|  1433     td = STAN_GetDefaultTrustDomain(); |  | 
|  1434     cc = STAN_GetDefaultCryptoContext(); |  | 
|  1435     printf("\n\nCertificates in the cache:\n"); |  | 
|  1436     nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL); |  | 
|  1437     printf("\n\nCertificates in the temporary store:\n"); |  | 
|  1438     if (cc->certStore) { |  | 
|  1439         nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL); |  | 
|  1440     } |  | 
|  1441 } |  | 
|  1442  |  | 
| OLD | NEW |