Bug 991815 - Part 2/2 - Tests for OCSP responses up to 1 year old. r=keeler

--HG--
extra : rebase_source : cc012870da3a165a0a3d0d5c6c9671eeeda37f3f
This commit is contained in:
Camilo Viecco 2014-05-28 14:08:02 -07:00
Родитель 5bce267045
Коммит d4c50fa1b7
7 изменённых файлов: 106 добавлений и 5 удалений

Просмотреть файл

@ -444,13 +444,15 @@ function getFailingHttpServer(serverPort, serverIdentities) {
// what is the expected base path of the OCSP request.
function startOCSPResponder(serverPort, identity, invalidIdentities,
nssDBLocation, expectedCertNames,
expectedBasePaths, expectedMethods) {
expectedBasePaths, expectedMethods,
expectedResponseTypes) {
let httpServer = new HttpServer();
httpServer.registerPrefixHandler("/",
function handleServerCallback(aRequest, aResponse) {
invalidIdentities.forEach(function(identity) {
do_check_neq(aRequest.host, identity)
});
do_print("got request for: " + aRequest.path);
let basePath = aRequest.path.slice(1).split("/")[0];
if (expectedBasePaths.length >= 1) {
do_check_eq(basePath, expectedBasePaths.shift());
@ -459,12 +461,16 @@ function startOCSPResponder(serverPort, identity, invalidIdentities,
if (expectedMethods && expectedMethods.length >= 1) {
do_check_eq(aRequest.method, expectedMethods.shift());
}
let responseType = "good";
if (expectedResponseTypes && expectedResponseTypes.length >= 1) {
responseType = expectedResponseTypes.shift();
}
let expectedNick = expectedCertNames.shift();
do_print("Generating ocsp response for '" + expectedNick + "(" +
basePath + ")'");
do_print("Generating ocsp response(" + responseType + ") for '" +
expectedNick + "(" + basePath + ")'");
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
aResponse.setHeader("Content-Type", "application/ocsp-response");
let args = [ ["good", expectedNick, "unused" ] ];
let args = [ [responseType, expectedNick, "unused" ] ];
let retArray = generateOCSPResponses(args, nssDBLocation);
let responseBody = retArray[0];
aResponse.bodyOutputStream.write(responseBody, responseBody.length);
@ -483,6 +489,9 @@ function startOCSPResponder(serverPort, identity, invalidIdentities,
if (expectedBasePaths) {
do_check_eq(expectedBasePaths.length, 0);
}
if (expectedResponseTypes) {
do_check_eq(expectedResponseTypes.length, 0);
}
httpServer.stop(callback);
}
};

Просмотреть файл

@ -210,6 +210,65 @@ function add_tests_in_mode(useMozillaPKIX)
});
});
// Bug 991815 old but valid intermediates are OK
add_test(function () {
clearOCSPCache();
let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
"test_ev_certs",
isDebugBuild ? ["int-ev-valid", "ev-valid"]
: ["ev-valid"],
[], [],
isDebugBuild ? ["longvalidityalmostold", "good"]
: ["good"]);
check_ee_for_ev("ev-valid", isDebugBuild);
ocspResponder.stop(run_next_test);
});
// Bug 991815 old but valid end-entities are NOT OK for EV
// Unfortunatelly because of soft-fail we consider these OK for DV
// libpkix does not enforce the age restriction and thus EV is valid
add_test(function () {
clearOCSPCache();
// Since Mozilla::pkix does not consider the old amost invalid OCSP
// response valid, it does not cache the old response and thus
// makes a separate request for DV
let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
let debugResponseArray = ["good", "longvalidityalmostold",
"longvalidityalmostold"];
if (!useMozillaPKIX) {
debugCertNickArray = ["int-ev-valid", "ev-valid"];
debugResponseArray = ["good", "longvalidityalmostold"];
}
let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
"test_ev_certs",
isDebugBuild ? debugCertNickArray : ["ev-valid"],
[], [],
isDebugBuild ? debugResponseArray
: ["longvalidityalmostold"]);
check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
ocspResponder.stop(run_next_test);
});
// Bug 991815 Valid but Ancient (almost two year old) responses are Not OK for
// EV (still OK for soft fail DV)
add_test(function () {
clearOCSPCache();
let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
let debugResponseArray = ["good", "ancientstillvalid",
"ancientstillvalid"];
if (!useMozillaPKIX) {
debugCertNickArray = ["int-ev-valid", "ev-valid"];
debugResponseArray = ["good", "ancientstillvalid"];
}
let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
"test_ev_certs",
isDebugBuild ? debugCertNickArray : ["ev-valid"],
[], [],
isDebugBuild ? debugResponseArray
: ["ancientstillvalid"]);
check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
ocspResponder.stop(run_next_test);
});
}
// bug 950240: add FLAG_MUST_BE_EV to CertVerifier::VerifyCert

Просмотреть файл

@ -100,6 +100,20 @@ function add_tests_in_mode(useMozillaPKIX)
add_ocsp_test("ocsp-stapling-expired.example.com",
getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNKNOWN_CERT),
ocspResponseUnknown);
if (useMozillaPKIX) {
// These tests are verifying that an valid but very old response
// is rejected as a valid stapled response, requiring a fetch
// from the ocsp responder.
add_ocsp_test("ocsp-stapling-ancient-valid.example.com", Cr.NS_OK,
ocspResponseGood);
add_ocsp_test("ocsp-stapling-ancient-valid.example.com",
getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE),
ocspResponseRevoked);
add_ocsp_test("ocsp-stapling-ancient-valid.example.com",
getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNKNOWN_CERT),
ocspResponseUnknown);
}
}
function check_ocsp_stapling_telemetry() {
@ -110,7 +124,11 @@ function check_ocsp_stapling_telemetry() {
do_check_eq(histogram.counts[0], 2 * 0); // histogram bucket 0 is unused
do_check_eq(histogram.counts[1], 2 * 0); // 0 connections with a good response
do_check_eq(histogram.counts[2], 2 * 0); // 0 connections with no stapled resp.
do_check_eq(histogram.counts[3], 2 * 9); // 9 connections with an expired response
do_check_eq(histogram.counts[3], 2 * 9 + 3); // 9 connections with an expired response
// 3 connection with a response
// considered expired due to being
// old but having an overly-long
// validity period
do_check_eq(histogram.counts[4], 2 * 0); // 0 connections with bad responses
run_next_test();
}

Просмотреть файл

@ -56,6 +56,12 @@ const static OCSPResponseName kOCSPResponseNameList[] = {
{ "unauthorized", ORTUnauthorized}, // the responder does not know about
// the cert
{ "bad-signature", ORTBadSignature}, // the response has a bad signature
{ "longvalidityalmostold", ORTLongValidityAlmostExpired}, // the response is
// still valid, but the generation
// is almost a year old
{ "ancientstillvalid", ORTAncientAlmostExpired}, // The response is still
// valid but the generation is almost
// two years old
};

Просмотреть файл

@ -49,6 +49,7 @@ const OCSPHost sOCSPHosts[] =
{ "ocsp-stapling-delegated-from-intermediate.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerFromIntermediate" },
{ "ocsp-stapling-delegated-keyUsage-crlSigning.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerKeyUsageCrlSigning" },
{ "ocsp-stapling-delegated-wrong-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerWrongExtKeyUsage" },
{ "ocsp-stapling-ancient-valid.example.com", ORTAncientAlmostExpired, nullptr},
{ nullptr, ORTNull, nullptr }
};

Просмотреть файл

@ -113,6 +113,12 @@ GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert,
context.thisUpdate = oldNow;
context.nextUpdate = oldNow + 10 * PR_USEC_PER_SEC;
}
if (aORT == ORTLongValidityAlmostExpired) {
context.thisUpdate = now - (320 * oneDay);
}
if (aORT == ORTAncientAlmostExpired) {
context.thisUpdate = now - (640 * oneDay);
}
if (aORT == ORTRevoked) {
context.certStatus = 1;
}

Просмотреть файл

@ -37,6 +37,8 @@ enum OCSPResponseType
ORTDelegatedIncludedLast, // same, but multiple other certificates are included
ORTDelegatedMissing, // the response is signed by a not included delegated responder
ORTDelegatedMissingMultiple, // same, but multiple other certificates are included
ORTLongValidityAlmostExpired, // a good response, but that was generated a almost a year ago
ORTAncientAlmostExpired, // a good response, with a validity of almost two years almost expiring
};
struct OCSPHost