UrlClassifierFeatureCryptominingProtection.cpp (7488B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "UrlClassifierFeatureCryptominingProtection.h" 8 9 #include "mozilla/AntiTrackingUtils.h" 10 #include "mozilla/net/UrlClassifierCommon.h" 11 #include "ChannelClassifierService.h" 12 #include "mozilla/StaticPrefs_privacy.h" 13 #include "nsNetUtil.h" 14 #include "mozilla/StaticPtr.h" 15 #include "nsIWebProgressListener.h" 16 #include "nsIHttpChannelInternal.h" 17 #include "nsIChannel.h" 18 19 namespace mozilla { 20 namespace net { 21 22 namespace { 23 24 #define CRYPTOMINING_FEATURE_NAME "cryptomining-protection" 25 26 #define URLCLASSIFIER_CRYPTOMINING_BLOCKLIST \ 27 "urlclassifier.features.cryptomining.blacklistTables" 28 #define URLCLASSIFIER_CRYPTOMINING_BLOCKLIST_TEST_ENTRIES \ 29 "urlclassifier.features.cryptomining.blacklistHosts" 30 #define URLCLASSIFIER_CRYPTOMINING_ENTITYLIST \ 31 "urlclassifier.features.cryptomining.whitelistTables" 32 #define URLCLASSIFIER_CRYPTOMINING_ENTITYLIST_TEST_ENTRIES \ 33 "urlclassifier.features.cryptomining.whitelistHosts" 34 #define URLCLASSIFIER_CRYPTOMINING_EXCEPTION_URLS \ 35 "urlclassifier.features.cryptomining.skipURLs" 36 #define TABLE_CRYPTOMINING_BLOCKLIST_PREF "cryptomining-blacklist-pref" 37 #define TABLE_CRYPTOMINING_ENTITYLIST_PREF "cryptomining-whitelist-pref" 38 39 StaticRefPtr<UrlClassifierFeatureCryptominingProtection> 40 gFeatureCryptominingProtection; 41 42 } // namespace 43 44 UrlClassifierFeatureCryptominingProtection:: 45 UrlClassifierFeatureCryptominingProtection() 46 : UrlClassifierFeatureAntiTrackingBase( 47 nsLiteralCString(CRYPTOMINING_FEATURE_NAME), 48 nsLiteralCString(URLCLASSIFIER_CRYPTOMINING_BLOCKLIST), 49 nsLiteralCString(URLCLASSIFIER_CRYPTOMINING_ENTITYLIST), 50 nsLiteralCString(URLCLASSIFIER_CRYPTOMINING_BLOCKLIST_TEST_ENTRIES), 51 nsLiteralCString(URLCLASSIFIER_CRYPTOMINING_ENTITYLIST_TEST_ENTRIES), 52 nsLiteralCString(TABLE_CRYPTOMINING_BLOCKLIST_PREF), 53 nsLiteralCString(TABLE_CRYPTOMINING_ENTITYLIST_PREF), 54 nsLiteralCString(URLCLASSIFIER_CRYPTOMINING_EXCEPTION_URLS)) {} 55 56 /* static */ const char* UrlClassifierFeatureCryptominingProtection::Name() { 57 return CRYPTOMINING_FEATURE_NAME; 58 } 59 60 /* static */ 61 void UrlClassifierFeatureCryptominingProtection::MaybeInitialize() { 62 UC_LOG_LEAK(("UrlClassifierFeatureCryptominingProtection::MaybeInitialize")); 63 64 if (!gFeatureCryptominingProtection) { 65 gFeatureCryptominingProtection = 66 new UrlClassifierFeatureCryptominingProtection(); 67 gFeatureCryptominingProtection->InitializePreferences(); 68 } 69 } 70 71 /* static */ 72 void UrlClassifierFeatureCryptominingProtection::MaybeShutdown() { 73 UC_LOG_LEAK(("UrlClassifierFeatureCryptominingProtection::MaybeShutdown")); 74 75 if (gFeatureCryptominingProtection) { 76 gFeatureCryptominingProtection->ShutdownPreferences(); 77 gFeatureCryptominingProtection = nullptr; 78 } 79 } 80 81 /* static */ 82 already_AddRefed<UrlClassifierFeatureCryptominingProtection> 83 UrlClassifierFeatureCryptominingProtection::MaybeCreate(nsIChannel* aChannel) { 84 MOZ_ASSERT(aChannel); 85 86 UC_LOG_LEAK( 87 ("UrlClassifierFeatureCryptominingProtection::MaybeCreate - channel %p", 88 aChannel)); 89 90 if (!StaticPrefs::privacy_trackingprotection_cryptomining_enabled()) { 91 return nullptr; 92 } 93 RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); 94 bool isThirdParty = loadInfo->GetIsThirdPartyContextToTopWindow(); 95 if (!isThirdParty) { 96 UC_LOG( 97 ("UrlClassifierFeatureCryptominingProtection::MaybeCreate - " 98 "skipping first party or top-level load for channel %p", 99 aChannel)); 100 return nullptr; 101 } 102 103 if (!UrlClassifierCommon::ShouldEnableProtectionForChannel(aChannel)) { 104 return nullptr; 105 } 106 107 MaybeInitialize(); 108 MOZ_ASSERT(gFeatureCryptominingProtection); 109 110 RefPtr<UrlClassifierFeatureCryptominingProtection> self = 111 gFeatureCryptominingProtection; 112 return self.forget(); 113 } 114 115 /* static */ 116 already_AddRefed<nsIUrlClassifierFeature> 117 UrlClassifierFeatureCryptominingProtection::GetIfNameMatches( 118 const nsACString& aName) { 119 if (!aName.EqualsLiteral(CRYPTOMINING_FEATURE_NAME)) { 120 return nullptr; 121 } 122 123 MaybeInitialize(); 124 MOZ_ASSERT(gFeatureCryptominingProtection); 125 126 RefPtr<UrlClassifierFeatureCryptominingProtection> self = 127 gFeatureCryptominingProtection; 128 return self.forget(); 129 } 130 131 NS_IMETHODIMP 132 UrlClassifierFeatureCryptominingProtection::ProcessChannel( 133 nsIChannel* aChannel, const nsTArray<nsCString>& aList, 134 const nsTArray<nsCString>& aHashes, bool* aShouldContinue) { 135 NS_ENSURE_ARG_POINTER(aChannel); 136 NS_ENSURE_ARG_POINTER(aShouldContinue); 137 138 bool isAllowListed = UrlClassifierCommon::IsAllowListed(aChannel); 139 140 // This is a blocking feature. 141 *aShouldContinue = isAllowListed; 142 143 if (isAllowListed) { 144 return NS_OK; 145 } 146 147 bool ShouldProcessByProtectionFeature = 148 UrlClassifierCommon::ShouldProcessWithProtectionFeature(aChannel); 149 150 *aShouldContinue = !ShouldProcessByProtectionFeature; 151 152 if (!ShouldProcessByProtectionFeature) { 153 return NS_OK; 154 } 155 156 nsAutoCString list; 157 UrlClassifierCommon::TablesToString(aList, list); 158 159 ChannelBlockDecision decision = 160 ChannelClassifierService::OnBeforeBlockChannel(aChannel, mName, list); 161 if (decision != ChannelBlockDecision::Blocked) { 162 uint32_t event = 163 decision == ChannelBlockDecision::Replaced 164 ? nsIWebProgressListener::STATE_REPLACED_TRACKING_CONTENT 165 : nsIWebProgressListener::STATE_ALLOWED_TRACKING_CONTENT; 166 167 // Need to set aBlocked to True if we replace the Cryptominer with a shim, 168 // since the shim is treated as a blocked event 169 // Note: If we need to account for which kind of tracker was replaced, 170 // we need to create a new event type in nsIWebProgressListener 171 if (event == nsIWebProgressListener::STATE_REPLACED_TRACKING_CONTENT) { 172 ContentBlockingNotifier::OnEvent(aChannel, event, true); 173 } else { 174 ContentBlockingNotifier::OnEvent(aChannel, event, false); 175 } 176 177 *aShouldContinue = true; 178 return NS_OK; 179 } 180 181 UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_CRYPTOMINING_URI, 182 list, ""_ns, ""_ns); 183 184 UC_LOG( 185 ("UrlClassifierFeatureCryptominingProtection::ProcessChannel - " 186 "cancelling channel %p", 187 aChannel)); 188 189 nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(aChannel); 190 191 if (httpChannel) { 192 (void)httpChannel->CancelByURLClassifier(NS_ERROR_CRYPTOMINING_URI); 193 } else { 194 (void)aChannel->Cancel(NS_ERROR_CRYPTOMINING_URI); 195 } 196 197 return NS_OK; 198 } 199 200 NS_IMETHODIMP 201 UrlClassifierFeatureCryptominingProtection::GetURIByListType( 202 nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType, 203 nsIUrlClassifierFeature::URIType* aURIType, nsIURI** aURI) { 204 NS_ENSURE_ARG_POINTER(aChannel); 205 NS_ENSURE_ARG_POINTER(aURIType); 206 NS_ENSURE_ARG_POINTER(aURI); 207 208 if (aListType == nsIUrlClassifierFeature::blocklist) { 209 *aURIType = nsIUrlClassifierFeature::blocklistURI; 210 return aChannel->GetURI(aURI); 211 } 212 213 MOZ_ASSERT(aListType == nsIUrlClassifierFeature::entitylist); 214 215 *aURIType = nsIUrlClassifierFeature::pairwiseEntitylistURI; 216 return UrlClassifierCommon::CreatePairwiseEntityListURI(aChannel, aURI); 217 } 218 219 } // namespace net 220 } // namespace mozilla