diff --git a/security/manager/ssl/OSKeyStore.cpp b/security/manager/ssl/OSKeyStore.cpp index b8ffa85b01d6..487c5770d784 100644 --- a/security/manager/ssl/OSKeyStore.cpp +++ b/security/manager/ssl/OSKeyStore.cpp @@ -235,7 +235,7 @@ OSKeyStore::GetIsNSSKeyStore(bool* aNSSKeyStore) // Async interfaces that return promises because the key store implementation // might block, e.g. asking for a password. -static nsresult +nsresult GetPromise(JSContext* aCx, /* out */ RefPtr& aPromise) { nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx); diff --git a/security/manager/ssl/OSKeyStore.h b/security/manager/ssl/OSKeyStore.h index 985173d7f444..339b3f87a6fc 100644 --- a/security/manager/ssl/OSKeyStore.h +++ b/security/manager/ssl/OSKeyStore.h @@ -68,6 +68,8 @@ private: #define NS_OSKEYSTORE_CID \ { 0x57972956, 0x5718, 0x42d2, { 0x80, 0x70, 0xb3, 0xfc, 0x72, 0x21, 0x2e, 0xaf } } +nsresult GetPromise(JSContext* aCx, /* out */ RefPtr& aPromise); + class OSKeyStore : public nsIOSKeyStore { public: diff --git a/security/manager/ssl/OSReauthenticator.cpp b/security/manager/ssl/OSReauthenticator.cpp new file mode 100644 index 000000000000..ee70503d5a5a --- /dev/null +++ b/security/manager/ssl/OSReauthenticator.cpp @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "OSReauthenticator.h" + +#include "OSKeyStore.h" + +NS_IMPL_ISUPPORTS(OSReauthenticator, nsIOSReauthenticator) + +using namespace mozilla; +using dom::Promise; + +static nsresult +ReauthenticateUser(const nsACString& prompt, /* out */ bool& reauthenticated) +{ + reauthenticated = false; + return NS_OK; +} + +static void +BackgroundReauthenticateUser(RefPtr& aPromise, + const nsACString& aPrompt) +{ + nsAutoCString recovery; + bool reauthenticated; + nsresult rv = ReauthenticateUser(aPrompt, reauthenticated); + nsCOMPtr runnable(NS_NewRunnableFunction( + "BackgroundReauthenticateUserResolve", + [rv, reauthenticated, aPromise = std::move(aPromise)]() { + if (NS_FAILED(rv)) { + aPromise->MaybeReject(rv); + } else { + aPromise->MaybeResolve(reauthenticated); + } + })); + NS_DispatchToMainThread(runnable.forget()); +} + +NS_IMETHODIMP +OSReauthenticator::AsyncReauthenticateUser(const nsACString& aPrompt, + JSContext* aCx, + Promise** promiseOut) +{ + NS_ENSURE_ARG_POINTER(aCx); + + RefPtr promiseHandle; + nsresult rv = GetPromise(aCx, promiseHandle); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr runnable( + NS_NewRunnableFunction("BackgroundReauthenticateUser", + [promiseHandle, aPrompt = nsAutoCString(aPrompt)]() mutable { + BackgroundReauthenticateUser(promiseHandle, aPrompt); + } + ) + ); + + nsCOMPtr thread; + rv = NS_NewNamedThread(NS_LITERAL_CSTRING("ReauthenticateUserThread"), + getter_AddRefs(thread), runnable); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + promiseHandle.forget(promiseOut); + return NS_OK; +} diff --git a/security/manager/ssl/OSReauthenticator.h b/security/manager/ssl/OSReauthenticator.h new file mode 100644 index 000000000000..c8583c29c9f5 --- /dev/null +++ b/security/manager/ssl/OSReauthenticator.h @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#ifndef OSReauthenticator_h +#define OSReauthenticator_h + +#include "nsIOSReauthenticator.h" + +#define NS_OSREAUTHENTICATOR_CONTRACTID "@mozilla.org/security/osreauthenticator;1" +#define NS_OSREAUTHENTICATOR_CID \ + { 0x4fe082ae, 0x6ff0, 0x4b41, { 0xb2, 0x4f, 0xea, 0xa6, 0x64, 0xf6, 0xe4, 0x6a } } + +class OSReauthenticator : public nsIOSReauthenticator +{ +public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIOSREAUTHENTICATOR + +private: + virtual ~OSReauthenticator() = default; +}; + +#endif // OSReauthenticator_h diff --git a/security/manager/ssl/moz.build b/security/manager/ssl/moz.build index d78de5334406..d4c9b0580ff1 100644 --- a/security/manager/ssl/moz.build +++ b/security/manager/ssl/moz.build @@ -26,6 +26,7 @@ XPIDL_SOURCES += [ 'nsINSSErrorsService.idl', 'nsINSSVersion.idl', 'nsIOSKeyStore.idl', + 'nsIOSReauthenticator.idl', 'nsIPK11Token.idl', 'nsIPK11TokenDB.idl', 'nsIPKCS11Module.idl', @@ -126,6 +127,7 @@ UNIFIED_SOURCES += [ 'nsSSLSocketProvider.cpp', 'nsTLSSocketProvider.cpp', 'OSKeyStore.cpp', + 'OSReauthenticator.cpp', 'PKCS11ModuleDB.cpp', 'PSMContentListener.cpp', 'PSMRunnable.cpp', diff --git a/security/manager/ssl/nsIOSReauthenticator.idl b/security/manager/ssl/nsIOSReauthenticator.idl new file mode 100644 index 000000000000..e90c516b37f3 --- /dev/null +++ b/security/manager/ssl/nsIOSReauthenticator.idl @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#include "nsISupports.idl" + +[scriptable, uuid(4fe082ae-6ff0-4b41-b24f-eaa664f6e46a)] +interface nsIOSReauthenticator: nsISupports { + /** + * This interface provides an abstract way to request that the user + * reauthenticate themselves to the operating system. It may be useful in + * conjunction with nsIOSKeyStore, whereby consumers of these APIs may + * consider some secrets too sensitive to access without first + * reauthenticating the user. + * + * Usage: + * + * // obtain the singleton nsIOSReauthenticator instance + * const reauthenticator = Cc["@mozilla.org/security/osreauthenticator;1"] + * .getService(Ci.nsIOSReauthenticator); + * if (await reauthenticator.asyncReauthenticate()) { + * // do something only authenticated users are allowed to do... + * } else { + * // show a "sorry, this isn't allowed" error + * } + */ + + /** + * Asynchronously cause the operating system to request that the user + * reauthenticate. This is typically in the form of a dialog box asking the + * user for their login password. The actual behaviour of this depends on the + * OS. + * + * @param prompt A short string that may be incorporated in the dialog + * @return Promise resolving to true if the user successfully authenticated + * and false otherwise. + */ + [implicit_jscontext, must_use] + Promise asyncReauthenticateUser(in ACString prompt); +}; diff --git a/security/manager/ssl/nsNSSCertTrust.cpp b/security/manager/ssl/nsNSSCertTrust.cpp index 46dd005f201d..51477e5d2a38 100644 --- a/security/manager/ssl/nsNSSCertTrust.cpp +++ b/security/manager/ssl/nsNSSCertTrust.cpp @@ -4,6 +4,8 @@ #include "nsNSSCertTrust.h" +#include "certdb.h" + void nsNSSCertTrust::AddCATrust(bool ssl, bool email) { diff --git a/security/manager/ssl/nsNSSCertTrust.h b/security/manager/ssl/nsNSSCertTrust.h index 8f546376346b..6ae995223a23 100644 --- a/security/manager/ssl/nsNSSCertTrust.h +++ b/security/manager/ssl/nsNSSCertTrust.h @@ -5,7 +5,6 @@ #ifndef nsNSSCertTrust_h #define nsNSSCertTrust_h -#include "certdb.h" #include "certt.h" /* diff --git a/security/manager/ssl/nsNSSModule.cpp b/security/manager/ssl/nsNSSModule.cpp index 7ee6d78f809d..12ae8291e473 100644 --- a/security/manager/ssl/nsNSSModule.cpp +++ b/security/manager/ssl/nsNSSModule.cpp @@ -34,6 +34,7 @@ #include "nsTLSSocketProvider.h" #include "nsXULAppAPI.h" #include "OSKeyStore.h" +#include "OSReauthenticator.h" #ifdef MOZ_XUL #include "nsCertTree.h" @@ -160,6 +161,7 @@ NS_DEFINE_NAMED_CID(NS_SECURE_BROWSER_UI_CID); NS_DEFINE_NAMED_CID(NS_SITE_SECURITY_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_CERT_BLOCKLIST_CID); NS_DEFINE_NAMED_CID(NS_OSKEYSTORE_CID); +NS_DEFINE_NAMED_CID(NS_OSREAUTHENTICATOR_CID); // Components that require main thread initialization could cause a deadlock // in necko code (bug 1418752). To prevent it we initialize all such components @@ -221,6 +223,10 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = { nullptr, ProcessRestriction::ParentProcessOnly, ThreadRestriction::MainThreadOnly> }, + { &kNS_OSREAUTHENTICATOR_CID, false, nullptr, Constructor }, { nullptr } }; @@ -253,6 +259,7 @@ static const mozilla::Module::ContractIDEntry kNSSContracts[] = { { NS_SSSERVICE_CONTRACTID, &kNS_SITE_SECURITY_SERVICE_CID }, { NS_CERTBLOCKLIST_CONTRACTID, &kNS_CERT_BLOCKLIST_CID }, { NS_OSKEYSTORE_CONTRACTID, &kNS_OSKEYSTORE_CID}, + { NS_OSREAUTHENTICATOR_CONTRACTID, &kNS_OSREAUTHENTICATOR_CID}, { nullptr } }; diff --git a/security/manager/ssl/tests/unit/test_osreauthenticator.js b/security/manager/ssl/tests/unit/test_osreauthenticator.js new file mode 100644 index 000000000000..c218b1bb7e80 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_osreauthenticator.js @@ -0,0 +1,16 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ +"use strict"; + +// Tests nsIOSReauthenticator.asyncReauthenticateUser(). +// Currently this always resolves to false on all platforms. As this gets implemented on various +// platforms, running this rest will result in a prompt from the OS. Consequently, we won't be able +// to run this in automation, but it will help in testing locally. +add_task(async function test_asyncReauthenticateUser() { + const reauthenticator = Cc["@mozilla.org/security/osreauthenticator;1"] + .getService(Ci.nsIOSReauthenticator); + ok(reauthenticator, "nsIOSReauthenticator should be available"); + ok(!await reauthenticator.asyncReauthenticateUser("this is the prompt string"), + "nsIOSReauthenticator.asyncReauthenticateUser always resolves to false for now"); +}); diff --git a/security/manager/ssl/tests/unit/xpcshell.ini b/security/manager/ssl/tests/unit/xpcshell.ini index db68ea2efbb1..4a0aac73c879 100644 --- a/security/manager/ssl/tests/unit/xpcshell.ini +++ b/security/manager/ssl/tests/unit/xpcshell.ini @@ -141,6 +141,7 @@ run-sequentially = hardcoded ports [test_ocsp_url.js] run-sequentially = hardcoded ports [test_oskeystore.js] +[test_osreauthenticator.js] [test_password_prompt.js] [test_pinning.js] run-sequentially = hardcoded ports