diff options
Diffstat (limited to 'toolkit/components/passwordmgr/LoginHelper.sys.mjs')
-rw-r--r-- | toolkit/components/passwordmgr/LoginHelper.sys.mjs | 105 |
1 files changed, 100 insertions, 5 deletions
diff --git a/toolkit/components/passwordmgr/LoginHelper.sys.mjs b/toolkit/components/passwordmgr/LoginHelper.sys.mjs index 5626312f17..615ac79449 100644 --- a/toolkit/components/passwordmgr/LoginHelper.sys.mjs +++ b/toolkit/components/passwordmgr/LoginHelper.sys.mjs @@ -18,6 +18,13 @@ ChromeUtils.defineESModuleGetters(lazy, { OSKeyStore: "resource://gre/modules/OSKeyStore.sys.mjs", }); +XPCOMUtils.defineLazyServiceGetter( + lazy, + "Crypto", + "@mozilla.org/login-manager/crypto/SDR;1", + "nsILoginManagerCrypto" +); + export class ParentAutocompleteOption { image; title; @@ -366,7 +373,7 @@ class ImportRowProcessor { return this.summary; } } - +const OS_AUTH_FOR_PASSWORDS_PREF = "signon.management.page.os-auth.optout"; /** * Contains functions shared by different Login Manager components. */ @@ -394,6 +401,7 @@ export const LoginHelper = { testOnlyUserHasInteractedWithDocument: null, userInputRequiredToCapture: null, captureInputChanges: null, + OS_AUTH_FOR_PASSWORDS_PREF, init() { // Watch for pref changes to update cached pref values. @@ -1583,6 +1591,90 @@ export const LoginHelper = { }, /** + * Get the decrypted value for a string pref. + * + * @param {string} prefName -> The pref whose value is needed. + * @param {string} safeDefaultValue -> Value to be returned incase the pref is not yet set. + * @returns {string} + */ + getSecurePref(prefName, safeDefaultValue) { + try { + const encryptedValue = Services.prefs.getStringPref(prefName, ""); + return encryptedValue === "" + ? safeDefaultValue + : lazy.Crypto.decrypt(encryptedValue); + } catch { + return safeDefaultValue; + } + }, + + /** + * Set the pref to the encrypted form of the value. + * + * @param {string} prefName -> The pref whose value is to be set. + * @param {string} value -> The value to be set in its encrypted form. + */ + setSecurePref(prefName, value) { + if (value) { + const encryptedValue = lazy.Crypto.encrypt(value); + Services.prefs.setStringPref(prefName, encryptedValue); + } else { + Services.prefs.clearUserPref(prefName); + } + }, + + /** + * Get whether the OSAuth is enabled or not. + * + * @param {string} prefName -> The name of the pref (creditcards or addresses) + * @returns {boolean} + */ + getOSAuthEnabled(prefName) { + return ( + lazy.OSKeyStore.canReauth() && + this.getSecurePref(prefName, "") !== "opt out" + ); + }, + + /** + * Set whether the OSAuth is enabled or not. + * + * @param {string} prefName -> The pref to encrypt. + * @param {boolean} enable -> Whether the pref is to be enabled. + */ + setOSAuthEnabled(prefName, enable) { + this.setSecurePref(prefName, enable ? null : "opt out"); + }, + + async verifyUserOSAuth( + prefName, + promptMessage, + captionDialog = "", + parentWindow = null, + generateKeyIfNotAvailable = true + ) { + if (!this.getOSAuthEnabled(prefName)) { + promptMessage = false; + } + try { + return ( + await lazy.OSKeyStore.ensureLoggedIn( + promptMessage, + captionDialog, + parentWindow, + generateKeyIfNotAvailable + ) + ).authenticated; + } catch (ex) { + // Since Win throws an exception whereas Mac resolves to false upon cancelling. + if (ex.result !== Cr.NS_ERROR_FAILURE) { + throw ex; + } + } + return false; + }, + + /** * Shows the Primary Password prompt if enabled, or the * OS auth dialog otherwise. * @param {Element} browser @@ -1637,18 +1729,21 @@ export const LoginHelper = { } // Use the OS auth dialog if there is no primary password if (!token.hasPassword && OSReauthEnabled) { - let result = await lazy.OSKeyStore.ensureLoggedIn( + let isAuthorized = await this.verifyUserOSAuth( + OS_AUTH_FOR_PASSWORDS_PREF, messageText, captionText, browser.ownerGlobal, false ); - isAuthorized = result.authenticated; + let value = lazy.OSKeyStore.canReauth() + ? "success" + : "success_unsupported_platform"; + telemetryEvent = { object: "os_auth", method: "reauthenticate", - value: result.auth_details, - extra: result.auth_details_extra, + value: isAuthorized ? value : "fail", }; return { isAuthorized, |