diff --git a/modules/ARHParser.jsm.js b/modules/ARHParser.jsm.js index 1984f63c..dafc78ca 100644 --- a/modules/ARHParser.jsm.js +++ b/modules/ARHParser.jsm.js @@ -1,14 +1,14 @@ /* * ARHParser.jsm.js - * + * * Parser for the Authentication-Results header as specified in RFC 7601. * * Version: 1.2.1 (13 January 2019) - * + * * Copyright (c) 2014-2019 Philippe Lieser - * + * * This software is licensed under the terms of the MIT License. - * + * * The above copyright and license notice shall be * included in all copies or substantial portions of the Software. */ @@ -56,7 +56,7 @@ const log = Logging.getLogger("ARHParser"); * @property {String} method * @property {Number} [method_version] * @property {String} result - * none|pass|fail|softfail|policy|neutral|temperror|permerror + * none|pass|fail|softfail|policy|neutral|temperror|permerror * @property {String} [reason] * @property {Object} propertys * @property {Object} propertys.smtp @@ -64,18 +64,18 @@ const log = Logging.getLogger("ARHParser"); * @property {Object} propertys.body * @property {Object} propertys.policy * @property {Object} [propertys._Keyword_] - * ARHResinfo can also include other propertys besides the aboves. + * ARHResinfo can also include other propertys besides the aboves. */ let ARHParser = { get version() { return module_version; }, /** - * Parses an Authentication-Results header. - * - * @param {String} authresHeader Authentication-Results header - * @return {ARHHeader} Parsed Authentication-Results header - * @throws {DKIM_Error} + * Parses an Authentication-Results header. + * + * @param {String} authresHeader Authentication-Results header + * @return {ARHHeader} Parsed Authentication-Results header + * @throws {DKIM_Error} */ parse: function _ARHParser_parse(authresHeader) { // remove header name @@ -122,11 +122,11 @@ let ARHParser = { }; /** - * Parses the next resinfo in str. The parsed part of str is removed from str. - * - * @param {RefString} str - * @return {ARHResinfo|null} Parsed resinfo - * @throws {DKIM_Error|Error} + * Parses the next resinfo in str. The parsed part of str is removed from str. + * + * @param {RefString} str + * @return {ARHResinfo|null} Parsed resinfo + * @throws {DKIM_Error|Error} */ function parseResinfo(str) { log.trace("parse str: " + str.toSource()); @@ -134,7 +134,7 @@ function parseResinfo(str) { let reg_match; /** @type {ARHResinfo} */ let res = {}; - + // get methodspec const method_version_p = `${rfcParser.get("CFWS_op")}/${rfcParser.get("CFWS_op")}([0-9]+)`; const method_p = `(${rfcParser.get("Keyword")})(?:${method_version_p})?`; @@ -196,7 +196,7 @@ function parseResinfo(str) { } if (!reg_match[2]) { throw new DKIM_Error("Error matching the ARH property sub-name."); - } + } let property = res.propertys[reg_match[1]]; if (!property) { property = {}; @@ -280,15 +280,15 @@ class RefString { } /** - * Matches a pattern to the beginning of str. - * Adds CFWS_op to the beginning of pattern. - * pattern must be followed by string end, ";" or CFWS_p. - * Removes the found match from str. - * - * @param {RefString} str - * @param {String} pattern - * @return {String[]} An Array, containing the matches - * @throws {DKIM_Error} if match no match found + * Matches a pattern to the beginning of str. + * Adds CFWS_op to the beginning of pattern. + * pattern must be followed by string end, ";" or CFWS_p. + * Removes the found match from str. + * + * @param {RefString} str + * @param {String} pattern + * @return {String[]} An Array, containing the matches + * @throws {DKIM_Error} if match no match found */ function match(str, pattern) { const reg_match = match_o(str, pattern); @@ -300,15 +300,15 @@ function match(str, pattern) { } /** - * Tries to matches a pattern to the beginning of str. - * Adds CFWS_op to the beginning of pattern. - * pattern must be followed by string end, ";" or CFWS_p. - * If match is found, removes it from str. - * - * @param {RefString} str - * @param {String} pattern - * @return {String[]|Null} Null if no match for the pattern is found, else - * an Array, containing the matches + * Tries to matches a pattern to the beginning of str. + * Adds CFWS_op to the beginning of pattern. + * pattern must be followed by string end, ";" or CFWS_p. + * If match is found, removes it from str. + * + * @param {RefString} str + * @param {String} pattern + * @return {String[]|Null} Null if no match for the pattern is found, else + * an Array, containing the matches */ function match_o(str, pattern) { const regexp = new RegExp(`^${rfcParser.get("CFWS_op")}(?:${pattern})(?:(?:${rfcParser.get("CFWS_op")}\r\n$)|(?=;)|(?=${rfcParser.get("CFWS")}))`); diff --git a/modules/bimi.jsm.js b/modules/bimi.jsm.js index 767a1295..d19fb74d 100644 --- a/modules/bimi.jsm.js +++ b/modules/bimi.jsm.js @@ -15,7 +15,7 @@ * The above copyright and license notice shall be * included in all copies or substantial portions of the Software. */ - + // options for ESLint /* global Components */ /* global Logging, rfcParser */ @@ -34,8 +34,8 @@ Cu.import("resource://dkim_verifier/logging.jsm.js"); Cu.import("resource://dkim_verifier/ARHParser.jsm.js"); Cu.import("resource://dkim_verifier/rfcParser.jsm.js"); -let BIMI = (function() { - +let BIMI = (function() { + const log = Logging.getLogger("BIMI"); let that = { @@ -50,9 +50,9 @@ let BIMI = (function() { // Assuming: // 1. We only get ARHs that can be trusted (i.e. from the receiving MTA). // 2. If the receiving MTA does not supports BIMI, - // we will not see an ARH with a BIMI result (because of 1) + // we will not see an ARH with a BIMI result (because of 1) // 3. If the receiving MTA supports BIMI, - // it will make sure we only see his BIMI-Indicator headers (as required by the RFC). + // it will make sure we only see his BIMI-Indicator headers (as required by the RFC). // // Given the above, it should be safe to trust the BIMI indicator from the BIMI-Indicator header // if we have a passing BIMI result there the MTA claims to have checked the Authority Evidence. @@ -64,7 +64,7 @@ let BIMI = (function() { if (!hasAuthorityPassBIMI) { return null; } - + const bimiIndicators = headers.get("bimi-indicator") || []; if (bimiIndicators.length > 1) { log.warn("Message contains more than one BIMI-Indicator header"); @@ -75,14 +75,14 @@ let BIMI = (function() { log.warn("Message contains an ARH with passing BIMI but does not have a BIMI-Indicator header"); return null; } - + // TODO: If in the future we support ARC we might want to check the policy.indicator-hash - + // Remove header name and new line at end bimiIndicator = bimiIndicator.slice("bimi-indicator:".length, -"\r\n".length); // Remove all whitespace bimiIndicator = bimiIndicator.replace(new RegExp(`${rfcParser.get("FWS")}`, "g"), ""); - + return bimiIndicator; } }; diff --git a/modules/dkimDMARC.jsm.js b/modules/dkimDMARC.jsm.js index 38c17310..90da72e5 100644 --- a/modules/dkimDMARC.jsm.js +++ b/modules/dkimDMARC.jsm.js @@ -1,17 +1,17 @@ /* * dkimDMARC.jsm.js - * + * * Implements a very small part of DMARC to determined if an e-mail should * have a DKIM signature. * * This module is NOT conform to DMARC. * * Version: 1.1.1 (13 January 2019) - * + * * Copyright (c) 2014-2019 Philippe Lieser - * + * * This software is licensed under the terms of the MIT License. - * + * * The above copyright and license notice shall be * included in all copies or substantial portions of the Software. */ @@ -57,18 +57,18 @@ var DMARC = { /** * Tries to determinate with DMARC if an e-mail should be signed. - * + * * @param {String} fromAddress - * + * * @return {Promise} - * .shouldBeSigned true if fromAddress should be signed - * .sdid {String[]} Signing Domain Identifier + * .shouldBeSigned true if fromAddress should be signed + * .sdid {String[]} Signing Domain Identifier */ shouldBeSigned: async function Policy_shouldBeSigned(fromAddress) { "use strict"; - + log.trace("shouldBeSigned Task begin"); - + // default result let res = {}; res.shouldBeSigned = false; @@ -79,7 +79,7 @@ var DMARC = { log.trace("shouldBeSigned Task end"); return res; } - + let DMARCPolicy; try { DMARCPolicy = await getDMARCPolicy(fromAddress); @@ -94,14 +94,14 @@ var DMARC = { (neededPolicy === "quarantine" && DMARCPolicy.p !== "none") || (neededPolicy === "reject" && DMARCPolicy.p === "reject"))) { res.shouldBeSigned = true; - + if (DMARCPolicy.source === DMARCPolicy.domain) { res.sdid = [DMARCPolicy.domain]; } else { res.sdid = [DMARCPolicy.domain, DMARCPolicy.source]; } } - + log.trace("shouldBeSigned Task end"); return res; } @@ -109,87 +109,87 @@ var DMARC = { /** * A DMARC Record. - * + * * @typedef {Object} DMARCRecord * @property {String} adkim - * DKIM identifier alignment mode - * Possible values: "r" (relaxed), "s" (strict) + * DKIM identifier alignment mode + * Possible values: "r" (relaxed), "s" (strict) * @property {String} p - * Requested Mail Receiver policy - * Possible values: "none", "quarantine", "reject" + * Requested Mail Receiver policy + * Possible values: "none", "quarantine", "reject" * @property {Number} pct - * Percentage of messages from the Domain Owner's mail stream to which the - * DMARC mechanism is to be applied + * Percentage of messages from the Domain Owner's mail stream to which the + * DMARC mechanism is to be applied * @property {String?} sp - * Requested Mail Receiver policy for all subdomains - * Possible values: "none", "quarantine", "reject" + * Requested Mail Receiver policy for all subdomains + * Possible values: "none", "quarantine", "reject" * @property {String} v - * Version - * Possible values: "DMARC1" + * Version + * Possible values: "DMARC1" */ /** * A DMARC Policy. - * + * * @typedef {Object} DMARCPolicy * @property {String} adkim - * DKIM identifier alignment mode - * Possible values: "r" (relaxed), "s" (strict) + * DKIM identifier alignment mode + * Possible values: "r" (relaxed), "s" (strict) * @property {String} p - * Requested Mail Receiver policy - * Possible values: "none", "quarantine", "reject" + * Requested Mail Receiver policy + * Possible values: "none", "quarantine", "reject" * @property {Number} pct - * Percentage of messages from the Domain Owner's mail stream to which the - * DMARC mechanism is to be applied + * Percentage of messages from the Domain Owner's mail stream to which the + * DMARC mechanism is to be applied * @property {String} domain - * Full domain of the e-mail address. + * Full domain of the e-mail address. * @property {String} source - * Domain in which the DMARC Policy was found. + * Domain in which the DMARC Policy was found. */ /** * Get the DMARC Policy. - * + * * @param {String} fromAddress - * + * * @return {Promise} - * + * * @throws {DKIM_TempError} */ async function getDMARCPolicy(fromAddress) { "use strict"; log.trace("getDMARCPolicy Task begin"); - + let dmarcRecord; let domain = getDomainFromAddr(fromAddress); let baseDomain; - + // 1. Mail Receivers MUST query the DNS for a DMARC TXT record at the - // DNS domain matching the one found in the RFC5322.From domain in - // the message. A possibly empty set of records is returned - + // DNS domain matching the one found in the RFC5322.From domain in + // the message. A possibly empty set of records is returned + // get the DMARC Record dmarcRecord = await getDMARCRecord(domain); - + // 2. Records that do not start with a "v=" tag that identifies the // current version of DMARC are discarded. - + // NOTE: record with "v=" tag not "DMARC1" are not parsed - + // 3. If the set is now empty, the Mail Receiver MUST query the DNS for - // a DMARC TXT record at the DNS domain matching the Organizational - // Domain in place of the RFC5322.From domain in the message (if - // different). This record can contain policy to be asserted for - // subdomains of the Organizational Domain. A possibly empty set of - // records is returned. - + // a DMARC TXT record at the DNS domain matching the Organizational + // Domain in place of the RFC5322.From domain in the message (if + // different). This record can contain policy to be asserted for + // subdomains of the Organizational Domain. A possibly empty set of + // records is returned. + if (!dmarcRecord) { // get the DMARC Record of the base domain baseDomain = getBaseDomainFromAddr(fromAddress); if (domain !== baseDomain) { dmarcRecord = await getDMARCRecord(baseDomain); - + if (dmarcRecord) { // overrides Receiver policy if one for subdomains was specified dmarcRecord.p = dmarcRecord.sp || dmarcRecord.p; @@ -199,26 +199,26 @@ async function getDMARCPolicy(fromAddress) { // 4. Records that do not start with a "v=" tag that identifies the // current version of DMARC are discarded. - + // NOTE: record with "v=" tag not "DMARC1" are not parsed // 5. If the remaining set contains multiple records or no records, - // processing terminates and the Mail Receiver takes no action. - + // processing terminates and the Mail Receiver takes no action. + // NOTE: no test for multiple records in DNS // 6. If a retrieved policy record does not contain a valid "p" tag, or - // contains an "sp" tag that is not valid, then: + // contains an "sp" tag that is not valid, then: // - // 1. if an "rua" tag is present and contains at least one - // syntactically valid reporting URI, the Mail Receiver SHOULD - // act as if a record containing a valid "v" tag and "p=none" - // was retrieved, and continue processing; + // 1. if an "rua" tag is present and contains at least one + // syntactically valid reporting URI, the Mail Receiver SHOULD + // act as if a record containing a valid "v" tag and "p=none" + // was retrieved, and continue processing; // - // 2. otherwise, the Mail Receiver SHOULD take no action. - + // 2. otherwise, the Mail Receiver SHOULD take no action. + // NOTE: records with invalid "p" or "sp" tag are not parsed - + if (!dmarcRecord) { log.trace("getDMARCPolicy Task end"); return null; @@ -238,23 +238,23 @@ async function getDMARCPolicy(fromAddress) { /** * Get the DMARC Record. - * + * * @param {String} domain - * + * * @return {Promise} - * + * * @throws {DKIM_TempError} */ async function getDMARCRecord(domain) { "use strict"; log.trace("getDMARCRecord Task begin"); - + let dmarcRecord = null; - + // get the DMARC Record let result = await DNS.resolve("_dmarc."+domain, "TXT"); - + // throw error on bogus result or DNS error if (result.bogus) { throw new DKIM_TempError("DKIM_DNSERROR_DNSSEC_BOGUS"); @@ -262,7 +262,7 @@ async function getDMARCRecord(domain) { if (result.rcode !== DNS.RCODE.NoError && result.rcode !== DNS.RCODE.NXDomain) { throw new DKIM_TempError("DKIM_DNSERROR_SERVER_ERROR"); } - + // try to parse DMARC Record if record was found in DNS Server if (result.data !== null && result.data[0]) { try { @@ -271,18 +271,18 @@ async function getDMARCRecord(domain) { log.error("Ignored error in parsing of DMARC record", e); } } - + log.trace("getDMARCRecord Task end"); return dmarcRecord; } /** * Parse the DMARC Policy Record. - * + * * @param {String} DMARCRecordStr - * + * * @return {DMARCRecord} - * + * * @throws {DKIM_Error} */ function parseDMARCRecord(DMARCRecordStr) { @@ -306,7 +306,7 @@ function parseDMARCRecord(DMARCRecordStr) { sp : null, // Requested Mail Receiver policy for all subdomains v : "" // Version }; - + // parse tag-value list let parsedTagMap = rfcParser.parseTagValueList(DMARCRecordStr); if (parsedTagMap === -1) { @@ -322,9 +322,9 @@ function parseDMARCRecord(DMARCRecordStr) { let tagMap = parsedTagMap; // v: Version (plain-text; REQUIRED). Identifies the record retrieved - // as a DMARC record. It MUST have the value of "DMARC1". The value + // as a DMARC record. It MUST have the value of "DMARC1". The value // of this tag MUST match precisely; if it does not or it is absent, - // the entire retrieved record MUST be ignored. It MUST be the first + // the entire retrieved record MUST be ignored. It MUST be the first // tag in the list. let versionTag = rfcParser.parseTagValue(tagMap, "v", "DMARC1", 3); if (versionTag === null) { @@ -332,8 +332,8 @@ function parseDMARCRecord(DMARCRecordStr) { } else { dmarcRecord.v = "DMARC1"; } - - // adkim: (plain-text; OPTIONAL, default is "r".) Indicates whether + + // adkim: (plain-text; OPTIONAL, default is "r".) Indicates whether // strict or relaxed DKIM identifier alignment mode is required by // the Domain Owner. let adkimTag = rfcParser.parseTagValue(tagMap, "adkim", "[rs]", 3); @@ -342,48 +342,48 @@ function parseDMARCRecord(DMARCRecordStr) { } else { dmarcRecord.adkim = adkimTag[0]; } - + // p: Requested Mail Receiver policy (plain-text; REQUIRED for policy // records). Indicates the policy to be enacted by the Receiver at - // the request of the Domain Owner. Policy applies to the domain + // the request of the Domain Owner. Policy applies to the domain // queried and to sub-domains unless sub-domain policy is explicitly // described using the "sp" tag. This tag is mandatory for policy // records only, but not for third-party reporting records (see // Section 7.1). Possible values are as follows: // none: The Domain Owner requests no specific action be taken - // regarding delivery of messages. - // quarantine: The Domain Owner wishes to have email that fails the - // DMARC mechanism check to be treated by Mail Receivers as - // suspicious. Depending on the capabilities of the Mail - // Receiver, this can mean "place into spam folder", "scrutinize - // with additional intensity", and/or "flag as suspicious". - // reject: The Domain Owner wishes for Mail Receivers to reject - // email that fails the DMARC mechanism check. Rejection SHOULD - // occur during the SMTP transaction. See Section 15.4 for some - // discussion of SMTP rejection methods and their implications. + // regarding delivery of messages. + // quarantine: The Domain Owner wishes to have email that fails the + // DMARC mechanism check to be treated by Mail Receivers as + // suspicious. Depending on the capabilities of the Mail + // Receiver, this can mean "place into spam folder", "scrutinize + // with additional intensity", and/or "flag as suspicious". + // reject: The Domain Owner wishes for Mail Receivers to reject + // email that fails the DMARC mechanism check. Rejection SHOULD + // occur during the SMTP transaction. See Section 15.4 for some + // discussion of SMTP rejection methods and their implications. let pTag = rfcParser.parseTagValue(tagMap, "p", "(?:none|quarantine|reject)", 3); if (pTag === null) { throw new DKIM_Error("DKIM_DMARCERROR_MISSING_P"); } else { dmarcRecord.p = pTag[0]; } - - // pct: (plain-text integer between 0 and 100, inclusive; OPTIONAL; - // default is 100). Percentage of messages from the Domain Owner's + + // pct: (plain-text integer between 0 and 100, inclusive; OPTIONAL; + // default is 100). Percentage of messages from the Domain Owner's // mail stream to which the DMARC mechanism is to be applied. // However, this MUST NOT be applied to the DMARC-generated reports, // all of which must be sent and received unhindered. The purpose of // the "pct" tag is to allow Domain Owners to enact a slow rollout - // enforcement of the DMARC mechanism. The prospect of "all or + // enforcement of the DMARC mechanism. The prospect of "all or // nothing" is recognized as preventing many organizations from // experimenting with strong authentication-based mechanisms. See - // Section 6.1 for details. Note that random selection based on this + // Section 6.1 for details. Note that random selection based on this // percentage, such as the following pseudocode, is adequate: - // - // if (random mod 100) < pct then - // selected = true - // else - // selected = false + // + // if (random mod 100) < pct then + // selected = true + // else + // selected = false let pctTag = rfcParser.parseTagValue(tagMap, "pct", "[0-9]{1,3}", 3); if (pctTag === null) { dmarcRecord.pct = 100; @@ -393,12 +393,12 @@ function parseDMARCRecord(DMARCRecordStr) { throw new DKIM_Error("DKIM_DMARCERROR_INVALID_PCT"); } } - - // sp: Requested Mail Receiver policy for all subdomains (plain-text; + + // sp: Requested Mail Receiver policy for all subdomains (plain-text; // OPTIONAL). Indicates the policy to be enacted by the Receiver at - // the request of the Domain Owner. It applies only to subdomains of - // the domain queried and not to the domain itself. Its syntax is - // identical to that of the "p" tag defined above. If absent, the + // the request of the Domain Owner. It applies only to subdomains of + // the domain queried and not to the domain itself. Its syntax is + // identical to that of the "p" tag defined above. If absent, the // policy specified by the "p" tag MUST be applied for subdomains. // Note that "sp" will be ignored for DMARC records published on sub- // domains of Organizational Domains due to the effect of the DMARC @@ -407,7 +407,7 @@ function parseDMARCRecord(DMARCRecordStr) { if (spTag !== null) { dmarcRecord.sp = spTag[0]; } - + log.trace("parseDMARCRecord end"); return dmarcRecord; } diff --git a/modules/dkimVerifier.jsm.js b/modules/dkimVerifier.jsm.js index a60e6759..f537aa47 100644 --- a/modules/dkimVerifier.jsm.js +++ b/modules/dkimVerifier.jsm.js @@ -18,9 +18,9 @@ /* * Violations against RFC 6376: * ============================ - * - at the moment, only a subset of valid Local-part in the i-Tag is recognized - * - no test for multiple key records in an DNS RRset (Section 3.6.2.2) - * - no test that the version tag of the DKIM key is the first tag in the record + * - at the moment, only a subset of valid Local-part in the i-Tag is recognized + * - no test for multiple key records in an DNS RRset (Section 3.6.2.2) + * - no test that the version tag of the DKIM key is the first tag in the record * */ @@ -35,7 +35,7 @@ const module_version = "2.3.0"; var EXPORTED_SYMBOLS = [ - "Verifier" + "Verifier" ]; // @ts-ignore @@ -64,19 +64,19 @@ var NaClUtil = {}; // ASN.1 Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/rsasign/asn1hex-1.1.js", - RSA, "UTF-8" /* The script's encoding */); + RSA, "UTF-8" /* The script's encoding */); // base64 converter Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/jsbn/base64.js", - RSA, "UTF-8" /* The script's encoding */); + RSA, "UTF-8" /* The script's encoding */); // RSA Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/jsbn/jsbn.js", - RSA, "UTF-8" /* The script's encoding */); + RSA, "UTF-8" /* The script's encoding */); Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/jsbn/jsbn2.js", - RSA, "UTF-8" /* The script's encoding */); + RSA, "UTF-8" /* The script's encoding */); Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/jsbn/rsa.js", - RSA, "UTF-8" /* The script's encoding */); + RSA, "UTF-8" /* The script's encoding */); Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/rsasign/rsasign-1.2.js", - RSA, "UTF-8" /* The script's encoding */); + RSA, "UTF-8" /* The script's encoding */); // ed25519 Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/tweetnacl-util/nacl-util.js", NaClUtil, "UTF-8"); Services.scriptloader.loadSubScript("resource://dkim_verifier_3p/tweetnacl/nacl-fast.js", NaCl, "UTF-8"); @@ -90,22 +90,22 @@ const PREF_BRANCH = "extensions.dkim_verifier."; * * @typedef {Object} dkimResultV1 * @property {String} version - * result version ("1.0" / "1.1") + * result version ("1.0" / "1.1") * @property {String} result - * "none" / "SUCCESS" / "PERMFAIL" / "TEMPFAIL" + * "none" / "SUCCESS" / "PERMFAIL" / "TEMPFAIL" * @property {String} [SDID] - * required if result="SUCCESS + * required if result="SUCCESS * @property {String} [selector] - * added in version 1.1 + * added in version 1.1 * @property {String[]} [warnings] - * required if result="SUCCESS + * required if result="SUCCESS * @property {String|undefined} [errorType] - * if result="PERMFAIL: DKIM_SigError.errorType or Undefined - * if result="TEMPFAIL: DKIM_TempError.errorType or Undefined + * if result="PERMFAIL: DKIM_SigError.errorType or Undefined + * if result="TEMPFAIL: DKIM_TempError.errorType or Undefined * @property {String} [shouldBeSignedBy] - * added in version 1.1 + * added in version 1.1 * @property {Boolean} [hideFail] - * added in version 1.1 + * added in version 1.1 */ /** @@ -119,18 +119,18 @@ const PREF_BRANCH = "extensions.dkim_verifier."; * * @typedef {Object} dkimSigResultV2 * @property {String} version - * result version ("2.0") + * result version ("2.0") * @property {String} result - * "none" / "SUCCESS" / "PERMFAIL" / "TEMPFAIL" + * "none" / "SUCCESS" / "PERMFAIL" / "TEMPFAIL" * @property {String} [sdid] * @property {String} [auid] * @property {String} [selector] * @property {dkimSigWarningV2[]} [warnings] - * Array of warning_objects. - * required if result="SUCCESS" + * Array of warning_objects. + * required if result="SUCCESS" * @property {String} [errorType] - * if result="PERMFAIL: DKIM_SigError.errorType - * if result="TEMPFAIL: DKIM_TempError.errorType or Undefined + * if result="PERMFAIL: DKIM_SigError.errorType + * if result="TEMPFAIL: DKIM_TempError.errorType or Undefined * @property {String[]} [errorStrParams] * @property {Boolean} [hideFail] * @property {Boolean} [keySecure] @@ -141,7 +141,7 @@ const PREF_BRANCH = "extensions.dkim_verifier."; * * @typedef {Object} dkimResultV2 * @property {String} version - * result version ("2.0") + * result version ("2.0") * @property {dkimSigResultV2[]} signatures */ @@ -159,14 +159,14 @@ var Verifier = (function() { RSA.KJUR = {}; RSA.KJUR.crypto = {}; RSA.KJUR.crypto.Util = {}; - RSA.KJUR.crypto.Util.DIGESTINFOHEAD = { - 'sha1': "3021300906052b0e03021a05000414", - 'sha224': "302d300d06096086480165030402040500041c", - 'sha256': "3031300d060960864801650304020105000420", - 'sha384': "3041300d060960864801650304020205000430", - 'sha512': "3051300d060960864801650304020305000440", - 'md2': "3020300c06082a864886f70d020205000410", - 'md5': "3020300c06082a864886f70d020505000410", + RSA.KJUR.crypto.Util.DIGESTINFOHEAD = { + 'sha1': "3021300906052b0e03021a05000414", + 'sha224': "302d300d06096086480165030402040500041c", + 'sha256': "3031300d060960864801650304020105000420", + 'sha384': "3041300d060960864801650304020205000430", + 'sha512': "3051300d060960864801650304020305000440", + 'md2': "3020300c06082a864886f70d020205000410", + 'md5': "3020300c06082a864886f70d020505000410", 'ripemd160': "3021300906052b2403020105000414", }; RSA.KJUR.crypto.Util.hashString = (s, algName) => dkim_hash(s, algName, "hex"); @@ -252,14 +252,14 @@ var Verifier = (function() { * Verifies an RSA signature. * * @param {String} key - * b64 encoded RSA key in ASN.1 DER format + * b64 encoded RSA key in ASN.1 DER format * @param {String} str - * plain string to be verified + * plain string to be verified * @param {String} hash_algo - * algorithm that should be used to calculate the hash - * (but is not used in this implementation) + * algorithm that should be used to calculate the hash + * (but is not used in this implementation) * @param {String} signature - * b64 encoded signature + * b64 encoded signature * @param {dkimSigWarning[]} warnings - out param * @param {Object} [keyInfo] - out param * @return {Boolean} @@ -289,7 +289,7 @@ var Verifier = (function() { throw new DKIM_SigError("DKIM_SIGERROR_KEYDECODE"); } if (RSA.ASN1HEX.getTLV(asnKey, posTopArray[0]) !== - "300d06092a864886f70d0101010500") { + "300d06092a864886f70d0101010500") { throw new DKIM_SigError("DKIM_SIGERROR_KEYDECODE"); } @@ -341,13 +341,13 @@ var Verifier = (function() { * Verifies an ed25519 signature. * * @param {String} key - * b64 encoded ed25519 key + * b64 encoded ed25519 key * @param {String} str - * b64 encoded string to be verified + * b64 encoded string to be verified * @param {String} hash_algo - * algorithm that should be used to calculate the hash + * algorithm that should be used to calculate the hash * @param {String} signature - * b64 encoded signature + * b64 encoded signature * @param {dkimSigWarning[]} warnings - out param * @param {Object} [_keyInfo] - out param * @return {Boolean} @@ -568,7 +568,7 @@ var Verifier = (function() { atom = [CFWS] 1*atext [CFWS] CFWS = (1*([FWS] comment) [FWS]) / FWS quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - VCHAR = %x21-7E ; visible (printing) characters + VCHAR = %x21-7E ; visible (printing) characters obs-qtext = obs-NO-WS-CTL obs-NO-WS-CTL = %d1-8 / ; US-ASCII control %d11 / ; characters that do not @@ -1152,7 +1152,7 @@ var Verifier = (function() { // if s flag is set in DKIM key record // AUID must be from the same domain as SDID (and not a subdomain) if (DKIMSignature.DKIMKey.t_array.includes("s") && - !stringEqual(DKIMSignature.i_domain, DKIMSignature.d)) { + !stringEqual(DKIMSignature.i_domain, DKIMSignature.d)) { throw new DKIM_SigError("DKIM_SIGERROR_DOMAIN_I"); } @@ -1160,7 +1160,7 @@ var Verifier = (function() { // the hash algorithm implied by the "a=" tag in the DKIM-Signature header field // must be included in the contents of the "h=" tag if (DKIMSignature.DKIMKey.h_array && - !DKIMSignature.DKIMKey.h_array.includes(DKIMSignature.a_hash)) { + !DKIMSignature.DKIMKey.h_array.includes(DKIMSignature.a_hash)) { throw new DKIM_SigError("DKIM_SIGERROR_KEY_HASHNOTINCLUDED"); } @@ -1192,7 +1192,7 @@ var Verifier = (function() { log.debug("Try with removed quotes in Content-Type charset."); msg.headerFields.get("content-type")[0] = msg.headerFields.get("content-type")[0]. - replace(/charset="([^"]+)"/i, "charset=$1"); + replace(/charset="([^"]+)"/i, "charset=$1"); // Compute the input for the header hash headerHashInput = computeHeaderHashInput(msg,DKIMSignature); log.debug("Header hash input:\n" + headerHashInput); @@ -1267,7 +1267,7 @@ var Verifier = (function() { // // The first added signature is verified first. for (iDKIMSignatureIdx = msg.headerFields.get("dkim-signature").length - 1; - iDKIMSignatureIdx >=0; iDKIMSignatureIdx--) { + iDKIMSignatureIdx >=0; iDKIMSignatureIdx--) { let sigRes; try { log.debug("Verifying DKIM-Signature " + (iDKIMSignatureIdx+1) + " ..."); diff --git a/modules/rfcParser.jsm.js b/modules/rfcParser.jsm.js index 592f4429..5566f45d 100644 --- a/modules/rfcParser.jsm.js +++ b/modules/rfcParser.jsm.js @@ -36,22 +36,22 @@ let rfcParser = (function() { RfcParserStd.token = "[^ \\x00-\\x1F\\x7F()<>@,;:\\\\\"/[\\]?=\\u0080-\\uFFFF]+"; ////// RFC 5234 - Augmented BNF for Syntax Specifications: ABNF - //// Appendix B.1. Core Rules + //// Appendix B.1. Core Rules RfcParserStd.VCHAR = "[!-~]"; RfcParserStd.WSP = "[ \t]"; ////// RFC 5321 - Simple Mail Transfer Protocol - //// 4.1.2. Command Argument Syntax + //// 4.1.2. Command Argument Syntax RfcParserStd.Let_dig = "[A-Za-z0-9]"; RfcParserStd.Ldh_str = `(?:[A-Za-z0-9-]*${RfcParserStd.Let_dig})`; RfcParserStd.Keyword = RfcParserStd.Ldh_str; RfcParserStd.sub_domain = `(?:${RfcParserStd.Let_dig}${RfcParserStd.Ldh_str}?)`; ////// RFC 5322 - Internet Message Format - //// 3.2.1. Quoted characters + //// 3.2.1. Quoted characters // Note: this is incomplete (obs-qp is missing) RfcParserStd.quoted_pair = `(?:\\\\(?:${RfcParserStd.VCHAR}|${RfcParserStd.WSP}))`; - //// 3.2.2. Folding White Space and Comments + //// 3.2.2. Folding White Space and Comments // Note: this is incomplete (obs-FWS is missing) // Note: this is as specified in Section 2.8. of RFC 6376 [DKIM] RfcParserStd.FWS = `(?:${RfcParserStd.WSP}*(?:\r\n)?${RfcParserStd.WSP}+)`; @@ -65,19 +65,19 @@ let rfcParser = (function() { RfcParserStd.CFWS = `(?:(?:(?:${RfcParserStd.FWS_op}${RfcParserStd.comment})+${RfcParserStd.FWS_op})|${RfcParserStd.FWS})`; // Note: helper only, not part of the RFC RfcParserStd.CFWS_op = `${RfcParserStd.CFWS}?`; - //// 3.2.3. Atom + //// 3.2.3. Atom RfcParserStd.atext = "[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]"; RfcParserStd.atom = `(?:${RfcParserStd.CFWS_op}${RfcParserStd.atext}+${RfcParserStd.CFWS_op})`; // Note: helper only, not part of the RFC: an atom without the optional surrounding CFWS. dot is included for obs-phrase RfcParserStd.atom_b_obs = `(?:(?:${RfcParserStd.atext}|\\.)+)`; RfcParserStd.dot_atom_text = `(?:${RfcParserStd.atext}+(?:\\.${RfcParserStd.atext}+)*)`; RfcParserStd.dot_atom = `(?:${RfcParserStd.CFWS_op}${RfcParserStd.dot_atom_text}${RfcParserStd.CFWS_op})`; - //// 3.2.4. Quoted Strings + //// 3.2.4. Quoted Strings // Note: this is incomplete (obs-qtext is missing) RfcParserStd.qtext = "[!#-[\\]-~]"; RfcParserStd.qcontent = `(?:${RfcParserStd.qtext}|${RfcParserStd.quoted_pair})`; RfcParserStd.quoted_string = `(?:${RfcParserStd.CFWS_op}"(?:${RfcParserStd.FWS_op}${RfcParserStd.qcontent})*${RfcParserStd.FWS_op}"${RfcParserStd.CFWS_op})`; - //// 3.2.5. Miscellaneous Tokens + //// 3.2.5. Miscellaneous Tokens RfcParserStd.word = `(?:${RfcParserStd.atom}|${RfcParserStd.quoted_string})`; // Note: helper only, not part of the RFC: chain of word (including dot for obs-phrase) without whitespace between, or quoted string chain RfcParserStd.word_chain = `(?:(?:${RfcParserStd.atom_b_obs}|(?:${RfcParserStd.atom_b_obs}?${RfcParserStd.quoted_string})+${RfcParserStd.atom_b_obs}?))`; @@ -89,7 +89,7 @@ let rfcParser = (function() { // Note: this is incomplete (obs-angle-addr is missing) RfcParserStd.angle_addr = `(?:${RfcParserStd.CFWS_op}<${RfcParserStd.addr_spec}>${RfcParserStd.CFWS_op})`; RfcParserStd.display_name = `(?:${RfcParserStd.phrase})`; - //// 3.4.1. Addr-Spec Specification + //// 3.4.1. Addr-Spec Specification RfcParserStd.addr_spec = `(?:${RfcParserStd.local_part}@${RfcParserStd.domain})`; // Note: this is incomplete (obs-local-part is missing) RfcParserStd.local_part = `(?:${RfcParserStd.dot_atom}|${RfcParserStd.quoted_string})`; @@ -124,7 +124,7 @@ let rfcParser = (function() { let RfcParserI = {}; ////// RFC 3629 - UTF-8, a transformation format of ISO 10646 - //// 4. Syntax of UTF-8 Byte Sequences + //// 4. Syntax of UTF-8 Byte Sequences //// https://datatracker.ietf.org/doc/html/rfc3629#section-4 RfcParserI.UTF8_tail = "[\x80-\xBF]"; RfcParserI.UTF8_2 = `(?:[\xC2-\xDF]${RfcParserI.UTF8_tail})`;