/* * Lookup a certificate in the database by name */ CERTCertificate * CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr) { CERTName *name; SECItem *nameItem; CERTCertificate *cert = NULL; PRArenaPool *arena = NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { goto loser; } name = CERT_AsciiToName(nameStr); if ( name ) { nameItem = SEC_ASN1EncodeItem (arena, NULL, (void *)name, CERT_NameTemplate); if ( nameItem != NULL ) { cert = CERT_FindCertByName(handle, nameItem); } CERT_DestroyName(name); } loser: if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } return(cert); }
/* find the given extension in the certificate of the Issuer of 'cert' */ SECStatus CERT_FindIssuerCertExtension(CERTCertificate *cert, int tag, SECItem *value) { CERTCertificate *issuercert; SECStatus rv; issuercert = CERT_FindCertByName(cert->dbhandle, &cert->derIssuer); if ( issuercert ) { rv = cert_FindExtension(issuercert->extensions, tag, value); CERT_DestroyCertificate(issuercert); } else { rv = SECFailure; } return(rv); }
static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls) { CERTCrlHeadNode *crlList = NULL; CERTCrlNode *crlNode = NULL; CERTName *name = NULL; PLArenaPool *arena = NULL; SECStatus rv; do { arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); if (arena == NULL) { fprintf(stderr, "%s: fail to allocate memory\n", progName); break; } name = PORT_ArenaZAlloc (arena, sizeof(*name)); if (name == NULL) { fprintf(stderr, "%s: fail to allocate memory\n", progName); break; } name->arena = arena; rv = SEC_LookupCrls (certHandle, &crlList, crlType); if (rv != SECSuccess) { fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName, SECU_Strerror(PORT_GetError())); break; } /* just in case */ if (!crlList) break; crlNode = crlList->first; fprintf (stdout, "\n"); fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type"); while (crlNode) { char* asciiname = NULL; CERTCertificate *cert = NULL; if (crlNode->crl && &crlNode->crl->crl.derName) { cert = CERT_FindCertByName(certHandle, &crlNode->crl->crl.derName); if (!cert) { SECU_PrintError(progName, "could not find signing " "certificate in database"); } } if (cert) { char* certName = NULL; if (cert->nickname && PORT_Strlen(cert->nickname) > 0) { certName = cert->nickname; } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) { certName = cert->emailAddr; } if (certName) { asciiname = PORT_Strdup(certName); } CERT_DestroyCertificate(cert); } if (!asciiname) { name = &crlNode->crl->crl.name; if (!name){ SECU_PrintError(progName, "fail to get the CRL " "issuer name"); continue; } asciiname = CERT_NameToAscii(name); } fprintf (stdout, "%-40s %-5s\n", asciiname, "CRL"); if (asciiname) { PORT_Free(asciiname); } if ( PR_TRUE == deletecrls) { CERTSignedCrl* acrl = NULL; SECItem* issuer = &crlNode->crl->crl.derName; acrl = SEC_FindCrlByName(certHandle, issuer, crlType); if (acrl) { SEC_DeletePermCRL(acrl); SEC_DestroyCrl(acrl); } } crlNode = crlNode->next; } } while (0); if (crlList) PORT_FreeArena (crlList->arena, PR_FALSE); PORT_FreeArena (arena, PR_FALSE); }
NS_IMETHODIMP nsCRLManager::ImportCrl (PRUint8 *aData, PRUint32 aLength, nsIURI * aURI, PRUint32 aType, PRBool doSilentDonwload, const PRUnichar* crlKey) { nsNSSShutDownPreventionLock locker; nsresult rv; PRArenaPool *arena = NULL; CERTCertificate *caCert; SECItem derName = { siBuffer, NULL, 0 }; SECItem derCrl; CERTSignedData sd; SECStatus sec_rv; CERTSignedCrl *crl; nsCAutoString url; nsCOMPtr<nsICRLInfo> crlData; PRBool importSuccessful; PRInt32 errorCode; nsString errorMessage; nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); if (NS_FAILED(rv)) return rv; aURI->GetSpec(url); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { goto loser; } memset(&sd, 0, sizeof(sd)); derCrl.data = (unsigned char*)aData; derCrl.len = aLength; sec_rv = CERT_KeyFromDERCrl(arena, &derCrl, &derName); if (sec_rv != SECSuccess) { goto loser; } caCert = CERT_FindCertByName(CERT_GetDefaultCertDB(), &derName); if (!caCert) { if (aType == SEC_KRL_TYPE){ goto loser; } } else { sec_rv = SEC_ASN1DecodeItem(arena, &sd, SEC_ASN1_GET(CERT_SignedDataTemplate), &derCrl); if (sec_rv != SECSuccess) { goto loser; } sec_rv = CERT_VerifySignedData(&sd, caCert, PR_Now(), nsnull); if (sec_rv != SECSuccess) { goto loser; } } crl = SEC_NewCrl(CERT_GetDefaultCertDB(), const_cast<char*>(url.get()), &derCrl, aType); if (!crl) { goto loser; } crlData = new nsCRLInfo(crl); SSL_ClearSessionCache(); SEC_DestroyCrl(crl); importSuccessful = PR_TRUE; goto done; loser: importSuccessful = PR_FALSE; errorCode = PR_GetError(); switch (errorCode) { case SEC_ERROR_CRL_EXPIRED: nssComponent->GetPIPNSSBundleString("CrlImportFailureExpired", errorMessage); break; case SEC_ERROR_CRL_BAD_SIGNATURE: nssComponent->GetPIPNSSBundleString("CrlImportFailureBadSignature", errorMessage); break; case SEC_ERROR_CRL_INVALID: nssComponent->GetPIPNSSBundleString("CrlImportFailureInvalid", errorMessage); break; case SEC_ERROR_OLD_CRL: nssComponent->GetPIPNSSBundleString("CrlImportFailureOld", errorMessage); break; case SEC_ERROR_CRL_NOT_YET_VALID: nssComponent->GetPIPNSSBundleString("CrlImportFailureNotYetValid", errorMessage); break; default: nssComponent->GetPIPNSSBundleString("CrlImportFailureReasonUnknown", errorMessage); errorMessage.AppendInt(errorCode,16); break; } done: if(!doSilentDonwload){ if (!importSuccessful){ nsString message; nsString temp; nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); nsCOMPtr<nsIPrompt> prompter; if (wwatch){ wwatch->GetNewPrompter(0, getter_AddRefs(prompter)); nssComponent->GetPIPNSSBundleString("CrlImportFailure1x", message); message.Append(NS_LITERAL_STRING("\n").get()); message.Append(errorMessage); nssComponent->GetPIPNSSBundleString("CrlImportFailure2", temp); message.Append(NS_LITERAL_STRING("\n").get()); message.Append(temp); if(prompter) { nsPSMUITracker tracker; if (!tracker.isUIForbidden()) { prompter->Alert(0, message.get()); } } } } else { nsCOMPtr<nsICertificateDialogs> certDialogs; // Not being able to display the success dialog should not // be a fatal error, so don't return a failure code. { nsPSMUITracker tracker; if (tracker.isUIForbidden()) { rv = NS_ERROR_NOT_AVAILABLE; } else { rv = ::getNSSDialogs(getter_AddRefs(certDialogs), NS_GET_IID(nsICertificateDialogs), NS_CERTIFICATEDIALOGS_CONTRACTID); } } if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext(); certDialogs->CrlImportStatusDialog(cxt, crlData); } } } else { if(crlKey == nsnull){ return NS_ERROR_FAILURE; } nsCOMPtr<nsIPrefService> prefSvc = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv); nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv); if (NS_FAILED(rv)){ return rv; } nsCAutoString updateErrCntPrefStr(CRL_AUTOUPDATE_ERRCNT_PREF); updateErrCntPrefStr.AppendWithConversion(crlKey); if(importSuccessful){ PRUnichar *updateTime; nsCAutoString updateTimeStr; nsCString updateURL; PRInt32 timingTypePref; double dayCnt; char *dayCntStr; nsCAutoString updateTypePrefStr(CRL_AUTOUPDATE_TIMIINGTYPE_PREF); nsCAutoString updateTimePrefStr(CRL_AUTOUPDATE_TIME_PREF); nsCAutoString updateUrlPrefStr(CRL_AUTOUPDATE_URL_PREF); nsCAutoString updateDayCntPrefStr(CRL_AUTOUPDATE_DAYCNT_PREF); nsCAutoString updateFreqCntPrefStr(CRL_AUTOUPDATE_FREQCNT_PREF); updateTypePrefStr.AppendWithConversion(crlKey); updateTimePrefStr.AppendWithConversion(crlKey); updateUrlPrefStr.AppendWithConversion(crlKey); updateDayCntPrefStr.AppendWithConversion(crlKey); updateFreqCntPrefStr.AppendWithConversion(crlKey); pref->GetIntPref(updateTypePrefStr.get(),&timingTypePref); //Compute and update the next download instant if(timingTypePref == TYPE_AUTOUPDATE_TIME_BASED){ pref->GetCharPref(updateDayCntPrefStr.get(),&dayCntStr); }else{ pref->GetCharPref(updateFreqCntPrefStr.get(),&dayCntStr); } dayCnt = atof(dayCntStr); nsMemory::Free(dayCntStr); PRBool toBeRescheduled = PR_FALSE; if(NS_SUCCEEDED(ComputeNextAutoUpdateTime(crlData, timingTypePref, dayCnt, &updateTime))){ updateTimeStr.AssignWithConversion(updateTime); nsMemory::Free(updateTime); pref->SetCharPref(updateTimePrefStr.get(),updateTimeStr.get()); //Now, check if this update time is already in the past. This would //imply we have downloaded the same crl, or there is something wrong //with the next update date. We will not reschedule this crl in this //session anymore - or else, we land into a loop. It would anyway be //imported once the browser is restarted. PRTime nextTime; PR_ParseTimeString(updateTimeStr.get(),PR_TRUE, &nextTime); if(LL_CMP(nextTime, > , PR_Now())){ toBeRescheduled = PR_TRUE; } } //Update the url to download from, next time crlData->GetLastFetchURL(updateURL); pref->SetCharPref(updateUrlPrefStr.get(),updateURL.get()); pref->SetIntPref(updateErrCntPrefStr.get(),0); if (toBeRescheduled) { nsAutoString hashKey(crlKey); nssComponent->RemoveCrlFromList(hashKey); nssComponent->DefineNextTimer(); } } else{
CERTSignedCrl* PK11_ImportCRL(PK11SlotInfo * slot, SECItem *derCRL, char *url, int type, void *wincx, PRInt32 importOptions, PRArenaPool* arena, PRInt32 decodeoptions) { CERTSignedCrl *newCrl, *crl; SECStatus rv; CERTCertificate *caCert = NULL; newCrl = crl = NULL; do { newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type, decodeoptions); if (newCrl == NULL) { if (type == SEC_CRL_TYPE) { /* only promote error when the error code is too generic */ if (PORT_GetError () == SEC_ERROR_BAD_DER) PORT_SetError(SEC_ERROR_CRL_INVALID); } else { PORT_SetError(SEC_ERROR_KRL_INVALID); } break; } if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){ CERTCertDBHandle* handle = CERT_GetDefaultCertDB(); PR_ASSERT(handle != NULL); caCert = CERT_FindCertByName (handle, &newCrl->crl.derName); if (caCert == NULL) { PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); break; } /* If caCert is a v3 certificate, make sure that it can be used for crl signing purpose */ rv = CERT_CheckCertUsage (caCert, KU_CRL_SIGN); if (rv != SECSuccess) { break; } rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert, PR_Now(), wincx); if (rv != SECSuccess) { if (type == SEC_CRL_TYPE) { PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE); } else { PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE); } break; } } crl = crl_storeCRL(slot, url, newCrl, derCRL, type); } while (0); if (crl == NULL) { SEC_DestroyCrl (newCrl); } if (caCert) { CERT_DestroyCertificate(caCert); } return (crl); }
/* * Look to see if any of the signers in the cert chain for "cert" are found * in the list of caNames. * Returns SECSuccess if so, SECFailure if not. */ SECStatus NSS_CmpCertChainWCANames(CERTCertificate *cert, CERTDistNames *caNames) { SECItem * caname; CERTCertificate * curcert; CERTCertificate * oldcert; PRInt32 contentlen; int j; int headerlen; int depth; SECStatus rv; SECItem issuerName; SECItem compatIssuerName; if (!cert || !caNames || !caNames->nnames || !caNames->names || !caNames->names->data) return SECFailure; depth=0; curcert = CERT_DupCertificate(cert); while( curcert ) { issuerName = curcert->derIssuer; /* compute an alternate issuer name for compatibility with 2.0 * enterprise server, which send the CA names without * the outer layer of DER header */ rv = DER_Lengths(&issuerName, &headerlen, (PRUint32 *)&contentlen); if ( rv == SECSuccess ) { compatIssuerName.data = &issuerName.data[headerlen]; compatIssuerName.len = issuerName.len - headerlen; } else { compatIssuerName.data = NULL; compatIssuerName.len = 0; } for (j = 0; j < caNames->nnames; j++) { caname = &caNames->names[j]; if (SECITEM_CompareItem(&issuerName, caname) == SECEqual) { rv = SECSuccess; CERT_DestroyCertificate(curcert); goto done; } else if (SECITEM_CompareItem(&compatIssuerName, caname) == SECEqual) { rv = SECSuccess; CERT_DestroyCertificate(curcert); goto done; } } if ( ( depth <= 20 ) && ( SECITEM_CompareItem(&curcert->derIssuer, &curcert->derSubject) != SECEqual ) ) { oldcert = curcert; curcert = CERT_FindCertByName(curcert->dbhandle, &curcert->derIssuer); CERT_DestroyCertificate(oldcert); depth++; } else { CERT_DestroyCertificate(curcert); curcert = NULL; } } rv = SECFailure; done: return rv; }
SECStatus ConfigSecureServerWithNamedCert(PRFileDesc *fd, const char *certName, /*optional*/ ScopedCERTCertificate *certOut, /*optional*/ SSLKEAType *keaOut) { ScopedCERTCertificate cert(PK11_FindCertFromNickname(certName, nullptr)); if (!cert) { PrintPRError("PK11_FindCertFromNickname failed"); return SECFailure; } // If an intermediate certificate issued the server certificate (rather than // directly by a trust anchor), we want to send it along in the handshake so // we don't encounter unknown issuer errors when that's not what we're // testing. UniqueCERTCertificateList certList; ScopedCERTCertificate issuerCert( CERT_FindCertByName(CERT_GetDefaultCertDB(), &cert->derIssuer)); // If we can't find the issuer cert, continue without it. if (issuerCert) { // Sadly, CERTCertificateList does not have a CERT_NewCertificateList // utility function, so we must create it ourselves. This consists // of creating an arena, allocating space for the CERTCertificateList, // and then transferring ownership of the arena to that list. ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { PrintPRError("PORT_NewArena failed"); return SECFailure; } certList.reset(static_cast<CERTCertificateList*>( PORT_ArenaAlloc(arena.get(), sizeof(CERTCertificateList)))); if (!certList) { PrintPRError("PORT_ArenaAlloc failed"); return SECFailure; } certList->arena = arena.forget(); // We also have to manually copy the certificates we care about to the // list, because there aren't any utility functions for that either. certList->certs = reinterpret_cast<SECItem*>( PORT_ArenaAlloc(certList->arena, 2 * sizeof(SECItem))); if (SECITEM_CopyItem(certList->arena, certList->certs, &cert->derCert) != SECSuccess) { PrintPRError("SECITEM_CopyItem failed"); return SECFailure; } if (SECITEM_CopyItem(certList->arena, certList->certs + 1, &issuerCert->derCert) != SECSuccess) { PrintPRError("SECITEM_CopyItem failed"); return SECFailure; } certList->len = 2; } ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); UniqueSECKEYPrivateKey key( PK11_FindKeyByDERCert(slot.get(), cert.get(), nullptr)); if (!key) { PrintPRError("PK11_FindKeyByDERCert failed"); return SECFailure; } SSLKEAType certKEA = NSS_FindCertKEAType(cert); if (SSL_ConfigSecureServerWithCertChain(fd, cert.get(), certList.get(), key.get(), certKEA) != SECSuccess) { PrintPRError("SSL_ConfigSecureServer failed"); return SECFailure; } if (certOut) { *certOut = cert.forget(); } if (keaOut) { *keaOut = certKEA; } return SECSuccess; }