/* * 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 https://mozilla.org/MPL/2.0/. */ "use strict"; var { EnigmailDialog } = ChromeUtils.import( "chrome://openpgp/content/modules/dialog.jsm" ); var { EnigmailKey } = ChromeUtils.import( "chrome://openpgp/content/modules/key.jsm" ); var { EnigmailKeyRing } = ChromeUtils.import( "chrome://openpgp/content/modules/keyRing.jsm" ); var { EnigmailArmor } = ChromeUtils.import( "chrome://openpgp/content/modules/armor.jsm" ); var { MailStringUtils } = ChromeUtils.import( "resource:///modules/MailStringUtils.jsm" ); var l10n = new Localization(["messenger/openpgp/openpgp.ftl"], true); /** * opens a prompt, asking the user to enter passphrase for given key id * returns: the passphrase if entered (empty string is allowed) * resultFlags.canceled is set to true if the user clicked cancel */ function passphrasePromptCallback(win, promptString, resultFlags) { let password = { value: "" }; if (!Services.prompt.promptPassword(win, "", promptString, password)) { resultFlags.canceled = true; return ""; } resultFlags.canceled = false; return password.value; } /** * @param {nsIFile} file * @returns {string} The first block of the wanted type, or empty string. * Skip blocks of wrong type. */ async function getKeyBlockFromFile(file, wantSecret) { let contents = await IOUtils.readUTF8(file.path).catch(() => ""); let searchOffset = 0; while (searchOffset < contents.length) { const beginIndexObj = {}; const endIndexObj = {}; const blockType = EnigmailArmor.locateArmoredBlock( contents, searchOffset, "", beginIndexObj, endIndexObj, {} ); if (!blockType) { return ""; } if ( (wantSecret && blockType.search(/^PRIVATE KEY BLOCK$/) !== 0) || (!wantSecret && blockType.search(/^PUBLIC KEY BLOCK$/) !== 0) ) { searchOffset = endIndexObj.value; continue; } return contents.substr( beginIndexObj.value, endIndexObj.value - beginIndexObj.value + 1 ); } return ""; } /** * import OpenPGP keys from file * * @param {string} what - "rev" for revocation, "pub" for public keys */ async function EnigmailCommon_importObjectFromFile(what) { if (what != "rev" && what != "pub") { throw new Error(`Can't import. Invalid argument: ${what}`); } let importingRevocation = what == "rev"; let promptStr = importingRevocation ? "import-rev-file" : "import-key-file"; let files = EnigmailDialog.filePicker( window, l10n.formatValueSync(promptStr), "", false, true, "*.asc", "", [l10n.formatValueSync("gnupg-file"), "*.asc;*.gpg;*.pgp"] ); if (!files.length) { return; } for (let file of files) { if (file.fileSize > 5000000) { document.l10n.formatValue("file-to-big-to-import").then(value => { EnigmailDialog.alert(window, value); }); continue; } let errorMsgObj = {}; if (importingRevocation) { await EnigmailKeyRing.importRevFromFile(file); continue; } let importBinary = false; let keyBlock = await getKeyBlockFromFile(file, false); // if we don't find an ASCII block, try to import as binary. if (!keyBlock) { importBinary = true; let data = await IOUtils.read(file.path); keyBlock = MailStringUtils.uint8ArrayToByteString(data); } // Generate a preview of the imported key. let preview = await EnigmailKey.getKeyListFromKeyBlock( keyBlock, errorMsgObj, true, // interactive true, false // not secret ); if (!preview || !preview.length || errorMsgObj.value) { document.l10n.formatValue("import-keys-failed").then(value => { EnigmailDialog.alert(window, value + "\n\n" + errorMsgObj.value); }); continue; } if (preview.length > 0) { let confirmImport = false; let autoAcceptance = null; let outParam = {}; confirmImport = EnigmailDialog.confirmPubkeyImport( window, preview, outParam ); if (confirmImport) { autoAcceptance = outParam.acceptance; } if (confirmImport) { // import let resultKeys = {}; let importExitCode = EnigmailKeyRing.importKey( window, false, // interactive, we already asked for confirmation keyBlock, importBinary, null, // expected keyId, ignored errorMsgObj, resultKeys, false, // minimize [], // filter true, // allow prompt for permissive autoAcceptance ); if (importExitCode !== 0) { document.l10n.formatValue("import-keys-failed").then(value => { EnigmailDialog.alert(window, value + "\n\n" + errorMsgObj.value); }); continue; } EnigmailDialog.keyImportDlg(window, resultKeys.value); } } } }