1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-27 10:32:58 +02:00
joplin/packages/lib/vendor/syswide-cas.js
2020-11-10 15:59:30 +00:00

107 lines
3.2 KiB
JavaScript

// From https://github.com/capriza/syswide-cas/tree/e0a214f23a072866abf6af540a5b4b88b892a109
// With a patch to make it work within Jest environment
const fs = require("fs");
const path = require("path");
const tls = require("tls");
const rootCAs = [];
// for node 7.2 and up, trapping method must be used.
var useTrap = false;
const parts = process.versions.node.split(".");
const major = parseInt(parts[0]);
const minor = parseInt(parts[1]);
if (major > 7 || (major == 7 && minor >= 2) || (major === 6 && minor >= 10)) {
useTrap = true;
}
// create an empty secure context loaded with the root CAs
const rootSecureContext = tls.createSecureContext ? tls.createSecureContext() : require("crypto").createCredentials();
function addDefaultCA(file) {
try {
var cert, match;
var content = fs.readFileSync(file, { encoding: "ascii" }).trim();
content = content.replace(/\r\n/g, "\n"); // Handles certificates that have been created in Windows
var regex = /-----BEGIN CERTIFICATE-----\n[\s\S]+?\n-----END CERTIFICATE-----/g;
var results = content.match(regex);
if (!results) throw new Error("Could not parse certificate");
results.forEach(function(match) {
var cert = match.trim();
rootCAs.push(cert);
// this will add the cert to the root certificate authorities list
// which will be used by all subsequent secure contexts with root CAs.
// this only works up to node 6. node 7 and up it has no affect.
if (!useTrap) {
rootSecureContext.context.addCACert(cert);
}
});
} catch (e) {
if (e.code !== "ENOENT") {
console.log("failed reading file " + file + ": " + e.message);
}
}
}
exports.addCAs = function(dirs) {
if (!dirs) {
return;
}
if (typeof dirs === "string") {
dirs = dirs.split(",").map(function(dir) {
return dir.trim();
});
}
var files, stat, file, i, j;
for (i = 0; i < dirs.length; ++i) {
try {
stat = fs.statSync(dirs[i]);
if (stat.isDirectory()) {
files = fs.readdirSync(dirs[i]);
for (j = 0; j < files.length; ++j) {
file = path.resolve(dirs[i], files[j]);
try {
stat = fs.statSync(file);
if (stat.isFile()) {
addDefaultCA(file);
}
} catch (e) {
if (e.code !== "ENOENT") {
console.log("failed reading " + file + ": " + e.message);
}
}
}
} else {
addDefaultCA(dirs[i]);
}
} catch (e) {
if (e.code !== "ENOENT") {
console.log("failed reading " + dirs[i] + ": " + e.message);
}
}
}
};
if (useTrap) {
// trap the createSecureContext method and inject custom root CAs whenever invoked
const origCreateSecureContext = tls.createSecureContext;
tls.createSecureContext = function(options) {
options = options || {}; // PATCH - in Jest, this is null
var c = origCreateSecureContext.apply(null, arguments);
if (!options.ca && rootCAs.length > 0) {
rootCAs.forEach(function(ca) {
// add to the created context our own root CAs
c.context.addCACert(ca);
});
}
return c;
};
}
const defaultCALocations = ["/etc/ssl/ca-node.pem"];
exports.addCAs(defaultCALocations);