From a66fa25b613c3b4ffcf64b630caa452a64ed8dc6 Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Mon, 20 May 2024 16:59:44 +0200 Subject: [PATCH 01/10] Extend dkimResult to hold more details --- modules/dkimVerifier.jsm.js | 101 +++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/modules/dkimVerifier.jsm.js b/modules/dkimVerifier.jsm.js index 0648785..1594f4b 100644 --- a/modules/dkimVerifier.jsm.js +++ b/modules/dkimVerifier.jsm.js @@ -28,7 +28,7 @@ /* eslint strict: ["warn", "function"] */ /* global Components, Services */ /* global Logging, Key, Policy, MsgReader, rfcParser */ -/* global dkimStrings, addrIsInDomain2, domainIsInDomain, stringEndsWith, stringEqual, writeStringToTmpFile, toType, DKIM_SigError, DKIM_TempError, DKIM_Error */ +/* global dkimStrings, addrIsInDomain2, domainIsInDomain, stringEndsWith, stringEqual, writeStringToTmpFile, toType, DKIM_SigError, DKIM_TempError, DKIM_Error, copy */ /* exported EXPORTED_SYMBOLS, Verifier */ // @ts-ignore @@ -119,7 +119,7 @@ const PREF_BRANCH = "extensions.dkim_verifier."; * * @typedef {Object} dkimSigResultV2 * @property {String} version - * result version ("2.0") + * result version ("2.1") * @property {String} result * "none" / "SUCCESS" / "PERMFAIL" / "TEMPFAIL" * @property {String} [sdid] @@ -134,6 +134,11 @@ const PREF_BRANCH = "extensions.dkim_verifier."; * @property {String[]} [errorStrParams] * @property {Boolean} [hideFail] * @property {Boolean} [keySecure] + * @property {number|null} [timestamp] + * @property {number|null} [expiration] + * @property {string} [algorithmSignature] + * @property {string} [algorithmHash] + * @property {string[]} [signedHeaders] */ /** @@ -698,6 +703,37 @@ var Verifier = (function() { return DKIMSignature; } + /** + * Get a DKIM result with some information from the header already in it. + * + * @param {string} result + * @param {Object} dkimSignature | null + * @returns {dkimSigResultV2} + */ + function createBaseResult(result, dkimSignature) { + let baseResult; + if (dkimSignature) { + baseResult = { + version : "2.1", + result : result, + sdid : dkimSignature.d, + auid : dkimSignature.i, + selector : dkimSignature.s, + timestamp : dkimSignature.t, + expiration : dkimSignature.x, + algorithmSignature : dkimSignature.a_sig, + algorithmHash : dkimSignature.a_hash, + signedHeaders : dkimSignature.h_array ? copy(dkimSignature.h_array) : undefined, + }; + } else { + baseResult = { + version : "2.1", + result : result, + }; + } + return baseResult; + } + /* * parse the DKIM key record * key record is specified in Section 3.6.1 of RFC 6376 @@ -915,13 +951,13 @@ var Verifier = (function() { // if a body length count is given if (DKIMSignature.l !== null) { - // check the value of the body lenght tag + // check the value of the body length tag if (DKIMSignature.l > bodyCanon.length) { - // lenght tag exceeds body size + // length tag exceeds body size log.debug("bodyCanon.length: " + bodyCanon.length); throw new DKIM_SigError("DKIM_SIGERROR_TOOLARGE_L"); } else if (DKIMSignature.l < bodyCanon.length){ - // lenght tag smaller when body size + // length tag smaller when body size DKIMSignature.warnings.push({name: "DKIM_SIGWARNING_SMALL_L"}); log.debug("Warning: DKIM_SIGWARNING_SMALL_L ("+ dkimStrings.getString("DKIM_SIGWARNING_SMALL_L")+")"); @@ -1008,7 +1044,7 @@ var Verifier = (function() { } /** - * handeles Exeption + * handles Exception * * @param {Error} e * @param {Object} msg @@ -1016,39 +1052,26 @@ var Verifier = (function() { * @return {dkimSigResultV2} */ function handleException(e, msg, dkimSignature = {} ) { + let result = createBaseResult("", dkimSignature); + if (e instanceof DKIM_SigError) { - // return result - let result = { - version : "2.0", - result : "PERMFAIL", - sdid : dkimSignature.d, - auid : dkimSignature.i, - selector : dkimSignature.s, - errorType : e.errorType, - errorStrParams : e.errorStrParams, - hideFail : e.errorType === "DKIM_SIGERROR_KEY_TESTMODE" || - msg.DKIMSignPolicy.hideFail, - keySecure : dkimSignature.keyQueryResult && - dkimSignature.keyQueryResult.secure, - }; + result.result = "PERMFAIL"; + result.errorType = e.errorType; + result.errorStrParams = e.errorStrParams; + result.hideFail = e.errorType === "DKIM_SIGERROR_KEY_TESTMODE" || + msg.DKIMSignPolicy.hideFail; + result.keySecure = dkimSignature.keyQueryResult && + dkimSignature.keyQueryResult.secure; log.warn(e); - - return result; - } - // return result - let result = { - version : "2.0", - result : "TEMPFAIL", - sdid : dkimSignature.d, - auid : dkimSignature.i, - selector : dkimSignature.s, - }; - - if (e instanceof DKIM_TempError) { + } else if (e instanceof DKIM_TempError) { + result.result = "TEMPFAIL"; result.errorType = e.errorType; + log.error("Temporary error during DKIM verification:", e); } else { + result.result = "TEMPFAIL"; + log.fatal("Error during DKIM verification:", e); } @@ -1229,15 +1252,9 @@ var Verifier = (function() { // return result log.trace("Everything is fine"); - var verification_result = { - version : "2.0", - result : "SUCCESS", - sdid : DKIMSignature.d, - auid : DKIMSignature.i, - selector : DKIMSignature.s, - warnings : DKIMSignature.warnings, - keySecure : DKIMSignature.keyQueryResult.secure, - }; + var verification_result = createBaseResult("SUCCESS", DKIMSignature); + verification_result.warnings = DKIMSignature.warnings; + verification_result.keySecure = DKIMSignature.keyQueryResult.secure; return verification_result; } From c515ae1f6a5fffda8e97b7af21195add2d5530f9 Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Fri, 24 May 2024 14:19:51 +0200 Subject: [PATCH 02/10] Tooltips containing detailed results --- chrome/content/dkim.js | 38 ++++++++++++++++++-- modules/AuthVerifier.d.ts | 1 + modules/AuthVerifier.jsm.js | 71 +++++++++++++++++++++++++++---------- 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/chrome/content/dkim.js b/chrome/content/dkim.js index 197fa5d..77b2798 100644 --- a/chrome/content/dkim.js +++ b/chrome/content/dkim.js @@ -67,11 +67,30 @@ DKIM_Verifier.Display = (function() { * Sets the result value for headerTooltips and statusbar panel. * * @param {String} value + * @param {String|undefined} [details] * @return {void} */ - function setValue(value) { + function setValue(value, details) { headerTooltips.value = value; statusbarPanel.value = value; + + let verifierBox = document.getElementById("expandeddkim-verifierBox"); + + if (details) { + headerTooltips.value = details; + if (verifierBox) { + // @ts-ignore + verifierBox.tooltipText = details; + } + statusbarPanel.tooltipText = details; + } else { + if (verifierBox) { + // @ts-ignore + verifierBox.tooltipText = ""; + } + // @ts-ignore + statusbarPanel.tooltipText = ""; + } } /** @@ -216,7 +235,22 @@ DKIM_Verifier.Display = (function() { statusbarPanel.dkimStatus = result.dkim[0].result; that.setCollapsed(result.dkim[0].res_num); header.value = result.dkim[0].result_str; - setValue(result.dkim[0].result_str); + + let sigCount = 0; + let detailsHint; + detailsHint = ""; + result.dkim.forEach(dkim => { + if (dkim.details_str) { + detailsHint += "\n----\n" + dkim.details_str; + sigCount += 1; + } + }); + if (sigCount > 0) { + detailsHint = "Signatures: " + sigCount + detailsHint; + } else { + detailsHint = undefined; + } + setValue(result.dkim[0].result_str, detailsHint); switch(result.dkim[0].res_num) { case DKIM_Verifier.AuthVerifier.DKIM_RES.SUCCESS: { diff --git a/modules/AuthVerifier.d.ts b/modules/AuthVerifier.d.ts index 3a26851..e989b3d 100644 --- a/modules/AuthVerifier.d.ts +++ b/modules/AuthVerifier.d.ts @@ -18,6 +18,7 @@ declare module IAuthVerifier { // 35: PERMFAIL treat as no sig // 40: no sig result_str: string; // localized result string + details_str?: string; // localized details block error_str?: string; // localized error string warnings_str?: string[]; // localized warnings favicon?: string; // url to the favicon of the sdid diff --git a/modules/AuthVerifier.jsm.js b/modules/AuthVerifier.jsm.js index ff8d99d..ac8a156 100644 --- a/modules/AuthVerifier.jsm.js +++ b/modules/AuthVerifier.jsm.js @@ -1,14 +1,14 @@ /* * AuthVerifier.jsm.js - * + * * Authentication Verifier. * * Version: 1.4.0 (28 January 2018) - * + * * Copyright (c) 2014-2018 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. */ @@ -90,7 +90,9 @@ let prefs = Services.prefs.getBranch(PREF_BRANCH); * 40: no sig * @property {String} result_str * localized result string - * @property {string} [error_str] Localized error string. + * @property {String} details_str + * localized details block + * @property {string} [error_str] localized error string * @property {String[]} [warnings_str] * localized warnings * @property {String} [favicon] @@ -238,7 +240,7 @@ var AuthVerifier = { /** * Get the Authentication-Results header as an SavedAuthResult. - * + * * @param {nsIMsgDBHdr} msgHdr * @param {Object} msg * @return {SavedAuthResult|Null} @@ -311,7 +313,7 @@ function getARHResult(msgHdr, msg) { // convert DKIM results let dkimSigResults = arhDKIM.map(arhDKIM_to_dkimSigResultV2); - // if ARH result is replacing the add-ons, + // if ARH result is replacing the add-ons, if (prefs.getBoolPref("arh.replaceAddonResult")) { // check SDID and AUID of DKIM results for (let i = 0; i < dkimSigResults.length; i++) { @@ -379,7 +381,7 @@ function getARHResult(msgHdr, msg) { /** * Save authentication result - * + * * @param {nsIMsgDBHdr} msgHdr * @param {SavedAuthResult|Null} savedAuthResult * @return {void} @@ -409,7 +411,7 @@ function saveAuthResult(msgHdr, savedAuthResult) { /** * Get saved authentication result - * + * * @param {nsIMsgDBHdr} msgHdr * @return {SavedAuthResult|Null} savedAuthResult * @throws {Error} @@ -474,7 +476,7 @@ function loadAuthResult(msgHdr) { /** * Convert DKIM ARHresinfo to dkimResult - * + * * @param {ARHResinfo} arhDKIM * @return {dkimSigResultV2} * @throws {Error} @@ -514,7 +516,7 @@ function arhDKIM_to_dkimSigResultV2(arhDKIM) { default: throw new Error(`invalid dkim result in arh: ${arhDKIM.result}`); } - + let sdid = arhDKIM.propertys.header.d; let auid = arhDKIM.propertys.header.i; if (sdid || auid) { @@ -526,13 +528,13 @@ function arhDKIM_to_dkimSigResultV2(arhDKIM) { dkimSigResult.sdid = sdid; dkimSigResult.auid = auid; } - + return dkimSigResult; } /** * Convert dkimResultV1 to dkimSigResultV2 - * + * * @param {dkimResultV1} dkimResultV1 * @return {dkimSigResultV2} */ @@ -565,7 +567,7 @@ function dkimResultV1_to_dkimSigResultV2(dkimResultV1) { /** * Convert dkimSigResultV2 to AuthResultDKIM - * + * * @param {dkimSigResultV2} dkimSigResult * @return {AuthResultDKIM} * @throws {Error} @@ -685,7 +687,7 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li dkimSigResult.errorStrParams) || errorType; authResultDKIM.error_str = errorMsg; - } + } if (errorMsg) { authResultDKIM.result_str = dkimStrings.getFormattedString("PERMFAIL", [errorMsg]); @@ -702,13 +704,43 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li throw new Error(`unknown result: ${dkimSigResult.result}`); } + if (dkimSigResult.errorType !== "DKIM_POLICYERROR_MISSING_SIG" && authResultDKIM.res_num !== AuthVerifier.DKIM_RES.NOSIG) { + let sdid = dkimSigResult.sdid; + let auid = dkimSigResult.auid; + let result = authResultDKIM.result_str; + let alg = dkimSigResult.algorithmSignature ? dkimSigResult.algorithmSignature.toUpperCase() : undefined; + let hash = dkimSigResult.algorithmHash ? dkimSigResult.algorithmHash.toUpperCase() : undefined; + let dnssec = dkimSigResult.keySecure ? "Yes" : "No"; + let signingTime = dkimSigResult.timestamp ? new Date(dkimSigResult.timestamp*1000).toLocaleString() : undefined; + let expirationTime = dkimSigResult.expiration ? new Date(dkimSigResult.expiration*1000).toLocaleString() : "never"; + let signedHeaders = dkimSigResult.signedHeaders ? dkimSigResult.signedHeaders.join(", ") : undefined; + + authResultDKIM.details_str = "Result: " + result; + if (sdid && auid) { + authResultDKIM.details_str += "\nSigned by " + sdid + " for " + auid; + } + if (signingTime) { + authResultDKIM.details_str += "\nSigned at " + signingTime + ", expires " + expirationTime; + } else { + authResultDKIM.details_str += "\nNo signing time included in signature"; + } + if ( alg && hash) { + authResultDKIM.details_str += "\nAlgorithm: " + alg + " / " + hash; + } + if (sdid) { + authResultDKIM.details_str += "\nDomain validated using DNSSEC: " + dnssec; + } + if (signedHeaders) { + authResultDKIM.details_str += "\nSigned headers: " + signedHeaders; + } + } return authResultDKIM; } /** * Convert SavedAuthResult to AuthResult - * + * * @param {SavedAuthResult} savedAuthResult * @param {String|undefined} from * @return {Promise} authResult @@ -727,7 +759,7 @@ async function SavedAuthResult_to_AuthResult(savedAuthResult, from) { // eslint- /** * Convert AuthResultV2 to dkimSigResultV2 - * + * * @param {AuthResultDKIMV2} authResultDKIM * @return {dkimSigResultV2} dkimSigResultV2 */ @@ -735,6 +767,7 @@ function AuthResultDKIMV2_to_dkimSigResultV2(authResultDKIM) { let dkimSigResult = authResultDKIM; dkimSigResult.res_num = undefined; dkimSigResult.result_str = undefined; + dkimSigResult.details_str = undefined; dkimSigResult.warnings_str = undefined; dkimSigResult.favicon = undefined; return dkimSigResult; @@ -742,7 +775,7 @@ function AuthResultDKIMV2_to_dkimSigResultV2(authResultDKIM) { /** * Add favicons to the DKIM results. - * + * * @param {AuthResult} authResult * @param {String|undefined} from * @param {String|undefined} bimiIndicator @@ -767,7 +800,7 @@ async function addFavicons(authResult, from, bimiIndicator) { /** * Checks if a message is outgoing - * + * * @param {nsIMsgDBHdr} msgHdr * @return {boolean} */ From b5e225bf0b1183fc903ce23f1ef2d6e7f9c805e9 Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Mon, 27 May 2024 18:06:23 +0200 Subject: [PATCH 03/10] Added translations support for signature details --- chrome/content/dkim.js | 10 ++++---- chrome/locale/de/dkim.properties | 13 +++++++++++ chrome/locale/en-US/dkim.properties | 13 +++++++++++ chrome/locale/fr/dkim.properties | 13 +++++++++++ chrome/locale/hu/dkim.properties | 13 +++++++++++ chrome/locale/it/dkim.properties | 13 +++++++++++ chrome/locale/ja-JP/dkim.properties | 13 +++++++++++ chrome/locale/zh-CN/dkim.properties | 13 +++++++++++ modules/AuthVerifier.jsm.js | 36 +++++++++++++++++++++-------- 9 files changed, 123 insertions(+), 14 deletions(-) diff --git a/chrome/content/dkim.js b/chrome/content/dkim.js index 77b2798..ba35908 100644 --- a/chrome/content/dkim.js +++ b/chrome/content/dkim.js @@ -97,11 +97,13 @@ DKIM_Verifier.Display = (function() { * Sets the warnings for header, headerTooltips and statusbar panel. * * @param {String[]} warnings + * @param {String|undefined} [details] * @return {void} */ - function setWarnings(warnings) { + function setWarnings(warnings, details) { header.warnings = warnings; - headerTooltips.warnings = warnings; + // The details hint already contains the warnings in the headerTooltip + if (!details) { headerTooltips.warnings = warnings; } statusbarPanel.warnings = warnings; } @@ -246,7 +248,7 @@ DKIM_Verifier.Display = (function() { } }); if (sigCount > 0) { - detailsHint = "Signatures: " + sigCount + detailsHint; + detailsHint = dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_SIG_COUNT", [sigCount]) + detailsHint; } else { detailsHint = undefined; } @@ -260,7 +262,7 @@ DKIM_Verifier.Display = (function() { { highlightHeader("success"); } else { - setWarnings(dkim.warnings_str); + setWarnings(dkim.warnings_str, detailsHint); highlightHeader("warning"); } diff --git a/chrome/locale/de/dkim.properties b/chrome/locale/de/dkim.properties index 78ca3a1..b6e0875 100644 --- a/chrome/locale/de/dkim.properties +++ b/chrome/locale/de/dkim.properties @@ -105,3 +105,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_AUID = Absender passt nicht zur Benutzeridentität # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Kopfzeile '%S' ist nicht signiert + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Anzahl der Signaturen: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signiert durch %S für %S +DKIM_RESULT_DETAILS_NO_TIME = Kein Signaturzeitpunkt in der Signatur enthalten +DKIM_RESULT_DETAILS_TIME_EXPIRY = Sigiert um %S, läuft ab um %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signiert um %S, läuft nie ab +DKIM_RESULT_DETAILS_ALGORITHM = Algorithmus: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain wurde mit DNSSEC validiert +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain konnte nicht validiert werden +DKIM_RESULT_DETAILS_HEADERS = Signierte Kopfzeilen: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnungen:\n- %S diff --git a/chrome/locale/en-US/dkim.properties b/chrome/locale/en-US/dkim.properties index a6dee9d..eba3d32 100644 --- a/chrome/locale/en-US/dkim.properties +++ b/chrome/locale/en-US/dkim.properties @@ -105,3 +105,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_AUID = From does not match the user identifier # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Header '%S' is not signed + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Signature count: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signed by %S for %S +DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature +DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never +DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated +DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/fr/dkim.properties b/chrome/locale/fr/dkim.properties index 90f213d..a3530fc 100644 --- a/chrome/locale/fr/dkim.properties +++ b/chrome/locale/fr/dkim.properties @@ -105,3 +105,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_AUID = L'expéditeur ne correspond pas avec l'identi # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Header '%S' is not signed + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Signature count: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signed by %S for %S +DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature +DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never +DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated +DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/hu/dkim.properties b/chrome/locale/hu/dkim.properties index 60041d6..8951956 100644 --- a/chrome/locale/hu/dkim.properties +++ b/chrome/locale/hu/dkim.properties @@ -105,3 +105,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_AUID = A feladó nem egyezik a felhasználói azonos # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Header '%S' is not signed + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Signature count: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signed by %S for %S +DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature +DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never +DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated +DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/it/dkim.properties b/chrome/locale/it/dkim.properties index 4f928f9..381458e 100644 --- a/chrome/locale/it/dkim.properties +++ b/chrome/locale/it/dkim.properties @@ -105,3 +105,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_AUID = Il mittente non corrisponde all’identificat # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Header '%S' is not signed + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Signature count: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signed by %S for %S +DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature +DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never +DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated +DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/ja-JP/dkim.properties b/chrome/locale/ja-JP/dkim.properties index aec04a9..f6e2d46 100644 --- a/chrome/locale/ja-JP/dkim.properties +++ b/chrome/locale/ja-JP/dkim.properties @@ -105,3 +105,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_AUID = 差出人がユーザ識別子とマッチし # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Header '%S' is not signed + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Signature count: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signed by %S for %S +DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature +DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never +DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated +DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/zh-CN/dkim.properties b/chrome/locale/zh-CN/dkim.properties index 3e5eef1..03d7a46 100644 --- a/chrome/locale/zh-CN/dkim.properties +++ b/chrome/locale/zh-CN/dkim.properties @@ -100,3 +100,16 @@ DKIM_SIGWARNING_FROM_NOT_IN_SDID=From 不在签名域中 DKIM_SIGWARNING_FROM_NOT_IN_AUID=From 不匹配用户标识符 # DKIM_SIGWARNING - POLICY DKIM_SIGWARNING_UNSIGNED_HEADER = Header '%S' is not signed + +# DKIM Result Details +DKIM_RESULT_DETAILS_SIG_COUNT = Signature count: %S +DKIM_RESULT_DETAILS_SIGNED_BY_FOR = Signed by %S for %S +DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature +DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S +DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never +DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC +DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated +DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S +DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/modules/AuthVerifier.jsm.js b/modules/AuthVerifier.jsm.js index ac8a156..bf6142e 100644 --- a/modules/AuthVerifier.jsm.js +++ b/modules/AuthVerifier.jsm.js @@ -709,35 +709,51 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li let auid = dkimSigResult.auid; let result = authResultDKIM.result_str; let alg = dkimSigResult.algorithmSignature ? dkimSigResult.algorithmSignature.toUpperCase() : undefined; + let keyLength; // = dkimSigResult.signatureKeyLength; let hash = dkimSigResult.algorithmHash ? dkimSigResult.algorithmHash.toUpperCase() : undefined; - let dnssec = dkimSigResult.keySecure ? "Yes" : "No"; + let dnssec = dkimSigResult.keySecure; let signingTime = dkimSigResult.timestamp ? new Date(dkimSigResult.timestamp*1000).toLocaleString() : undefined; - let expirationTime = dkimSigResult.expiration ? new Date(dkimSigResult.expiration*1000).toLocaleString() : "never"; + let expirationTime = dkimSigResult.expiration ? new Date(dkimSigResult.expiration*1000).toLocaleString() : undefined; let signedHeaders = dkimSigResult.signedHeaders ? dkimSigResult.signedHeaders.join(", ") : undefined; + let warnings = authResultDKIM.warnings_str && authResultDKIM.warnings_str.length > 0 ? authResultDKIM.warnings_str.join("\n- ") : undefined; - authResultDKIM.details_str = "Result: " + result; + authResultDKIM.details_str = result; if (sdid && auid) { - authResultDKIM.details_str += "\nSigned by " + sdid + " for " + auid; + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_SIGNED_BY_FOR", [sdid, auid]); } if (signingTime) { - authResultDKIM.details_str += "\nSigned at " + signingTime + ", expires " + expirationTime; + if (expirationTime) { + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_TIME_EXPIRY", [signingTime, expirationTime]); + } else { + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_TIME_NO_EXPIRY", [signingTime]); + } } else { - authResultDKIM.details_str += "\nNo signing time included in signature"; + authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_NO_TIME"); } if ( alg && hash) { - authResultDKIM.details_str += "\nAlgorithm: " + alg + " / " + hash; + if (keyLength) { + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH", [alg, keyLength, hash]); + } else { + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_ALGORITHM", [alg, hash]); + } } if (sdid) { - authResultDKIM.details_str += "\nDomain validated using DNSSEC: " + dnssec; + if (dnssec) { + authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_DNSSEC"); + } else { + authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_NO_DNSSEC"); + } } if (signedHeaders) { - authResultDKIM.details_str += "\nSigned headers: " + signedHeaders; + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_HEADERS", [signedHeaders]); + } + if (warnings) { + authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_WARNINGS", [warnings]); } } return authResultDKIM; } - /** * Convert SavedAuthResult to AuthResult * From 0edc4ff039ec27ff96d212794c0ffb49a71b38b9 Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Mon, 27 May 2024 18:33:17 +0200 Subject: [PATCH 04/10] Added support for signing key length in details --- chrome/locale/de/dkim.properties | 2 +- chrome/locale/en-US/dkim.properties | 2 +- chrome/locale/fr/dkim.properties | 2 +- chrome/locale/hu/dkim.properties | 2 +- chrome/locale/it/dkim.properties | 2 +- chrome/locale/ja-JP/dkim.properties | 2 +- chrome/locale/zh-CN/dkim.properties | 2 +- modules/AuthVerifier.jsm.js | 2 +- modules/dkimVerifier.jsm.js | 83 +++++++++++++++++++++++++++-- 9 files changed, 87 insertions(+), 12 deletions(-) diff --git a/chrome/locale/de/dkim.properties b/chrome/locale/de/dkim.properties index b6e0875..f7c840f 100644 --- a/chrome/locale/de/dkim.properties +++ b/chrome/locale/de/dkim.properties @@ -113,7 +113,7 @@ DKIM_RESULT_DETAILS_NO_TIME = Kein Signaturzeitpunkt in der Signatur enthalten DKIM_RESULT_DETAILS_TIME_EXPIRY = Sigiert um %S, läuft ab um %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signiert um %S, läuft nie ab DKIM_RESULT_DETAILS_ALGORITHM = Algorithmus: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithmus: %S (%S Bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain wurde mit DNSSEC validiert DKIM_RESULT_DETAILS_NO_DNSSEC = Domain konnte nicht validiert werden DKIM_RESULT_DETAILS_HEADERS = Signierte Kopfzeilen: %S diff --git a/chrome/locale/en-US/dkim.properties b/chrome/locale/en-US/dkim.properties index eba3d32..197c7ac 100644 --- a/chrome/locale/en-US/dkim.properties +++ b/chrome/locale/en-US/dkim.properties @@ -113,7 +113,7 @@ DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S diff --git a/chrome/locale/fr/dkim.properties b/chrome/locale/fr/dkim.properties index a3530fc..c3b48de 100644 --- a/chrome/locale/fr/dkim.properties +++ b/chrome/locale/fr/dkim.properties @@ -113,7 +113,7 @@ DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S diff --git a/chrome/locale/hu/dkim.properties b/chrome/locale/hu/dkim.properties index 8951956..99b0ede 100644 --- a/chrome/locale/hu/dkim.properties +++ b/chrome/locale/hu/dkim.properties @@ -113,7 +113,7 @@ DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S diff --git a/chrome/locale/it/dkim.properties b/chrome/locale/it/dkim.properties index 381458e..21a6ddd 100644 --- a/chrome/locale/it/dkim.properties +++ b/chrome/locale/it/dkim.properties @@ -113,7 +113,7 @@ DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S diff --git a/chrome/locale/ja-JP/dkim.properties b/chrome/locale/ja-JP/dkim.properties index f6e2d46..47b6088 100644 --- a/chrome/locale/ja-JP/dkim.properties +++ b/chrome/locale/ja-JP/dkim.properties @@ -113,7 +113,7 @@ DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S diff --git a/chrome/locale/zh-CN/dkim.properties b/chrome/locale/zh-CN/dkim.properties index 03d7a46..dae8767 100644 --- a/chrome/locale/zh-CN/dkim.properties +++ b/chrome/locale/zh-CN/dkim.properties @@ -108,7 +108,7 @@ DKIM_RESULT_DETAILS_NO_TIME = No signing time included in signature DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S -DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S) / %S +DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S diff --git a/modules/AuthVerifier.jsm.js b/modules/AuthVerifier.jsm.js index bf6142e..435d656 100644 --- a/modules/AuthVerifier.jsm.js +++ b/modules/AuthVerifier.jsm.js @@ -709,7 +709,7 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li let auid = dkimSigResult.auid; let result = authResultDKIM.result_str; let alg = dkimSigResult.algorithmSignature ? dkimSigResult.algorithmSignature.toUpperCase() : undefined; - let keyLength; // = dkimSigResult.signatureKeyLength; + let keyLength = dkimSigResult.signatureKeyLength ? dkimSigResult.signatureKeyLength.toString() : undefined; let hash = dkimSigResult.algorithmHash ? dkimSigResult.algorithmHash.toUpperCase() : undefined; let dnssec = dkimSigResult.keySecure; let signingTime = dkimSigResult.timestamp ? new Date(dkimSigResult.timestamp*1000).toLocaleString() : undefined; diff --git a/modules/dkimVerifier.jsm.js b/modules/dkimVerifier.jsm.js index 1594f4b..f1d6465 100644 --- a/modules/dkimVerifier.jsm.js +++ b/modules/dkimVerifier.jsm.js @@ -134,6 +134,7 @@ const PREF_BRANCH = "extensions.dkim_verifier."; * @property {String[]} [errorStrParams] * @property {Boolean} [hideFail] * @property {Boolean} [keySecure] + * @property {number|null} [signatureKeyLength] * @property {number|null} [timestamp] * @property {number|null} [expiration] * @property {string} [algorithmSignature] @@ -253,6 +254,74 @@ var Verifier = (function() { } } + /** + * Get the length of an RSA key in bit. + * + * @param {String} key + * b64 encoded RSA key in ASN.1 DER format + * @return {Number} + * @throws {DKIM_SigError|Error} + */ + function getRSAKeyLength(key) { + // get RSA-key + /* + the rsa key must be in the following ASN.1 DER format + + SEQUENCE(2 elem) -- our posTopArray + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.1.1 (Comment: PKCS #1; Description: rsaEncryption) + NULL + BIT STRING(1 elem) + SEQUENCE(2 elem) -- our posKeyArray + INTEGER (modulus) + INTEGER (publicExponent) + */ + let asnKey = RSA.b64tohex(key); + let posTopArray = null; + let posKeyArray = null; + + // check format by comparing the 1. child in the top element + posTopArray = RSA.ASN1HEX.getChildIdx(asnKey,0); + if (posTopArray === null || posTopArray.length !== 2) { + throw new DKIM_SigError("DKIM_SIGERROR_KEYDECODE"); + } + if (RSA.ASN1HEX.getTLV(asnKey, posTopArray[0]) !== + "300d06092a864886f70d0101010500") { + throw new DKIM_SigError("DKIM_SIGERROR_KEYDECODE"); + } + + // get pos of SEQUENCE under BIT STRING + // asn1hex does not support BIT STRING, so we will compute the position + let pos = RSA.ASN1HEX.getVidx(asnKey, posTopArray[1]) + 2; + + // get pos of modulus and publicExponent + posKeyArray = RSA.ASN1HEX.getChildIdx(asnKey, pos); + if (posKeyArray === null || posKeyArray.length !== 2) { + throw new DKIM_SigError("DKIM_SIGERROR_KEYDECODE"); + } + + // get modulus + let m_hex = RSA.ASN1HEX.getV(asnKey,posKeyArray[0]); + // trim leading zeros + m_hex = m_hex.replace(/^0+/, ''); + // one hex digit represents 4 bits + return m_hex.length * 4; + } + + /** + * Get the length of an ED25519 key in bit. + * + * @param {String} key + * b64 encoded ED25519 key + * @return {Number} + * @throws {DKIM_SigError|Error} + */ + function getED25519KeyLength(key) { + let key_byte = NaClUtil.nacl.util.decodeBase64(key); + // each byte has 8 bit (a valid key_byte array has a length of 32) + return key_byte.length * 8; + } + /** * Verifies an RSA signature. * @@ -313,13 +382,15 @@ var Verifier = (function() { // get public exponent let e_hex = RSA.ASN1HEX.getV(asnKey,posKeyArray[1]); - if (m_hex.length * 4 < 1024) { + let keyLength = getRSAKeyLength(key); + + if (keyLength < 1024) { // error if key is too short - log.debug("rsa key size: " + m_hex.length * 4); + log.debug("rsa key size: " + keyLength); throw new DKIM_SigError("DKIM_SIGWARNING_KEYSMALL"); - } else if (m_hex.length * 4 < 2048) { + } else if (keyLength < 2048) { // weak key - log.debug("rsa key size: " + m_hex.length * 4); + log.debug("rsa key size: " + keyLength); switch (prefs.getIntPref("error.algorithm.rsa.weakKeyLength.treatAs")) { case 0: // error throw new DKIM_SigError("DKIM_SIGWARNING_KEY_IS_WEAK"); @@ -371,6 +442,7 @@ var Verifier = (function() { v : null, // Version a_sig : null, // signature algorithm (signing part) a_hash : null, // signature algorithm (hashing part) + a_keylength : null, // signature algorithm: signing key length b : null, // signature (unfolded) b_folded : null, // signature (still folded) bh : null, // body hash @@ -724,6 +796,7 @@ var Verifier = (function() { algorithmSignature : dkimSignature.a_sig, algorithmHash : dkimSignature.a_hash, signedHeaders : dkimSignature.h_array ? copy(dkimSignature.h_array) : undefined, + signatureKeyLength : dkimSignature.a_keylength }; } else { baseResult = { @@ -1199,9 +1272,11 @@ var Verifier = (function() { switch (DKIMSignature.a_sig) { case "ed25519": verifyFunction = verifyED25519Sig; + DKIMSignature.a_keylength = getED25519KeyLength(DKIMSignature.DKIMKey.p); break; case "rsa": verifyFunction = verifyRSASig; + DKIMSignature.a_keylength = getRSAKeyLength(DKIMSignature.DKIMKey.p); break; default: // this should never happen, as it's already handled in newDKIMSignature From 5d8a70969f247b3d770b95ac1c3e611b23e214e5 Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Mon, 27 May 2024 21:09:32 +0200 Subject: [PATCH 05/10] Hidden properties to configure advanced information in hints --- chrome/content/dkim.js | 34 ++++++++++++++++++++++++---------- defaults/preferences/prefs.js | 4 ++++ modules/AuthVerifier.jsm.js | 12 +++++++----- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/chrome/content/dkim.js b/chrome/content/dkim.js index ba35908..e576f47 100644 --- a/chrome/content/dkim.js +++ b/chrome/content/dkim.js @@ -240,17 +240,31 @@ DKIM_Verifier.Display = (function() { let sigCount = 0; let detailsHint; - detailsHint = ""; - result.dkim.forEach(dkim => { - if (dkim.details_str) { - detailsHint += "\n----\n" + dkim.details_str; - sigCount += 1; + if (prefs.getBoolPref("advancedInfo.show")) { + detailsHint = ""; + if (prefs.getBoolPref("advancedInfo.allSignatures")) { + result.dkim.forEach(dkim => { + if (dkim.details_str) { + detailsHint += "\n----\n" + dkim.details_str; + sigCount += 1; + } + }); + if (sigCount === 0) { + // the check resulted in an error, because the signature wasn't well formed + // or there was no signature + detailsHint = undefined; + } + } else { + detailsHint = result.dkim[0].details_str; + } + if (detailsHint) { + // there is extended information to display + let caption = ""; + if (prefs.getBoolPref("advancedInfo.allSignatures")) { + caption = dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_SIG_COUNT", [sigCount]); + } + detailsHint = caption + detailsHint; } - }); - if (sigCount > 0) { - detailsHint = dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_SIG_COUNT", [sigCount]) + detailsHint; - } else { - detailsHint = undefined; } setValue(result.dkim[0].result_str, detailsHint); diff --git a/defaults/preferences/prefs.js b/defaults/preferences/prefs.js index 91ff9ce..1b1dc7b 100644 --- a/defaults/preferences/prefs.js +++ b/defaults/preferences/prefs.js @@ -122,6 +122,10 @@ pref("extensions.dkim_verifier.color.tempfail.background", "unset"); pref("extensions.dkim_verifier.color.nosig.text", "unset"); pref("extensions.dkim_verifier.color.nosig.background", "unset"); +pref("extensions.dkim_verifier.advancedInfo.show", false); +pref("extensions.dkim_verifier.advancedInfo.allSignatures", false); +pref("extensions.dkim_verifier.advancedInfo.includeHeaders", false); +pref("extensions.dkim_verifier.advancedInfo.includeDNSSEC", false); //////////////////////////////////////////////////////////////////////////////// // advanced preferences diff --git a/modules/AuthVerifier.jsm.js b/modules/AuthVerifier.jsm.js index 435d656..41874d3 100644 --- a/modules/AuthVerifier.jsm.js +++ b/modules/AuthVerifier.jsm.js @@ -738,13 +738,15 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li } } if (sdid) { - if (dnssec) { - authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_DNSSEC"); - } else { - authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_NO_DNSSEC"); + if (prefs.getBoolPref("advancedInfo.includeDNSSEC")) { + if (dnssec) { + authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_DNSSEC"); + } else { + authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_NO_DNSSEC"); + } } } - if (signedHeaders) { + if (prefs.getBoolPref("advancedInfo.includeHeaders") && signedHeaders) { authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_HEADERS", [signedHeaders]); } if (warnings) { From 34260314155339db249815dde259cdfca1f0e2dd Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Tue, 28 May 2024 19:34:01 +0200 Subject: [PATCH 06/10] Removed redundand DNSSEC information --- chrome/locale/de/dkim.properties | 2 -- chrome/locale/en-US/dkim.properties | 2 -- chrome/locale/fr/dkim.properties | 2 -- chrome/locale/hu/dkim.properties | 2 -- chrome/locale/it/dkim.properties | 2 -- chrome/locale/ja-JP/dkim.properties | 2 -- chrome/locale/zh-CN/dkim.properties | 2 -- defaults/preferences/prefs.js | 3 +-- modules/AuthVerifier.jsm.js | 10 ---------- 9 files changed, 1 insertion(+), 26 deletions(-) diff --git a/chrome/locale/de/dkim.properties b/chrome/locale/de/dkim.properties index f7c840f..30cae0a 100644 --- a/chrome/locale/de/dkim.properties +++ b/chrome/locale/de/dkim.properties @@ -114,7 +114,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Sigiert um %S, läuft ab um %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signiert um %S, läuft nie ab DKIM_RESULT_DETAILS_ALGORITHM = Algorithmus: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithmus: %S (%S Bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain wurde mit DNSSEC validiert -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain konnte nicht validiert werden DKIM_RESULT_DETAILS_HEADERS = Signierte Kopfzeilen: %S DKIM_RESULT_DETAILS_WARNINGS = Warnungen:\n- %S diff --git a/chrome/locale/en-US/dkim.properties b/chrome/locale/en-US/dkim.properties index 197c7ac..e9c89c2 100644 --- a/chrome/locale/en-US/dkim.properties +++ b/chrome/locale/en-US/dkim.properties @@ -114,7 +114,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/fr/dkim.properties b/chrome/locale/fr/dkim.properties index c3b48de..a4da862 100644 --- a/chrome/locale/fr/dkim.properties +++ b/chrome/locale/fr/dkim.properties @@ -114,7 +114,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/hu/dkim.properties b/chrome/locale/hu/dkim.properties index 99b0ede..073bfc3 100644 --- a/chrome/locale/hu/dkim.properties +++ b/chrome/locale/hu/dkim.properties @@ -114,7 +114,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/it/dkim.properties b/chrome/locale/it/dkim.properties index 21a6ddd..fd6e407 100644 --- a/chrome/locale/it/dkim.properties +++ b/chrome/locale/it/dkim.properties @@ -114,7 +114,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/ja-JP/dkim.properties b/chrome/locale/ja-JP/dkim.properties index 47b6088..f92bfbd 100644 --- a/chrome/locale/ja-JP/dkim.properties +++ b/chrome/locale/ja-JP/dkim.properties @@ -114,7 +114,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/chrome/locale/zh-CN/dkim.properties b/chrome/locale/zh-CN/dkim.properties index dae8767..fe82de3 100644 --- a/chrome/locale/zh-CN/dkim.properties +++ b/chrome/locale/zh-CN/dkim.properties @@ -109,7 +109,5 @@ DKIM_RESULT_DETAILS_TIME_EXPIRY = Signed at %S, expires at %S DKIM_RESULT_DETAILS_TIME_NO_EXPIRY = Signed at %S, expires never DKIM_RESULT_DETAILS_ALGORITHM = Algorithm: %S / %S DKIM_RESULT_DETAILS_ALGORITHM_WITH_LENGTH = Algorithm: %S (%S bit) / %S -DKIM_RESULT_DETAILS_DNSSEC = Domain was validated using DNSSEC -DKIM_RESULT_DETAILS_NO_DNSSEC = Domain could not be validated DKIM_RESULT_DETAILS_HEADERS = Signed headers: %S DKIM_RESULT_DETAILS_WARNINGS = Warnings:\n- %S diff --git a/defaults/preferences/prefs.js b/defaults/preferences/prefs.js index 1b1dc7b..875ccec 100644 --- a/defaults/preferences/prefs.js +++ b/defaults/preferences/prefs.js @@ -64,7 +64,7 @@ pref("extensions.dkim_verifier.policy.DMARC.shouldBeSigned.neededPolicy", "none" pref("extensions.dkim_verifier.display.favicon.show", true); -/* +/* * Mode to handle headers, which should be signed, but are not * 10 relaxed * 20 recommended @@ -125,7 +125,6 @@ pref("extensions.dkim_verifier.color.nosig.background", "unset"); pref("extensions.dkim_verifier.advancedInfo.show", false); pref("extensions.dkim_verifier.advancedInfo.allSignatures", false); pref("extensions.dkim_verifier.advancedInfo.includeHeaders", false); -pref("extensions.dkim_verifier.advancedInfo.includeDNSSEC", false); //////////////////////////////////////////////////////////////////////////////// // advanced preferences diff --git a/modules/AuthVerifier.jsm.js b/modules/AuthVerifier.jsm.js index 41874d3..a334549 100644 --- a/modules/AuthVerifier.jsm.js +++ b/modules/AuthVerifier.jsm.js @@ -711,7 +711,6 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li let alg = dkimSigResult.algorithmSignature ? dkimSigResult.algorithmSignature.toUpperCase() : undefined; let keyLength = dkimSigResult.signatureKeyLength ? dkimSigResult.signatureKeyLength.toString() : undefined; let hash = dkimSigResult.algorithmHash ? dkimSigResult.algorithmHash.toUpperCase() : undefined; - let dnssec = dkimSigResult.keySecure; let signingTime = dkimSigResult.timestamp ? new Date(dkimSigResult.timestamp*1000).toLocaleString() : undefined; let expirationTime = dkimSigResult.expiration ? new Date(dkimSigResult.expiration*1000).toLocaleString() : undefined; let signedHeaders = dkimSigResult.signedHeaders ? dkimSigResult.signedHeaders.join(", ") : undefined; @@ -737,15 +736,6 @@ function dkimSigResultV2_to_AuthResultDKIM(dkimSigResult) { // eslint-disable-li authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_ALGORITHM", [alg, hash]); } } - if (sdid) { - if (prefs.getBoolPref("advancedInfo.includeDNSSEC")) { - if (dnssec) { - authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_DNSSEC"); - } else { - authResultDKIM.details_str += "\n" + dkimStrings.getString("DKIM_RESULT_DETAILS_NO_DNSSEC"); - } - } - } if (prefs.getBoolPref("advancedInfo.includeHeaders") && signedHeaders) { authResultDKIM.details_str += "\n" + dkimStrings.getFormattedString("DKIM_RESULT_DETAILS_HEADERS", [signedHeaders]); } From b74ca62f897303ddd74d78db956db00dcecb36d0 Mon Sep 17 00:00:00 2001 From: dodmi <4572946+dodmi@users.noreply.github.com> Date: Tue, 28 May 2024 20:14:07 +0200 Subject: [PATCH 07/10] Added GUI options for advanced hints --- chrome/content/options_display.js | 27 ++++++++++++++++++++ chrome/content/options_display.xul | 41 +++++++++++++++++++++++++----- chrome/locale/de/options.dtd | 4 +++ chrome/locale/en-US/options.dtd | 4 +++ chrome/locale/fr/options.dtd | 4 +++ chrome/locale/hu/options.dtd | 4 +++ chrome/locale/it/options.dtd | 4 +++ chrome/locale/ja-JP/options.dtd | 4 +++ chrome/locale/zh-CN/options.dtd | 4 +++ 9 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 chrome/content/options_display.js diff --git a/chrome/content/options_display.js b/chrome/content/options_display.js new file mode 100644 index 0000000..53f0c50 --- /dev/null +++ b/chrome/content/options_display.js @@ -0,0 +1,27 @@ +// @ts-nocheck +/* eslint-env browser */ +/* eslint strict: ["warn", "function"] */ +/* exported toggleDetailsOptionsEnabled */ + +let checkBox = { + showAdvancedInfo : null, + allSignatures : null, + includeHeaders : null +}; + +function init() { + "use strict"; + checkBox.showAdvancedInfo = document.getElementById("display.advancedInfo.show"); + checkBox.allSignatures = document.getElementById("display.advancedInfo.allSignatures"); + checkBox.includeHeaders = document.getElementById("display.advancedInfo.includeHeaders"); + toggleDetailsOptionsEnabled(); +} + +function toggleDetailsOptionsEnabled() { + "use strict"; + let disabled = !checkBox.showAdvancedInfo.checked; + checkBox.allSignatures.disabled = disabled; + checkBox.includeHeaders.disabled = disabled; +} + +window.addEventListener("load", init, false); \ No newline at end of file diff --git a/chrome/content/options_display.xul b/chrome/content/options_display.xul index c1a4569..aca8d89 100644 --- a/chrome/content/options_display.xul +++ b/chrome/content/options_display.xul @@ -5,6 +5,7 @@ +