Bug 1390131 - Modify GenerateOCSPResponse.cpp to allow thisUpdate to be modified r=keeler draft
authorMark Goodwin <mgoodwin@mozilla.com>
Wed, 16 Aug 2017 10:05:03 +0100
changeset 647426 5b72ddc51ffd6dabeb9e3afc45b9851336b0db88
parent 646498 564e82f0f289af976da01c2d50507017bbc152b5
child 726494 630e3d2814cf064545b53a034a4352aab8968599
push id74397
push usermgoodwin@mozilla.com
push dateWed, 16 Aug 2017 09:10:30 +0000
reviewerskeeler
bugs1390131
milestone57.0a1
Bug 1390131 - Modify GenerateOCSPResponse.cpp to allow thisUpdate to be modified r=keeler MozReview-Commit-ID: EL9E4UtZg17
security/manager/ssl/tests/unit/head_psm.js
security/manager/ssl/tests/unit/test_ocsp_caching.js
security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js
security/manager/ssl/tests/unit/test_ocsp_required.js
security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -536,38 +536,39 @@ function _setupTLSServerTest(serverBinNa
   do_register_cleanup(function() {
     process.kill();
   });
 }
 
 // Returns an Array of OCSP responses for a given ocspRespArray and a location
 // for a nssDB where the certs and public keys are prepopulated.
 // ocspRespArray is an array of arrays like:
-// [ [typeOfResponse, certnick, extracertnick]...]
+// [ [typeOfResponse, certnick, extracertnick, thisUpdateSkew]...]
 function generateOCSPResponses(ocspRespArray, nssDBlocation) {
   let utilBinName = "GenerateOCSPResponse";
   let ocspGenBin = _getBinaryUtil(utilBinName);
   let retArray = [];
 
   for (let i = 0; i < ocspRespArray.length; i++) {
     let argArray = [];
     let ocspFilepre = do_get_file(i.toString() + ".ocsp", true);
     let filename = ocspFilepre.path;
     // Using "sql:" causes the SQL DB to be used so we can run tests on Android.
     argArray.push("sql:" + nssDBlocation);
     argArray.push(ocspRespArray[i][0]); // ocsRespType;
     argArray.push(ocspRespArray[i][1]); // nick;
     argArray.push(ocspRespArray[i][2]); // extranickname
+    argArray.push(ocspRespArray[i][3]); // thisUpdate skew
     argArray.push(filename);
     do_print("argArray = " + argArray);
 
     let process = Cc["@mozilla.org/process/util;1"]
                     .createInstance(Ci.nsIProcess);
     process.init(ocspGenBin);
-    process.run(true, argArray, 5);
+    process.run(true, argArray, argArray.length);
     Assert.equal(0, process.exitValue, "Process exit value should be 0");
     let ocspFile = do_get_file(i.toString() + ".ocsp", false);
     retArray.push(readFile(ocspFile));
     ocspFile.remove(false);
   }
   return retArray;
 }
 
@@ -612,17 +613,17 @@ function startOCSPResponder(serverPort, 
                             expectedCertNames, expectedBasePaths,
                             expectedMethods, expectedResponseTypes) {
   let ocspResponseGenerationArgs = expectedCertNames.map(
     function(expectedNick) {
       let responseType = "good";
       if (expectedResponseTypes && expectedResponseTypes.length >= 1) {
         responseType = expectedResponseTypes.shift();
       }
-      return [responseType, expectedNick, "unused"];
+      return [responseType, expectedNick, "unused", 0];
     }
   );
   let ocspResponses = generateOCSPResponses(ocspResponseGenerationArgs,
                                             nssDBLocation);
   let httpServer = new HttpServer();
   httpServer.registerPrefixHandler("/",
     function handleServerCallback(aRequest, aResponse) {
       do_print("got request for: " + aRequest.path);
--- a/security/manager/ssl/tests/unit/test_ocsp_caching.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_caching.js
@@ -19,30 +19,30 @@ function respondWithGoodOCSP(request, re
   response.write(gGoodOCSPResponse);
 }
 
 function respondWithSHA1OCSP(request, response) {
   do_print("returning 200 OK with sha-1 delegated response");
   response.setStatusLine(request.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "application/ocsp-response");
 
-  let args = [ ["good-delegated", "default-ee", "delegatedSHA1Signer" ] ];
+  let args = [ ["good-delegated", "default-ee", "delegatedSHA1Signer", 0 ] ];
   let responses = generateOCSPResponses(args, "ocsp_certs");
   response.write(responses[0]);
 }
 
 function respondWithError(request, response) {
   do_print("returning 500 Internal Server Error");
   response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
   let body = "Refusing to return a response";
   response.bodyOutputStream.write(body, body.length);
 }
 
 function generateGoodOCSPResponse() {
-  let args = [ ["good", "default-ee", "unused" ] ];
+  let args = [ ["good", "default-ee", "unused", 0 ] ];
   let responses = generateOCSPResponses(args, "ocsp_certs");
   return responses[0];
 }
 
 function add_ocsp_test(aHost, aExpectedResult, aResponses, aMessage,
                        aOriginAttributes) {
   add_connection_test(aHost, aExpectedResult,
       function() {
--- a/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js
@@ -11,17 +11,17 @@ function run_test() {
   do_get_profile();
   // OCSP required means this test will only pass if the request succeeds.
   Services.prefs.setBoolPref("security.OCSP.require", true);
 
   // We don't actually make use of stapling in this test. This is just how we
   // get a TLS connection.
   add_tls_server_setup("OCSPStaplingServer", "ocsp_certs");
 
-  let args = [["good", "default-ee", "unused"]];
+  let args = [["good", "default-ee", "unused", 0]];
   let ocspResponses = generateOCSPResponses(args, "ocsp_certs");
   let goodOCSPResponse = ocspResponses[0];
 
   let ocspResponder = new HttpServer();
   ocspResponder.registerPrefixHandler("/", function (request, response) {
     response.setStatusLine(request.httpVersion, 200, "OK");
     response.setHeader("Content-Type", "application/ocsp-response");
     response.write(goodOCSPResponse);
--- a/security/manager/ssl/tests/unit/test_ocsp_required.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_required.js
@@ -15,17 +15,17 @@ function run_test() {
   do_get_profile();
   Services.prefs.setBoolPref("security.OCSP.require", true);
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
 
   // We don't actually make use of stapling in this test. This is just how we
   // get a TLS connection.
   add_tls_server_setup("OCSPStaplingServer", "ocsp_certs");
 
-  let args = [["bad-signature", "default-ee", "unused"]];
+  let args = [["bad-signature", "default-ee", "unused", 0]];
   let ocspResponses = generateOCSPResponses(args, "ocsp_certs");
   let ocspResponseBadSignature = ocspResponses[0];
 
   let ocspResponder = new HttpServer();
   ocspResponder.registerPrefixHandler("/", function (request, response) {
     response.setStatusLine(request.httpVersion, 200, "OK");
     response.setHeader("Content-Type", "application/ocsp-response");
     response.write(ocspResponseBadSignature);
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
@@ -27,21 +27,21 @@ function add_ocsp_test(aHost, aExpectedR
             " fallback OCSP request" + (aExpectedRequestCount == 1 ? "" : "s"));
     });
 }
 
 do_get_profile();
 Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
 Services.prefs.setIntPref("security.OCSP.enabled", 1);
 Services.prefs.setIntPref("security.pki.sha1_enforcement_level", 4);
-var args = [["good", "default-ee", "unused"],
-             ["expiredresponse", "default-ee", "unused"],
-             ["oldvalidperiod", "default-ee", "unused"],
-             ["revoked", "default-ee", "unused"],
-             ["unknown", "default-ee", "unused"],
+var args = [["good", "default-ee", "unused", 0],
+             ["expiredresponse", "default-ee", "unused", 0],
+             ["oldvalidperiod", "default-ee", "unused", 0],
+             ["revoked", "default-ee", "unused", 0],
+             ["unknown", "default-ee", "unused", 0],
             ];
 var ocspResponses = generateOCSPResponses(args, "ocsp_certs");
 // Fresh response, certificate is good.
 var ocspResponseGood = ocspResponses[0];
 // Expired response, certificate is good.
 var expiredOCSPResponseGood = ocspResponses[1];
 // Fresh signature, old validity period, certificate is good.
 var oldValidityPeriodOCSPResponseGood = ocspResponses[2];
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
@@ -108,57 +108,60 @@ WriteResponse(const char* filename, cons
 
   return true;
 }
 
 int
 main(int argc, char* argv[])
 {
 
-  if (argc < 6 || (argc - 6) % 4 != 0) {
+  if (argc < 7 || (argc - 7) % 5 != 0) {
     PR_fprintf(PR_STDERR, "usage: %s <NSS DB directory> <responsetype> "
-                          "<cert_nick> <extranick> <outfilename> [<resptype> "
-                          "<cert_nick> <extranick> <outfilename>]* \n",
+                          "<cert_nick> <extranick> <this_update_skew> <outfilename> [<resptype> "
+                          "<cert_nick> <extranick> <this_update_skew> <outfilename>]* \n",
                           argv[0]);
     exit(EXIT_FAILURE);
   }
   SECStatus rv = InitializeNSS(argv[1]);
   if (rv != SECSuccess) {
     PR_fprintf(PR_STDERR, "Failed to initialize NSS\n");
     exit(EXIT_FAILURE);
   }
   UniquePLArenaPool arena(PORT_NewArena(256 * argc));
   if (!arena) {
     PrintPRError("PORT_NewArena failed");
     exit(EXIT_FAILURE);
   }
 
-  for (int i = 2; i + 3 < argc; i += 4) {
+  for (int i = 2; i + 3 < argc; i += 5) {
     const char* ocspTypeText  = argv[i];
     const char* certNick      = argv[i + 1];
     const char* extraCertname = argv[i + 2];
-    const char* filename      = argv[i + 3];
+    const char* skewChars     = argv[i + 3];
+    const char* filename      = argv[i + 4];
 
     OCSPResponseType ORT;
     if (!StringToOCSPResponseType(ocspTypeText, &ORT)) {
       PR_fprintf(PR_STDERR, "Cannot generate OCSP response of type %s\n",
                  ocspTypeText);
       exit(EXIT_FAILURE);
     }
 
     UniqueCERTCertificate cert(PK11_FindCertFromNickname(certNick, nullptr));
     if (!cert) {
       PrintPRError("PK11_FindCertFromNickname failed");
       PR_fprintf(PR_STDERR, "Failed to find certificate with nick '%s'\n",
                  certNick);
       exit(EXIT_FAILURE);
     }
 
+    time_t skew = static_cast<time_t>(atoll(skewChars));
+
     SECItemArray* response = GetOCSPResponseForType(ORT, cert, arena,
-                                                    extraCertname);
+                                                    extraCertname, skew);
     if (!response) {
       PR_fprintf(PR_STDERR, "Failed to generate OCSP response of type %s "
                             "for %s\n", ocspTypeText, certNick);
       exit(EXIT_FAILURE);
     }
 
     if (!WriteResponse(filename, &response->items[0])) {
       PR_fprintf(PR_STDERR, "Failed to write file %s\n", filename);
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -97,17 +97,17 @@ DoSNISocketConfig(PRFileDesc *aFd, const
   UniquePLArenaPool arena(PORT_NewArena(1024));
   if (!arena) {
     PrintPRError("PORT_NewArena failed");
     return SSL_SNI_SEND_ALERT;
   }
 
   // response is contained by the arena - freeing the arena will free it
   SECItemArray *response = GetOCSPResponseForType(host->mORT, cert, arena,
-                                                  host->mAdditionalCertName);
+                                                  host->mAdditionalCertName, 0);
   if (!response) {
     return SSL_SNI_SEND_ALERT;
   }
 
   // SSL_SetStapledOCSPResponses makes a deep copy of response
   SECStatus st = SSL_SetStapledOCSPResponses(aFd, response, certKEA);
   if (st != SECSuccess) {
     PrintPRError("SSL_SetStapledOCSPResponses failed");
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
@@ -37,17 +37,17 @@ CreateTestKeyPairFromCert(const UniqueCE
     return nullptr;
   }
   return CreateTestKeyPair(RSA_PKCS1(), *publicKey.get(), privateKey.release());
 }
 
 SECItemArray*
 GetOCSPResponseForType(OCSPResponseType aORT, const UniqueCERTCertificate& aCert,
                        const UniquePLArenaPool& aArena,
-                       const char* aAdditionalCertName)
+                       const char* aAdditionalCertName, time_t aThisUpdateSkew)
 {
   MOZ_ASSERT(aArena);
   MOZ_ASSERT(aCert);
   // Note: |aAdditionalCertName| may or may not need to be non-null depending
   //       on the |aORT| value given.
 
   if (aORT == ORTNone) {
     if (gDebugLevel >= DEBUG_WARNINGS) {
@@ -59,17 +59,17 @@ GetOCSPResponseForType(OCSPResponseType 
 
   if (aORT == ORTEmpty) {
     SECItemArray* arr = SECITEM_AllocArray(aArena.get(), nullptr, 1);
     arr->items[0].data = nullptr;
     arr->items[0].len = 0;
     return arr;
   }
 
-  time_t now = time(nullptr);
+  time_t now = time(nullptr) + aThisUpdateSkew;
   time_t oldNow = now - (8 * Time::ONE_DAY_IN_SECONDS);
 
   mozilla::UniqueCERTCertificate cert(CERT_DupCertificate(aCert.get()));
 
   if (aORT == ORTGoodOtherCert) {
     cert.reset(PK11_FindCertFromNickname(aAdditionalCertName, nullptr));
     if (!cert) {
       PrintPRError("PK11_FindCertFromNickname failed");
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
@@ -51,11 +51,12 @@ struct OCSPHost
   const char *mAdditionalCertName; // useful for ORTGoodOtherCert, etc.
   const char *mServerCertName;
 };
 
 SECItemArray*
 GetOCSPResponseForType(OCSPResponseType aORT,
                        const mozilla::UniqueCERTCertificate& aCert,
                        const mozilla::UniquePLArenaPool& aArena,
-                       const char* aAdditionalCertName);
+                       const char* aAdditionalCertName,
+                       time_t aThisUpdateSkew);
 
 #endif // OCSPCommon_h