зеркало из https://github.com/mozilla/gecko-dev.git
Bug 975122: Allow cert error overrides when insanity::pkix is used, r?cviecco, r?keeler
--HG-- extra : rebase_source : 47f5e779a16c462e40baa2d9cec2e83946c9076c
This commit is contained in:
Родитель
0a4df845e2
Коммит
c3a50adf07
|
@ -746,6 +746,8 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
// CreateCertErrorRunnable assumes that CERT_VerifyCertName is only called
|
||||
// if VerifyCert succeeded.
|
||||
ScopedCERTCertList validationChain;
|
||||
SECStatus rv = VerifyCert(peerCert, stapledOCSPResponse,
|
||||
certificateUsageSSLServer, time,
|
||||
|
|
|
@ -33,7 +33,7 @@ interface nsIOpenSignedAppFileCallback : nsISupports
|
|||
* This represents a service to access and manipulate
|
||||
* X.509 certificates stored in a database.
|
||||
*/
|
||||
[scriptable, uuid(398dfa21-f29d-4530-bb42-136c6e7d9486)]
|
||||
[scriptable, uuid(7446a5b1-84ca-491f-a2fe-0bc60a71ffa5)]
|
||||
interface nsIX509CertDB : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -197,6 +197,14 @@ interface nsIX509CertDB : nsISupports {
|
|||
in unsigned long type,
|
||||
in unsigned long trust);
|
||||
|
||||
/**
|
||||
* @param cert The certificate for which to modify trust.
|
||||
* @param trustString decoded by CERT_DecodeTrustString. 3 comma separated
|
||||
* characters, indicating SSL, Email, and Obj signing
|
||||
* trust.
|
||||
*/
|
||||
void setCertTrustFromString(in nsIX509Cert3 cert, in string trustString);
|
||||
|
||||
/**
|
||||
* Query whether a certificate is trusted for a particular use.
|
||||
*
|
||||
|
|
|
@ -303,7 +303,6 @@ MapCertErrorToProbeValue(PRErrorCode errorCode)
|
|||
case SEC_ERROR_UNTRUSTED_ISSUER: return 4;
|
||||
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: return 5;
|
||||
case SEC_ERROR_UNTRUSTED_CERT: return 6;
|
||||
case SEC_ERROR_INADEQUATE_KEY_USAGE: return 7;
|
||||
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: return 8;
|
||||
case SSL_ERROR_BAD_CERT_DOMAIN: return 9;
|
||||
case SEC_ERROR_EXPIRED_CERTIFICATE: return 10;
|
||||
|
@ -313,6 +312,79 @@ MapCertErrorToProbeValue(PRErrorCode errorCode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
InsanityDetermineCertOverrideErrors(CERTCertificate* cert,
|
||||
const char* hostName, PRTime now,
|
||||
PRErrorCode defaultErrorCodeToReport,
|
||||
/*out*/ uint32_t& collectedErrors,
|
||||
/*out*/ PRErrorCode& errorCodeTrust,
|
||||
/*out*/ PRErrorCode& errorCodeMismatch,
|
||||
/*out*/ PRErrorCode& errorCodeExpired)
|
||||
{
|
||||
MOZ_ASSERT(cert);
|
||||
MOZ_ASSERT(hostName);
|
||||
MOZ_ASSERT(collectedErrors == 0);
|
||||
MOZ_ASSERT(errorCodeTrust == 0);
|
||||
MOZ_ASSERT(errorCodeMismatch == 0);
|
||||
MOZ_ASSERT(errorCodeExpired == 0);
|
||||
|
||||
// Assumes the error prioritization described in insanity::pkix's
|
||||
// BuildForward function. Also assumes that CERT_VerifyCertName was only
|
||||
// called if CertVerifier::VerifyCert succeeded.
|
||||
switch (defaultErrorCodeToReport) {
|
||||
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
|
||||
case SEC_ERROR_UNKNOWN_ISSUER:
|
||||
{
|
||||
collectedErrors = nsICertOverrideService::ERROR_UNTRUSTED;
|
||||
errorCodeTrust = defaultErrorCodeToReport;
|
||||
|
||||
SECCertTimeValidity validity = CERT_CheckCertValidTimes(cert, now, false);
|
||||
if (validity == secCertTimeUndetermined) {
|
||||
PR_SetError(defaultErrorCodeToReport, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
if (validity != secCertTimeValid) {
|
||||
collectedErrors |= nsICertOverrideService::ERROR_TIME;
|
||||
errorCodeExpired = SEC_ERROR_EXPIRED_CERTIFICATE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SEC_ERROR_EXPIRED_CERTIFICATE:
|
||||
collectedErrors = nsICertOverrideService::ERROR_TIME;
|
||||
errorCodeExpired = SEC_ERROR_EXPIRED_CERTIFICATE;
|
||||
break;
|
||||
|
||||
case SSL_ERROR_BAD_CERT_DOMAIN:
|
||||
collectedErrors = nsICertOverrideService::ERROR_MISMATCH;
|
||||
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
NS_ERROR("No error code set during certificate validation failure.");
|
||||
PR_SetError(PR_INVALID_STATE_ERROR, 0);
|
||||
return SECFailure;
|
||||
|
||||
default:
|
||||
PR_SetError(defaultErrorCodeToReport, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (defaultErrorCodeToReport != SSL_ERROR_BAD_CERT_DOMAIN) {
|
||||
if (CERT_VerifyCertName(cert, hostName) != SECSuccess) {
|
||||
if (PR_GetError() != SSL_ERROR_BAD_CERT_DOMAIN) {
|
||||
PR_SetError(defaultErrorCodeToReport, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
collectedErrors |= nsICertOverrideService::ERROR_MISMATCH;
|
||||
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SSLServerCertVerificationResult*
|
||||
CertErrorRunnable::CheckCertOverrides()
|
||||
{
|
||||
|
@ -494,7 +566,6 @@ PRErrorCodeToOverrideType(PRErrorCode errorCode)
|
|||
case SEC_ERROR_UNTRUSTED_ISSUER:
|
||||
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
|
||||
case SEC_ERROR_UNTRUSTED_CERT:
|
||||
case SEC_ERROR_INADEQUATE_KEY_USAGE:
|
||||
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
|
||||
// We group all these errors as "cert not trusted"
|
||||
return nsICertOverrideService::ERROR_UNTRUSTED;
|
||||
|
@ -507,6 +578,100 @@ PRErrorCodeToOverrideType(PRErrorCode errorCode)
|
|||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
NSSDetermineCertOverrideErrors(CertVerifier& certVerifier,
|
||||
CERTCertificate* cert,
|
||||
const SECItem* stapledOCSPResponse,
|
||||
TransportSecurityInfo* infoObject,
|
||||
PRTime now,
|
||||
PRErrorCode defaultErrorCodeToReport,
|
||||
/*out*/ uint32_t& collectedErrors,
|
||||
/*out*/ PRErrorCode& errorCodeTrust,
|
||||
/*out*/ PRErrorCode& errorCodeMismatch,
|
||||
/*out*/ PRErrorCode& errorCodeExpired)
|
||||
{
|
||||
MOZ_ASSERT(cert);
|
||||
MOZ_ASSERT(infoObject);
|
||||
MOZ_ASSERT(defaultErrorCodeToReport != 0);
|
||||
MOZ_ASSERT(collectedErrors == 0);
|
||||
MOZ_ASSERT(errorCodeTrust == 0);
|
||||
MOZ_ASSERT(errorCodeMismatch == 0);
|
||||
MOZ_ASSERT(errorCodeExpired == 0);
|
||||
|
||||
if (defaultErrorCodeToReport == 0) {
|
||||
NS_ERROR("No error code set during certificate validation failure.");
|
||||
PR_SetError(PR_INVALID_STATE_ERROR, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
// We only allow overrides for certain errors. Return early if the error
|
||||
// is not one of them. This is to avoid doing revocation fetching in the
|
||||
// case of OCSP stapling and probably for other reasons.
|
||||
if (PRErrorCodeToOverrideType(defaultErrorCodeToReport) == 0) {
|
||||
PR_SetError(defaultErrorCodeToReport, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PLArenaPool* log_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
PLArenaPoolCleanerFalseParam log_arena_cleaner(log_arena);
|
||||
if (!log_arena) {
|
||||
NS_ERROR("PORT_NewArena failed");
|
||||
return SECFailure; // PORT_NewArena set error code
|
||||
}
|
||||
|
||||
CERTVerifyLog* verify_log = PORT_ArenaZNew(log_arena, CERTVerifyLog);
|
||||
if (!verify_log) {
|
||||
NS_ERROR("PORT_ArenaZNew failed");
|
||||
return SECFailure; // PORT_ArenaZNew set error code
|
||||
}
|
||||
CERTVerifyLogContentsCleaner verify_log_cleaner(verify_log);
|
||||
verify_log->arena = log_arena;
|
||||
|
||||
// We ignore the result code of the cert verification (i.e. VerifyCert's rv)
|
||||
// Either it is a failure, which is expected, and we'll process the
|
||||
// verify log below.
|
||||
// Or it is a success, then a domain mismatch is the only
|
||||
// possible failure.
|
||||
// XXX TODO: convert to VerifySSLServerCert
|
||||
// XXX TODO: get rid of error log
|
||||
certVerifier.VerifyCert(cert, stapledOCSPResponse, certificateUsageSSLServer,
|
||||
now, infoObject, 0, nullptr, nullptr, verify_log);
|
||||
|
||||
// Check the name field against the desired hostname.
|
||||
if (CERT_VerifyCertName(cert, infoObject->GetHostNameRaw()) != SECSuccess) {
|
||||
collectedErrors |= nsICertOverrideService::ERROR_MISMATCH;
|
||||
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
|
||||
}
|
||||
|
||||
CERTVerifyLogNode* i_node;
|
||||
for (i_node = verify_log->head; i_node; i_node = i_node->next) {
|
||||
uint32_t overrideType = PRErrorCodeToOverrideType(i_node->error);
|
||||
// If this isn't an overridable error, set the error and return.
|
||||
if (overrideType == 0) {
|
||||
PR_SetError(i_node->error, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
collectedErrors |= overrideType;
|
||||
if (overrideType == nsICertOverrideService::ERROR_UNTRUSTED) {
|
||||
if (errorCodeTrust == 0) {
|
||||
errorCodeTrust = i_node->error;
|
||||
}
|
||||
} else if (overrideType == nsICertOverrideService::ERROR_MISMATCH) {
|
||||
if (errorCodeMismatch == 0) {
|
||||
errorCodeMismatch = i_node->error;
|
||||
}
|
||||
} else if (overrideType == nsICertOverrideService::ERROR_TIME) {
|
||||
if (errorCodeExpired == 0) {
|
||||
errorCodeExpired = i_node->error;
|
||||
}
|
||||
} else {
|
||||
MOZ_CRASH("unexpected return value from PRErrorCodeToOverrideType");
|
||||
}
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
// Returns null with the error code (PR_GetError()) set if it does not create
|
||||
// the CertErrorRunnable.
|
||||
CertErrorRunnable*
|
||||
|
@ -522,17 +687,41 @@ CreateCertErrorRunnable(CertVerifier& certVerifier,
|
|||
MOZ_ASSERT(infoObject);
|
||||
MOZ_ASSERT(cert);
|
||||
|
||||
// We only allow overrides for certain errors. Return early if the error
|
||||
// is not one of them. This is to avoid doing revocation fetching in the
|
||||
// case of OCSP stapling and probably for other reasons.
|
||||
if (PRErrorCodeToOverrideType(defaultErrorCodeToReport) == 0) {
|
||||
PR_SetError(defaultErrorCodeToReport, 0);
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t collected_errors = 0;
|
||||
PRErrorCode errorCodeTrust = 0;
|
||||
PRErrorCode errorCodeMismatch = 0;
|
||||
PRErrorCode errorCodeExpired = 0;
|
||||
|
||||
if (defaultErrorCodeToReport == 0) {
|
||||
NS_ERROR("No error code set during certificate validation failure.");
|
||||
PR_SetError(PR_INVALID_STATE_ERROR, 0);
|
||||
SECStatus rv;
|
||||
switch (certVerifier.mImplementation) {
|
||||
case CertVerifier::classic:
|
||||
#ifndef NSS_NO_LIBPKIX
|
||||
case CertVerifier::libpkix:
|
||||
#endif
|
||||
rv = NSSDetermineCertOverrideErrors(certVerifier, cert, stapledOCSPResponse,
|
||||
infoObject, now,
|
||||
defaultErrorCodeToReport,
|
||||
collected_errors, errorCodeTrust,
|
||||
errorCodeMismatch, errorCodeExpired);
|
||||
break;
|
||||
|
||||
case CertVerifier::insanity:
|
||||
rv = InsanityDetermineCertOverrideErrors(cert,
|
||||
infoObject->GetHostNameRaw(),
|
||||
now, defaultErrorCodeToReport,
|
||||
collected_errors,
|
||||
errorCodeTrust,
|
||||
errorCodeMismatch,
|
||||
errorCodeExpired);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("unexpected CertVerifier implementation");
|
||||
PR_SetError(defaultErrorCodeToReport, 0);
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -543,70 +732,7 @@ CreateCertErrorRunnable(CertVerifier& certVerifier,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PLArenaPool* log_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
PLArenaPoolCleanerFalseParam log_arena_cleaner(log_arena);
|
||||
if (!log_arena) {
|
||||
NS_ERROR("PORT_NewArena failed");
|
||||
return nullptr; // PORT_NewArena set error code
|
||||
}
|
||||
|
||||
CERTVerifyLog* verify_log = PORT_ArenaZNew(log_arena, CERTVerifyLog);
|
||||
if (!verify_log) {
|
||||
NS_ERROR("PORT_ArenaZNew failed");
|
||||
return nullptr; // PORT_ArenaZNew set error code
|
||||
}
|
||||
CERTVerifyLogContentsCleaner verify_log_cleaner(verify_log);
|
||||
verify_log->arena = log_arena;
|
||||
|
||||
|
||||
// We ignore the result code of the cert verification (i.e. VerifyCert's rv)
|
||||
// Either it is a failure, which is expected, and we'll process the
|
||||
// verify log below.
|
||||
// Or it is a success, then a domain mismatch is the only
|
||||
// possible failure.
|
||||
// XXX TODO: convert to VerifySSLServerCert
|
||||
// XXX TODO: get rid of error log
|
||||
certVerifier.VerifyCert(cert, stapledOCSPResponse,
|
||||
certificateUsageSSLServer, now,
|
||||
infoObject, 0, nullptr, nullptr, verify_log);
|
||||
|
||||
PRErrorCode errorCodeMismatch = 0;
|
||||
PRErrorCode errorCodeTrust = 0;
|
||||
PRErrorCode errorCodeExpired = 0;
|
||||
|
||||
uint32_t collected_errors = 0;
|
||||
|
||||
// Check the name field against the desired hostname.
|
||||
if (CERT_VerifyCertName(cert, infoObject->GetHostNameRaw()) != SECSuccess) {
|
||||
collected_errors |= nsICertOverrideService::ERROR_MISMATCH;
|
||||
errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
|
||||
}
|
||||
|
||||
CERTVerifyLogNode* i_node;
|
||||
for (i_node = verify_log->head; i_node; i_node = i_node->next)
|
||||
{
|
||||
uint32_t overrideType = PRErrorCodeToOverrideType(i_node->error);
|
||||
// If this isn't an overridable error, set the error and return.
|
||||
if (overrideType == 0) {
|
||||
PR_SetError(i_node->error, 0);
|
||||
return nullptr;
|
||||
}
|
||||
collected_errors |= overrideType;
|
||||
if (overrideType == nsICertOverrideService::ERROR_UNTRUSTED) {
|
||||
errorCodeTrust = (errorCodeTrust == 0 ? i_node->error : errorCodeTrust);
|
||||
} else if (overrideType == nsICertOverrideService::ERROR_MISMATCH) {
|
||||
errorCodeMismatch = (errorCodeMismatch == 0 ? i_node->error
|
||||
: errorCodeMismatch);
|
||||
} else if (overrideType == nsICertOverrideService::ERROR_TIME) {
|
||||
errorCodeExpired = (errorCodeExpired == 0 ? i_node->error
|
||||
: errorCodeExpired);
|
||||
} else {
|
||||
MOZ_CRASH("unexpected return value from PRErrorCodeToOverrideType");
|
||||
}
|
||||
}
|
||||
|
||||
if (!collected_errors)
|
||||
{
|
||||
if (!collected_errors) {
|
||||
// This will happen when CERT_*Verify* only returned error(s) that are
|
||||
// not on our whitelist of overridable certificate errors.
|
||||
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] !collected_errors: %d\n",
|
||||
|
|
|
@ -1630,15 +1630,30 @@ nsNSSCertificateDB::AddCert(const nsACString & aCertDER, const char *aTrust,
|
|||
return AddCertFromBase64(base64.get(), aTrust, aName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert3* cert,
|
||||
const char* trustString)
|
||||
{
|
||||
CERTCertTrust trust;
|
||||
|
||||
// need to calculate the trust bits from the aTrust string.
|
||||
SECStatus srv = CERT_DecodeTrustString(&trust,
|
||||
const_cast<char *>(trustString));
|
||||
if (srv != SECSuccess) {
|
||||
return MapSECStatus(SECFailure);
|
||||
}
|
||||
insanity::pkix::ScopedCERTCertificate nssCert(cert->GetCert());
|
||||
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nssCert.get(), &trust);
|
||||
return MapSECStatus(srv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
|
||||
nsCOMPtr<nsIX509CertList> nssCertList;
|
||||
|
|
|
@ -73,6 +73,20 @@ function addCertFromFile(certdb, filename, trustString) {
|
|||
certdb.addCert(der, trustString, null);
|
||||
}
|
||||
|
||||
function constructCertFromFile(filename) {
|
||||
let certFile = do_get_file(filename, false);
|
||||
let certDER = readFile(certFile);
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
return certdb.constructX509(certDER, certDER.length);
|
||||
}
|
||||
|
||||
function setCertTrust(cert, trustString) {
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
certdb.setCertTrustFromString(cert, trustString);
|
||||
}
|
||||
|
||||
function getXPCOMStatusFromNSS(statusNSS) {
|
||||
let nssErrorsService = Cc["@mozilla.org/nss_errors_service;1"]
|
||||
.getService(Ci.nsINSSErrorsService);
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
// 2. Add an override for that host/port/certificate/override bits.
|
||||
// 3. Connect again. This should succeed.
|
||||
|
||||
do_get_profile();
|
||||
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
||||
.getService(Ci.nsICertOverrideService);
|
||||
|
||||
function add_cert_override(aHost, aExpectedBits, aSecurityInfo) {
|
||||
let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider)
|
||||
.SSLStatus;
|
||||
|
@ -20,8 +24,6 @@ function add_cert_override(aHost, aExpectedBits, aSecurityInfo) {
|
|||
(sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0);
|
||||
do_check_eq(bits, aExpectedBits);
|
||||
let cert = sslstatus.serverCert;
|
||||
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
||||
.getService(Ci.nsICertOverrideService);
|
||||
certOverrideService.rememberValidityOverride(aHost, 8443, cert, aExpectedBits,
|
||||
true);
|
||||
}
|
||||
|
@ -38,66 +40,170 @@ function check_telemetry() {
|
|||
.getHistogramById("SSL_CERT_ERROR_OVERRIDES")
|
||||
.snapshot();
|
||||
do_check_eq(histogram.counts[ 0], 0);
|
||||
do_check_eq(histogram.counts[ 1], 1);
|
||||
do_check_eq(histogram.counts[ 2], 1);
|
||||
do_check_eq(histogram.counts[ 3], 1);
|
||||
do_check_eq(histogram.counts[ 4], 1);
|
||||
do_check_eq(histogram.counts[ 5], 1);
|
||||
do_check_eq(histogram.counts[ 6], 1);
|
||||
do_check_eq(histogram.counts[ 7], 1);
|
||||
do_check_eq(histogram.counts[ 8], 1);
|
||||
do_check_eq(histogram.counts[ 9], 1);
|
||||
do_check_eq(histogram.counts[10], 1);
|
||||
do_check_eq(histogram.counts[ 2], 6 + 1); // SEC_ERROR_UNKNOWN_ISSUER
|
||||
do_check_eq(histogram.counts[ 3], 0 + 1); // SEC_ERROR_CA_CERT_INVALID
|
||||
do_check_eq(histogram.counts[ 4], 0 + 4); // SEC_ERROR_UNTRUSTED_ISSUER
|
||||
do_check_eq(histogram.counts[ 5], 0 + 1); // SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
|
||||
do_check_eq(histogram.counts[ 6], 0 + 1); // SEC_ERROR_UNTRUSTED_CERT
|
||||
do_check_eq(histogram.counts[ 7], 0); // SEC_ERROR_INADEQUATE_KEY_USAGE
|
||||
do_check_eq(histogram.counts[ 8], 2 + 2); // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
|
||||
do_check_eq(histogram.counts[ 9], 4 + 4); // SSL_ERROR_BAD_CERT_DOMAIN
|
||||
do_check_eq(histogram.counts[10], 5 + 5); // SEC_ERROR_EXPIRED_CERTIFICATE
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
add_tls_server_setup("BadCertServer");
|
||||
|
||||
let fakeOCSPResponder = new HttpServer();
|
||||
fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
|
||||
response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
|
||||
});
|
||||
fakeOCSPResponder.start(8080);
|
||||
|
||||
add_tests_in_mode(true);
|
||||
add_tests_in_mode(false);
|
||||
|
||||
add_test(function () {
|
||||
fakeOCSPResponder.stop(check_telemetry);
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function add_tests_in_mode(useInsanity) {
|
||||
add_test(function () {
|
||||
Services.prefs.setBoolPref("security.use_insanity_verification",
|
||||
useInsanity);
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_simple_tests(useInsanity);
|
||||
add_combo_tests(useInsanity);
|
||||
add_distrust_tests(useInsanity);
|
||||
|
||||
add_test(function () {
|
||||
certOverrideService.clearValidityOverride("all:temporary-certificates", 0);
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function add_simple_tests(useInsanity) {
|
||||
add_cert_override_test("expired.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_TIME,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_EXPIRED_CERTIFICATE));
|
||||
add_cert_override_test("selfsigned.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID));
|
||||
getXPCOMStatusFromNSS(
|
||||
useInsanity ? SEC_ERROR_UNKNOWN_ISSUER
|
||||
: SEC_ERROR_CA_CERT_INVALID));
|
||||
add_cert_override_test("unknownissuer.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
|
||||
add_cert_override_test("expiredissuer.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE));
|
||||
getXPCOMStatusFromNSS(
|
||||
useInsanity ? SEC_ERROR_UNKNOWN_ISSUER
|
||||
: SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE));
|
||||
add_cert_override_test("md5signature.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
|
||||
add_cert_override_test("inadequatekeyusage.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_INADEQUATE_KEY_USAGE));
|
||||
getXPCOMStatusFromNSS(
|
||||
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
|
||||
add_cert_override_test("mismatch.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH,
|
||||
getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
|
||||
}
|
||||
|
||||
function add_combo_tests(useInsanity) {
|
||||
// Note that "untrusted" here really is "unknown issuer" in the
|
||||
// insanity::pkix case.
|
||||
|
||||
add_cert_override_test("mismatch-expired.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_TIME,
|
||||
getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
|
||||
add_cert_override_test("mismatch-untrusted.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(
|
||||
useInsanity ? SEC_ERROR_UNKNOWN_ISSUER
|
||||
: SEC_ERROR_UNTRUSTED_ISSUER));
|
||||
add_cert_override_test("untrusted-expired.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_TIME,
|
||||
getXPCOMStatusFromNSS(
|
||||
useInsanity ? SEC_ERROR_UNKNOWN_ISSUER
|
||||
: SEC_ERROR_UNTRUSTED_ISSUER));
|
||||
add_cert_override_test("mismatch-untrusted-expired.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_MISMATCH |
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_TIME,
|
||||
getXPCOMStatusFromNSS(
|
||||
useInsanity ? SEC_ERROR_UNKNOWN_ISSUER
|
||||
: SEC_ERROR_UNTRUSTED_ISSUER));
|
||||
|
||||
add_cert_override_test("md5signature-expired.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||
Ci.nsICertOverrideService.ERROR_TIME,
|
||||
getXPCOMStatusFromNSS(
|
||||
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
|
||||
}
|
||||
|
||||
function add_distrust_tests(useInsanity) {
|
||||
// Before we specifically distrust this certificate, it should be trusted.
|
||||
add_connection_test("untrusted.example.com", Cr.NS_OK);
|
||||
add_test(function() {
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
// A trust argument of "pu" means the cert is actively distrusted.
|
||||
addCertFromFile(certdb, "tlsserver/default-ee.der", "pu,,");
|
||||
|
||||
// XXX(Bug 975777): Active distrust is an overridable error when NSS-based
|
||||
// verification is used.
|
||||
add_distrust_override_test("tlsserver/default-ee.der",
|
||||
"untrusted.example.com",
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT),
|
||||
useInsanity
|
||||
? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT)
|
||||
: Cr.NS_OK);
|
||||
|
||||
// XXX(Bug 975777): Active distrust is an overridable error when NSS-based
|
||||
// verification is used.
|
||||
add_distrust_override_test("tlsserver/other-test-ca.der",
|
||||
"untrustedissuer.example.com",
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER),
|
||||
useInsanity
|
||||
? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER)
|
||||
: Cr.NS_OK);
|
||||
|
||||
}
|
||||
|
||||
function add_distrust_override_test(certFileName, hostName,
|
||||
expectedResultBefore, expectedResultAfter) {
|
||||
let certToDistrust = constructCertFromFile(certFileName);
|
||||
|
||||
add_test(function () {
|
||||
// "pu" means the cert is actively distrusted.
|
||||
setCertTrust(certToDistrust, "pu,,");
|
||||
clearSessionCache();
|
||||
run_next_test();
|
||||
});
|
||||
add_cert_override_test("untrusted.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT));
|
||||
add_test(function() {
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
// A trust argument of "pu" means the cert is actively distrusted.
|
||||
addCertFromFile(certdb, "tlsserver/other-test-ca.der", "pu,,");
|
||||
run_next_test();
|
||||
});
|
||||
add_cert_override_test("untrustedissuer.example.com",
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER));
|
||||
add_test(check_telemetry);
|
||||
run_next_test();
|
||||
add_connection_test(hostName, expectedResultBefore, null,
|
||||
function (securityInfo) {
|
||||
securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
|
||||
// XXX(Bug 754369): SSLStatus isn't available for
|
||||
// non-overridable errors.
|
||||
if (securityInfo.SSLStatus) {
|
||||
certOverrideService.rememberValidityOverride(
|
||||
hostName, 8443, securityInfo.SSLStatus.serverCert,
|
||||
Ci.nsICertOverrideService.ERROR_UNTRUSTED, true);
|
||||
} else {
|
||||
// A missing SSLStatus probably means (due to bug
|
||||
// 754369) that the error was non-overridable, which
|
||||
// is what we're trying to test, though we'd rather
|
||||
// not test it this way.
|
||||
do_check_neq(expectedResultAfter, Cr.NS_OK);
|
||||
}
|
||||
clearSessionCache();
|
||||
});
|
||||
add_connection_test(hostName, expectedResultAfter, null,
|
||||
function () {
|
||||
setCertTrust(certToDistrust, "u,,");
|
||||
});
|
||||
}
|
||||
|
|
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/cert8.db
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/cert8.db
Двоичный файл не отображается.
|
@ -33,8 +33,12 @@ const BadCertHost sBadCertHosts[] =
|
|||
{ "expiredissuer.example.com", "expiredissuer" },
|
||||
{ "md5signature.example.com", "md5signature" },
|
||||
{ "untrusted.example.com", "localhostAndExampleCom" },
|
||||
{ "inadequatekeyusage.example.com", "inadequatekeyusage" },
|
||||
{ "untrustedissuer.example.com", "untrustedissuer" },
|
||||
{ "mismatch-expired.example.com", "mismatch-expired" },
|
||||
{ "mismatch-untrusted.example.com", "mismatch-untrusted" },
|
||||
{ "untrusted-expired.example.com", "untrusted-expired" },
|
||||
{ "md5signature-expired.example.com", "md5signature-expired" },
|
||||
{ "mismatch-untrusted-expired.example.com", "mismatch-untrusted-expired" },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
|
|
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/default-ee.der
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/default-ee.der
Двоичный файл не отображается.
|
@ -99,7 +99,7 @@ function make_EE {
|
|||
SUBJECT="${2}"
|
||||
CA="${3}"
|
||||
SUBJECT_ALT_NAME="${4}"
|
||||
EXTRA_ARGS="${5}"
|
||||
EXTRA_ARGS="${5} ${6}"
|
||||
|
||||
echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S \
|
||||
-n $NICKNAME \
|
||||
|
@ -136,7 +136,12 @@ $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -D -n deletedINT
|
|||
make_INT expiredINT 'CN=Expired Test Intermediate' testCA "-w -400"
|
||||
make_EE expiredissuer 'CN=Test End-entity with expired issuer' expiredINT "expiredissuer.example.com"
|
||||
NSS_ALLOW_WEAK_SIGNATURE_ALG=1 make_EE md5signature 'CN=Test End-entity with MD5 signature' testCA "md5signature.example.com" "-Z MD5"
|
||||
make_EE inadequatekeyusage 'CN=Test End-entity with inadequate key usage' testCA "inadequatekeyusage.example.com" "--keyUsage crlSigning"
|
||||
make_EE untrustedissuer 'CN=Test End-entity with untrusted issuer' otherCA "untrustedissuer.example.com"
|
||||
|
||||
make_EE mismatch-expired 'CN=Mismatch-Expired Test End-entity' testCA "doesntmatch.example.com" "-w -400"
|
||||
make_EE mismatch-untrusted 'CN=Mismatch-Untrusted Test End-entity' otherCA "doesntmatch.example.com"
|
||||
make_EE untrusted-expired 'CN=Untrusted-Expired Test End-entity' otherCA "untrusted-expired.example.com" "-w -400"
|
||||
make_EE mismatch-untrusted-expired 'CN=Mismatch-Untrusted-Expired Test End-entity' otherCA "doesntmatch.example.com" "-w -400"
|
||||
NSS_ALLOW_WEAK_SIGNATURE_ALG=1 make_EE md5signature-expired 'CN=Test MD5Signature-Expired End-entity' testCA "md5signature-expired.example.com" "-Z MD5" "-w -400"
|
||||
|
||||
cleanup
|
||||
|
|
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/key3.db
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/key3.db
Двоичный файл не отображается.
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
Двоичный файл не отображается.
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/test-ca.der
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/test-ca.der
Двоичный файл не отображается.
Загрузка…
Ссылка в новой задаче