зеркало из https://github.com/mozilla/gecko-dev.git
116 строки
4.3 KiB
JavaScript
116 строки
4.3 KiB
JavaScript
/* 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/. */
|
|
|
|
"use strict";
|
|
|
|
this.EXPORTED_SYMBOLS = ["OneCRLClient"];
|
|
|
|
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|
|
|
Cu.import("resource://services-common/moz-kinto-client.js");
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/Task.jsm");
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
|
"@mozilla.org/uuid-generator;1",
|
|
"nsIUUIDGenerator");
|
|
|
|
const PREF_KINTO_BASE = "services.kinto.base";
|
|
const PREF_KINTO_BUCKET = "services.kinto.bucket";
|
|
const PREF_KINTO_ONECRL_COLLECTION = "services.kinto.onecrl.collection";
|
|
const PREF_KINTO_ONECRL_CHECKED_SECONDS = "services.kinto.onecrl.checked";
|
|
|
|
const RE_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
|
|
// Kinto.js assumes version 4 UUIDs but allows you to specify custom
|
|
// validators and generators. The tooling that generates records in the
|
|
// certificates collection currently uses a version 1 UUID so we must
|
|
// specify a validator that's less strict. We must also supply a generator
|
|
// since Kinto.js does not allow one without the other.
|
|
function makeIDSchema() {
|
|
return {
|
|
validate: RE_UUID.test.bind(RE_UUID),
|
|
generate: function() {
|
|
return uuidgen.generateUUID().toString();
|
|
}
|
|
};
|
|
}
|
|
|
|
// A Kinto based client to keep the OneCRL certificate blocklist up to date.
|
|
function CertBlocklistClient() {
|
|
// maybe sync the collection of certificates with remote data.
|
|
// lastModified - the lastModified date (on the server, milliseconds since
|
|
// epoch) of data in the remote collection
|
|
// serverTime - the time on the server (milliseconds since epoch)
|
|
// returns a promise which rejects on sync failure
|
|
this.maybeSync = function(lastModified, serverTime) {
|
|
let base = Services.prefs.getCharPref(PREF_KINTO_BASE);
|
|
let bucket = Services.prefs.getCharPref(PREF_KINTO_BUCKET);
|
|
|
|
let Kinto = loadKinto();
|
|
|
|
let FirefoxAdapter = Kinto.adapters.FirefoxAdapter;
|
|
|
|
|
|
let certList = Cc["@mozilla.org/security/certblocklist;1"]
|
|
.getService(Ci.nsICertBlocklist);
|
|
|
|
// Future blocklist clients can extract the sync-if-stale logic. For
|
|
// now, since this is currently the only client, we'll do this here.
|
|
let config = {
|
|
remote: base,
|
|
bucket: bucket,
|
|
adapter: FirefoxAdapter,
|
|
};
|
|
|
|
let db = new Kinto(config);
|
|
let collectionName = Services.prefs.getCharPref(PREF_KINTO_ONECRL_COLLECTION,
|
|
"certificates");
|
|
let blocklist = db.collection(collectionName,
|
|
{ idSchema: makeIDSchema() });
|
|
|
|
let updateLastCheck = function() {
|
|
let checkedServerTimeInSeconds = Math.round(serverTime / 1000);
|
|
Services.prefs.setIntPref(PREF_KINTO_ONECRL_CHECKED_SECONDS,
|
|
checkedServerTimeInSeconds);
|
|
}
|
|
|
|
return Task.spawn(function* () {
|
|
try {
|
|
yield blocklist.db.open();
|
|
let collectionLastModified = yield blocklist.db.getLastModified();
|
|
// if the data is up to date, there's no need to sync. We still need
|
|
// to record the fact that a check happened.
|
|
if (lastModified <= collectionLastModified) {
|
|
updateLastCheck();
|
|
return;
|
|
}
|
|
yield blocklist.sync();
|
|
let list = yield blocklist.list();
|
|
for (let item of list.data) {
|
|
if (item.issuerName && item.serialNumber) {
|
|
certList.revokeCertByIssuerAndSerial(item.issuerName,
|
|
item.serialNumber);
|
|
} else if (item.subject && item.pubKeyHash) {
|
|
certList.revokeCertBySubjectAndPubKey(item.subject,
|
|
item.pubKeyHash);
|
|
} else {
|
|
throw new Error("Cert blocklist record has incomplete data");
|
|
}
|
|
}
|
|
// We explicitly do not want to save entries or update the
|
|
// last-checked time if sync fails
|
|
certList.saveEntries();
|
|
updateLastCheck();
|
|
} finally {
|
|
blocklist.db.close()
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
this.OneCRLClient = new CertBlocklistClient();
|