"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSignVendorPath = getSignVendorPath; exports.sign = sign; exports.getCertInfo = getCertInfo; exports.getCertificateFromStoreInfo = getCertificateFromStoreInfo; exports.isOldWin6 = isOldWin6; function _util() { const data = require("builder-util/out/util"); _util = function () { return data; }; return data; } function _binDownload() { const data = require("../binDownload"); _binDownload = function () { return data; }; return data; } function _appBuilder() { const data = require("../util/appBuilder"); _appBuilder = function () { return data; }; return data; } function _bundledTool() { const data = require("../util/bundledTool"); _bundledTool = function () { return data; }; return data; } function _fsExtra() { const data = require("fs-extra"); _fsExtra = function () { return data; }; return data; } function os() { const data = _interopRequireWildcard(require("os")); os = function () { return data; }; return data; } var path = _interopRequireWildcard(require("path")); function _platformPackager() { const data = require("../platformPackager"); _platformPackager = function () { return data; }; return data; } function _flags() { const data = require("../util/flags"); _flags = function () { return data; }; return data; } function _vm() { const data = require("../vm/vm"); _vm = function () { return data; }; return data; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } function getSignVendorPath() { return (0, _binDownload().getBin)("winCodeSign"); } async function sign(options, packager) { let hashes = options.options.signingHashAlgorithms; // msi does not support dual-signing if (options.path.endsWith(".msi")) { hashes = [hashes != null && !hashes.includes("sha1") ? "sha256" : "sha1"]; } else if (options.path.endsWith(".appx")) { hashes = ["sha256"]; } else if (hashes == null) { hashes = ["sha1", "sha256"]; } else { hashes = Array.isArray(hashes) ? hashes : [hashes]; } function defaultExecutor(configuration) { return doSign(configuration, packager); } const executor = (0, _platformPackager().resolveFunction)(options.options.sign, "sign") || defaultExecutor; let isNest = false; for (const hash of hashes) { const taskConfiguration = Object.assign({}, options, { hash, isNest }); await executor(Object.assign({}, taskConfiguration, { computeSignToolArgs: isWin => computeSignToolArgs(taskConfiguration, isWin) })); isNest = true; if (taskConfiguration.resultOutputPath != null) { await (0, _fsExtra().rename)(taskConfiguration.resultOutputPath, options.path); } } } async function getCertInfo(file, password) { let result = null; const errorMessagePrefix = "Cannot extract publisher name from code signing certificate. As workaround, set win.publisherName. Error: "; try { result = await (0, _appBuilder().executeAppBuilderAsJson)(["certificate-info", "--input", file, "--password", password]); } catch (e) { throw new Error(`${errorMessagePrefix}${e.stack || e}`); } if (result.error != null) { // noinspection ExceptionCaughtLocallyJS throw new (_util().InvalidConfigurationError)(`${errorMessagePrefix}${result.error}`); } return result; } async function getCertificateFromStoreInfo(options, vm) { const certificateSubjectName = options.certificateSubjectName; const certificateSha1 = options.certificateSha1; // ExcludeProperty doesn't work, so, we cannot exclude RawData, it is ok // powershell can return object if the only item const rawResult = await vm.exec("powershell.exe", ["Get-ChildItem -Recurse Cert: -CodeSigningCert | Select-Object -Property Subject,PSParentPath,Thumbprint | ConvertTo-Json -Compress"]); const certList = rawResult.length === 0 ? [] : (0, _util().asArray)(JSON.parse(rawResult)); for (const certInfo of certList) { if (certificateSubjectName != null) { if (!certInfo.Subject.includes(certificateSubjectName)) { continue; } } else if (certInfo.Thumbprint !== certificateSha1) { continue; } const parentPath = certInfo.PSParentPath; const store = parentPath.substring(parentPath.lastIndexOf("\\") + 1); _util().log.debug({ store, PSParentPath: parentPath }, "auto-detect certificate store"); // https://github.com/electron-userland/electron-builder/issues/1717 const isLocalMachineStore = parentPath.includes("Certificate::LocalMachine"); _util().log.debug(null, "auto-detect using of LocalMachine store"); return { thumbprint: certInfo.Thumbprint, subject: certInfo.Subject, store, isLocalMachineStore }; } throw new Error(`Cannot find certificate ${certificateSubjectName || certificateSha1}, all certs: ${rawResult}`); } async function doSign(configuration, packager) { // https://github.com/electron-userland/electron-builder/pull/1944 const timeout = parseInt(process.env.SIGNTOOL_TIMEOUT, 10) || 10 * 60 * 1000; let tool; let args; let env = process.env; let vm; if (configuration.path.endsWith(".appx") || !("file" in configuration.cscInfo) /* certificateSubjectName and other such options */ ) { vm = await packager.vm.value; tool = getWinSignTool((await getSignVendorPath())); args = computeSignToolArgs(configuration, true, vm); } else { vm = new (_vm().VmManager)(); const toolInfo = await getToolPath(); tool = toolInfo.path; args = configuration.computeSignToolArgs(process.platform === "win32"); if (toolInfo.env != null) { env = toolInfo.env; } } try { await vm.exec(tool, args, { timeout, env }); } catch (e) { if (e.message.includes("The file is being used by another process") || e.message.includes("The specified timestamp server either could not be reached")) { _util().log.warn(`First attempt to code sign failed, another attempt will be made in 2 seconds: ${e.message}`); await new Promise((resolve, reject) => { setTimeout(() => { vm.exec(tool, args, { timeout, env }).then(resolve).catch(reject); }, 2000); }); } throw e; } } // on windows be aware of http://stackoverflow.com/a/32640183/1910191 function computeSignToolArgs(options, isWin, vm = new (_vm().VmManager)()) { const inputFile = vm.toVmFile(options.path); const outputPath = isWin ? inputFile : getOutputPath(inputFile, options.hash); if (!isWin) { options.resultOutputPath = outputPath; } const args = isWin ? ["sign"] : ["-in", inputFile, "-out", outputPath]; if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") { const timestampingServiceUrl = options.options.timeStampServer || "http://timestamp.digicert.com"; if (isWin) { args.push(options.isNest || options.hash === "sha256" ? "/tr" : "/t", options.isNest || options.hash === "sha256" ? options.options.rfc3161TimeStampServer || "http://timestamp.comodoca.com/rfc3161" : timestampingServiceUrl); } else { args.push("-t", timestampingServiceUrl); } } const certificateFile = options.cscInfo.file; if (certificateFile == null) { const cscInfo = options.cscInfo; const subjectName = cscInfo.thumbprint; if (!isWin) { throw new Error(`${subjectName == null ? "certificateSha1" : "certificateSubjectName"} supported only on Windows`); } args.push("/sha1", cscInfo.thumbprint); args.push("/s", cscInfo.store); if (cscInfo.isLocalMachineStore) { args.push("/sm"); } } else { const certExtension = path.extname(certificateFile); if (certExtension === ".p12" || certExtension === ".pfx") { args.push(isWin ? "/f" : "-pkcs12", vm.toVmFile(certificateFile)); } else { throw new Error(`Please specify pkcs12 (.p12/.pfx) file, ${certificateFile} is not correct`); } } if (!isWin || options.hash !== "sha1") { args.push(isWin ? "/fd" : "-h", options.hash); if (isWin && process.env.ELECTRON_BUILDER_OFFLINE !== "true") { args.push("/td", "sha256"); } } if (options.name) { args.push(isWin ? "/d" : "-n", options.name); } if (options.site) { args.push(isWin ? "/du" : "-i", options.site); } // msi does not support dual-signing if (options.isNest) { args.push(isWin ? "/as" : "-nest"); } const password = options.cscInfo == null ? null : options.cscInfo.password; if (password) { args.push(isWin ? "/p" : "-pass", password); } if (options.options.additionalCertificateFile) { args.push(isWin ? "/ac" : "-ac", vm.toVmFile(options.options.additionalCertificateFile)); } const httpsProxyFromEnv = process.env.HTTPS_PROXY; if (!isWin && httpsProxyFromEnv != null && httpsProxyFromEnv.length) { args.push("-p", httpsProxyFromEnv); } if (isWin) { // https://github.com/electron-userland/electron-builder/issues/2875#issuecomment-387233610 args.push("/debug"); // must be last argument args.push(inputFile); } return args; } function getOutputPath(inputPath, hash) { const extension = path.extname(inputPath); return path.join(path.dirname(inputPath), `${path.basename(inputPath, extension)}-signed-${hash}${extension}`); } /** @internal */ function isOldWin6() { const winVersion = os().release(); return winVersion.startsWith("6.") && !winVersion.startsWith("6.3"); } function getWinSignTool(vendorPath) { // use modern signtool on Windows Server 2012 R2 to be able to sign AppX if (isOldWin6()) { return path.join(vendorPath, "windows-6", "signtool.exe"); } else { return path.join(vendorPath, "windows-10", process.arch, "signtool.exe"); } } async function getToolPath() { if ((0, _flags().isUseSystemSigncode)()) { return { path: "osslsigncode" }; } const result = process.env.SIGNTOOL_PATH; if (result) { return { path: result }; } const vendorPath = await getSignVendorPath(); if (process.platform === "win32") { // use modern signtool on Windows Server 2012 R2 to be able to sign AppX return { path: getWinSignTool(vendorPath) }; } else if (process.platform === "darwin") { const toolDirPath = path.join(vendorPath, process.platform, "10.12"); return { path: path.join(toolDirPath, "osslsigncode"), env: (0, _bundledTool().computeToolEnv)([path.join(toolDirPath, "lib")]) }; } else { return { path: path.join(vendorPath, process.platform, "osslsigncode") }; } } // __ts-babel@6.0.4 //# sourceMappingURL=windowsCodeSign.js.map