summaryrefslogtreecommitdiffstats
path: root/comm/chat/content/otr-auth.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/chat/content/otr-auth.js
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/chat/content/otr-auth.js')
-rw-r--r--comm/chat/content/otr-auth.js198
1 files changed, 198 insertions, 0 deletions
diff --git a/comm/chat/content/otr-auth.js b/comm/chat/content/otr-auth.js
new file mode 100644
index 0000000000..24199a6acc
--- /dev/null
+++ b/comm/chat/content/otr-auth.js
@@ -0,0 +1,198 @@
+/* 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/. */
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+const { l10nHelper } = ChromeUtils.importESModule(
+ "resource:///modules/imXPCOMUtils.sys.mjs"
+);
+const { OTR } = ChromeUtils.importESModule("resource:///modules/OTR.sys.mjs");
+
+window.addEventListener("DOMContentLoaded", event => {
+ otrAuth.onload();
+});
+
+var [mode, uiConv, contactInfo] = window.arguments;
+
+function showSection(selected, hideMenu) {
+ document.getElementById("how").hidden = !!hideMenu;
+ ["questionAndAnswer", "sharedSecret", "manualVerification", "ask"].forEach(
+ function (key) {
+ document.getElementById(key).hidden = key !== selected;
+ }
+ );
+ window.sizeToContent();
+}
+
+function startSMP(context, answer, question) {
+ OTR.sendSecret(context, answer, question);
+ OTR.authUpdate(context, 10);
+}
+
+function manualVerification(fingerprint, context) {
+ let opts = document.getElementById("verifiedOption");
+ let trust = opts.selectedItem.value === "yes";
+ OTR.setTrust(fingerprint, trust, context);
+}
+
+async function populateFingers(context, theirs, trust) {
+ let yours = OTR.privateKeyFingerprint(context.account, context.protocol);
+ if (!yours) {
+ throw new Error("Fingerprint should already be generated.");
+ }
+
+ let [yourFPLabel, theirFPLabel] = await document.l10n.formatValues([
+ { id: "auth-your-fp-value", args: { own_name: context.account } },
+ { id: "auth-their-fp-value", args: { their_name: context.username } },
+ ]);
+
+ document.getElementById("yourFPLabel").value = yourFPLabel;
+ document.getElementById("theirFPLabel").value = theirFPLabel;
+
+ document.getElementById("yourFPValue").value = yours;
+ document.getElementById("theirFPValue").value = theirs;
+
+ let opts = document.getElementById("verifiedOption");
+ let verified = trust ? "yes" : "no";
+ for (let item of opts.menupopup.children) {
+ if (verified === item.value) {
+ opts.selectedItem = item;
+ break;
+ }
+ }
+}
+
+var otrAuth = {
+ async onload() {
+ // This window implements the interactive authentication of a buddy's
+ // key. At open time, we're given several parameters, and the "mode"
+ // parameter tells us from where we've been called.
+ // mode == "pref" means that we have been opened from the preferences,
+ // and it means we cannot rely on the other user being online, and
+ // we there might be no uiConv active currently, so we fall back.
+
+ let nameSource =
+ mode === "pref" ? contactInfo.screenname : uiConv.normalizedName;
+ let title = await document.l10n.formatValue("auth-title", {
+ name: nameSource,
+ });
+ document.title = title;
+
+ document.addEventListener("dialogaccept", () => {
+ return this.accept();
+ });
+
+ document.addEventListener("dialogcancel", () => {
+ return this.cancel();
+ });
+
+ let context, theirs;
+ switch (mode) {
+ case "start":
+ context = OTR.getContext(uiConv.target);
+ theirs = OTR.hashToHuman(context.fingerprint);
+ populateFingers(context, theirs, context.trust);
+ showSection("questionAndAnswer");
+ break;
+ case "pref":
+ context = OTR.getContextFromRecipient(
+ contactInfo.account,
+ contactInfo.protocol,
+ contactInfo.screenname
+ );
+ theirs = contactInfo.fingerprint;
+ populateFingers(context, theirs, contactInfo.trust);
+ showSection("manualVerification", true);
+ this.oninput({ value: true });
+ break;
+ case "ask":
+ let receivedQuestionLabel = document.getElementById(
+ "receivedQuestionLabel"
+ );
+ let receivedQuestionDisplay =
+ document.getElementById("receivedQuestion");
+ let responseLabel = document.getElementById("responseLabel");
+ if (contactInfo.question) {
+ receivedQuestionLabel.hidden = false;
+ receivedQuestionDisplay.hidden = false;
+ receivedQuestionDisplay.value = contactInfo.question;
+ responseLabel.value = await document.l10n.formatValue("auth-answer");
+ } else {
+ receivedQuestionLabel.hidden = true;
+ receivedQuestionDisplay.hidden = true;
+ responseLabel.value = await document.l10n.formatValue("auth-secret");
+ }
+ showSection("ask", true);
+ break;
+ }
+ },
+
+ accept() {
+ // uiConv may not be present in pref mode
+ let context = uiConv ? OTR.getContext(uiConv.target) : null;
+ if (mode === "pref") {
+ manualVerification(contactInfo.fpointer, context);
+ } else if (mode === "start") {
+ let how = document.getElementById("howOption");
+ switch (how.selectedItem.value) {
+ case "questionAndAnswer":
+ let question = document.getElementById("question").value;
+ let answer = document.getElementById("answer").value;
+ startSMP(context, answer, question);
+ break;
+ case "sharedSecret":
+ let secret = document.getElementById("secret").value;
+ startSMP(context, secret);
+ break;
+ case "manualVerification":
+ manualVerification(context.fingerprint, context);
+ break;
+ default:
+ throw new Error("Unreachable!");
+ }
+ } else if (mode === "ask") {
+ let response = document.getElementById("response").value;
+ OTR.sendResponse(context, response);
+ OTR.authUpdate(context, contactInfo.progress);
+ } else {
+ throw new Error("Unreachable!");
+ }
+ return true;
+ },
+
+ cancel() {
+ if (mode === "ask") {
+ let context = OTR.getContext(uiConv.target);
+ OTR.abortSMP(context);
+ // Close the ask-auth notification if it was previously triggered.
+ OTR.notifyObservers(
+ {
+ context,
+ },
+ "otr:cancel-ask-auth"
+ );
+ }
+ },
+
+ oninput(e) {
+ document.querySelector("dialog").getButton("accept").disabled = !e.value;
+ },
+
+ how() {
+ let how = document.getElementById("howOption").selectedItem.value;
+ switch (how) {
+ case "questionAndAnswer":
+ this.oninput(document.getElementById("answer"));
+ break;
+ case "sharedSecret":
+ this.oninput(document.getElementById("secret"));
+ break;
+ case "manualVerification":
+ this.oninput({ value: true });
+ break;
+ }
+ showSection(how);
+ },
+};