From b6a922c797336a56e19fec38208bf60366905c69 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Sat, 15 Dec 2018 09:54:02 +0100 Subject: [PATCH] Bug 1514133 - Port Login-Reputation classification to nsIUrlClassifierFeature, r=dimi --- modules/libpref/init/StaticPrefList.h | 7 ++ modules/libpref/init/all.js | 3 - .../UrlClassifierFeatureFactory.cpp | 8 ++ .../UrlClassifierFeatureFactory.h | 2 + .../UrlClassifierFeatureLoginReputation.cpp | 97 +++++++++++++++++++ .../UrlClassifierFeatureLoginReputation.h | 47 +++++++++ netwerk/url-classifier/moz.build | 1 + .../reputationservice/LoginReputation.cpp | 95 +++++++----------- .../reputationservice/LoginReputation.h | 7 +- .../nsCheckSummedOutputStream.h | 1 + 10 files changed, 200 insertions(+), 68 deletions(-) create mode 100644 netwerk/url-classifier/UrlClassifierFeatureLoginReputation.cpp create mode 100644 netwerk/url-classifier/UrlClassifierFeatureLoginReputation.h diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h index 1f8b3df90dde..c9fddd88e7ed 100644 --- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -1812,6 +1812,13 @@ VARCACHE_PREF( RelaxedAtomicBool, false ) +// Password protection +VARCACHE_PREF( + "browser.safebrowsing.passwords.enabled", + browser_safebrowsing_passwords_enabled, + bool, false +) + //--------------------------------------------------------------------------- // ChannelClassifier prefs //--------------------------------------------------------------------------- diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ffa8c3df1cff..27bc655ae9ff 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5599,9 +5599,6 @@ pref("browser.safebrowsing.downloads.remote.block_dangerous_host", true); pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", true); pref("browser.safebrowsing.downloads.remote.block_uncommon", true); -// Password protection -pref("browser.safebrowsing.passwords.enabled", false); - // Google Safe Browsing provider (legacy) pref("browser.safebrowsing.provider.google.pver", "2.2"); pref("browser.safebrowsing.provider.google.lists", "goog-badbinurl-shavar,goog-downloadwhite-digest256,goog-phish-shavar,googpub-phish-shavar,goog-malware-shavar,goog-unwanted-shavar"); diff --git a/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp b/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp index edba62919fad..780a2321e8a1 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp @@ -7,6 +7,7 @@ #include "mozilla/net/UrlClassifierFeatureFactory.h" // List of Features +#include "UrlClassifierFeatureLoginReputation.h" #include "UrlClassifierFeatureTrackingProtection.h" #include "UrlClassifierFeatureTrackingAnnotation.h" @@ -31,6 +32,7 @@ namespace net { return; } + UrlClassifierFeatureLoginReputation::MaybeShutdown(); UrlClassifierFeatureTrackingAnnotation::Shutdown(); UrlClassifierFeatureTrackingProtection::Shutdown(); } @@ -61,5 +63,11 @@ namespace net { } } +/* static */ +nsIUrlClassifierFeature* +UrlClassifierFeatureFactory::GetFeatureLoginReputation() { + return UrlClassifierFeatureLoginReputation::MaybeGetOrCreate(); +} + } // namespace net } // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureFactory.h b/netwerk/url-classifier/UrlClassifierFeatureFactory.h index 59c95373fd11..23531e2d3c13 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureFactory.h +++ b/netwerk/url-classifier/UrlClassifierFeatureFactory.h @@ -25,6 +25,8 @@ class UrlClassifierFeatureFactory final { static void GetFeaturesFromChannel( nsIChannel* aChannel, nsTArray>& aFeatures); + + static nsIUrlClassifierFeature* GetFeatureLoginReputation(); }; } // namespace net diff --git a/netwerk/url-classifier/UrlClassifierFeatureLoginReputation.cpp b/netwerk/url-classifier/UrlClassifierFeatureLoginReputation.cpp new file mode 100644 index 000000000000..bcb0df8faeba --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureLoginReputation.cpp @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "UrlClassifierFeatureLoginReputation.h" + +#include "mozilla/StaticPrefs.h" + +namespace mozilla { +namespace net { + +namespace { + +#define PREF_PASSWORD_ALLOW_TABLE "urlclassifier.passwordAllowTable" + +StaticRefPtr gFeatureLoginReputation; + +} // namespace + +UrlClassifierFeatureLoginReputation::UrlClassifierFeatureLoginReputation() + : UrlClassifierFeatureBase(NS_LITERAL_CSTRING("login-reputation"), + EmptyCString(), // blacklist tables + NS_LITERAL_CSTRING(PREF_PASSWORD_ALLOW_TABLE), + EmptyCString(), // blacklist pref + EmptyCString(), // whitelist pref + EmptyCString(), // blacklist pref table name + EmptyCString(), // whitelist pref table name + EmptyCString()) // skip host pref +{} + +/* static */ void UrlClassifierFeatureLoginReputation::MaybeShutdown() { + UC_LOG(("UrlClassifierFeatureLoginReputation: MaybeShutdown")); + + if (gFeatureLoginReputation) { + gFeatureLoginReputation->ShutdownPreferences(); + gFeatureLoginReputation = nullptr; + } +} + +/* static */ nsIUrlClassifierFeature* +UrlClassifierFeatureLoginReputation::MaybeGetOrCreate() { + if (!StaticPrefs::browser_safebrowsing_passwords_enabled()) { + return nullptr; + } + + if (!gFeatureLoginReputation) { + gFeatureLoginReputation = new UrlClassifierFeatureLoginReputation(); + gFeatureLoginReputation->InitializePreferences(); + } + + return gFeatureLoginReputation; +} + +NS_IMETHODIMP +UrlClassifierFeatureLoginReputation::ProcessChannel(nsIChannel* aChannel, + const nsACString& aList, + bool* aShouldContinue) { + MOZ_CRASH( + "UrlClassifierFeatureLoginReputation::ProcessChannel should never be " + "called"); + return NS_OK; +} + +NS_IMETHODIMP +UrlClassifierFeatureLoginReputation::GetTables( + nsIUrlClassifierFeature::listType aListType, nsTArray& aTables) { + MOZ_ASSERT(aListType == nsIUrlClassifierFeature::whitelist, + "UrlClassifierFeatureLoginReputation is meant to be used just to " + "whitelist URLs"); + return UrlClassifierFeatureBase::GetTables(aListType, aTables); +} + +NS_IMETHODIMP +UrlClassifierFeatureLoginReputation::HasTable( + const nsACString& aTable, nsIUrlClassifierFeature::listType aListType, + bool* aResult) { + MOZ_ASSERT(aListType == nsIUrlClassifierFeature::whitelist, + "UrlClassifierFeatureLoginReputation is meant to be used just to " + "whitelist URLs"); + return UrlClassifierFeatureBase::HasTable(aTable, aListType, aResult); +} + +NS_IMETHODIMP +UrlClassifierFeatureLoginReputation::HasHostInPreferences( + const nsACString& aHost, nsIUrlClassifierFeature::listType aListType, + nsACString& aPrefTableName, bool* aResult) { + MOZ_ASSERT(aListType == nsIUrlClassifierFeature::whitelist, + "UrlClassifierFeatureLoginReputation is meant to be used just to " + "whitelist URLs"); + return UrlClassifierFeatureBase::HasHostInPreferences( + aHost, aListType, aPrefTableName, aResult); +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureLoginReputation.h b/netwerk/url-classifier/UrlClassifierFeatureLoginReputation.h new file mode 100644 index 000000000000..d7e6197af80c --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureLoginReputation.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 mozilla_net_UrlClassifierFeatureLoginReputation_h +#define mozilla_net_UrlClassifierFeatureLoginReputation_h + +#include "UrlClassifierFeatureBase.h" + +class nsIChannel; + +namespace mozilla { +namespace net { + +class UrlClassifierFeatureLoginReputation final + : public UrlClassifierFeatureBase { + public: + static void MaybeShutdown(); + + static nsIUrlClassifierFeature* MaybeGetOrCreate(); + + NS_IMETHOD + GetTables(nsIUrlClassifierFeature::listType aListType, + nsTArray& aResult) override; + + NS_IMETHOD + HasTable(const nsACString& aTable, + nsIUrlClassifierFeature::listType aListType, bool* aResult) override; + + NS_IMETHOD + HasHostInPreferences(const nsACString& aHost, + nsIUrlClassifierFeature::listType aListType, + nsACString& aPrefTableName, bool* aResult) override; + + NS_IMETHOD ProcessChannel(nsIChannel* aChannel, const nsACString& aList, + bool* aShouldContinue) override; + + private: + UrlClassifierFeatureLoginReputation(); +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_UrlClassifierFeatureLoginReputation_h diff --git a/netwerk/url-classifier/moz.build b/netwerk/url-classifier/moz.build index 1e59e8d67120..e3eeb562307c 100644 --- a/netwerk/url-classifier/moz.build +++ b/netwerk/url-classifier/moz.build @@ -23,6 +23,7 @@ UNIFIED_SOURCES += [ 'UrlClassifierCommon.cpp', 'UrlClassifierFeatureBase.cpp', 'UrlClassifierFeatureFactory.cpp', + 'UrlClassifierFeatureLoginReputation.cpp', 'UrlClassifierFeatureResult.cpp', 'UrlClassifierFeatureTrackingAnnotation.cpp', 'UrlClassifierFeatureTrackingProtection.cpp', diff --git a/toolkit/components/reputationservice/LoginReputation.cpp b/toolkit/components/reputationservice/LoginReputation.cpp index 6c7eb1a348dc..1056fa0aa676 100644 --- a/toolkit/components/reputationservice/LoginReputation.cpp +++ b/toolkit/components/reputationservice/LoginReputation.cpp @@ -7,19 +7,19 @@ #include "nsThreadUtils.h" #include "mozilla/ErrorNames.h" #include "mozilla/Logging.h" +#include "mozilla/net/UrlClassifierFeatureFactory.h" #include "mozilla/Preferences.h" +#include "mozilla/StaticPrefs.h" #include "mozilla/Telemetry.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/HTMLInputElement.h" #include "mozilla/ipc/URIUtils.h" +#include "nsIUrlClassifierFeature.h" using namespace mozilla; using namespace mozilla::dom; #define PREF_PP_ENABLED "browser.safebrowsing.passwords.enabled" -#define PREF_PASSWORD_ALLOW_TABLE "urlclassifier.passwordAllowTable" - -static bool sPasswordProtectionEnabled = false; // MOZ_LOG=LoginReputation:5 LazyLogModule gLoginReputationLogModule("LoginReputation"); @@ -30,11 +30,6 @@ LazyLogModule gLoginReputationLogModule("LoginReputation"); static Atomic gShuttingDown(false); -static const char* kObservedPrefs[] = { - PREF_PASSWORD_ALLOW_TABLE, - nullptr, -}; - // ------------------------------------------------------------------------- // ReputationQueryParam // @@ -67,39 +62,29 @@ ReputationQueryParam::GetFormURI(nsIURI** aURI) { // This class is a wrapper that encapsulate asynchronous callback API provided // by DBService into a MozPromise callback. // -class LoginWhitelist final : public nsIURIClassifierCallback { +class LoginWhitelist final : public nsIUrlClassifierFeatureCallback { public: NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIURICLASSIFIERCALLBACK + NS_DECL_NSIURLCLASSIFIERFEATURECALLBACK RefPtr QueryLoginWhitelist( nsILoginReputationQuery* aParam); LoginWhitelist() = default; - nsresult Init(); - nsresult Uninit(); - - void UpdateWhitelistTables(); + nsresult Shutdown(); private: ~LoginWhitelist() = default; - nsCString mTables; - - // Queries that are waiting for callback from ::AsyncClassifyLocalWithTables. + // Queries that are waiting for callback from + // ::AsyncClassifyLocalWithFeatures. nsTArray>> mQueryPromises; }; -NS_IMPL_ISUPPORTS(LoginWhitelist, nsIURIClassifierCallback) +NS_IMPL_ISUPPORTS(LoginWhitelist, nsIUrlClassifierFeatureCallback) -nsresult LoginWhitelist::Init() { - UpdateWhitelistTables(); - - return NS_OK; -} - -nsresult LoginWhitelist::Uninit() { +nsresult LoginWhitelist::Shutdown() { // Reject all query promise before releasing. for (uint8_t i = 0; i < mQueryPromises.Length(); i++) { mQueryPromises[i]->Reject(NS_ERROR_ABORT, __func__); @@ -136,8 +121,18 @@ RefPtr LoginWhitelist::QueryLoginWhitelist( // AsyncClassifyLocalWithTables API won't trigger a gethash request on // a full-length match, so this API call should only include local operation. // We don't support prefs overwrite for this classification. - rv = uriClassifier->AsyncClassifyLocalWithTables( - uri, mTables, nsTArray(), nsTArray(), this); + + nsCOMPtr feature = + mozilla::net::UrlClassifierFeatureFactory::GetFeatureLoginReputation(); + if (NS_WARN_IF(!feature)) { + return p; + } + + nsTArray> features; + features.AppendElement(feature); + + rv = uriClassifier->AsyncClassifyLocalWithFeatures( + uri, features, nsIUrlClassifierFeature::whitelist, this); if (NS_FAILED(rv)) { return p; } @@ -147,27 +142,22 @@ RefPtr LoginWhitelist::QueryLoginWhitelist( return p; } -nsresult LoginWhitelist::OnClassifyComplete(nsresult aErrorCode, - const nsACString& aLists, - const nsACString& aProvider, - const nsACString& aFullHash) { +nsresult LoginWhitelist::OnClassifyComplete( + const nsTArray>& aResults) { MOZ_ASSERT(NS_IsMainThread()); if (gShuttingDown) { return NS_OK; } - LR_LOG(("OnClassifyComplete : list = %s", aLists.BeginReading())); + LR_LOG(("OnClassifyComplete : %s", + aResults.IsEmpty() ? "blacklisted" : "whitelisted")); UniquePtr> holder = std::move(mQueryPromises.ElementAt(0)); mQueryPromises.RemoveElementAt(0); - if (NS_FAILED(aErrorCode)) { - // This should not happen - MOZ_ASSERT_UNREACHABLE("unexpected error received in OnClassifyComplete"); - holder->Reject(aErrorCode, __func__); - } else if (aLists.IsEmpty()) { + if (aResults.IsEmpty()) { // Reject if we can not find url in white list. holder->Reject(NS_OK, __func__); } else { @@ -177,10 +167,6 @@ nsresult LoginWhitelist::OnClassifyComplete(nsresult aErrorCode, return NS_OK; } -void LoginWhitelist::UpdateWhitelistTables() { - Preferences::GetCString(PREF_PASSWORD_ALLOW_TABLE, mTables); -} - // ------------------------------------------------------------------------- // LoginReputationService // @@ -215,9 +201,6 @@ NS_IMETHODIMP LoginReputationService::Init() { MOZ_ASSERT(NS_IsMainThread()); - Preferences::AddBoolVarCache(&sPasswordProtectionEnabled, PREF_PP_ENABLED, - true); - switch (XRE_GetProcessType()) { case GeckoProcessType_Default: LR_LOG(("Init login reputation service in parent")); @@ -240,7 +223,7 @@ LoginReputationService::Init() { mLoginWhitelist = new LoginWhitelist(); - if (sPasswordProtectionEnabled) { + if (StaticPrefs::browser_safebrowsing_passwords_enabled()) { Enable(); } @@ -249,15 +232,10 @@ LoginReputationService::Init() { nsresult LoginReputationService::Enable() { MOZ_ASSERT(XRE_IsParentProcess()); - MOZ_ASSERT(sPasswordProtectionEnabled); + MOZ_ASSERT(StaticPrefs::browser_safebrowsing_passwords_enabled()); LR_LOG(("Enable login reputation service")); - nsresult rv = mLoginWhitelist->Init(); - Unused << NS_WARN_IF(NS_FAILED(rv)); - - Preferences::AddStrongObservers(this, kObservedPrefs); - return NS_OK; } @@ -266,16 +244,11 @@ nsresult LoginReputationService::Disable() { LR_LOG(("Disable login reputation service")); - nsresult rv = mLoginWhitelist->Uninit(); + nsresult rv = mLoginWhitelist->Shutdown(); Unused << NS_WARN_IF(NS_FAILED(rv)); mQueryRequests.Clear(); - nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); - if (prefs) { - Preferences::RemoveObservers(this, kObservedPrefs); - } - return NS_OK; } @@ -308,7 +281,7 @@ LoginReputationService::QueryReputationAsync( LR_LOG(("QueryReputationAsync() [this=%p]", this)); - if (!sPasswordProtectionEnabled) { + if (!StaticPrefs::browser_safebrowsing_passwords_enabled()) { return NS_ERROR_FAILURE; } @@ -351,7 +324,7 @@ LoginReputationService::QueryReputation( LR_LOG(("QueryReputation() [this=%p]", this)); - if (gShuttingDown || !sPasswordProtectionEnabled) { + if (gShuttingDown || !StaticPrefs::browser_safebrowsing_passwords_enabled()) { LR_LOG(("QueryReputation() abort [this=%p]", this)); aCallback->OnComplete(NS_ERROR_ABORT, nsILoginReputationVerdictType::UNSPECIFIED); @@ -479,10 +452,8 @@ LoginReputationService::Observe(nsISupports* aSubject, const char* aTopic, nsDependentString data(aData); if (data.EqualsLiteral(PREF_PP_ENABLED)) { - nsresult rv = sPasswordProtectionEnabled ? Enable() : Disable(); + nsresult rv = StaticPrefs::browser_safebrowsing_passwords_enabled() ? Enable() : Disable(); Unused << NS_WARN_IF(NS_FAILED(rv)); - } else if (data.EqualsLiteral(PREF_PASSWORD_ALLOW_TABLE)) { - mLoginWhitelist->UpdateWhitelistTables(); } } else if (!strcmp(aTopic, "quit-application")) { // Prepare to shutdown, won't allow any query request after 'gShuttingDown' diff --git a/toolkit/components/reputationservice/LoginReputation.h b/toolkit/components/reputationservice/LoginReputation.h index 3a17c69b2de9..4759cbdcaf23 100644 --- a/toolkit/components/reputationservice/LoginReputation.h +++ b/toolkit/components/reputationservice/LoginReputation.h @@ -6,11 +6,12 @@ #ifndef LoginReputation_h__ #define LoginReputation_h__ -#include "nsILoginReputation.h" -#include "nsIURIClassifier.h" -#include "nsIObserver.h" #include "mozilla/Logging.h" #include "mozilla/MozPromise.h" +#include "nsILoginReputation.h" +#include "nsIObserver.h" +#include "nsISupportsImpl.h" +#include "nsIURIClassifier.h" class LoginWhitelist; diff --git a/toolkit/components/url-classifier/nsCheckSummedOutputStream.h b/toolkit/components/url-classifier/nsCheckSummedOutputStream.h index f888648f7b8d..fcf3ca3f39e2 100644 --- a/toolkit/components/url-classifier/nsCheckSummedOutputStream.h +++ b/toolkit/components/url-classifier/nsCheckSummedOutputStream.h @@ -10,6 +10,7 @@ #include "nsIOutputStream.h" #include "nsICryptoHash.h" #include "nsNetCID.h" +#include "nsNetUtil.h" #include "nsString.h" #include "nsToolkitCompsCID.h" #include "../../../netwerk/base/nsBufferedStreams.h"