mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
bug 1519492 - reorganize NSSCertDBTrustDomain::FindIssuer to facilitate future improvements r=jcj
Before this patch, NSSCertDBTrustDomain::FindIssuer would iterate over its candidate list (a CERTCertList) twice. This would have made it difficult to add in candidate issuers from other sources (see e.g. bug 1514118, wherein the goal is to bypass NSS' view of what certificates exist to facilitate third party/enterprise roots). This patch reorganizes this function to make future improvements easier. Differential Revision: https://phabricator.services.mozilla.com/D16341 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
5f076f7b17
commit
f1b40f3220
@ -85,79 +85,67 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(
|
|||||||
mSCTListFromCertificate(),
|
mSCTListFromCertificate(),
|
||||||
mSCTListFromOCSPStapling() {}
|
mSCTListFromOCSPStapling() {}
|
||||||
|
|
||||||
// If useRoots is true, we only use root certificates in the candidate list.
|
Result NSSCertDBTrustDomain::FindIssuer(Input encodedIssuerName,
|
||||||
// If useRoots is false, we only use non-root certificates in the list.
|
IssuerChecker& checker, Time) {
|
||||||
static Result FindIssuerInner(const UniqueCERTCertList& candidates,
|
// NSS seems not to differentiate between "no potential issuers found" and
|
||||||
bool useRoots, Input encodedIssuerName,
|
// "there was an error trying to retrieve the potential issuers." We assume
|
||||||
TrustDomain::IssuerChecker& checker,
|
// there was no error.
|
||||||
/*out*/ bool& keepGoing) {
|
SECItem encodedIssuerNameItem = UnsafeMapInputToSECItem(encodedIssuerName);
|
||||||
keepGoing = true;
|
UniqueCERTCertList candidates(CERT_CreateSubjectCertList(
|
||||||
|
nullptr, CERT_GetDefaultCertDB(), &encodedIssuerNameItem, 0, false));
|
||||||
|
if (!candidates) {
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Input> rootCandidates;
|
||||||
|
Vector<Input> intermediateCandidates;
|
||||||
for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
|
for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
|
||||||
!CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
|
!CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
|
||||||
bool candidateIsRoot = !!n->cert->isRoot;
|
|
||||||
if (candidateIsRoot != useRoots) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Input certDER;
|
Input certDER;
|
||||||
Result rv = certDER.Init(n->cert->derCert.data, n->cert->derCert.len);
|
Result rv = certDER.Init(n->cert->derCert.data, n->cert->derCert.len);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
continue; // probably too big
|
continue; // probably too big
|
||||||
}
|
}
|
||||||
|
if (n->cert->isRoot) {
|
||||||
const SECItem encodedIssuerNameItem = {
|
if (!rootCandidates.append(certDER)) {
|
||||||
siBuffer, const_cast<unsigned char*>(encodedIssuerName.UnsafeGetData()),
|
return Result::FATAL_ERROR_NO_MEMORY;
|
||||||
encodedIssuerName.GetLength()};
|
|
||||||
ScopedAutoSECItem nameConstraints;
|
|
||||||
SECStatus srv = CERT_GetImposedNameConstraints(&encodedIssuerNameItem,
|
|
||||||
&nameConstraints);
|
|
||||||
if (srv != SECSuccess) {
|
|
||||||
if (PR_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
|
|
||||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no imposed name constraints were found, continue without them
|
|
||||||
rv = checker.Check(certDER, nullptr, keepGoing);
|
|
||||||
} else {
|
} else {
|
||||||
// Otherwise apply the constraints
|
if (!intermediateCandidates.append(certDER)) {
|
||||||
Input nameConstraintsInput;
|
return Result::FATAL_ERROR_NO_MEMORY;
|
||||||
if (nameConstraintsInput.Init(nameConstraints.data,
|
|
||||||
nameConstraints.len) != Success) {
|
|
||||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
|
||||||
}
|
}
|
||||||
rv = checker.Check(certDER, &nameConstraintsInput, keepGoing);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle imposed name constraints, if any.
|
||||||
|
ScopedAutoSECItem nameConstraints;
|
||||||
|
Input nameConstraintsInput;
|
||||||
|
Input* nameConstraintsInputPtr = nullptr;
|
||||||
|
SECStatus srv =
|
||||||
|
CERT_GetImposedNameConstraints(&encodedIssuerNameItem, &nameConstraints);
|
||||||
|
if (srv == SECSuccess) {
|
||||||
|
if (nameConstraintsInput.Init(nameConstraints.data, nameConstraints.len) !=
|
||||||
|
Success) {
|
||||||
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
}
|
||||||
|
nameConstraintsInputPtr = &nameConstraintsInput;
|
||||||
|
} else if (PR_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
|
||||||
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try all root certs first and then all (presumably) intermediates.
|
||||||
|
if (!rootCandidates.appendAll(intermediateCandidates)) {
|
||||||
|
return Result::FATAL_ERROR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Input candidate : rootCandidates) {
|
||||||
|
bool keepGoing;
|
||||||
|
Result rv = checker.Check(candidate, nameConstraintsInputPtr, keepGoing);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
if (!keepGoing) {
|
if (!keepGoing) {
|
||||||
break;
|
return Success;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result NSSCertDBTrustDomain::FindIssuer(Input encodedIssuerName,
|
|
||||||
IssuerChecker& checker, Time) {
|
|
||||||
// TODO: NSS seems to be ambiguous between "no potential issuers found" and
|
|
||||||
// "there was an error trying to retrieve the potential issuers."
|
|
||||||
SECItem encodedIssuerNameItem = UnsafeMapInputToSECItem(encodedIssuerName);
|
|
||||||
UniqueCERTCertList candidates(CERT_CreateSubjectCertList(
|
|
||||||
nullptr, CERT_GetDefaultCertDB(), &encodedIssuerNameItem, 0, false));
|
|
||||||
if (candidates) {
|
|
||||||
// First, try all the root certs; then try all the non-root certs.
|
|
||||||
bool keepGoing;
|
|
||||||
Result rv = FindIssuerInner(candidates, true, encodedIssuerName, checker,
|
|
||||||
keepGoing);
|
|
||||||
if (rv != Success) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
if (keepGoing) {
|
|
||||||
rv = FindIssuerInner(candidates, false, encodedIssuerName, checker,
|
|
||||||
keepGoing);
|
|
||||||
if (rv != Success) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user