Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(450)

Side by Side Diff: chrome/browser/policy/user_cloud_policy_store_chromeos.cc

Issue 12189011: Split up chrome/browser/policy subdirectory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "chrome/browser/policy/user_cloud_policy_store_chromeos.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/file_util.h"
13 #include "base/memory/ref_counted.h"
14 #include "chrome/browser/policy/proto/cloud_policy.pb.h"
15 #include "chrome/browser/policy/proto/device_management_local.pb.h"
16 #include "chrome/browser/policy/user_policy_disk_cache.h"
17 #include "chrome/browser/policy/user_policy_token_loader.h"
18 #include "chromeos/dbus/session_manager_client.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "google_apis/gaia/gaia_auth_util.h"
21
22 namespace em = enterprise_management;
23
24 namespace policy {
25
26 namespace {
27 // Subdirectory in the user's profile for storing user policies.
28 const FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("Device Management");
29 // File in the above directory for stroing user policy dmtokens.
30 const FilePath::CharType kTokenCacheFile[] = FILE_PATH_LITERAL("Token");
31 // File in the above directory for storing user policy data.
32 const FilePath::CharType kPolicyCacheFile[] = FILE_PATH_LITERAL("Policy");
33 } // namespace
34
35
36 // Helper class for loading legacy policy caches.
37 class LegacyPolicyCacheLoader : public UserPolicyTokenLoader::Delegate,
38 public UserPolicyDiskCache::Delegate {
39 public:
40 typedef base::Callback<void(const std::string&,
41 const std::string&,
42 CloudPolicyStore::Status,
43 scoped_ptr<em::PolicyFetchResponse>)> Callback;
44
45 LegacyPolicyCacheLoader(const FilePath& token_cache_file,
46 const FilePath& policy_cache_file);
47 virtual ~LegacyPolicyCacheLoader();
48
49 // Starts loading, and reports the result to |callback| when done.
50 void Load(const Callback& callback);
51
52 // UserPolicyTokenLoader::Delegate:
53 virtual void OnTokenLoaded(const std::string& token,
54 const std::string& device_id) OVERRIDE;
55
56 // UserPolicyDiskCache::Delegate:
57 virtual void OnDiskCacheLoaded(
58 UserPolicyDiskCache::LoadResult result,
59 const em::CachedCloudPolicyResponse& policy) OVERRIDE;
60
61 private:
62 // Checks whether the load operations from the legacy caches completed. If so,
63 // fires the appropriate notification.
64 void CheckLoadFinished();
65
66 // Maps a disk cache LoadResult to a CloudPolicyStore::Status.
67 static CloudPolicyStore::Status TranslateLoadResult(
68 UserPolicyDiskCache::LoadResult result);
69
70 base::WeakPtrFactory<LegacyPolicyCacheLoader> weak_factory_;
71
72 scoped_refptr<UserPolicyTokenLoader> token_loader_;
73 scoped_refptr<UserPolicyDiskCache> policy_cache_;
74
75 std::string dm_token_;
76 std::string device_id_;
77 bool has_policy_;
78 scoped_ptr<em::PolicyFetchResponse> policy_;
79 CloudPolicyStore::Status status_;
80
81 Callback callback_;
82
83 DISALLOW_COPY_AND_ASSIGN(LegacyPolicyCacheLoader);
84 };
85
86 LegacyPolicyCacheLoader::LegacyPolicyCacheLoader(
87 const FilePath& token_cache_file,
88 const FilePath& policy_cache_file)
89 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
90 has_policy_(false),
91 status_(CloudPolicyStore::STATUS_OK) {
92 token_loader_ = new UserPolicyTokenLoader(weak_factory_.GetWeakPtr(),
93 token_cache_file);
94 policy_cache_ = new UserPolicyDiskCache(weak_factory_.GetWeakPtr(),
95 policy_cache_file);
96 }
97
98 LegacyPolicyCacheLoader::~LegacyPolicyCacheLoader() {}
99
100 void LegacyPolicyCacheLoader::Load(const Callback& callback) {
101 callback_ = callback;
102 token_loader_->Load();
103 policy_cache_->Load();
104 }
105
106 void LegacyPolicyCacheLoader::OnTokenLoaded(const std::string& token,
107 const std::string& device_id) {
108 dm_token_ = token;
109 device_id_ = device_id;
110 token_loader_ = NULL;
111 CheckLoadFinished();
112 }
113
114 void LegacyPolicyCacheLoader::OnDiskCacheLoaded(
115 UserPolicyDiskCache::LoadResult result,
116 const em::CachedCloudPolicyResponse& policy) {
117 status_ = TranslateLoadResult(result);
118 if (result == UserPolicyDiskCache::LOAD_RESULT_SUCCESS) {
119 if (policy.has_cloud_policy())
120 policy_.reset(new em::PolicyFetchResponse(policy.cloud_policy()));
121 } else {
122 LOG(WARNING) << "Failed to load legacy policy cache: " << result;
123 }
124 policy_cache_ = NULL;
125 CheckLoadFinished();
126 }
127
128 void LegacyPolicyCacheLoader::CheckLoadFinished() {
129 if (!token_loader_.get() && !policy_cache_.get())
130 callback_.Run(dm_token_, device_id_, status_, policy_.Pass());
131 }
132
133 // static
134 CloudPolicyStore::Status LegacyPolicyCacheLoader::TranslateLoadResult(
135 UserPolicyDiskCache::LoadResult result) {
136 switch (result) {
137 case UserPolicyDiskCache::LOAD_RESULT_SUCCESS:
138 case UserPolicyDiskCache::LOAD_RESULT_NOT_FOUND:
139 return CloudPolicyStore::STATUS_OK;
140 case UserPolicyDiskCache::LOAD_RESULT_PARSE_ERROR:
141 case UserPolicyDiskCache::LOAD_RESULT_READ_ERROR:
142 return CloudPolicyStore::STATUS_LOAD_ERROR;
143 }
144 NOTREACHED();
145 return CloudPolicyStore::STATUS_OK;
146 }
147
148 UserCloudPolicyStoreChromeOS::UserCloudPolicyStoreChromeOS(
149 chromeos::SessionManagerClient* session_manager_client,
150 const std::string& username,
151 const FilePath& legacy_token_cache_file,
152 const FilePath& legacy_policy_cache_file)
153 : session_manager_client_(session_manager_client),
154 username_(username),
155 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
156 legacy_cache_dir_(legacy_token_cache_file.DirName()),
157 legacy_loader_(new LegacyPolicyCacheLoader(legacy_token_cache_file,
158 legacy_policy_cache_file)),
159 legacy_caches_loaded_(false) {}
160
161 UserCloudPolicyStoreChromeOS::~UserCloudPolicyStoreChromeOS() {}
162
163 void UserCloudPolicyStoreChromeOS::Store(
164 const em::PolicyFetchResponse& policy) {
165 // Cancel all pending requests.
166 weak_factory_.InvalidateWeakPtrs();
167 Validate(
168 scoped_ptr<em::PolicyFetchResponse>(new em::PolicyFetchResponse(policy)),
169 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyToStoreValidated,
170 weak_factory_.GetWeakPtr()));
171 }
172
173 void UserCloudPolicyStoreChromeOS::Load() {
174 // Cancel all pending requests.
175 weak_factory_.InvalidateWeakPtrs();
176 session_manager_client_->RetrieveUserPolicy(
177 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyRetrieved,
178 weak_factory_.GetWeakPtr()));
179 }
180
181 void UserCloudPolicyStoreChromeOS::OnPolicyRetrieved(
182 const std::string& policy_blob) {
183 if (policy_blob.empty()) {
184 // Policy fetch failed. Try legacy caches if we haven't done that already.
185 if (!legacy_caches_loaded_ && legacy_loader_.get()) {
186 legacy_caches_loaded_ = true;
187 legacy_loader_->Load(
188 base::Bind(&UserCloudPolicyStoreChromeOS::OnLegacyLoadFinished,
189 weak_factory_.GetWeakPtr()));
190 } else {
191 // session_manager doesn't have policy. Adjust internal state and notify
192 // the world about the policy update.
193 policy_.reset();
194 NotifyStoreLoaded();
195 }
196 return;
197 }
198
199 // Policy is supplied by session_manager. Disregard legacy data from now on.
200 legacy_loader_.reset();
201
202 scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse());
203 if (!policy->ParseFromString(policy_blob)) {
204 status_ = STATUS_PARSE_ERROR;
205 NotifyStoreError();
206 return;
207 }
208
209 Validate(policy.Pass(),
210 base::Bind(&UserCloudPolicyStoreChromeOS::OnRetrievedPolicyValidated,
211 weak_factory_.GetWeakPtr()));
212 }
213
214 void UserCloudPolicyStoreChromeOS::OnRetrievedPolicyValidated(
215 UserCloudPolicyValidator* validator) {
216 validation_status_ = validator->status();
217 if (!validator->success()) {
218 status_ = STATUS_VALIDATION_ERROR;
219 NotifyStoreError();
220 return;
221 }
222
223 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
224 status_ = STATUS_OK;
225
226 // Policy has been loaded successfully. This indicates that new-style policy
227 // is working, so the legacy cache directory can be removed.
228 if (!legacy_cache_dir_.empty()) {
229 content::BrowserThread::PostBlockingPoolTask(
230 FROM_HERE,
231 base::Bind(&UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir,
232 legacy_cache_dir_));
233 legacy_cache_dir_.clear();
234 }
235 NotifyStoreLoaded();
236 }
237
238 void UserCloudPolicyStoreChromeOS::OnPolicyToStoreValidated(
239 UserCloudPolicyValidator* validator) {
240 validation_status_ = validator->status();
241 if (!validator->success()) {
242 status_ = STATUS_VALIDATION_ERROR;
243 NotifyStoreError();
244 return;
245 }
246
247 std::string policy_blob;
248 if (!validator->policy()->SerializeToString(&policy_blob)) {
249 status_ = STATUS_SERIALIZE_ERROR;
250 NotifyStoreError();
251 return;
252 }
253
254 session_manager_client_->StoreUserPolicy(
255 policy_blob,
256 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyStored,
257 weak_factory_.GetWeakPtr()));
258 }
259
260 void UserCloudPolicyStoreChromeOS::OnPolicyStored(bool success) {
261 if (!success) {
262 status_ = STATUS_STORE_ERROR;
263 NotifyStoreError();
264 } else {
265 // TODO(mnissler): Once we do signature verifications, we'll have to reload
266 // the key at this point to account for key rotations.
267 Load();
268 }
269 }
270
271 void UserCloudPolicyStoreChromeOS::Validate(
272 scoped_ptr<em::PolicyFetchResponse> policy,
273 const UserCloudPolicyValidator::CompletionCallback& callback) {
274 // Configure the validator.
275 scoped_ptr<UserCloudPolicyValidator> validator =
276 CreateValidator(policy.Pass());
277 validator->ValidateUsername(username_);
278
279 // TODO(mnissler): Do a signature check here as well. The key is stored by
280 // session_manager in the root-owned cryptohome area, which is currently
281 // inaccessible to Chrome though.
282
283 // Start validation. The Validator will free itself once validation is
284 // complete.
285 validator.release()->StartValidation(callback);
286 }
287
288 void UserCloudPolicyStoreChromeOS::OnLegacyLoadFinished(
289 const std::string& dm_token,
290 const std::string& device_id,
291 Status status,
292 scoped_ptr<em::PolicyFetchResponse> policy) {
293 status_ = status;
294 if (policy.get()) {
295 Validate(policy.Pass(),
296 base::Bind(&UserCloudPolicyStoreChromeOS::OnLegacyPolicyValidated,
297 weak_factory_.GetWeakPtr(),
298 dm_token, device_id));
299 } else {
300 InstallLegacyTokens(dm_token, device_id);
301 }
302 }
303
304 void UserCloudPolicyStoreChromeOS::OnLegacyPolicyValidated(
305 const std::string& dm_token,
306 const std::string& device_id,
307 UserCloudPolicyValidator* validator) {
308 validation_status_ = validator->status();
309 if (validator->success()) {
310 status_ = STATUS_OK;
311 InstallPolicy(validator->policy_data().Pass(),
312 validator->payload().Pass());
313
314 // Clear the public key version. The public key version field would
315 // otherwise indicate that we have key installed in the store when in fact
316 // we haven't. This may result in policy updates failing signature
317 // verification.
318 policy_->clear_public_key_version();
319 } else {
320 status_ = STATUS_VALIDATION_ERROR;
321 }
322
323 InstallLegacyTokens(dm_token, device_id);
324 }
325
326 void UserCloudPolicyStoreChromeOS::InstallLegacyTokens(
327 const std::string& dm_token,
328 const std::string& device_id) {
329 // Write token and device ID to |policy_|, giving them precedence over the
330 // policy blob. This is to match the legacy behavior, which used token and
331 // device id exclusively from the token cache file.
332 if (!dm_token.empty() && !device_id.empty()) {
333 if (!policy_.get())
334 policy_.reset(new em::PolicyData());
335 policy_->set_request_token(dm_token);
336 policy_->set_device_id(device_id);
337 }
338
339 // Tell the rest of the world that the policy load completed.
340 NotifyStoreLoaded();
341 }
342
343 // static
344 void UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir(const FilePath& dir) {
345 if (file_util::PathExists(dir) && !file_util::Delete(dir, true))
346 LOG(ERROR) << "Failed to remove cache dir " << dir.value();
347 }
348
349 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698