botbook/node_modules/devcert/dist/platforms/shared.js

145 lines
20 KiB
JavaScript
Raw Normal View History

2024-09-04 13:13:15 -03:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertNotTouchingFiles = exports.openCertificateInFirefox = exports.closeFirefox = exports.removeCertificateFromNSSCertDB = exports.addCertificateToNSSCertDB = void 0;
const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path"));
const url_1 = tslib_1.__importDefault(require("url"));
const debug_1 = tslib_1.__importDefault(require("debug"));
const assert_1 = tslib_1.__importDefault(require("assert"));
const get_port_1 = tslib_1.__importDefault(require("get-port"));
const http_1 = tslib_1.__importDefault(require("http"));
const glob_1 = require("glob");
const fs_1 = require("fs");
const utils_1 = require("../utils");
const constants_1 = require("../constants");
const user_interface_1 = tslib_1.__importDefault(require("../user-interface"));
const child_process_1 = require("child_process");
const debug = debug_1.default('devcert:platforms:shared');
/**
* Given a directory or glob pattern of directories, run a callback for each db
* directory, with a version argument.
*/
function doForNSSCertDB(nssDirGlob, callback) {
glob_1.sync(nssDirGlob).forEach((potentialNSSDBDir) => {
debug(`checking to see if ${potentialNSSDBDir} is a valid NSS database directory`);
if (fs_1.existsSync(path_1.default.join(potentialNSSDBDir, 'cert8.db'))) {
debug(`Found legacy NSS database in ${potentialNSSDBDir}, running callback...`);
callback(potentialNSSDBDir, 'legacy');
}
if (fs_1.existsSync(path_1.default.join(potentialNSSDBDir, 'cert9.db'))) {
debug(`Found modern NSS database in ${potentialNSSDBDir}, running callback...`);
callback(potentialNSSDBDir, 'modern');
}
});
}
/**
* Given a directory or glob pattern of directories, attempt to install the
* CA certificate to each directory containing an NSS database.
*/
function addCertificateToNSSCertDB(nssDirGlob, certPath, certutilPath) {
debug(`trying to install certificate into NSS databases in ${nssDirGlob}`);
doForNSSCertDB(nssDirGlob, (dir, version) => {
const dirArg = version === 'modern' ? `sql:${dir}` : dir;
utils_1.run(certutilPath, ['-A', '-d', dirArg, '-t', 'C,,', '-i', certPath, '-n', 'devcert']);
});
debug(`finished scanning & installing certificate in NSS databases in ${nssDirGlob}`);
}
exports.addCertificateToNSSCertDB = addCertificateToNSSCertDB;
function removeCertificateFromNSSCertDB(nssDirGlob, certPath, certutilPath) {
debug(`trying to remove certificates from NSS databases in ${nssDirGlob}`);
doForNSSCertDB(nssDirGlob, (dir, version) => {
const dirArg = version === 'modern' ? `sql:${dir}` : dir;
try {
utils_1.run(certutilPath, ['-A', '-d', dirArg, '-t', 'C,,', '-i', certPath, '-n', 'devcert']);
}
catch (e) {
debug(`failed to remove ${certPath} from ${dir}, continuing. ${e.toString()}`);
}
});
debug(`finished scanning & installing certificate in NSS databases in ${nssDirGlob}`);
}
exports.removeCertificateFromNSSCertDB = removeCertificateFromNSSCertDB;
/**
* Check to see if Firefox is still running, and if so, ask the user to close
* it. Poll until it's closed, then return.
*
* This is needed because Firefox appears to load the NSS database in-memory on
* startup, and overwrite on exit. So we have to ask the user to quite Firefox
* first so our changes don't get overwritten.
*/
function closeFirefox() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (isFirefoxOpen()) {
yield user_interface_1.default.closeFirefoxBeforeContinuing();
while (isFirefoxOpen()) {
yield sleep(50);
}
}
});
}
exports.closeFirefox = closeFirefox;
/**
* Check if Firefox is currently open
*/
function isFirefoxOpen() {
// NOTE: We use some Windows-unfriendly methods here (ps) because Windows
// never needs to check this, because it doesn't update the NSS DB
// automaticaly.
assert_1.default(constants_1.isMac || constants_1.isLinux, 'checkForOpenFirefox was invoked on a platform other than Mac or Linux');
return child_process_1.execSync('ps aux').indexOf('firefox') > -1;
}
function sleep(ms) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return new Promise((resolve) => setTimeout(resolve, ms));
});
}
/**
* Firefox manages it's own trust store for SSL certificates, which can be
* managed via the certutil command (supplied by NSS tooling packages). In the
* event that certutil is not already installed, and either can't be installed
* (Windows) or the user doesn't want to install it (skipCertutilInstall:
* true), it means that we can't programmatically tell Firefox to trust our
* root CA certificate.
*
* There is a recourse though. When a Firefox tab is directed to a URL that
* responds with a certificate, it will automatically prompt the user if they
* want to add it to their trusted certificates. So if we can't automatically
* install the certificate via certutil, we instead start a quick web server
* and host our certificate file. Then we open the hosted cert URL in Firefox
* to kick off the GUI flow.
*
* This method does all this, along with providing user prompts in the terminal
* to walk them through this process.
*/
function openCertificateInFirefox(firefoxPath, certPath) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
debug('Adding devert to Firefox trust stores manually. Launching a webserver to host our certificate temporarily ...');
let port = yield get_port_1.default();
let server = http_1.default.createServer((req, res) => tslib_1.__awaiter(this, void 0, void 0, function* () {
let { pathname } = url_1.default.parse(req.url);
if (pathname === '/certificate') {
res.writeHead(200, { 'Content-type': 'application/x-x509-ca-cert' });
res.write(fs_1.readFileSync(certPath));
res.end();
}
else {
res.writeHead(200);
res.write(yield user_interface_1.default.firefoxWizardPromptPage(`http://localhost:${port}/certificate`));
res.end();
}
})).listen(port);
debug('Certificate server is up. Printing instructions for user and launching Firefox with hosted certificate URL');
yield user_interface_1.default.startFirefoxWizard(`http://localhost:${port}`);
utils_1.run(firefoxPath, [`http://localhost:${port}`]);
yield user_interface_1.default.waitForFirefoxWizard();
server.close();
});
}
exports.openCertificateInFirefox = openCertificateInFirefox;
function assertNotTouchingFiles(filepath, operation) {
if (!filepath.startsWith(constants_1.configDir) && !filepath.startsWith(constants_1.getLegacyConfigDir())) {
throw new Error(`Devcert cannot ${operation} ${filepath}; it is outside known devcert config directories!`);
}
}
exports.assertNotTouchingFiles = assertNotTouchingFiles;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLmpzIiwic291cmNlUm9vdCI6Ii4vIiwic291cmNlcyI6WyJwbGF0Zm9ybXMvc2hhcmVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSx3REFBd0I7QUFDeEIsc0RBQXNCO0FBQ3RCLDBEQUFnQztBQUNoQyw0REFBNEI7QUFDNUIsZ0VBQStCO0FBQy9CLHdEQUF3QjtBQUN4QiwrQkFBb0M7QUFDcEMsMkJBQW9FO0FBQ3BFLG9DQUErQjtBQUMvQiw0Q0FBOEU7QUFDOUUsK0VBQW1DO0FBQ25DLGlEQUFpRDtBQUVqRCxNQUFNLEtBQUssR0FBRyxlQUFXLENBQUMsMEJBQTBCLENBQUMsQ0FBQztBQUV0RDs7O0dBR0c7QUFDSCxTQUFTLGNBQWMsQ0FBQyxVQUFrQixFQUFFLFFBQTZEO0lBQ3ZHLFdBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxpQkFBaUIsRUFBRSxFQUFFO1FBQzdDLEtBQUssQ0FBQyxzQkFBdUIsaUJBQWtCLG9DQUFvQyxDQUFDLENBQUM7UUFDckYsSUFBSSxlQUFNLENBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxVQUFVLENBQUMsQ0FBQyxFQUFFO1lBQ3BELEtBQUssQ0FBQyxnQ0FBaUMsaUJBQWtCLHVCQUF1QixDQUFDLENBQUE7WUFDakYsUUFBUSxDQUFDLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQ3ZDO1FBQ0QsSUFBSSxlQUFNLENBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxVQUFVLENBQUMsQ0FBQyxFQUFFO1lBQ3BELEtBQUssQ0FBQyxnQ0FBaUMsaUJBQWtCLHVCQUF1QixDQUFDLENBQUE7WUFDakYsUUFBUSxDQUFDLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQ3ZDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZ0IseUJBQXlCLENBQUMsVUFBa0IsRUFBRSxRQUFnQixFQUFFLFlB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