forked from mirrors/gecko-dev
145 lines
5.9 KiB
JavaScript
145 lines
5.9 KiB
JavaScript
"use strict";
|
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
ctypes: "resource://gre/modules/ctypes.jsm",
|
|
NativeManifests: "resource://gre/modules/NativeManifests.jsm",
|
|
OS: "resource://gre/modules/osfile.jsm",
|
|
});
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this,
|
|
"pkcs11db",
|
|
"@mozilla.org/security/pkcs11moduledb;1",
|
|
"nsIPKCS11ModuleDB");
|
|
|
|
var {DefaultMap} = ExtensionUtils;
|
|
|
|
const findModuleByPath = function(path) {
|
|
let modules = pkcs11db.listModules();
|
|
for (let module of XPCOMUtils.IterSimpleEnumerator(modules, Ci.nsIPKCS11Module)) {
|
|
if (module && module.libName === path) {
|
|
return module;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
this.pkcs11 = class extends ExtensionAPI {
|
|
getAPI(context) {
|
|
let manifestCache = new DefaultMap(async name => {
|
|
let hostInfo = await NativeManifests.lookupManifest("pkcs11", name, context);
|
|
if (hostInfo) {
|
|
if (AppConstants.platform === "win") {
|
|
hostInfo.manifest.path = OS.Path.join(OS.Path.dirname(hostInfo.path), hostInfo.manifest.path);
|
|
}
|
|
let manifestLib = OS.Path.basename(hostInfo.manifest.path);
|
|
if (AppConstants.platform !== "linux") {
|
|
manifestLib = manifestLib.toLowerCase(manifestLib);
|
|
}
|
|
if (manifestLib !== ctypes.libraryName("nssckbi")) {
|
|
return hostInfo.manifest;
|
|
}
|
|
}
|
|
return Promise.reject({message: `No such PKCS#11 module ${name}`});
|
|
});
|
|
return {
|
|
pkcs11: {
|
|
/**
|
|
* Verify whether a given PKCS#11 module is installed.
|
|
*
|
|
* @param {string} name The name of the module, as specified in
|
|
* the manifest file.
|
|
* @returns {Promise} A Promise that resolves to true if the package
|
|
* is installed, or false if it is not. May be
|
|
* rejected if the module could not be found.
|
|
*/
|
|
async isModuleInstalled(name) {
|
|
let manifest = await manifestCache.get(name);
|
|
return findModuleByPath(manifest.path) !== null;
|
|
},
|
|
/**
|
|
* Install a PKCS#11 module
|
|
*
|
|
* @param {string} name The name of the module, as specified in
|
|
* the manifest file.
|
|
* @param {integer} [flags = 0] Any flags to be passed on to the
|
|
* nsIPKCS11ModuleDB.addModule method
|
|
* @returns {Promise} When the Promise resolves, the module will have
|
|
* been installed. When it is rejected, the module
|
|
* either is already installed or could not be
|
|
* installed for some reason.
|
|
*/
|
|
async installModule(name, flags = 0) {
|
|
let manifest = await manifestCache.get(name);
|
|
if (!manifest.description) {
|
|
return Promise.reject({message: `The description field in the manifest for PKCS#11 module ${name} must have a value`});
|
|
}
|
|
pkcs11db.addModule(manifest.description, manifest.path, flags, 0);
|
|
},
|
|
/**
|
|
* Uninstall a PKCS#11 module
|
|
*
|
|
* @param {string} name The name of the module, as specified in
|
|
* the manifest file.
|
|
* @returns {Promise}. When the Promise resolves, the module will have
|
|
* been uninstalled. When it is rejected, the
|
|
* module either was not installed or could not be
|
|
* uninstalled for some reason.
|
|
*/
|
|
async uninstallModule(name) {
|
|
let manifest = await manifestCache.get(name);
|
|
let module = findModuleByPath(manifest.path);
|
|
if (!module) {
|
|
return Promise.reject({message: `The PKCS#11 module ${name} is not loaded`});
|
|
}
|
|
pkcs11db.deleteModule(module.name);
|
|
},
|
|
/**
|
|
* Get a list of slots for a given PKCS#11 module, with
|
|
* information on the token (if any) in the slot.
|
|
*
|
|
* The PKCS#11 standard defines slots as an abstract concept
|
|
* that may or may not have at most one token. In practice, when
|
|
* using PKCS#11 for smartcards (the most likely use case of
|
|
* PKCS#11 for Firefox), a slot corresponds to a cardreader, and
|
|
* a token corresponds to a card.
|
|
*
|
|
* @param {string} name The name of the PKCS#11 module, as
|
|
* specified in the manifest file.
|
|
* @returns {Promise} A promise that resolves to an array of objects
|
|
* with two properties. The `name` object contains
|
|
* the name of the slot; the `token` object is null
|
|
* if there is no token in the slot, or is an object
|
|
* describing various properties of the token if
|
|
* there is.
|
|
*/
|
|
async getModuleSlots(name) {
|
|
let manifest = await manifestCache.get(name);
|
|
let module = findModuleByPath(manifest.path);
|
|
if (!module) {
|
|
return Promise.reject({message: `The module ${name} is not installed`});
|
|
}
|
|
let rv = [];
|
|
for (let slot of XPCOMUtils.IterSimpleEnumerator(module.listSlots(), Ci.nsIPKCS11Slot)) {
|
|
let token = slot.getToken();
|
|
let slotobj = {
|
|
name: slot.name,
|
|
token: null,
|
|
};
|
|
if (slot.status != 1 /* SLOT_NOT_PRESENT */) {
|
|
slotobj.token = {
|
|
name: token.tokenName,
|
|
manufacturer: token.tokenManID,
|
|
HWVersion: token.tokenHWVersion,
|
|
FWVersion: token.tokenFWVersion,
|
|
serial: token.tokenSerialNumber,
|
|
isLoggedIn: token.isLoggedIn(),
|
|
};
|
|
}
|
|
rv.push(slotobj);
|
|
}
|
|
return rv;
|
|
},
|
|
},
|
|
};
|
|
}
|
|
};
|