in evReady/src/ev-checker.cpp [190:317]
int main(int argc, char* argv[]) {
if (argc < 7) {
PrintUsage(argv[0]);
return 1;
}
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
PrintPRError("NSS_NoDB_Init failed");
}
const char* certsFileName = nullptr;
const char* dottedOID = nullptr;
const char* oidDescription = nullptr;
const char* hostname = nullptr;
ScopedPLOptState opt(PL_CreateOptState(argc, argv, "c:o:d:h:"));
PLOptStatus os;
while ((os = PL_GetNextOpt(opt.get())) != PL_OPT_EOL) {
if (os == PL_OPT_BAD) {
continue;
}
switch (opt->option) {
case 'c':
certsFileName = opt->value;
break;
case 'o':
dottedOID = opt->value;
break;
case 'd':
oidDescription = opt->value;
break;
case 'h':
hostname = opt->value;
break;
default:
PrintUsage(argv[0]);
return 1;
}
}
if (!certsFileName || !dottedOID || !hostname) {
PrintUsage(argv[0]);
return 1;
}
mozilla::pkix::RegisterErrorTable();
ScopedCERTCertList certs(ReadCertsFromFile(certsFileName));
if (CERT_LIST_END(CERT_LIST_HEAD(certs), certs)) {
std::cerr << "Couldn't read certificates from '" << certsFileName << "'";
std::cerr << std::endl;
return 1;
}
CERTCertificate* root = CERT_LIST_TAIL(certs.get())->cert;
CERTCertificate* ee = CERT_LIST_HEAD(certs.get())->cert;
if (oidDescription) {
std::cout << "// " << root->subjectName << std::endl;
std::cout << "\"" << dottedOID << "\"," << std::endl;
std::cout << "\"" << oidDescription << "\"," << std::endl;
PrintSHA256HashOf(root->derCert);
PrintBase64Of(root->derIssuer);
PrintBase64Of(root->serialNumber);
}
EVCheckerTrustDomain trustDomain(CERT_DupCertificate(root));
if (trustDomain.Init(dottedOID, oidDescription) != SECSuccess) {
return 1;
}
ScopedCERTCertList results;
mozilla::pkix::CertPolicyId evPolicy;
if (trustDomain.GetFirstEVPolicyForCert(ee, evPolicy)
!= SECSuccess) {
PrintPRError("GetFirstEVPolicyForCert failed");
std::cerr << "This may mean that the specified EV Policy OID was not ";
std::cerr << "found in the end-entity certificate." << std::endl;
return 1;
}
mozilla::pkix::Input eeInput;
mozilla::pkix::Result rv = eeInput.Init(ee->derCert.data, ee->derCert.len);
if (rv != mozilla::pkix::Success) {
std::cerr << "Couldn't initialize Input from ee cert" << std::endl;
return 1;
}
rv = BuildCertChain(trustDomain, eeInput, mozilla::pkix::Now(),
mozilla::pkix::EndEntityOrCA::MustBeEndEntity,
mozilla::pkix::KeyUsage::noParticularKeyUsageRequired,
mozilla::pkix::KeyPurposeId::anyExtendedKeyUsage,
evPolicy, nullptr);
if (rv != mozilla::pkix::Success) {
PR_SetError(mozilla::pkix::MapResultToPRErrorCode(rv), 0);
PrintPRError("BuildCertChain failed");
PrintPRErrorString();
if (rv == mozilla::pkix::Result::ERROR_POLICY_VALIDATION_FAILED) {
std::cerr << "It appears be the case that the end-entity certificate ";
std::cerr << "was issued directly by the root. There should be at ";
std::cerr << "least one intermediate in the certificate issuance chain.";
std::cerr << std::endl;
} else if (rv == mozilla::pkix::Result::ERROR_CERT_BAD_ACCESS_LOCATION) {
std::cerr << "It appears to be the case that a certificate in the ";
std::cerr << "issuance chain has a malformed or missing OCSP AIA URI";
std::cerr << std::endl;
}
return 1;
}
mozilla::pkix::Input hostnameInput;
rv = hostnameInput.Init(reinterpret_cast<const uint8_t*>(hostname),
strlen(hostname));
if (rv != mozilla::pkix::Success) {
PrintPRError("Couldn't initialize Input from hostname");
return 1;
}
rv = CheckCertHostname(eeInput, hostnameInput);
if (rv != mozilla::pkix::Success) {
PR_SetError(mozilla::pkix::MapResultToPRErrorCode(rv), 0);
PrintPRError("CheckCertHostname failed");
PrintPRErrorString();
if (rv == mozilla::pkix::Result::ERROR_BAD_CERT_DOMAIN) {
std::cerr << "It appears that the end-entity certificate is not valid ";
std::cerr << "for the domain it is hosted at.";
std::cerr << std::endl;
} else if (rv == mozilla::pkix::Result::ERROR_BAD_DER) {
std::cerr << "It appears that the name information in the end-entity ";
std::cerr << "certificate does not conform to RFC 822, RFC 5280, or ";
std::cerr << "RFC 6125.";
std::cerr << std::endl;
}
return 1;
}
std::cout << "Success!" << std::endl;
return 0;
}