/* would not do name in pluto, but dn */ static CERTCertList *get_trust_certlist(CERTCertDBHandle *handle, const char *name) { CERTCertList *trustcl = NULL; CERTCertList *tmpcl = NULL; CERTCertificate *ca = NULL; CERTCertListNode *node = NULL; if ((ca = CERT_FindCertByNickname(handle, name)) == NULL) { printf("CERT_FindCertByNickname failed %d\n", PORT_GetError()); return NULL; } if (ca->isRoot) { printf("trust anchor: %s\n",ca->subjectName); trustcl = CERT_NewCertList(); CERT_AddCertToListTail(trustcl, ca); } else { tmpcl = CERT_GetCertChainFromCert(ca, PR_Now(), certUsageAnyCA); if (tmpcl == NULL) { printf("CERT_GetCertChainFromCert failed %d\n", PORT_GetError()); return NULL; } for (node = CERT_LIST_HEAD(tmpcl); !CERT_LIST_END(node, tmpcl); node = CERT_LIST_NEXT(node)) { printf("CERT list: %s\n", node->cert->subjectName); if (node->cert->isRoot) { trustcl = CERT_NewCertList(); CERT_AddCertToListTail(trustcl, node->cert); break; } } } if (trustcl == NULL || CERT_LIST_EMPTY(trustcl)) { printf("Trust chain empty!\n"); return NULL; } return trustcl; }
/** Compares the common name specified in the subject DN for a certificate * with a specified hostname. */ SECStatus CERT_VerifyCertName(const CERTCertificate *cert, const char *hostname) { LOG_DEBUG(">> CERT_VerifyCertName: %s", hostname); static SECStatus (*VerifyCertName)(CERTCertificate *cert, const char *hostname) = NULL; if (!VerifyCertName) VerifyCertName = getfunc("CERT_VerifyCertName", LIBNSS3); if (!VerifyCertName) return SECFailure; SECStatus ret = VerifyCertName(cert, hostname); LOG_DEBUG(">>> result = %d", ret); PATROL_init(); if (!cfg.loaded) PATROL_get_config(&cfg); PRNetAddr addr; if (PR_SUCCESS != PR_GetPeerName(nss_fd, &addr)) return ret; PatrolData *chain = NULL; size_t chain_len = PATROL_NSS_convert_chain(CERT_GetCertChainFromCert(cert, PR_Now(), certUsageSSLCA), &chain); PatrolRC pret = PATROL_check(&cfg, chain, chain_len, PATROL_CERT_X509, ret == SECSuccess ? PATROL_OK : PATROL_ERROR, hostname, 0, "tcp", // FIXME PR_ntohs((addr.raw.family == PR_AF_INET6) ? addr.ipv6.port : addr.inet.port)); LOG_DEBUG(">>> patrol result = %d", pret); free(chain); PATROL_deinit(); return pret == PATROL_OK ? SECSuccess : SECFailure; }
/* * nsIEnumerator getChain(); */ NS_IMETHODIMP nsNSSCertificate::GetChain(nsIArray **_rvChain) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) return NS_ERROR_NOT_AVAILABLE; NS_ENSURE_ARG(_rvChain); nsresult rv; /* Get the cert chain from NSS */ CERTCertList *nssChain = NULL; PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting chain for \"%s\"\n", mCert->nickname)); nssChain = CERT_GetCertChainFromCert(mCert, PR_Now(), certUsageSSLClient); if (!nssChain) return NS_ERROR_FAILURE; /* enumerate the chain for scripting purposes */ nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); if (NS_FAILED(rv)) { goto done; } CERTCertListNode *node; for (node = CERT_LIST_HEAD(nssChain); !CERT_LIST_END(node, nssChain); node = CERT_LIST_NEXT(node)) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("adding %s to chain\n", node->cert->nickname)); nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert); array->AppendElement(cert, false); } *_rvChain = array; NS_IF_ADDREF(*_rvChain); rv = NS_OK; done: if (nssChain) CERT_DestroyCertList(nssChain); return rv; }
SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd, PRBool checksig, PRBool isServer) { nsNSSShutDownPreventionLock locker; // first the default action SECStatus rv = SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); // We want to remember the CA certs in the temp db, so that the application can find the // complete chain at any time it might need it. // But we keep only those CA certs in the temp db, that we didn't already know. CERTCertificate *serverCert = SSL_PeerCertificate(fd); CERTCertificateCleaner serverCertCleaner(serverCert); if (serverCert) { nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret; nsRefPtr<nsSSLStatus> status = infoObject->SSLStatus(); nsRefPtr<nsNSSCertificate> nsc; if (!status || !status->mServerCert) { nsc = new nsNSSCertificate(serverCert); } if (SECSuccess == rv) { if (nsc) { PRBool dummyIsEV; nsc->GetIsExtendedValidation(&dummyIsEV); // the nsc object will cache the status } CERTCertList *certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA); nsCOMPtr<nsINSSComponent> nssComponent; for (CERTCertListNode *node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node)) { if (node->cert->slot) { // This cert was found on a token, no need to remember it in the temp db. continue; } if (node->cert->isperm) { // We don't need to remember certs already stored in perm db. continue; } if (node->cert == serverCert) { // We don't want to remember the server cert, // the code that cares for displaying page info does this already. continue; } // We have found a signer cert that we want to remember. nsCAutoString nickname; nickname = nsNSSCertificate::defaultServerNickname(node->cert); if (!nickname.IsEmpty()) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); if (slot) { PK11_ImportCert(slot, node->cert, CK_INVALID_HANDLE, const_cast<char*>(nickname.get()), PR_FALSE); PK11_FreeSlot(slot); } } } CERT_DestroyCertList(certList); } // The connection may get terminated, for example, if the server requires // a client cert. Let's provide a minimal SSLStatus // to the caller that contains at least the cert and its status. if (!status) { status = new nsSSLStatus(); infoObject->SetSSLStatus(status); } if (status && !status->mServerCert) { status->mServerCert = nsc; PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("AuthCertificateCallback setting NEW cert %p\n", status->mServerCert.get())); } } return rv; }
static SECStatus ClassicVerifyCert(CERTCertificate * cert, const SECCertificateUsage usage, const PRTime time, nsIInterfaceRequestor * pinArg, /*optional out*/ CERTCertList **validationChain, /*optional out*/ CERTVerifyLog *verifyLog) { SECStatus rv; SECCertUsage enumUsage; if (validationChain) { switch(usage){ case certificateUsageSSLClient: enumUsage = certUsageSSLClient; break; case certificateUsageSSLServer: enumUsage = certUsageSSLServer; break; case certificateUsageSSLServerWithStepUp: enumUsage = certUsageSSLServerWithStepUp; break; case certificateUsageSSLCA: enumUsage = certUsageSSLCA; break; case certificateUsageEmailSigner: enumUsage = certUsageEmailSigner; break; case certificateUsageEmailRecipient: enumUsage = certUsageEmailRecipient; break; case certificateUsageObjectSigner: enumUsage = certUsageObjectSigner; break; case certificateUsageUserCertImport: enumUsage = certUsageUserCertImport; break; case certificateUsageVerifyCA: enumUsage = certUsageVerifyCA; break; case certificateUsageProtectedObjectSigner: enumUsage = certUsageProtectedObjectSigner; break; case certificateUsageStatusResponder: enumUsage = certUsageStatusResponder; break; case certificateUsageAnyCA: enumUsage = certUsageAnyCA; break; default: return SECFailure; } } if (usage == certificateUsageSSLServer) { /* SSL server cert verification has always used CERT_VerifyCert, so we * continue to use it for SSL cert verification to minimize the risk of * there being any differnce in results between CERT_VerifyCert and * CERT_VerifyCertificate. */ rv = CERT_VerifyCert(CERT_GetDefaultCertDB(), cert, true, certUsageSSLServer, time, pinArg, verifyLog); } else { rv = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), cert, true, usage, time, pinArg, verifyLog, nullptr); } if (rv == SECSuccess && validationChain) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: getting chain in 'classic' \n")); *validationChain = CERT_GetCertChainFromCert(cert, time, enumUsage); if (!*validationChain) { rv = SECFailure; } } return rv; }