Line data Source code
1 : //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-/
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef nsUrlClassifierDBService_h_
7 : #define nsUrlClassifierDBService_h_
8 :
9 : #include <nsISupportsUtils.h>
10 :
11 : #include "nsID.h"
12 : #include "nsInterfaceHashtable.h"
13 : #include "nsIObserver.h"
14 : #include "nsUrlClassifierPrefixSet.h"
15 : #include "nsIUrlClassifierHashCompleter.h"
16 : #include "nsIUrlListManager.h"
17 : #include "nsIUrlClassifierDBService.h"
18 : #include "nsIUrlClassifierInfo.h"
19 : #include "nsIURIClassifier.h"
20 : #include "nsToolkitCompsCID.h"
21 : #include "nsICryptoHMAC.h"
22 : #include "mozilla/Attributes.h"
23 : #include "mozilla/Mutex.h"
24 : #include "mozilla/TimeStamp.h"
25 :
26 : #include "Entries.h"
27 : #include "LookupCache.h"
28 :
29 : // GCC < 6.1 workaround, see bug 1329593
30 : #if defined(XP_WIN) && defined(__MINGW32__)
31 : #define GCC_MANGLING_WORKAROUND __stdcall
32 : #else
33 : #define GCC_MANGLING_WORKAROUND
34 : #endif
35 :
36 : // The hash length for a domain key.
37 : #define DOMAIN_LENGTH 4
38 :
39 : // The hash length of a partial hash entry.
40 : #define PARTIAL_LENGTH 4
41 :
42 : // The hash length of a complete hash entry.
43 : #define COMPLETE_LENGTH 32
44 :
45 : // Prefs for implementing nsIURIClassifier to block page loads
46 : #define CHECK_MALWARE_PREF "browser.safebrowsing.malware.enabled"
47 : #define CHECK_MALWARE_DEFAULT false
48 :
49 : #define CHECK_PHISHING_PREF "browser.safebrowsing.phishing.enabled"
50 : #define CHECK_PHISHING_DEFAULT false
51 :
52 : #define CHECK_BLOCKED_PREF "browser.safebrowsing.blockedURIs.enabled"
53 : #define CHECK_BLOCKED_DEFAULT false
54 :
55 : // Comma-separated lists
56 : #define MALWARE_TABLE_PREF "urlclassifier.malwareTable"
57 : #define PHISH_TABLE_PREF "urlclassifier.phishTable"
58 : #define TRACKING_TABLE_PREF "urlclassifier.trackingTable"
59 : #define TRACKING_WHITELIST_TABLE_PREF "urlclassifier.trackingWhitelistTable"
60 : #define BLOCKED_TABLE_PREF "urlclassifier.blockedTable"
61 : #define DOWNLOAD_BLOCK_TABLE_PREF "urlclassifier.downloadBlockTable"
62 : #define DOWNLOAD_ALLOW_TABLE_PREF "urlclassifier.downloadAllowTable"
63 : #define DISALLOW_COMPLETION_TABLE_PREF "urlclassifier.disallow_completions"
64 :
65 : using namespace mozilla::safebrowsing;
66 :
67 : class nsUrlClassifierDBServiceWorker;
68 : class nsIThread;
69 : class nsIURI;
70 : class UrlClassifierDBServiceWorkerProxy;
71 : namespace mozilla {
72 : namespace safebrowsing {
73 : class Classifier;
74 : class ProtocolParser;
75 : class TableUpdate;
76 :
77 : nsresult
78 : TablesToResponse(const nsACString& tables);
79 :
80 : } // namespace safebrowsing
81 : } // namespace mozilla
82 :
83 : // This is a proxy class that just creates a background thread and delegates
84 : // calls to the background thread.
85 : class nsUrlClassifierDBService final : public nsIUrlClassifierDBService,
86 : public nsIURIClassifier,
87 : public nsIUrlClassifierInfo,
88 : public nsIObserver
89 : {
90 : public:
91 : // This is thread safe. It throws an exception if the thread is busy.
92 : nsUrlClassifierDBService();
93 :
94 : nsresult Init();
95 :
96 : static nsUrlClassifierDBService* GetInstance(nsresult *result);
97 :
98 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_URLCLASSIFIERDBSERVICE_CID)
99 :
100 : NS_DECL_THREADSAFE_ISUPPORTS
101 : NS_DECL_NSIURLCLASSIFIERDBSERVICE
102 : NS_DECL_NSIURICLASSIFIER
103 : NS_DECL_NSIURLCLASSIFIERINFO
104 : NS_DECL_NSIOBSERVER
105 :
106 : bool CanComplete(const nsACString &tableName);
107 : bool GetCompleter(const nsACString& tableName,
108 : nsIUrlClassifierHashCompleter** completer);
109 : nsresult CacheCompletions(mozilla::safebrowsing::CacheResultArray *results);
110 :
111 : static nsIThread* BackgroundThread();
112 :
113 : static bool ShutdownHasStarted();
114 :
115 : private:
116 :
117 : const nsTArray<nsCString> kObservedPrefs = {
118 : NS_LITERAL_CSTRING(CHECK_MALWARE_PREF),
119 : NS_LITERAL_CSTRING(CHECK_PHISHING_PREF),
120 : NS_LITERAL_CSTRING(CHECK_BLOCKED_PREF),
121 : NS_LITERAL_CSTRING(MALWARE_TABLE_PREF),
122 : NS_LITERAL_CSTRING(PHISH_TABLE_PREF),
123 : NS_LITERAL_CSTRING(TRACKING_TABLE_PREF),
124 : NS_LITERAL_CSTRING(TRACKING_WHITELIST_TABLE_PREF),
125 : NS_LITERAL_CSTRING(BLOCKED_TABLE_PREF),
126 : NS_LITERAL_CSTRING(DOWNLOAD_BLOCK_TABLE_PREF),
127 : NS_LITERAL_CSTRING(DOWNLOAD_ALLOW_TABLE_PREF),
128 : NS_LITERAL_CSTRING(DISALLOW_COMPLETION_TABLE_PREF)
129 12 : };
130 :
131 : // No subclassing
132 : ~nsUrlClassifierDBService();
133 :
134 : // Disallow copy constructor
135 : nsUrlClassifierDBService(nsUrlClassifierDBService&);
136 :
137 : nsresult LookupURI(nsIPrincipal* aPrincipal,
138 : const nsACString& tables,
139 : nsIUrlClassifierCallback* c,
140 : bool forceCheck, bool *didCheck);
141 :
142 : // Close db connection and join the background thread if it exists.
143 : nsresult Shutdown();
144 :
145 : // Check if the key is on a known-clean host.
146 : nsresult CheckClean(const nsACString &lookupKey,
147 : bool *clean);
148 :
149 : nsresult ReadTablesFromPrefs();
150 :
151 : RefPtr<nsUrlClassifierDBServiceWorker> mWorker;
152 : RefPtr<UrlClassifierDBServiceWorkerProxy> mWorkerProxy;
153 :
154 : nsInterfaceHashtable<nsCStringHashKey, nsIUrlClassifierHashCompleter> mCompleters;
155 :
156 : // TRUE if the nsURIClassifier implementation should check for malware
157 : // uris on document loads.
158 : bool mCheckMalware;
159 :
160 : // TRUE if the nsURIClassifier implementation should check for phishing
161 : // uris on document loads.
162 : bool mCheckPhishing;
163 :
164 : // TRUE if the nsURIClassifier implementation should check for blocked
165 : // uris on document loads.
166 : bool mCheckBlockedURIs;
167 :
168 : // TRUE if a BeginUpdate() has been called without an accompanying
169 : // CancelUpdate()/FinishUpdate(). This is used to prevent competing
170 : // updates, not to determine whether an update is still being
171 : // processed.
172 : bool mInUpdate;
173 :
174 : // The list of tables that can use the default hash completer object.
175 : nsTArray<nsCString> mGethashTables;
176 :
177 : // The list of tables that should never be hash completed.
178 : nsTArray<nsCString> mDisallowCompletionsTables;
179 :
180 : // Comma-separated list of tables to use in lookups.
181 : nsCString mTrackingProtectionTables;
182 : nsCString mBaseTables;
183 :
184 : // Thread that we do the updates on.
185 : static nsIThread* gDbBackgroundThread;
186 : };
187 :
188 : class nsUrlClassifierDBServiceWorker final : public nsIUrlClassifierDBService
189 : {
190 : public:
191 : nsUrlClassifierDBServiceWorker();
192 :
193 : NS_DECL_THREADSAFE_ISUPPORTS
194 : NS_DECL_NSIURLCLASSIFIERDBSERVICE
195 :
196 : nsresult Init(uint32_t aGethashNoise,
197 : nsCOMPtr<nsIFile> aCacheDir,
198 : nsUrlClassifierDBService* aDBService);
199 :
200 : // Queue a lookup for the worker to perform, called in the main thread.
201 : // tables is a comma-separated list of tables to query
202 : nsresult QueueLookup(const nsACString& lookupKey,
203 : const nsACString& tables,
204 : nsIUrlClassifierLookupCallback* callback);
205 :
206 : // Handle any queued-up lookups. We call this function during long-running
207 : // update operations to prevent lookups from blocking for too long.
208 : nsresult HandlePendingLookups();
209 :
210 : // Perform a blocking classifier lookup for a given url. Can be called on
211 : // either the main thread or the worker thread.
212 : nsresult DoLocalLookup(const nsACString& spec,
213 : const nsACString& tables,
214 : LookupResultArray* results);
215 :
216 : // Open the DB connection
217 : nsresult GCC_MANGLING_WORKAROUND OpenDb();
218 :
219 : // Provide a way to forcibly close the db connection.
220 : nsresult GCC_MANGLING_WORKAROUND CloseDb();
221 :
222 : nsresult CacheCompletions(CacheResultArray * aEntries);
223 :
224 : // Used to probe the state of the worker thread. When the update begins,
225 : // mUpdateObserver will be set. When the update finished, mUpdateObserver
226 : // will be nulled out in NotifyUpdateObserver.
227 2 : bool IsBusyUpdating() const { return !!mUpdateObserver; }
228 :
229 : // Delegate Classifier to disable async update. If there is an
230 : // ongoing update on the update thread, we will be blocked until
231 : // the background update is done and callback is fired.
232 : // Should be called on the worker thread.
233 : void FlushAndDisableAsyncUpdate();
234 :
235 : // A synchronous call to get cache information for the given table.
236 : // This is only used by about:url-classifier now.
237 : nsresult GetCacheInfo(const nsACString& aTable,
238 : nsIUrlClassifierCacheInfo** aCache);
239 : private:
240 : // No subclassing
241 : ~nsUrlClassifierDBServiceWorker();
242 :
243 : // Disallow copy constructor
244 : nsUrlClassifierDBServiceWorker(nsUrlClassifierDBServiceWorker&);
245 :
246 : nsresult NotifyUpdateObserver(nsresult aUpdateStatus);
247 :
248 : // Reset the in-progress update stream
249 : void ResetStream();
250 :
251 : // Reset the in-progress update
252 : void ResetUpdate();
253 :
254 : // Perform a classifier lookup for a given url.
255 : nsresult DoLookup(const nsACString& spec,
256 : const nsACString& tables,
257 : nsIUrlClassifierLookupCallback* c);
258 :
259 : nsresult AddNoise(const Prefix aPrefix,
260 : const nsCString tableName,
261 : uint32_t aCount,
262 : LookupResultArray& results);
263 :
264 : nsresult CacheResultToTableUpdate(CacheResult* aCacheResult,
265 : TableUpdate* aUpdate);
266 :
267 : bool IsSameAsLastResults(CacheResultArray& aResult);
268 :
269 : // Can only be used on the background thread
270 : nsCOMPtr<nsICryptoHash> mCryptoHash;
271 :
272 : nsAutoPtr<mozilla::safebrowsing::Classifier> mClassifier;
273 : // The class that actually parses the update chunks.
274 : nsAutoPtr<ProtocolParser> mProtocolParser;
275 :
276 : // Directory where to store the SB databases.
277 : nsCOMPtr<nsIFile> mCacheDir;
278 :
279 : RefPtr<nsUrlClassifierDBService> mDBService;
280 :
281 : // XXX: maybe an array of autoptrs. Or maybe a class specifically
282 : // storing a series of updates.
283 : nsTArray<mozilla::safebrowsing::TableUpdate*> mTableUpdates;
284 :
285 : uint32_t mUpdateWaitSec;
286 :
287 : // Stores the last results that triggered a table update.
288 : nsAutoPtr<CacheResultArray> mLastResults;
289 :
290 : nsresult mUpdateStatus;
291 : nsTArray<nsCString> mUpdateTables;
292 :
293 : nsCOMPtr<nsIUrlClassifierUpdateObserver> mUpdateObserver;
294 : bool mInStream;
295 :
296 : // The number of noise entries to add to the set of lookup results.
297 : uint32_t mGethashNoise;
298 :
299 : // Pending lookups are stored in a queue for processing. The queue
300 : // is protected by mPendingLookupLock.
301 : mozilla::Mutex mPendingLookupLock;
302 :
303 0 : class PendingLookup {
304 : public:
305 : mozilla::TimeStamp mStartTime;
306 : nsCString mKey;
307 : nsCString mTables;
308 : nsCOMPtr<nsIUrlClassifierLookupCallback> mCallback;
309 : };
310 :
311 : // list of pending lookups
312 : nsTArray<PendingLookup> mPendingLookups;
313 :
314 : #ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
315 : // The raw update response for debugging.
316 : nsCString mRawTableUpdates;
317 : #endif
318 : };
319 :
320 : NS_DEFINE_STATIC_IID_ACCESSOR(nsUrlClassifierDBService, NS_URLCLASSIFIERDBSERVICE_CID)
321 :
322 : #endif // nsUrlClassifierDBService_h_
|