1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // The Safe Browsing service is responsible for downloading anti-phishing and 6 // anti-malware tables and checking urls against them. 7 8 #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ 9 #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ 10 #pragma once 11 12 #include <deque> 13 #include <set> 14 #include <string> 15 #include <vector> 16 17 #include "base/hash_tables.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/memory/scoped_ptr.h" 20 #include "base/synchronization/lock.h" 21 #include "base/task.h" 22 #include "base/time.h" 23 #include "chrome/browser/safe_browsing/safe_browsing_util.h" 24 #include "googleurl/src/gurl.h" 25 #include "webkit/glue/resource_type.h" 26 27 class MalwareDetails; 28 class PrefService; 29 class SafeBrowsingDatabase; 30 class SafeBrowsingProtocolManager; 31 class SafeBrowsingServiceFactory; 32 33 namespace base { 34 class Thread; 35 } 36 37 namespace net { 38 class URLRequestContextGetter; 39 } 40 41 // Construction needs to happen on the main thread. 42 class SafeBrowsingService 43 : public base::RefCountedThreadSafe<SafeBrowsingService> { 44 public: 45 class Client; 46 // Users of this service implement this interface to be notified 47 // asynchronously of the result. 48 enum UrlCheckResult { 49 SAFE, 50 URL_PHISHING, 51 URL_MALWARE, 52 BINARY_MALWARE_URL, // Binary url leads to a malware. 53 BINARY_MALWARE_HASH, // Binary hash indicates this is a malware. 54 }; 55 56 // Structure used to pass parameters between the IO and UI thread when 57 // interacting with the blocking page. 58 struct UnsafeResource { 59 UnsafeResource(); 60 ~UnsafeResource(); 61 62 GURL url; 63 GURL original_url; 64 std::vector<GURL> redirect_urls; 65 ResourceType::Type resource_type; 66 UrlCheckResult threat_type; 67 Client* client; 68 int render_process_host_id; 69 int render_view_id; 70 }; 71 72 // Bundle of SafeBrowsing state for one URL or hash prefix check. 73 struct SafeBrowsingCheck { 74 SafeBrowsingCheck(); 75 ~SafeBrowsingCheck(); 76 77 // Either |urls| or |prefix| is used to lookup database. 78 std::vector<GURL> urls; 79 scoped_ptr<SBFullHash> full_hash; 80 81 Client* client; 82 bool need_get_hash; 83 base::TimeTicks start; // When check was sent to SB service. 84 UrlCheckResult result; 85 bool is_download; // If this check for download url or hash. 86 std::vector<SBPrefix> prefix_hits; 87 std::vector<SBFullHashResult> full_hits; 88 89 // Task to make the callback to safebrowsing clients in case 90 // safebrowsing check takes too long to finish. Not owned by 91 // this class. 92 // TODO(lzheng): We should consider to use this time out check 93 // for browsing too (instead of implementin in 94 // safe_browsing_resource_handler.cc). 95 CancelableTask* timeout_task; 96 97 private: 98 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingCheck); 99 }; 100 101 class Client { 102 public: ~Client()103 virtual ~Client() {} 104 105 void OnSafeBrowsingResult(const SafeBrowsingCheck& check); 106 107 // Called when the user has made a decision about how to handle the 108 // SafeBrowsing interstitial page. OnBlockingPageComplete(bool proceed)109 virtual void OnBlockingPageComplete(bool proceed) {} 110 111 protected: 112 // Called when the result of checking a browse URL is known. OnBrowseUrlCheckResult(const GURL & url,UrlCheckResult result)113 virtual void OnBrowseUrlCheckResult(const GURL& url, 114 UrlCheckResult result) {} 115 116 // Called when the result of checking a download URL is known. OnDownloadUrlCheckResult(const std::vector<GURL> & url_chain,UrlCheckResult result)117 virtual void OnDownloadUrlCheckResult(const std::vector<GURL>& url_chain, 118 UrlCheckResult result) {} 119 120 // Called when the result of checking a download binary hash is known. OnDownloadHashCheckResult(const std::string & hash,UrlCheckResult result)121 virtual void OnDownloadHashCheckResult(const std::string& hash, 122 UrlCheckResult result) {} 123 }; 124 125 126 // Makes the passed |factory| the factory used to instanciate 127 // a SafeBrowsingService. Useful for tests. RegisterFactory(SafeBrowsingServiceFactory * factory)128 static void RegisterFactory(SafeBrowsingServiceFactory* factory) { 129 factory_ = factory; 130 } 131 132 // Create an instance of the safe browsing service. 133 static SafeBrowsingService* CreateSafeBrowsingService(); 134 135 // Called on the UI thread to initialize the service. 136 void Initialize(); 137 138 // Called on the main thread to let us know that the io_thread is going away. 139 void ShutDown(); 140 141 // Returns true if the url's scheme can be checked. 142 bool CanCheckUrl(const GURL& url) const; 143 144 // Called on UI thread to decide if safe browsing related stats 145 // could be reported. 146 bool CanReportStats() const; 147 148 // Called on UI thread to decide if the download file's sha256 hash 149 // should be calculated for safebrowsing. 150 bool DownloadBinHashNeeded() const; 151 152 // Called on the IO thread to check if the given url is safe or not. If we 153 // can synchronously determine that the url is safe, CheckUrl returns true. 154 // Otherwise it returns false, and "client" is called asynchronously with the 155 // result when it is ready. 156 virtual bool CheckBrowseUrl(const GURL& url, Client* client); 157 158 // Check if the prefix for |url| is in safebrowsing download add lists. 159 // Result will be passed to callback in |client|. 160 bool CheckDownloadUrl(const std::vector<GURL>& url_chain, Client* client); 161 162 // Check if the prefix for |full_hash| is in safebrowsing binhash add lists. 163 // Result will be passed to callback in |client|. 164 virtual bool CheckDownloadHash(const std::string& full_hash, Client* client); 165 166 // Check if the |url| matches any of the full-length hashes from the 167 // client-side phishing detection whitelist. Returns true if there was a 168 // match and false otherwise. To make sure we are conservative we will return 169 // true if an error occurs. This method is expected to be called on the IO 170 // thread. 171 virtual bool MatchCsdWhitelistUrl(const GURL& url); 172 173 // Called on the IO thread to cancel a pending check if the result is no 174 // longer needed. 175 void CancelCheck(Client* client); 176 177 // Called on the IO thread to display an interstitial page. 178 // |url| is the url of the resource that matches a safe browsing list. 179 // If the request contained a chain of redirects, |url| is the last url 180 // in the chain, and |original_url| is the first one (the root of the 181 // chain). Otherwise, |original_url| = |url|. 182 virtual void DisplayBlockingPage(const GURL& url, 183 const GURL& original_url, 184 const std::vector<GURL>& redirect_urls, 185 ResourceType::Type resource_type, 186 UrlCheckResult result, 187 Client* client, 188 int render_process_host_id, 189 int render_view_id); 190 191 // Called on the IO thread when the SafeBrowsingProtocolManager has received 192 // the full hash results for prefix hits detected in the database. 193 void HandleGetHashResults( 194 SafeBrowsingCheck* check, 195 const std::vector<SBFullHashResult>& full_hashes, 196 bool can_cache); 197 198 // Called on the IO thread. 199 void HandleChunk(const std::string& list, SBChunkList* chunks); 200 void HandleChunkDelete(std::vector<SBChunkDelete>* chunk_deletes); 201 202 // Update management. Called on the IO thread. 203 void UpdateStarted(); 204 void UpdateFinished(bool update_succeeded); 205 // Whether there is an update in progress. Called on the IO thread. 206 bool IsUpdateInProgress() const; 207 208 // The blocking page on the UI thread has completed. 209 void OnBlockingPageDone(const std::vector<UnsafeResource>& resources, 210 bool proceed); 211 212 // Called on the UI thread when the SafeBrowsingProtocolManager has received 213 // updated MAC keys. 214 void OnNewMacKeys(const std::string& client_key, 215 const std::string& wrapped_key); 216 217 // Notification on the UI thread from the advanced options UI. 218 void OnEnable(bool enabled); 219 enabled()220 bool enabled() const { return enabled_; } 221 download_protection_enabled()222 bool download_protection_enabled() const { 223 return enabled_ && enable_download_protection_; 224 } 225 226 // Preference handling. 227 static void RegisterPrefs(PrefService* prefs); 228 229 // Called on the IO thread to try to close the database, freeing the memory 230 // associated with it. The database will be automatically reopened as needed. 231 // 232 // NOTE: Actual database closure is asynchronous, and until it happens, the IO 233 // thread is not allowed to access it; may not actually trigger a close if one 234 // is already pending or doing so would cause problems. 235 void CloseDatabase(); 236 237 // Called on the IO thread to reset the database. 238 void ResetDatabase(); 239 240 // Log the user perceived delay caused by SafeBrowsing. This delay is the time 241 // delta starting from when we would have started reading data from the 242 // network, and ending when the SafeBrowsing check completes indicating that 243 // the current page is 'safe'. 244 void LogPauseDelay(base::TimeDelta time); 245 246 // Called on the IO thread by the MalwareDetails with the serialized 247 // protocol buffer, so the service can send it over. 248 virtual void SendSerializedMalwareDetails(const std::string& serialized); 249 250 // Report hits to the unsafe contents (malware, phishing, unsafe download URL) 251 // to the server. Can only be called on UI thread. If |post_data| is 252 // non-empty, the request will be sent as a POST instead of a GET. 253 void ReportSafeBrowsingHit(const GURL& malicious_url, 254 const GURL& page_url, 255 const GURL& referrer_url, 256 bool is_subresource, 257 UrlCheckResult threat_type, 258 const std::string& post_data); 259 260 protected: 261 // Creates the safe browsing service. Need to initialize before using. 262 SafeBrowsingService(); 263 264 virtual ~SafeBrowsingService(); 265 266 private: 267 friend class SafeBrowsingServiceFactoryImpl; 268 269 typedef std::set<SafeBrowsingCheck*> CurrentChecks; 270 typedef std::vector<SafeBrowsingCheck*> GetHashRequestors; 271 typedef base::hash_map<SBPrefix, GetHashRequestors> GetHashRequests; 272 273 // Used for whitelisting a render view when the user ignores our warning. 274 struct WhiteListedEntry; 275 276 // Clients that we've queued up for checking later once the database is ready. 277 struct QueuedCheck { 278 Client* client; 279 GURL url; 280 base::TimeTicks start; // When check was queued. 281 }; 282 283 friend class base::RefCountedThreadSafe<SafeBrowsingService>; 284 friend class SafeBrowsingServiceTest; 285 286 // Called to initialize objects that are used on the io_thread. 287 void OnIOInitialize(const std::string& client_key, 288 const std::string& wrapped_key, 289 net::URLRequestContextGetter* request_context_getter); 290 291 // Called to shutdown operations on the io_thread. 292 void OnIOShutdown(); 293 294 // Returns whether |database_| exists and is accessible. 295 bool DatabaseAvailable() const; 296 297 // Called on the IO thread. If the database does not exist, queues up a call 298 // on the db thread to create it. Returns whether the database is available. 299 // 300 // Note that this is only needed outside the db thread, since functions on the 301 // db thread can call GetDatabase() directly. 302 bool MakeDatabaseAvailable(); 303 304 // Should only be called on db thread as SafeBrowsingDatabase is not 305 // threadsafe. 306 SafeBrowsingDatabase* GetDatabase(); 307 308 // Called on the IO thread with the check result. 309 void OnCheckDone(SafeBrowsingCheck* info); 310 311 // Called on the database thread to retrieve chunks. 312 void GetAllChunksFromDatabase(); 313 314 // Called on the IO thread with the results of all chunks. 315 void OnGetAllChunksFromDatabase(const std::vector<SBListChunkRanges>& lists, 316 bool database_error); 317 318 // Called on the IO thread after the database reports that it added a chunk. 319 void OnChunkInserted(); 320 321 // Notification that the database is done loading its bloom filter. We may 322 // have had to queue checks until the database is ready, and if so, this 323 // checks them. 324 void DatabaseLoadComplete(); 325 326 // Called on the database thread to add/remove chunks and host keys. 327 // Callee will free the data when it's done. 328 void HandleChunkForDatabase(const std::string& list, 329 SBChunkList* chunks); 330 331 void DeleteChunks(std::vector<SBChunkDelete>* chunk_deletes); 332 333 static UrlCheckResult GetResultFromListname(const std::string& list_name); 334 335 void NotifyClientBlockingComplete(Client* client, bool proceed); 336 337 void DatabaseUpdateFinished(bool update_succeeded); 338 339 // Start up SafeBrowsing objects. This can be called at browser start, or when 340 // the user checks the "Enable SafeBrowsing" option in the Advanced options 341 // UI. 342 void Start(); 343 344 // Called on the db thread to close the database. See CloseDatabase(). 345 void OnCloseDatabase(); 346 347 // Runs on the db thread to reset the database. We assume that resetting the 348 // database is a synchronous operation. 349 void OnResetDatabase(); 350 351 // Store in-memory the GetHash response. Runs on the database thread. 352 void CacheHashResults(const std::vector<SBPrefix>& prefixes, 353 const std::vector<SBFullHashResult>& full_hashes); 354 355 // Internal worker function for processing full hashes. 356 void OnHandleGetHashResults(SafeBrowsingCheck* check, 357 const std::vector<SBFullHashResult>& full_hashes); 358 359 // Run one check against |full_hashes|. Returns |true| if the check 360 // finds a match in |full_hashes|. 361 bool HandleOneCheck(SafeBrowsingCheck* check, 362 const std::vector<SBFullHashResult>& full_hashes); 363 364 // Invoked on the UI thread to show the blocking page. 365 void DoDisplayBlockingPage(const UnsafeResource& resource); 366 367 // Call protocol manager on IO thread to report hits of unsafe contents. 368 void ReportSafeBrowsingHitOnIOThread(const GURL& malicious_url, 369 const GURL& page_url, 370 const GURL& referrer_url, 371 bool is_subresource, 372 UrlCheckResult threat_type, 373 const std::string& post_data); 374 375 // Checks the download hash on safe_browsing_thread_. 376 void CheckDownloadHashOnSBThread(SafeBrowsingCheck* check); 377 378 // Invoked by CheckDownloadUrl. It checks the download URL on 379 // safe_browsing_thread_. 380 void CheckDownloadUrlOnSBThread(SafeBrowsingCheck* check); 381 382 // The callback function when a safebrowsing check is timed out. Client will 383 // be notified that the safebrowsing check is SAFE when this happens. 384 void TimeoutCallback(SafeBrowsingCheck* check); 385 386 // Calls the Client's callback on IO thread after CheckDownloadUrl finishes. 387 void CheckDownloadUrlDone(SafeBrowsingCheck* check); 388 389 // Calls the Client's callback on IO thread after CheckDownloadHash finishes. 390 void CheckDownloadHashDone(SafeBrowsingCheck* check); 391 392 // Helper function that calls safe browsing client and cleans up |checks_|. 393 void SafeBrowsingCheckDone(SafeBrowsingCheck* check); 394 395 // Helper function to set |check| with default values and start a safe 396 // browsing check with timeout of |timeout_ms|. |task| will be called upon 397 // success, otherwise TimeoutCallback will be called. 398 void StartDownloadCheck(SafeBrowsingCheck* check, 399 Client* client, 400 CancelableTask* task, 401 int64 timeout_ms); 402 403 // The factory used to instanciate a SafeBrowsingService object. 404 // Useful for tests, so they can provide their own implementation of 405 // SafeBrowsingService. 406 static SafeBrowsingServiceFactory* factory_; 407 408 CurrentChecks checks_; 409 410 // Used for issuing only one GetHash request for a given prefix. 411 GetHashRequests gethash_requests_; 412 413 // The persistent database. We don't use a scoped_ptr because it 414 // needs to be destructed on a different thread than this object. 415 SafeBrowsingDatabase* database_; 416 417 // Lock used to prevent possible data races due to compiler optimizations. 418 mutable base::Lock database_lock_; 419 420 // Handles interaction with SafeBrowsing servers. 421 SafeBrowsingProtocolManager* protocol_manager_; 422 423 std::vector<WhiteListedEntry> white_listed_entries_; 424 425 // Whether the service is running. 'enabled_' is used by SafeBrowsingService 426 // on the IO thread during normal operations. 427 bool enabled_; 428 429 // Indicate if download_protection is enabled by command switch 430 // so we allow this feature to be exersized. 431 bool enable_download_protection_; 432 433 // Indicate if client-side phishing detection whitelist should be enabled 434 // or not. 435 bool enable_csd_whitelist_; 436 437 // The SafeBrowsing thread that runs database operations. 438 // 439 // Note: Functions that run on this thread should run synchronously and return 440 // to the IO thread, not post additional tasks back to this thread, lest we 441 // cause a race condition at shutdown time that leads to a database leak. 442 scoped_ptr<base::Thread> safe_browsing_thread_; 443 444 // Indicates if we're currently in an update cycle. 445 bool update_in_progress_; 446 447 // When true, newly fetched chunks may not in the database yet since the 448 // database is still updating. 449 bool database_update_in_progress_; 450 451 // Indicates if we're in the midst of trying to close the database. If this 452 // is true, nothing on the IO thread should access the database. 453 bool closing_database_; 454 455 std::deque<QueuedCheck> queued_checks_; 456 457 // When download url check takes this long, client's callback will be called 458 // without waiting for the result. 459 int64 download_urlcheck_timeout_ms_; 460 461 // Similar to |download_urlcheck_timeout_ms_|, but for download hash checks. 462 int64 download_hashcheck_timeout_ms_; 463 464 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService); 465 }; 466 467 // Factory for creating SafeBrowsingService. Useful for tests. 468 class SafeBrowsingServiceFactory { 469 public: SafeBrowsingServiceFactory()470 SafeBrowsingServiceFactory() { } ~SafeBrowsingServiceFactory()471 virtual ~SafeBrowsingServiceFactory() { } 472 virtual SafeBrowsingService* CreateSafeBrowsingService() = 0; 473 private: 474 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactory); 475 }; 476 477 #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ 478