Page MenuHome GnuPG

decryption.jsm
No OneTemporary

decryption.jsm

/*global Components: false, EnigmailData: false, EnigmailLog: false, EnigmailPrefs: false, EnigmailLocale: false, EnigmailArmor: false, EnigmailExecution: false, EnigmailDialog: false */
/*jshint -W097 */
/*
* 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 http://mozilla.org/MPL/2.0/.
*/
"use strict";
var EXPORTED_SYMBOLS = ["EnigmailDecryption"];
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://enigmail/core.jsm"); /*global EnigmailCore: false */
Cu.import("resource://enigmail/data.jsm");
Cu.import("resource://enigmail/log.jsm");
Cu.import("resource://enigmail/prefs.jsm");
Cu.import("resource://enigmail/armor.jsm");
Cu.import("resource://enigmail/locale.jsm");
Cu.import("resource://enigmail/data.jsm");
Cu.import("resource://enigmail/execution.jsm");
Cu.import("resource://enigmail/dialog.jsm");
Cu.import("resource://enigmail/httpProxy.jsm"); /*global EnigmailHttpProxy: false */
Cu.import("resource://enigmail/gpgAgent.jsm"); /*global EnigmailGpgAgent: false */
Cu.import("resource://enigmail/files.jsm"); /*global EnigmailFiles: false */
Cu.import("resource://enigmail/gpg.jsm"); /*global EnigmailGpg: false */
Cu.import("resource://enigmail/errorHandling.jsm"); /*global EnigmailErrorHandling: false */
Cu.import("resource://enigmail/keyRing.jsm"); /*global EnigmailKeyRing: false */
Cu.import("resource://enigmail/key.jsm"); /*global EnigmailKey: false */
Cu.import("resource://enigmail/passwords.jsm"); /*global EnigmailPassword: false */
Cu.import("resource://enigmail/funcs.jsm"); /*global EnigmailFuncs: false */
const nsIEnigmail = Ci.nsIEnigmail;
const EC = EnigmailCore;
const STATUS_ERROR = nsIEnigmail.BAD_SIGNATURE | nsIEnigmail.DECRYPTION_FAILED;
const STATUS_DECRYPTION_OK = nsIEnigmail.DECRYPTION_OKAY;
const STATUS_GOODSIG = nsIEnigmail.GOOD_SIGNATURE;
const NS_WRONLY = 0x02;
function statusObjectFrom(signatureObj, exitCodeObj, statusFlagsObj, keyIdObj, userIdObj, sigDetailsObj, errorMsgObj, blockSeparationObj, encToDetailsObj) {
return {
signature: signatureObj,
exitCode: exitCodeObj,
statusFlags: statusFlagsObj,
keyId: keyIdObj,
userId: userIdObj,
sigDetails: sigDetailsObj,
message: errorMsgObj,
blockSeparation: blockSeparationObj,
encToDetails: encToDetailsObj
};
}
function newStatusObject() {
return statusObjectFrom({
value: ""
}, {}, {}, {}, {}, {}, {}, {}, {});
}
const EnigmailDecryption = {
decryptMessageStart: function(win, verifyOnly, noOutput, listener,
statusFlagsObj, errorMsgObj, mimeSignatureFile,
maxOutputLength) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageStart: verifyOnly=" + verifyOnly + "\n");
if (!EnigmailCore.getService(win)) {
EnigmailLog.ERROR("enigmailCommon.jsm: decryptMessageStart: not yet initialized\n");
errorMsgObj.value = EnigmailLocale.getString("notInit");
return null;
}
if (EnigmailKeyRing.isGeneratingKey()) {
errorMsgObj.value = EnigmailLocale.getString("notComplete");
return null;
}
var args = EnigmailGpg.getStandardArgs(true);
var keyserver = EnigmailPrefs.getPref("autoKeyRetrieve");
if (keyserver && keyserver !== "") {
keyserver = keyserver.trim();
args.push("--keyserver-options");
var keySrvArgs = "auto-key-retrieve";
var srvProxy = EnigmailHttpProxy.getHttpProxy(keyserver);
if (srvProxy) {
keySrvArgs += ",http-proxy=" + srvProxy;
}
args.push(keySrvArgs);
args.push("--keyserver");
args.push(keyserver);
}
if (EnigmailGpg.getGpgFeature("supports-sender") &&
win && win.gFolderDisplay && win.gFolderDisplay.selectedMessage) {
var fromAddr = win.gFolderDisplay.selectedMessage.author;
try {
fromAddr = EnigmailFuncs.stripEmail(fromAddr);
}
catch (ex) {
fromAddr = false;
}
if (fromAddr) {
args.push("--sender");
args.push(fromAddr.toLowerCase());
}
}
if (noOutput) {
args.push("--verify");
if (mimeSignatureFile) {
args.push(mimeSignatureFile);
args.push("-");
}
}
else {
if (maxOutputLength) {
args.push("--max-output");
args.push(String(maxOutputLength));
}
args.push("--decrypt");
}
var proc = EnigmailExecution.execStart(EnigmailGpgAgent.agentPath,
args, !verifyOnly, win,
listener, statusFlagsObj);
if (statusFlagsObj.value & nsIEnigmail.MISSING_PASSPHRASE) {
EnigmailLog.ERROR("enigmailCommon.jsm: decryptMessageStart: Error - no passphrase supplied\n");
errorMsgObj.value = EnigmailLocale.getString("noPassphrase");
return null;
}
return proc;
},
decryptMessageEnd: function(stderrStr, exitCode, outputLen, verifyOnly, noOutput, uiFlags, retStatusObj) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: uiFlags=" + uiFlags + ", verifyOnly=" + verifyOnly + ", noOutput=" + noOutput + "\n");
stderrStr = stderrStr.replace(/\r\n/g, "\n");
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: stderrStr=\n" + stderrStr + "\n");
var interactive = uiFlags & nsIEnigmail.UI_INTERACTIVE;
var pgpMime = uiFlags & nsIEnigmail.UI_PGP_MIME;
var allowImport = uiFlags & nsIEnigmail.UI_ALLOW_KEY_IMPORT;
var unverifiedEncryptedOK = uiFlags & nsIEnigmail.UI_UNVERIFIED_ENC_OK;
var j;
retStatusObj.statusFlags = 0;
retStatusObj.errorMsg = "";
retStatusObj.blockSeparation = "";
var errorMsg = EnigmailErrorHandling.parseErrorOutput(stderrStr, retStatusObj);
if (retStatusObj.statusFlags & STATUS_ERROR) {
retStatusObj.errorMsg = errorMsg;
}
else {
retStatusObj.errorMsg = "";
}
if (pgpMime) {
retStatusObj.statusFlags |= verifyOnly ? nsIEnigmail.PGP_MIME_SIGNED : nsIEnigmail.PGP_MIME_ENCRYPTED;
}
var statusMsg = retStatusObj.statusMsg;
exitCode = EnigmailExecution.fixExitCode(exitCode, retStatusObj);
if ((exitCode === 0) && !noOutput && !outputLen &&
((retStatusObj.statusFlags & (STATUS_DECRYPTION_OK | STATUS_GOODSIG)) === 0)) {
exitCode = -1;
}
if (retStatusObj.statusFlags & nsIEnigmail.DISPLAY_MESSAGE && retStatusObj.extendedStatus.search(/\bdisp:/) >= 0) {
EnigmailDialog.alert(null, statusMsg);
return -1;
}
var errLines;
if (statusMsg) {
errLines = statusMsg.split(/\r?\n/);
}
else {
// should not really happen ...
errLines = stderrStr.split(/\r?\n/);
}
// possible STATUS Patterns (see GPG dod DETAILS.txt):
// one of these should be set for a signature:
var goodsigPat = /GOODSIG (\w{16}) (.*)$/i;
var badsigPat = /BADSIG (\w{16}) (.*)$/i;
var expsigPat = /EXPSIG (\w{16}) (.*)$/i;
var expkeysigPat = /EXPKEYSIG (\w{16}) (.*)$/i;
var revkeysigPat = /REVKEYSIG (\w{16}) (.*)$/i;
var errsigPat = /ERRSIG (\w{16}) (.*)$/i;
// additional infos for good signatures:
var validSigPat = /VALIDSIG (\w+) (.*) (\d+) (.*)/i;
// hint for a certain key id:
var userIdHintPat = /USERID_HINT (\w{16}) (.*)$/i;
// to find out for which recipients the email was encrypted:
var encToPat = /ENC_TO (\w{16}) (.*)$/i;
var matches;
var signed = false;
var goodOrExpOrRevSignature = false;
var sigKeyId = ""; // key of sender
var sigUserId = ""; // user ID of sender
var sigDetails = "";
var encToDetails = "";
var encToArray = []; // collect ENC_TO lines here
for (j = 0; j < errLines.length; j++) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: process: " + errLines[j] + "\n");
// ENC_TO entry
// - collect them for later processing to print details
matches = errLines[j].match(encToPat);
if (matches && (matches.length > 2)) {
encToArray.push("0x" + matches[1]);
}
// USERID_HINT entry
// - NOTE: NO END of loop
// ERROR: wrong to set userId because ecom is NOT the sender:
//matches = errLines[j].match(userIdHintPat);
//if (matches && (matches.length > 2)) {
// sigKeyId = matches[1];
// sigUserId = matches[2];
//}
// check for one of the possible SIG entries:
// GOODSIG entry
matches = errLines[j].match(goodsigPat);
if (matches && (matches.length > 2)) {
if (signed) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: OOPS: multiple SIGN entries\n");
}
signed = true;
goodOrExpOrRevSignature = true;
sigKeyId = matches[1];
sigUserId = matches[2];
}
else {
// BADSIG entry => signature found but bad
matches = errLines[j].match(badsigPat);
if (matches && (matches.length > 2)) {
if (signed) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: OOPS: multiple SIGN entries\n");
}
signed = true;
goodOrExpOrRevSignature = false;
sigKeyId = matches[1];
sigUserId = matches[2];
}
else {
// EXPSIG entry => expired signature found
matches = errLines[j].match(expsigPat);
if (matches && (matches.length > 2)) {
if (signed) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: OOPS: multiple SIGN entries\n");
}
signed = true;
goodOrExpOrRevSignature = true;
sigKeyId = matches[1];
sigUserId = matches[2];
}
else {
// EXPKEYSIG entry => signature found but key expired
matches = errLines[j].match(expkeysigPat);
if (matches && (matches.length > 2)) {
if (signed) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: OOPS: multiple SIGN entries\n");
}
signed = true;
goodOrExpOrRevSignature = true;
sigKeyId = matches[1];
sigUserId = matches[2];
}
else {
// REVKEYSIG entry => signature found but key revoked
matches = errLines[j].match(revkeysigPat);
if (matches && (matches.length > 2)) {
if (signed) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: OOPS: multiple SIGN entries\n");
}
signed = true;
goodOrExpOrRevSignature = true;
sigKeyId = matches[1];
sigUserId = matches[2];
}
else {
// ERRSIG entry => signature found but key not usable or unavailable
matches = errLines[j].match(errsigPat);
if (matches && (matches.length > 2)) {
if (signed) {
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: OOPS: multiple SIGN entries\n");
}
signed = true;
goodOrExpOrRevSignature = false;
sigKeyId = matches[1];
// no user id with ecom istatus entry
}
}
}
}
}
}
} // end loop of processing errLines
if (goodOrExpOrRevSignature) {
for (j = 0; j < errLines.length; j++) {
matches = errLines[j].match(validSigPat);
if (matches && (matches.length > 4)) {
if (matches[4].length == 40)
// in case of several subkeys refer to the main key ID.
// Only works with PGP V4 keys (Fingerprint length ==40)
sigKeyId = matches[4].substr(-16);
}
if (matches && (matches.length > 2)) {
sigDetails = errLines[j].substr(9);
break;
}
}
}
if (sigUserId && sigKeyId && EnigmailPrefs.getPref("displaySecondaryUid")) {
let keyObj = EnigmailKeyRing.getKeyById(sigKeyId);
if (keyObj) {
if (keyObj.photoAvailable) {
retStatusObj.statusFlags |= nsIEnigmail.PHOTO_AVAILABLE;
}
sigUserId = EnigmailKeyRing.getValidUids(sigKeyId).join("\n");
}
}
else if (sigUserId) {
sigUserId = EnigmailData.convertToUnicode(sigUserId, "UTF-8");
}
// add list of keys used for encryption if known (and their user IDs) if known
// Parsed status messages are something like (here the German version):
// [GNUPG:] ENC_TO AAAAAAAAAAAAAAAA 1 0
// [GNUPG:] ENC_TO 5B820D2D4553884F 16 0
// [GNUPG:] ENC_TO 37904DF2E631552F 1 0
// [GNUPG:] ENC_TO BBBBBBBBBBBBBBBB 1 0
// gpg: verschlüsselt mit 3072-Bit RSA Schlüssel, ID BBBBBBBB, erzeugt 2009-11-28
// "Joe Doo <joe.doo@domain.de>"
// [GNUPG:] NO_SECKEY E71712DF47BBCC40
// gpg: verschlüsselt mit RSA Schlüssel, ID AAAAAAAA
// [GNUPG:] NO_SECKEY AAAAAAAAAAAAAAAA
if (encToArray.length > 0) {
// for each key also show an associated user ID if known:
for (var encIdx = 0; encIdx < encToArray.length; ++encIdx) {
var localKeyId = encToArray[encIdx];
// except for ID 00000000, which signals hidden keys
if (localKeyId != "0x0000000000000000") {
let localKey = EnigmailKeyRing.getKeyById(localKeyId);
if (localKey) {
encToArray[encIdx] += " (" + localKey.userId + ")";
}
}
else {
encToArray[encIdx] = EnigmailLocale.getString("hiddenKey");
}
}
encToDetails = "\n " + encToArray.join(",\n ") + "\n";
}
retStatusObj.userId = sigUserId;
retStatusObj.keyId = sigKeyId;
retStatusObj.sigDetails = sigDetails;
retStatusObj.encToDetails = encToDetails;
if (signed) {
var trustPrefix = "";
if (retStatusObj.statusFlags & nsIEnigmail.UNTRUSTED_IDENTITY) {
trustPrefix += EnigmailLocale.getString("prefUntrusted") + " ";
}
if (retStatusObj.statusFlags & nsIEnigmail.REVOKED_KEY) {
trustPrefix += EnigmailLocale.getString("prefRevoked") + " ";
}
if (retStatusObj.statusFlags & nsIEnigmail.EXPIRED_KEY_SIGNATURE) {
trustPrefix += EnigmailLocale.getString("prefExpiredKey") + " ";
}
else if (retStatusObj.statusFlags & nsIEnigmail.EXPIRED_SIGNATURE) {
trustPrefix += EnigmailLocale.getString("prefExpired") + " ";
}
if (goodOrExpOrRevSignature) {
retStatusObj.errorMsg = trustPrefix + EnigmailLocale.getString("prefGood", [sigUserId]);
/* + ", " + EnigmailLocale.getString("keyId") + " 0x" + sigKeyId.substring(8,16); */
}
else {
if (sigUserId.length > 0) {
retStatusObj.errorMsg = trustPrefix + EnigmailLocale.getString("prefBad", [sigUserId]);
}
if (!exitCode)
exitCode = 1;
}
}
if (retStatusObj.statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE) {
retStatusObj.keyId = EnigmailKey.extractPubkey(statusMsg);
if (retStatusObj.statusFlags & nsIEnigmail.DECRYPTION_OKAY) {
exitCode = 0;
}
}
if (exitCode !== 0) {
// Error processing
EnigmailLog.DEBUG("enigmailCommon.jsm: decryptMessageEnd: command execution exit code: " + exitCode + "\n");
}
return exitCode;
},
/**
* Decrypts a PGP ciphertext and returns the the plaintext
*
*in @parent a window object
*in @uiFlags see flag options in nsIEnigmail.idl, UI_INTERACTIVE, UI_ALLOW_KEY_IMPORT
*in @cipherText a string containing a PGP Block
*out @signatureObj
*out @exitCodeObj contains the exit code
*out @statusFlagsObj see status flags in nslEnigmail.idl, GOOD_SIGNATURE, BAD_SIGNATURE
*out @keyIdObj holds the key id
*out @userIdObj holds the user id
*out @sigDetailsObj
*out @errorMsgObj error string
*out @blockSeparationObj
*out @encToDetailsObj returns in details, which keys the mesage was encrypted for (ENC_TO entries)
*
* @return string plaintext ("" if error)
*
*/
decryptMessage: function(parent, uiFlags, cipherText,
signatureObj, exitCodeObj,
statusFlagsObj, keyIdObj, userIdObj, sigDetailsObj, errorMsgObj,
blockSeparationObj, encToDetailsObj) {
const esvc = EnigmailCore.getEnigmailService();
EnigmailLog.DEBUG("enigmail.js: Enigmail.decryptMessage: " + cipherText.length + " bytes, " + uiFlags + "\n");
if (!cipherText)
return "";
var interactive = uiFlags & nsIEnigmail.UI_INTERACTIVE;
var allowImport = uiFlags & nsIEnigmail.UI_ALLOW_KEY_IMPORT;
var unverifiedEncryptedOK = uiFlags & nsIEnigmail.UI_UNVERIFIED_ENC_OK;
var oldSignature = signatureObj.value;
EnigmailLog.DEBUG("enigmail.js: Enigmail.decryptMessage: oldSignature=" + oldSignature + "\n");
signatureObj.value = "";
exitCodeObj.value = -1;
statusFlagsObj.value = 0;
keyIdObj.value = "";
userIdObj.value = "";
errorMsgObj.value = "";
var beginIndexObj = {};
var endIndexObj = {};
var indentStrObj = {};
var blockType = EnigmailArmor.locateArmoredBlock(cipherText, 0, "", beginIndexObj, endIndexObj, indentStrObj);
if (!blockType || blockType == "SIGNATURE") {
errorMsgObj.value = EnigmailLocale.getString("noPGPblock");
statusFlagsObj.value |= nsIEnigmail.DISPLAY_MESSAGE;
return "";
}
var publicKey = (blockType == "PUBLIC KEY BLOCK");
var verifyOnly = (blockType == "SIGNED MESSAGE");
var pgpBlock = cipherText.substr(beginIndexObj.value,
endIndexObj.value - beginIndexObj.value + 1);
if (indentStrObj.value) {
var indentRegexp = new RegExp("^" + indentStrObj.value, "gm");
pgpBlock = pgpBlock.replace(indentRegexp, "");
if (indentStrObj.value.substr(-1) == " ") {
var indentRegexpStr = "^" + indentStrObj.value.replace(/ $/m, "$");
indentRegexp = new RegExp(indentRegexpStr, "gm");
pgpBlock = pgpBlock.replace(indentRegexp, "");
}
}
// HACK to better support messages from Outlook: if there are empty lines, drop them
if (pgpBlock.search(/MESSAGE-----\r?\n\r?\nVersion/) >= 0) {
EnigmailLog.DEBUG("enigmail.js: Enigmail.decryptMessage: apply Outlook empty line workaround\n");
pgpBlock = pgpBlock.replace(/\r?\n\r?\n/g, "\n");
}
var head = cipherText.substr(0, beginIndexObj.value);
var tail = cipherText.substr(endIndexObj.value + 1,
cipherText.length - endIndexObj.value - 1);
if (publicKey) {
if (!allowImport) {
errorMsgObj.value = EnigmailLocale.getString("keyInMessageBody");
statusFlagsObj.value |= nsIEnigmail.DISPLAY_MESSAGE;
statusFlagsObj.value |= nsIEnigmail.INLINE_KEY;
return "";
}
// Import public key
exitCodeObj.value = EnigmailKeyRing.importKey(parent, true, pgpBlock, "",
errorMsgObj);
if (exitCodeObj.value === 0) {
statusFlagsObj.value |= nsIEnigmail.IMPORTED_KEY;
}
return "";
}
var newSignature = "";
if (verifyOnly) {
newSignature = EnigmailArmor.extractSignaturePart(pgpBlock, nsIEnigmail.SIGNATURE_ARMOR);
if (oldSignature && (newSignature != oldSignature)) {
EnigmailLog.ERROR("enigmail.js: Enigmail.decryptMessage: Error - signature mismatch " + newSignature + "\n");
errorMsgObj.value = EnigmailLocale.getString("sigMismatch");
statusFlagsObj.value |= nsIEnigmail.DISPLAY_MESSAGE;
return "";
}
}
var startErrorMsgObj = {};
var noOutput = false;
var listener = EnigmailExecution.newSimpleListener(
function _stdin(pipe) {
pipe.write(pgpBlock);
pipe.close();
});
var maxOutput = pgpBlock.length * 100; // limit output to 100 times message size
// to avoid DoS attack
var proc = EnigmailDecryption.decryptMessageStart(parent, verifyOnly, noOutput, listener,
statusFlagsObj, startErrorMsgObj,
null, maxOutput);
if (!proc) {
errorMsgObj.value = startErrorMsgObj.value;
statusFlagsObj.value |= nsIEnigmail.DISPLAY_MESSAGE;
return "";
}
// Wait for child to close
proc.wait();
var plainText = EnigmailData.getUnicodeData(listener.stdoutData);
var retStatusObj = {};
var exitCode = EnigmailDecryption.decryptMessageEnd(EnigmailData.getUnicodeData(listener.stderrData), listener.exitCode,
plainText.length, verifyOnly, noOutput,
uiFlags, retStatusObj);
exitCodeObj.value = exitCode;
statusFlagsObj.value = retStatusObj.statusFlags;
errorMsgObj.value = retStatusObj.errorMsg;
userIdObj.value = retStatusObj.userId;
keyIdObj.value = retStatusObj.keyId;
sigDetailsObj.value = retStatusObj.sigDetails;
if (encToDetailsObj) {
encToDetailsObj.value = retStatusObj.encToDetails;
}
blockSeparationObj.value = retStatusObj.blockSeparation;
if ((head.search(/\S/) >= 0) ||
(tail.search(/\S/) >= 0)) {
statusFlagsObj.value |= nsIEnigmail.PARTIALLY_PGP;
}
if (exitCodeObj.value === 0) {
// Normal return
var doubleDashSeparator = false;
try {
doubleDashSeparator = EnigmailPrefs.getPrefBranch().getBoolPref("doubleDashSeparator");
}
catch (ex) {}
if (doubleDashSeparator && (plainText.search(/(\r|\n)-- +(\r|\n)/) < 0)) {
// Workaround for MsgCompose stripping trailing spaces from sig separator
plainText = plainText.replace(/(\r|\n)--(\r|\n)/, "$1-- $2");
}
statusFlagsObj.value |= nsIEnigmail.DISPLAY_MESSAGE;
if (verifyOnly && indentStrObj.value) {
plainText = plainText.replace(/^/gm, indentStrObj.value);
}
return EnigmailDecryption.inlineInnerVerification(parent, uiFlags, plainText,
statusObjectFrom(signatureObj, exitCodeObj, statusFlagsObj, keyIdObj, userIdObj,
sigDetailsObj, errorMsgObj, blockSeparationObj, encToDetailsObj));
}
var pubKeyId = keyIdObj.value;
if (statusFlagsObj.value & nsIEnigmail.BAD_SIGNATURE) {
if (verifyOnly && indentStrObj.value) {
// Probably replied message that could not be verified
errorMsgObj.value = EnigmailLocale.getString("unverifiedReply") + "\n\n" + errorMsgObj.value;
return "";
}
// Return bad signature (for checking later)
signatureObj.value = newSignature;
}
else if (pubKeyId &&
(statusFlagsObj.value & nsIEnigmail.UNVERIFIED_SIGNATURE)) {
var innerKeyBlock;
if (verifyOnly) {
// Search for indented public key block in signed message
var innerBlockType = EnigmailArmor.locateArmoredBlock(pgpBlock, 0, "- ", beginIndexObj, endIndexObj, indentStrObj);
if (innerBlockType == "PUBLIC KEY BLOCK") {
innerKeyBlock = pgpBlock.substr(beginIndexObj.value,
endIndexObj.value - beginIndexObj.value + 1);
innerKeyBlock = innerKeyBlock.replace(/- -----/g, "-----");
statusFlagsObj.value |= nsIEnigmail.INLINE_KEY;
EnigmailLog.DEBUG("enigmail.js: Enigmail.decryptMessage: innerKeyBlock found\n");
}
}
if (allowImport) {
var importedKey = false;
if (innerKeyBlock) {
var importErrorMsgObj = {};
var exitStatus = EnigmailKeyRing.importKey(parent, true, innerKeyBlock,
pubKeyId, importErrorMsgObj);
importedKey = (exitStatus === 0);
if (exitStatus > 0) {
EnigmailDialog.alert(parent, EnigmailLocale.getString("cantImport") + importErrorMsgObj.value);
}
}
if (importedKey) {
// Recursive call; note that nsIEnigmail.UI_ALLOW_KEY_IMPORT is unset
// to break the recursion
var uiFlagsDeep = interactive ? nsIEnigmail.UI_INTERACTIVE : 0;
signatureObj.value = "";
return EnigmailDecryption.decryptMessage(parent, uiFlagsDeep, pgpBlock,
signatureObj, exitCodeObj, statusFlagsObj,
keyIdObj, userIdObj, sigDetailsObj, errorMsgObj);
}
}
if (plainText && !unverifiedEncryptedOK) {
// Append original PGP block to unverified message
plainText = "-----BEGIN PGP UNVERIFIED MESSAGE-----\r\n" + plainText +
"-----END PGP UNVERIFIED MESSAGE-----\r\n\r\n" + pgpBlock;
}
}
return verifyOnly ? "" : plainText;
},
inlineInnerVerification: function(parent, uiFlags, text, statusObject) {
EnigmailLog.DEBUG("enigmail.js: Enigmail.inlineInnerVerification\n");
if (text && text.indexOf("-----BEGIN PGP SIGNED MESSAGE-----") === 0) {
var status = newStatusObject();
var newText = EnigmailDecryption.decryptMessage(parent, uiFlags, text,
status.signature, status.exitCode, status.statusFlags, status.keyId, status.userId,
status.sigDetails, status.message, status.blockSeparation, status.encToDetails);
if (status.exitCode.value === 0) {
text = newText;
// merge status into status object:
statusObject.statusFlags.value = statusObject.statusFlags.value | status.statusFlags.value;
statusObject.keyId.value = status.keyId.value;
statusObject.userId.value = status.userId.value;
statusObject.sigDetails.value = status.sigDetails.value;
statusObject.message.value = status.message.value;
// we don't merge encToDetails
}
}
return text;
},
decryptAttachment: function(parent, outFile, displayName, byteData,
exitCodeObj, statusFlagsObj, errorMsgObj) {
const esvc = EnigmailCore.getEnigmailService();
EnigmailLog.DEBUG("enigmail.js: Enigmail.decryptAttachment: parent=" + parent + ", outFileName=" + outFile.path + "\n");
let attachmentHead = byteData.substr(0, 200);
if (attachmentHead.match(/\-\-\-\-\-BEGIN PGP \w+ KEY BLOCK\-\-\-\-\-/)) {
// attachment appears to be a PGP key file
if (EnigmailDialog.confirmDlg(parent, EnigmailLocale.getString("attachmentPgpKey", [displayName]),
EnigmailLocale.getString("keyMan.button.import"), EnigmailLocale.getString("dlg.button.view"))) {
let preview = EnigmailKey.getKeyListFromKeyBlock(byteData, errorMsgObj);
exitCodeObj.keyList = preview;
let exitStatus = 0;
if (errorMsgObj.value === "") {
if (preview.length > 0) {
if (preview.length == 1) {
exitStatus = EnigmailDialog.confirmDlg(parent, EnigmailLocale.getString("doImportOne", [preview[0].name, preview[0].id]));
}
else {
exitStatus = EnigmailDialog.confirmDlg(parent,
EnigmailLocale.getString("doImportMultiple", [
preview.map(function(a) {
return "\t" + a.name + " (" + a.id + ")";
}).
join("\n")
]));
}
if (exitStatus) {
exitCodeObj.value = EnigmailKeyRing.importKey(parent, false, byteData, "", errorMsgObj);
statusFlagsObj.value = nsIEnigmail.IMPORTED_KEY;
}
else {
exitCodeObj.value = 0;
statusFlagsObj.value = nsIEnigmail.DISPLAY_MESSAGE;
}
}
}
}
else {
exitCodeObj.value = 0;
statusFlagsObj.value = nsIEnigmail.DISPLAY_MESSAGE;
}
return true;
}
//var outFileName = EnigmailFiles.getEscapedFilename(EnigmailFiles.getFilePathReadonly(outFile.QueryInterface(Ci.nsIFile), NS_WRONLY));
let args = EnigmailGpg.getStandardArgs(true);
args.push("--yes");
args = args.concat(EnigmailPassword.command());
args.push("-d");
statusFlagsObj.value = 0;
let listener = EnigmailExecution.newSimpleListener(
function _stdin(pipe) {
pipe.write(byteData);
pipe.close();
});
let proc = EnigmailExecution.execStart(EnigmailGpgAgent.agentPath, args, false, parent,
listener, statusFlagsObj);
if (!proc) {
return false;
}
// Wait for child STDOUT to close
proc.wait();
let statusMsgObj = {};
let cmdLineObj = {};
exitCodeObj.value = EnigmailExecution.execEnd(listener, statusFlagsObj, statusMsgObj, cmdLineObj, errorMsgObj);
if (listener.stdoutData.length > 0) {
return EnigmailFiles.writeFileContents(outFile, listener.stdoutData);
}
return false;
},
registerOn: function(target) {
target.decryptMessage = EnigmailDecryption.decryptMessage;
target.decryptAttachment = EnigmailDecryption.decryptAttachment;
}
};

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 23, 7:15 PM (1 h, 37 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b2/af/e99dfd0ec2a11a8715014d6be938

Event Timeline