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
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_INSTALL_VERIFIER_H_
#define CHROME_BROWSER_EXTENSIONS_INSTALL_VERIFIER_H_
#include <memory>
#include <set>
#include <string>
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "extensions/browser/management_policy.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_id.h"
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace content {
class BrowserContext;
}
namespace extensions {
class Extension;
class ExtensionPrefs;
class InstallSigner;
struct InstallSignature;
// This class implements verification that a set of extensions are either from
// the webstore or are allowlisted by enterprise policy. The webstore
// verification process works by sending a request to a backend server to get a
// signature proving that a set of extensions are verified. This signature is
// written into the extension preferences and is checked for validity when
// being read back again.
//
// This class should be kept notified of runtime changes to the set of
// extensions installed from the webstore.
class InstallVerifier : public KeyedService,
public ManagementPolicy::Provider {
public:
InstallVerifier(ExtensionPrefs* prefs, content::BrowserContext* context);
InstallVerifier(const InstallVerifier&) = delete;
InstallVerifier& operator=(const InstallVerifier&) = delete;
~InstallVerifier() override;
// Convenience method to return the InstallVerifier for a given `context`.
static InstallVerifier* Get(content::BrowserContext* context);
// Returns whether install verification should be enforced.
static bool ShouldEnforce();
// Returns whether `extension` is of a type that needs verification.
static bool NeedsVerification(const Extension& extension,
content::BrowserContext* context);
// Determines if an extension claims to be from the webstore.
static bool IsFromStore(const Extension& extension,
content::BrowserContext* context);
// Initializes this object for use, including reading preferences and
// validating the stored signature.
void Init();
// Returns the timestamp of our InstallSignature, if we have one.
base::Time SignatureTimestamp();
// Returns true if `id` is either verified or our stored signature explicitly
// tells us that it was invalid when we asked the server about it.
bool IsKnownId(const std::string& id) const;
// Returns whether the given `id` is considered invalid by our verified
// signature.
bool IsInvalid(const std::string& id) const;
// Attempts to verify a single extension and add it to the verified list.
void VerifyExtension(const std::string& extension_id);
// Attempts to verify all extensions.
void VerifyAllExtensions();
// Call this to add a set of ids that will immediately be considered allowed,
// and kick off an asynchronous request to Add.
void AddProvisional(const ExtensionIdSet& ids);
// Removes an id or set of ids from the verified list.
void Remove(const std::string& id);
void RemoveMany(const ExtensionIdSet& ids);
// Returns whether an extension id is allowed by policy.
bool AllowedByEnterprisePolicy(const std::string& id) const;
// ManagementPolicy::Provider interface.
std::string GetDebugPolicyProviderName() const override;
bool MustRemainDisabled(const Extension* extension,
disable_reason::DisableReason* reason) const override;
private:
// We keep a list of operations to the current set of extensions.
enum OperationType {
ADD_SINGLE, // Adding a single extension to be verified.
ADD_ALL, // Adding all extensions to be verified.
ADD_ALL_BOOTSTRAP, // Adding all extensions because of a bootstrapping.
ADD_PROVISIONAL, // Adding one or more provisionally-allowed extensions.
REMOVE // Remove one or more extensions.
};
// This is an operation we want to apply to the current set of verified ids.
struct PendingOperation {
OperationType type;
// This is the set of ids being either added or removed.
ExtensionIdSet ids;
explicit PendingOperation(OperationType type);
~PendingOperation();
};
// Returns the set of IDs for all extensions that potentially need to be
// verified.
ExtensionIdSet GetExtensionsToVerify() const;
// Bootstrap the InstallVerifier if we do not already have a signature, or if
// there are unknown extensions which need to be verified.
void MaybeBootstrapSelf();
// Try adding a new set of `ids` to the list of verified ids.
void AddMany(const ExtensionIdSet& ids, OperationType type);
// Record the result of the verification for the histograms, and notify the
// ExtensionPrefs if we verified all extensions.
void OnVerificationComplete(bool success, OperationType type);
// Removes any no-longer-installed ids, requesting a new signature if needed.
void GarbageCollect();
// Returns whether the given `id` is included in our verified signature.
bool IsVerified(const std::string& id) const;
// Returns true if the extension with `id` was installed later than the
// timestamp of our signature.
bool WasInstalledAfterSignature(const std::string& id) const;
// Begins the process of fetching a new signature, based on applying the
// operation at the head of the queue to the current set of ids in
// `signature_` (if any) and then sending a request to sign that.
void BeginFetch();
// Saves the current value of `signature_` to the prefs;
void SaveToPrefs();
// Called with the result of a signature request, or NULL on failure.
void SignatureCallback(std::unique_ptr<InstallSignature> signature);
raw_ptr<ExtensionPrefs> prefs_;
// The context with which the InstallVerifier is associated.
raw_ptr<content::BrowserContext> context_;
// Have we finished our bootstrap check yet?
bool bootstrap_check_complete_;
// This is the most up-to-date signature, read out of `prefs_` during
// initialization and updated anytime we get new id's added.
std::unique_ptr<InstallSignature> signature_;
// The current InstallSigner, if we have a signature request running.
std::unique_ptr<InstallSigner> signer_;
// A queue of operations to apply to the current set of allowed ids.
base::queue<std::unique_ptr<PendingOperation>> operation_queue_;
// A set of ids that have been provisionally added, which we're willing to
// consider allowed until we hear back from the server signature request.
ExtensionIdSet provisional_;
base::WeakPtrFactory<InstallVerifier> weak_factory_{this};
};
// Instances of this class can be constructed to disable install verification
// during tests.
class ScopedInstallVerifierBypassForTest {
public:
enum ForceType {
kForceOn,
kForceOff,
};
explicit ScopedInstallVerifierBypassForTest(ForceType force_type = kForceOff);
ScopedInstallVerifierBypassForTest(
const ScopedInstallVerifierBypassForTest&) = delete;
ScopedInstallVerifierBypassForTest& operator=(
const ScopedInstallVerifierBypassForTest&) = delete;
~ScopedInstallVerifierBypassForTest();
private:
ForceType value_;
raw_ptr<ForceType> old_value_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_INSTALL_VERIFIER_H_
|