1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ENUMERATE_MODULES_MODEL_WIN_H_
#define CHROME_BROWSER_ENUMERATE_MODULES_MODEL_WIN_H_
#include <utility>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "base/strings/string16.h"
#include "base/timer/timer.h"
#include "content/public/browser/browser_thread.h"
#include "url/gurl.h"
class EnumerateModulesModel;
namespace base {
class FilePath;
class ListValue;
}
// A helper class that implements the enumerate module functionality on the File
// thread.
class ModuleEnumerator : public base::RefCountedThreadSafe<ModuleEnumerator> {
public:
// What type of module we are dealing with. Loaded modules are modules we
// detect as loaded in the process at the time of scanning. The others are
// modules of interest and may or may not be loaded in the process at the
// time of scan.
enum ModuleType {
LOADED_MODULE = 1 << 0,
SHELL_EXTENSION = 1 << 1,
WINSOCK_MODULE_REGISTRATION = 1 << 2,
};
// The blacklist status of the module. Suspected Bad modules have been
// partially matched (ie. name matches and location, but not description)
// whereas Confirmed Bad modules have been identified further (ie.
// AuthentiCode signer matches).
enum ModuleStatus {
// This is returned by the matching function when comparing against the
// blacklist and the module does not match the current entry in the
// blacklist.
NOT_MATCHED,
// The module is not on the blacklist. Assume it is good.
GOOD,
// Module is a suspected bad module.
SUSPECTED_BAD,
// Module is a bad bad dog.
CONFIRMED_BAD,
};
// A bitmask with the possible resolutions for bad modules.
enum RecommendedAction {
NONE = 0,
INVESTIGATING = 1 << 0,
UNINSTALL = 1 << 1,
DISABLE = 1 << 2,
UPDATE = 1 << 3,
SEE_LINK = 1 << 4,
NOTIFY_USER = 1 << 5,
};
// Which Windows OS is affected.
enum OperatingSystem {
ALL = -1,
XP = 1 << 0,
};
// The structure we populate when enumerating modules.
struct Module {
// The type of module found
ModuleType type;
// The module status (benign/bad/etc).
ModuleStatus status;
// The module path, not including filename.
base::string16 location;
// The name of the module (filename).
base::string16 name;
// The name of the product the module belongs to.
base::string16 product_name;
// The module file description.
base::string16 description;
// The module version.
base::string16 version;
// The signer of the digital certificate for the module.
base::string16 digital_signer;
// The help tips bitmask.
RecommendedAction recommended_action;
// The duplicate count within each category of modules.
int duplicate_count;
// Whether this module has been normalized (necessary before checking it
// against blacklist).
bool normalized;
};
// A vector typedef of all modules enumerated.
typedef std::vector<Module> ModulesVector;
// A structure we populate with the blacklist entries.
struct BlacklistEntry {
const char* filename;
const char* location;
const char* desc_or_signer;
const char* version_from; // Version where conflict started.
const char* version_to; // First version that works.
OperatingSystem os; // Bitmask, representing what OS this entry applies to.
RecommendedAction help_tip;
};
// A static function that normalizes the module information in the |module|
// struct. Module information needs to be normalized before comparing against
// the blacklist. This is because the same module can be described in many
// different ways, ie. file paths can be presented in long/short name form,
// and are not case sensitive on Windows. Also, the version string returned
// can include appended text, which we don't want to use during comparison
// against the blacklist.
static void NormalizeModule(Module* module);
// A static function that checks whether |module| has been |blacklisted|.
static ModuleStatus Match(const Module& module,
const BlacklistEntry& blacklisted);
explicit ModuleEnumerator(EnumerateModulesModel* observer);
~ModuleEnumerator();
// Start scanning the loaded module list (if a scan is not already in
// progress). This function does not block while reading the module list
// (unless we are in limited_mode, see below), and will notify when done
// through the MODULE_LIST_ENUMERATED notification.
// The process will also send MODULE_INCOMPATIBILITY_BADGE_CHANGE to let
// observers know when it is time to update the wrench menu badge.
// When in |limited_mode|, this function will not leverage the File thread
// to run asynchronously and will therefore block until scanning is done
// (and will also not send out any notifications).
void ScanNow(ModulesVector* list, bool limited_mode);
private:
FRIEND_TEST_ALL_PREFIXES(EnumerateModulesTest, CollapsePath);
// The (currently) hard coded blacklist of known bad modules.
static const BlacklistEntry kModuleBlacklist[];
// This function does the actual file scanning work on the FILE thread (or
// block the main thread when in limited_mode). It enumerates all loaded
// modules in the process and other modules of interest, such as the
// registered Winsock LSP modules and stores them in |enumerated_modules_|.
// It then normalizes the module info and matches them against a blacklist
// of known bad modules. Finally, it calls ReportBack to let the observer
// know we are done.
void ScanImpl();
// Enumerate all modules loaded into the Chrome process.
void EnumerateLoadedModules();
// Enumerate all registered Windows shell extensions.
void EnumerateShellExtensions();
// Enumerate all registered Winsock LSP modules.
void EnumerateWinsockModules();
// Reads the registered shell extensions found under |parent| key in the
// registry.
void ReadShellExtensions(HKEY parent);
// Given a |module|, initializes the structure and loads additional
// information using the location field of the module.
void PopulateModuleInformation(Module* module);
// Checks the module list to see if a |module| of the same type, location
// and name has been added before and if so, increments its duplication
// counter. If it doesn't appear in the list, it is added.
void AddToListWithoutDuplicating(const Module&);
// Builds up a vector of path values mapping to environment variable,
// with pairs like [c:\windows\, %systemroot%]. This is later used to
// collapse paths like c:\windows\system32 into %systemroot%\system32, which
// we can use for comparison against our blacklist (which uses only env vars).
// NOTE: The vector will not contain an exhaustive list of environment
// variables, only the ones currently found on the blacklist or ones that are
// likely to appear there.
void PreparePathMappings();
// For a given |module|, collapse the path from c:\windows to %systemroot%,
// based on the |path_mapping_| vector.
void CollapsePath(Module* module);
// Takes each module in the |enumerated_modules_| vector and matches it
// against a fixed blacklist of bad and suspected bad modules.
void MatchAgainstBlacklist();
// This function executes on the UI thread when the scanning and matching
// process is done. It notifies the observer.
void ReportBack();
// Given a filename, returns the Subject (who signed it) retrieved from
// the digital signature (Authenticode).
base::string16 GetSubjectNameFromDigitalSignature(
const base::FilePath& filename);
// The typedef for the vector that maps a regular file path to %env_var%.
typedef std::vector< std::pair<base::string16, base::string16> > PathMapping;
// The vector of paths to %env_var%, used to account for differences in
// where people keep there files, c:\windows vs. d:\windows, etc.
PathMapping path_mapping_;
// The vector containing all the enumerated modules (loaded and modules of
// interest).
ModulesVector* enumerated_modules_;
// The observer, who needs to be notified when we are done.
EnumerateModulesModel* observer_;
// See limited_mode below.
bool limited_mode_;
// The thread that we need to call back on to report that we are done.
content::BrowserThread::ID callback_thread_id_;
DISALLOW_COPY_AND_ASSIGN(ModuleEnumerator);
};
// This is a singleton class that enumerates all modules loaded into Chrome,
// both currently loaded modules (called DLLs on Windows) and modules 'of
// interest', such as WinSock LSP modules. This class also marks each module
// as benign or suspected bad or outright bad, using a supplied blacklist that
// is currently hard-coded.
//
// To use this class, grab the singleton pointer and call ScanNow().
// Then wait to get notified through MODULE_LIST_ENUMERATED when the list is
// ready.
//
// This class can be used on the UI thread as it asynchronously offloads the
// file work over to the FILE thread and reports back to the caller with a
// notification.
class EnumerateModulesModel {
public:
// UMA histogram constants.
enum UmaModuleConflictHistogramOptions {
ACTION_BUBBLE_SHOWN = 0,
ACTION_BUBBLE_LEARN_MORE,
ACTION_MENU_LEARN_MORE,
ACTION_BOUNDARY, // Must be the last value.
};
static EnumerateModulesModel* GetInstance();
// Returns true if we should show the conflict notification. The conflict
// notification is only shown once during the lifetime of the process.
bool ShouldShowConflictWarning() const;
// Called when the user has acknowledged the conflict notification.
void AcknowledgeConflictNotification();
// Returns the number of suspected bad modules found in the last scan.
// Returns 0 if no scan has taken place yet.
int suspected_bad_modules_detected() const {
return suspected_bad_modules_detected_;
}
// Returns the number of confirmed bad modules found in the last scan.
// Returns 0 if no scan has taken place yet.
int confirmed_bad_modules_detected() const {
return confirmed_bad_modules_detected_;
}
// Returns how many modules to notify the user about.
int modules_to_notify_about() const {
return modules_to_notify_about_;
}
// Set to true when we the scanning process can not rely on certain Chrome
// services to exists.
void set_limited_mode(bool limited_mode) {
limited_mode_ = limited_mode;
}
// Checks to see if a scanning task should be started and sets one off, if so.
void MaybePostScanningTask();
// Asynchronously start the scan for the loaded module list, except when in
// limited_mode (in which case it blocks).
void ScanNow();
// Gets the whole module list as a ListValue.
base::ListValue* GetModuleList() const;
// Gets the Help Center URL for the first *notable* conflict module that we've
// elected to notify the user about.
GURL GetFirstNotableConflict();
private:
friend struct DefaultSingletonTraits<EnumerateModulesModel>;
friend class ModuleEnumerator;
EnumerateModulesModel();
virtual ~EnumerateModulesModel();
// Called on the UI thread when the helper class is done scanning.
void DoneScanning();
// Constructs a Help Center article URL for help with a particular module.
// The module must have the SEE_LINK attribute for |recommended_action| set,
// otherwise this returns a blank string.
GURL ConstructHelpCenterUrl(const ModuleEnumerator::Module& module) const;
// The vector containing all the modules enumerated. Will be normalized and
// any bad modules will be marked.
ModuleEnumerator::ModulesVector enumerated_modules_;
// The object responsible for enumerating the modules on the File thread.
scoped_refptr<ModuleEnumerator> module_enumerator_;
// When this singleton object is constructed we go and fire off this timer to
// start scanning for modules after a certain amount of time has passed.
base::OneShotTimer<EnumerateModulesModel> check_modules_timer_;
// While normally |false|, this mode can be set to indicate that the scanning
// process should not rely on certain services normally available to Chrome,
// such as the resource bundle and the notification system, not to mention
// having multiple threads. This mode is useful during diagnostics, which
// runs without firing up all necessary Chrome services first.
bool limited_mode_;
// True if we are currently scanning for modules.
bool scanning_;
// Whether the conflict notification has been acknowledged by the user.
bool conflict_notification_acknowledged_;
// The number of confirmed bad modules (not including suspected bad ones)
// found during last scan.
int confirmed_bad_modules_detected_;
// The number of bad modules the user needs to be aggressively notified about.
int modules_to_notify_about_;
// The number of suspected bad modules (not including confirmed bad ones)
// found during last scan.
int suspected_bad_modules_detected_;
DISALLOW_COPY_AND_ASSIGN(EnumerateModulesModel);
};
#endif // CHROME_BROWSER_ENUMERATE_MODULES_MODEL_WIN_H_
|