Bug 1002696 - Minimum set of changes to make genHPKPStaticPins.js productionizable. r=cviecco, dkeeler
authorMonica Chew <mmc@mozilla.com>
Thu, 01 May 2014 14:48:37 -0700
changeset 181719 e4fe6d86d885a51d68abbbb0f8cec3e27f994796
parent 181718 e8c9253239a5bdff82933198ee1abe0c4b4e96ee
child 181720 cfa3ce9b653fcde310010053e2832daa15316f47
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewerscviecco, dkeeler
bugs1002696
milestone32.0a1
Bug 1002696 - Minimum set of changes to make genHPKPStaticPins.js productionizable. r=cviecco, dkeeler
security/manager/boot/src/PreloadedHPKPins.json
security/manager/boot/src/StaticHPKPins.h
security/manager/boot/src/default-ee.der
security/manager/boot/src/genHPKPStaticPins.js
security/manager/tools/PreloadedHPKPins.json
security/manager/tools/genHPKPStaticPins.js
--- a/security/manager/boot/src/StaticHPKPins.h
+++ b/security/manager/boot/src/StaticHPKPins.h
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
-/* PublicKeyPinningSerice.cpp, you shouldn't be #including it.               */
+/* PublicKeyPinningService.cpp, you shouldn't be #including it.              */
 /*****************************************************************************/
 #include <stdint.h>
 /* Baltimore CyberTrust Root */
 static const char kBaltimore_CyberTrust_RootFingerprint[]=
   "Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=";
 
 /* DigiCert Assured ID Root CA */
 static const char kDigiCert_Assured_ID_Root_CAFingerprint[]=
@@ -197,9 +197,9 @@ static const TransportSecurityPreload kP
   { "cdn.mozilla.org",	true,	&kPinSet_mozilla_cdn },
   { "exclude-subdomains.pinning.example.com",	false,	&kPinSet_mozilla_test },
   { "include-subdomains.pinning.example.com",	true,	&kPinSet_mozilla_test },
   { "media.mozilla.com",	true,	&kPinSet_mozilla_cdn },
 };
 
 static const int kPublicKeyPinningPreloadListLength = 7;
 
-const PRTime kPreloadPKPinsExpirationTime = INT64_C(1409782406553000);
+const PRTime kPreloadPKPinsExpirationTime = INT64_C(1409867186821000);
deleted file mode 100644
index 6874346226edccf7133f7f249ead3b1c39c318be..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
rename from security/manager/boot/src/PreloadedHPKPins.json
rename to security/manager/tools/PreloadedHPKPins.json
rename from security/manager/boot/src/genHPKPStaticPins.js
rename to security/manager/tools/genHPKPStaticPins.js
--- a/security/manager/boot/src/genHPKPStaticPins.js
+++ b/security/manager/tools/genHPKPStaticPins.js
@@ -1,80 +1,76 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // How to run this file:
 // 1. [obtain firefox source code]
 // 2. [build/obtain firefox binaries]
 // 3. run `[path to]/run-mozilla.sh [path to]/xpcshell \
-//                                  [path to]/genHPKPStaticpins.js
-// Files PreloadedHPKPins.json and default-ee.der must be in the current
-// working directory.
+//                                  [path to]/genHPKPStaticpins.js \
+//                                  [absolute path to]/PreloadedHPKPins.json \
+//                                  [absolute path to]/default-ee.der \
+//                                  [absolute path to]/StaticHPKPins.h
+
+if (arguments.length != 3) {
+  throw "Usage: genHPKPins.js <absolute path to PreloadedHPKPins.json> " +
+        "<absolute path to default-ee.der> " +
+        "<absolute path to StaticHPKPins.h>";
+}
 
 const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components;
 
 let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
 
 const certdb2 = Cc["@mozilla.org/security/x509certdb;1"]
                    .getService(Ci.nsIX509CertDB2);
 
-const OUTPUT = "StaticHPKPins.h";
-const MOZINPUT = "PreloadedHPKPins.json";
+// Pins expire in 18 weeks
 const PINNING_MINIMUM_REQUIRED_MAX_AGE = 60 * 60 * 24 * 7 * 18;
 const FILE_HEADER = "/* This Source Code Form is subject to the terms of the Mozilla Public\n" +
 " * License, v. 2.0. If a copy of the MPL was not distributed with this\n" +
 " * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n" +
 "\n" +
 "/*****************************************************************************/\n" +
 "/* This is an automatically generated file. If you're not                    */\n" +
-"/* PublicKeyPinningSerice.cpp, you shouldn't be #including it.               */\n" +
+"/* PublicKeyPinningService.cpp, you shouldn't be #including it.              */\n" +
 "/*****************************************************************************/\n" +
 "#include <stdint.h>" +
 "\n";
 const DOMAINHEADER ="/*Domainlist*/\n" +
 "typedef struct {\n"+
 "  const char *mHost;\n"+
 "  const bool mIncludeSubdomains;\n"+
 "  const StaticPinset *pinset;\n"+
 "} TransportSecurityPreload;\n"+
 "\nstatic const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {\n";
 const PINSETDEF ="/*Now the pinsets, each is an ordered list by the actual value of the FP*/\n"+
 "typedef struct {\n"+
 "  const size_t size;\n"+
 "  const char* const* data;\n"+
 "} StaticPinset;\n";
 
+// Command-line arguments
+var gStaticPins = parseJson(arguments[0]);
+var gTestCertFile = arguments[1];
+var gOutputFile = arguments[2];
+
 function writeTo(string, fos) {
   fos.write(string, string.length);
 }
 
 function readFileToString(filename) {
-  let path = filename;
-
-  let lf = Components.classes["@mozilla.org/file/directory_service;1"]
-             .getService(Components.interfaces.nsIProperties)
-             .get("CurWorkD", Components.interfaces.nsILocalFile);
-
-  let bits = path.split("/");
-  for (let i = 0; i < bits.length; i++) {
-    if (bits[i]) {
-      if (bits[i] == "..") {
-        lf = lf.parent;
-      }
-      else {
-        lf.append(bits[i]);
-      }
-    }
-  }
+  let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+  file.initWithPath(filename);
   let stream = Cc["@mozilla.org/network/file-input-stream;1"]
                  .createInstance(Ci.nsIFileInputStream);
-  stream.init(lf, -1, 0, 0);
+  stream.init(file, -1, 0, 0);
   let buf = NetUtil.readInputStreamToString(stream, stream.available());
   return buf;
 }
 
 function stripComments(buf) {
   var lines = buf.split("\n");
   let entryRegex = /^\s*\/\//;
   let data = "";
@@ -100,17 +96,17 @@ function isCertBuiltIn(cert) {
   if (tokenNames.some(isBuiltinToken)) {
     return true;
   }
   return false;
 }
 
 // Returns a pair of maps [certNameToSKD, certSDKToName] between cert
 // nicknames and digests of the SPKInfo for the mozilla trust store
-function loadNSSCertinfo() {
+function loadNSSCertinfo(derTestFile) {
   let allCerts = certdb2.getCerts();
   let enumerator = allCerts.getEnumerator();
   let certNameToSKD = {};
   let certSDKToName = {};
   const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
   while (enumerator.hasMoreElements()) {
     let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
     if (!isCertBuiltIn(cert)) {
@@ -118,35 +114,34 @@ function loadNSSCertinfo() {
     }
     let name = cert.nickname.substr(BUILT_IN_NICK_PREFIX.length);
     let SDK  = cert.sha256SubjectPublicKeyInfoDigest;
     certNameToSKD[name] = SDK;
     certSDKToName[SDK] = name;
   }
   {
     // A certificate for *.example.com.
-    let der = readFileToString("default-ee.der");
+    let der = readFileToString(derTestFile);
     // XPCOM is too dumb to automatically query the parent interface of
     // nsIX509CertDB2 without a hint.
     let certdb = certdb2.QueryInterface(Ci.nsIX509CertDB);
     let testCert = certdb.constructX509(der, der.length);
     // We can't include this cert in the previous loop, because it skips
     // non-builtin certs and the nickname is not built-in to the cert.
     let name = "End Entity Test Cert";
     let SDK  = testCert.sha256SubjectPublicKeyInfoDigest;
     certNameToSKD[name] = SDK;
     certSDKToName[SDK] = name;
   }
   return [certNameToSKD, certSDKToName];
 }
 
-function parseMozFile() {
-  mozFile = stripComments(readFileToString(MOZINPUT));
-  mozJSON = JSON.parse(mozFile);
-  return mozJSON;
+function parseJson(filename) {
+  let json = stripComments(readFileToString(filename));
+  return JSON.parse(json);
 }
 
 function nameToAlias(certName) {
   // change the name to a string valid as a c identifier
   // remove  non-ascii characters
   certName = certName.replace( /[^[:ascii:]]/g, "_");
   // replace non word characters
   certName = certName.replace(/[^A-Za-z0-9]/g ,"_");
@@ -164,17 +159,18 @@ function genExpirationTime() {
   let expirationMillis = nowMillis + (PINNING_MINIMUM_REQUIRED_MAX_AGE * 1000);
   let expirationMicros = expirationMillis * 1000;
   return "const PRTime kPreloadPKPinsExpirationTime = INT64_C(" +
          expirationMicros +");\n";
 }
 
 function writeFile(certNameToSDK, certSDKToName, jsonPins) {
   try {
-    let file = FileUtils.getFile("CurWorkD", [OUTPUT]);
+    let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+    file.initWithPath(gOutputFile);
     let fos = FileUtils.openSafeFileOutputStream(file);
 
     writeTo(FILE_HEADER, fos);
 
     // compute used keys
     let usedFingerPrints = {};
     let pinset = jsonPins["pinsets"];
     for (let pinsetEntry of pinset) {
@@ -228,18 +224,16 @@ function writeFile(certNameToSDK, certSD
                        jsonPins["entries"].length + ";\n";
     writeTo(domainFooter, fos);
     writeTo("\n", fos);
     writeTo(genExpirationTime(), fos);
 
     FileUtils.closeSafeFileOutputStream(fos);
 
   } catch (e) {
-    dump("ERROR: problem writing output to '" + OUTPUT + "': " + e + "\n");
+    dump("ERROR: problem writing output to '" + gOutputFile + "': " + e + "\n");
   }
 }
 
 // ****************************************************************************
 // This is where the action happens:
-
-let [certNameToSKD, certSDKToName] = loadNSSCertinfo();
-let mozJSON = parseMozFile();
-writeFile(certNameToSKD, certSDKToName, mozJSON);
+let [ certNameToSKD, certSDKToName ] = loadNSSCertinfo(gTestCertFile);
+writeFile(certNameToSKD, certSDKToName, gStaticPins);