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

Side by Side Diff: chrome/browser/policy/cloud/cloud_policy_client.cc

Issue 109743002: Move policy code into components/policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moar fixes Created 7 years 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/cloud/cloud_policy_client.h"
6
7 #include "base/bind.h"
8 #include "base/guid.h"
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "chrome/browser/policy/cloud/device_management_service.h"
12 #include "google_apis/gaia/gaia_constants.h"
13 #include "google_apis/gaia/gaia_urls.h"
14 #include "net/url_request/url_request_context_getter.h"
15
16 namespace em = enterprise_management;
17
18 namespace policy {
19
20 namespace {
21
22 // Translates the DeviceRegisterResponse::DeviceMode |mode| to the enum used
23 // internally to represent different device modes.
24 DeviceMode TranslateProtobufDeviceMode(
25 em::DeviceRegisterResponse::DeviceMode mode) {
26 switch (mode) {
27 case em::DeviceRegisterResponse::ENTERPRISE:
28 return DEVICE_MODE_ENTERPRISE;
29 case em::DeviceRegisterResponse::RETAIL:
30 return DEVICE_MODE_RETAIL_KIOSK;
31 }
32 LOG(ERROR) << "Unknown enrollment mode in registration response: " << mode;
33 return DEVICE_MODE_NOT_SET;
34 }
35
36 bool IsChromePolicy(const std::string& type) {
37 return type == dm_protocol::kChromeDevicePolicyType ||
38 type == GetChromeUserPolicyType();
39 }
40
41 } // namespace
42
43 CloudPolicyClient::Observer::~Observer() {}
44
45 void CloudPolicyClient::Observer::OnRobotAuthCodesFetched(
46 CloudPolicyClient* client) {}
47
48 CloudPolicyClient::StatusProvider::~StatusProvider() {}
49
50 CloudPolicyClient::CloudPolicyClient(
51 const std::string& machine_id,
52 const std::string& machine_model,
53 UserAffiliation user_affiliation,
54 StatusProvider* status_provider,
55 DeviceManagementService* service,
56 scoped_refptr<net::URLRequestContextGetter> request_context)
57 : machine_id_(machine_id),
58 machine_model_(machine_model),
59 user_affiliation_(user_affiliation),
60 device_mode_(DEVICE_MODE_NOT_SET),
61 submit_machine_id_(false),
62 public_key_version_(-1),
63 public_key_version_valid_(false),
64 invalidation_version_(0),
65 fetched_invalidation_version_(0),
66 service_(service), // Can be NULL for unit tests.
67 status_provider_(status_provider), // Can be NULL for unit tests.
68 status_(DM_STATUS_SUCCESS),
69 request_context_(request_context) {
70 }
71
72 CloudPolicyClient::~CloudPolicyClient() {
73 STLDeleteValues(&responses_);
74 }
75
76 void CloudPolicyClient::SetupRegistration(const std::string& dm_token,
77 const std::string& client_id) {
78 DCHECK(!dm_token.empty());
79 DCHECK(!client_id.empty());
80 DCHECK(!is_registered());
81
82 dm_token_ = dm_token;
83 client_id_ = client_id;
84 request_job_.reset();
85 STLDeleteValues(&responses_);
86
87 NotifyRegistrationStateChanged();
88 }
89
90 void CloudPolicyClient::Register(em::DeviceRegisterRequest::Type type,
91 const std::string& auth_token,
92 const std::string& client_id,
93 bool is_auto_enrollement,
94 const std::string& requisition) {
95 DCHECK(service_);
96 DCHECK(!auth_token.empty());
97 DCHECK(!is_registered());
98
99 if (client_id.empty()) {
100 // Generate a new client ID. This is intentionally done on each new
101 // registration request in order to preserve privacy. Reusing IDs would mean
102 // the server could track clients by their registration attempts.
103 client_id_ = base::GenerateGUID();
104 } else {
105 client_id_ = client_id;
106 }
107
108 request_job_.reset(
109 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION,
110 GetRequestContext()));
111 request_job_->SetOAuthToken(auth_token);
112 request_job_->SetClientID(client_id_);
113
114 em::DeviceRegisterRequest* request =
115 request_job_->GetRequest()->mutable_register_request();
116 if (!client_id.empty())
117 request->set_reregister(true);
118 request->set_type(type);
119 if (!machine_id_.empty())
120 request->set_machine_id(machine_id_);
121 if (!machine_model_.empty())
122 request->set_machine_model(machine_model_);
123 if (is_auto_enrollement)
124 request->set_auto_enrolled(true);
125 if (!requisition.empty())
126 request->set_requisition(requisition);
127
128 request_job_->SetRetryCallback(
129 base::Bind(&CloudPolicyClient::OnRetryRegister, base::Unretained(this)));
130
131 request_job_->Start(base::Bind(&CloudPolicyClient::OnRegisterCompleted,
132 base::Unretained(this)));
133 }
134
135 void CloudPolicyClient::SetInvalidationInfo(
136 int64 version,
137 const std::string& payload) {
138 invalidation_version_ = version;
139 invalidation_payload_ = payload;
140 }
141
142 void CloudPolicyClient::FetchPolicy() {
143 CHECK(is_registered());
144 CHECK(!namespaces_to_fetch_.empty());
145
146 request_job_.reset(
147 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH,
148 GetRequestContext()));
149 request_job_->SetDMToken(dm_token_);
150 request_job_->SetClientID(client_id_);
151 request_job_->SetUserAffiliation(user_affiliation_);
152
153 em::DeviceManagementRequest* request = request_job_->GetRequest();
154
155 // Build policy fetch requests.
156 em::DevicePolicyRequest* policy_request = request->mutable_policy_request();
157 for (NamespaceSet::iterator it = namespaces_to_fetch_.begin();
158 it != namespaces_to_fetch_.end(); ++it) {
159 em::PolicyFetchRequest* fetch_request = policy_request->add_request();
160 fetch_request->set_policy_type(it->first);
161 if (!it->second.empty())
162 fetch_request->set_settings_entity_id(it->second);
163
164 #if defined(OS_CHROMEOS)
165 // All policy types on ChromeOS ask for a signed policy blob.
166 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA);
167 #else
168 // Don't request signed blobs for desktop policy.
169 fetch_request->set_signature_type(em::PolicyFetchRequest::NONE);
170 #endif
171 if (public_key_version_valid_)
172 fetch_request->set_public_key_version(public_key_version_);
173
174 // These fields are included only in requests for chrome policy.
175 if (IsChromePolicy(it->first)) {
176 if (submit_machine_id_ && !machine_id_.empty())
177 fetch_request->set_machine_id(machine_id_);
178 if (!last_policy_timestamp_.is_null()) {
179 base::TimeDelta timestamp(
180 last_policy_timestamp_ - base::Time::UnixEpoch());
181 fetch_request->set_timestamp(timestamp.InMilliseconds());
182 }
183 if (!invalidation_payload_.empty()) {
184 fetch_request->set_invalidation_version(invalidation_version_);
185 fetch_request->set_invalidation_payload(invalidation_payload_);
186 }
187 }
188 }
189
190 // Add status data.
191 if (status_provider_) {
192 if (!status_provider_->GetDeviceStatus(
193 request->mutable_device_status_report_request())) {
194 request->clear_device_status_report_request();
195 }
196 if (!status_provider_->GetSessionStatus(
197 request->mutable_session_status_report_request())) {
198 request->clear_session_status_report_request();
199 }
200 }
201
202 // Set the fetched invalidation version to the latest invalidation version
203 // since it is now the invalidation version used for the latest fetch.
204 fetched_invalidation_version_ = invalidation_version_;
205
206 // Fire the job.
207 request_job_->Start(base::Bind(&CloudPolicyClient::OnPolicyFetchCompleted,
208 base::Unretained(this)));
209 }
210
211 void CloudPolicyClient::FetchRobotAuthCodes(const std::string& auth_token) {
212 CHECK(is_registered());
213 DCHECK(!auth_token.empty());
214
215 request_job_.reset(service_->CreateJob(
216 DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH,
217 GetRequestContext()));
218 // The credentials of a domain user are needed in order to mint a new OAuth2
219 // authorization token for the robot account.
220 request_job_->SetOAuthToken(auth_token);
221 request_job_->SetDMToken(dm_token_);
222 request_job_->SetClientID(client_id_);
223
224 em::DeviceServiceApiAccessRequest* request =
225 request_job_->GetRequest()->mutable_service_api_access_request();
226 request->set_oauth2_client_id(
227 GaiaUrls::GetInstance()->oauth2_chrome_client_id());
228 request->add_auth_scope(GaiaConstants::kAnyApiOAuth2Scope);
229
230 request_job_->Start(
231 base::Bind(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted,
232 base::Unretained(this)));
233 }
234
235 void CloudPolicyClient::Unregister() {
236 DCHECK(service_);
237 request_job_.reset(
238 service_->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION,
239 GetRequestContext()));
240 request_job_->SetDMToken(dm_token_);
241 request_job_->SetClientID(client_id_);
242 request_job_->GetRequest()->mutable_unregister_request();
243 request_job_->Start(base::Bind(&CloudPolicyClient::OnUnregisterCompleted,
244 base::Unretained(this)));
245 }
246
247 void CloudPolicyClient::UploadCertificate(
248 const std::string& certificate_data,
249 const CloudPolicyClient::StatusCallback& callback) {
250 CHECK(is_registered());
251 request_job_.reset(
252 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE,
253 GetRequestContext()));
254 request_job_->SetDMToken(dm_token_);
255 request_job_->SetClientID(client_id_);
256
257 em::DeviceManagementRequest* request = request_job_->GetRequest();
258 request->mutable_cert_upload_request()->set_device_certificate(
259 certificate_data);
260
261 DeviceManagementRequestJob::Callback job_callback = base::Bind(
262 &CloudPolicyClient::OnCertificateUploadCompleted,
263 base::Unretained(this),
264 callback);
265 request_job_->Start(job_callback);
266 }
267
268 void CloudPolicyClient::AddObserver(Observer* observer) {
269 observers_.AddObserver(observer);
270 }
271
272 void CloudPolicyClient::RemoveObserver(Observer* observer) {
273 observers_.RemoveObserver(observer);
274 }
275
276 void CloudPolicyClient::AddNamespaceToFetch(const PolicyNamespaceKey& key) {
277 namespaces_to_fetch_.insert(key);
278 }
279
280 void CloudPolicyClient::RemoveNamespaceToFetch(const PolicyNamespaceKey& key) {
281 namespaces_to_fetch_.erase(key);
282 }
283
284 const em::PolicyFetchResponse* CloudPolicyClient::GetPolicyFor(
285 const PolicyNamespaceKey& key) const {
286 ResponseMap::const_iterator it = responses_.find(key);
287 return it == responses_.end() ? NULL : it->second;
288 }
289
290 scoped_refptr<net::URLRequestContextGetter>
291 CloudPolicyClient::GetRequestContext() {
292 return request_context_;
293 }
294
295 void CloudPolicyClient::OnRetryRegister(DeviceManagementRequestJob* job) {
296 DCHECK_EQ(request_job_.get(), job);
297 // If the initial request managed to get to the server but the response didn't
298 // arrive at the client then retrying with the same client ID will fail.
299 // Set the re-registration flag so that the server accepts it.
300 // If the server hasn't seen the client ID before then it will also accept
301 // the re-registration.
302 job->GetRequest()->mutable_register_request()->set_reregister(true);
303 }
304
305 void CloudPolicyClient::OnRegisterCompleted(
306 DeviceManagementStatus status,
307 int net_error,
308 const em::DeviceManagementResponse& response) {
309 if (status == DM_STATUS_SUCCESS &&
310 (!response.has_register_response() ||
311 !response.register_response().has_device_management_token())) {
312 LOG(WARNING) << "Invalid registration response.";
313 status = DM_STATUS_RESPONSE_DECODING_ERROR;
314 }
315
316 status_ = status;
317 if (status == DM_STATUS_SUCCESS) {
318 dm_token_ = response.register_response().device_management_token();
319 DVLOG(1) << "Client registration complete - DMToken = " << dm_token_;
320
321 // Device mode is only relevant for device policy really, it's the
322 // responsibility of the consumer of the field to check validity.
323 device_mode_ = DEVICE_MODE_NOT_SET;
324 if (response.register_response().has_enrollment_type()) {
325 device_mode_ = TranslateProtobufDeviceMode(
326 response.register_response().enrollment_type());
327 }
328
329 NotifyRegistrationStateChanged();
330 } else {
331 NotifyClientError();
332 }
333 }
334
335 void CloudPolicyClient::OnFetchRobotAuthCodesCompleted(
336 DeviceManagementStatus status,
337 int net_error,
338 const em::DeviceManagementResponse& response) {
339 if (status == DM_STATUS_SUCCESS &&
340 (!response.has_service_api_access_response() ||
341 response.service_api_access_response().auth_code().empty())) {
342 LOG(WARNING) << "Invalid service api access response.";
343 status = DM_STATUS_RESPONSE_DECODING_ERROR;
344 }
345
346 status_ = status;
347 if (status == DM_STATUS_SUCCESS) {
348 robot_api_auth_code_ = response.service_api_access_response().auth_code();
349 DVLOG(1) << "Device robot account auth code fetch complete - code = "
350 << robot_api_auth_code_;
351
352 NotifyRobotAuthCodesFetched();
353 } else {
354 NotifyClientError();
355 }
356 }
357
358 void CloudPolicyClient::OnPolicyFetchCompleted(
359 DeviceManagementStatus status,
360 int net_error,
361 const em::DeviceManagementResponse& response) {
362 if (status == DM_STATUS_SUCCESS) {
363 if (!response.has_policy_response() ||
364 response.policy_response().response_size() == 0) {
365 LOG(WARNING) << "Empty policy response.";
366 status = DM_STATUS_RESPONSE_DECODING_ERROR;
367 }
368 }
369
370 status_ = status;
371 if (status == DM_STATUS_SUCCESS) {
372 const em::DevicePolicyResponse& policy_response =
373 response.policy_response();
374 STLDeleteValues(&responses_);
375 for (int i = 0; i < policy_response.response_size(); ++i) {
376 const em::PolicyFetchResponse& response = policy_response.response(i);
377 em::PolicyData policy_data;
378 if (!policy_data.ParseFromString(response.policy_data()) ||
379 !policy_data.IsInitialized() ||
380 !policy_data.has_policy_type()) {
381 LOG(WARNING) << "Invalid PolicyData received, ignoring";
382 continue;
383 }
384 const std::string& type = policy_data.policy_type();
385 std::string entity_id;
386 if (policy_data.has_settings_entity_id())
387 entity_id = policy_data.settings_entity_id();
388 PolicyNamespaceKey key(type, entity_id);
389 if (ContainsKey(responses_, key)) {
390 LOG(WARNING) << "Duplicate PolicyFetchResponse for type: "
391 << type << ", entity: " << entity_id << ", ignoring";
392 continue;
393 }
394 responses_[key] = new em::PolicyFetchResponse(response);
395 }
396 if (status_provider_)
397 status_provider_->OnSubmittedSuccessfully();
398 NotifyPolicyFetched();
399 } else {
400 NotifyClientError();
401 }
402 }
403
404 void CloudPolicyClient::OnUnregisterCompleted(
405 DeviceManagementStatus status,
406 int net_error,
407 const em::DeviceManagementResponse& response) {
408 if (status == DM_STATUS_SUCCESS && !response.has_unregister_response()) {
409 // Assume unregistration has succeeded either way.
410 LOG(WARNING) << "Empty unregistration response.";
411 }
412
413 status_ = status;
414 if (status == DM_STATUS_SUCCESS) {
415 dm_token_.clear();
416 NotifyRegistrationStateChanged();
417 } else {
418 NotifyClientError();
419 }
420 }
421
422 void CloudPolicyClient::OnCertificateUploadCompleted(
423 const CloudPolicyClient::StatusCallback& callback,
424 DeviceManagementStatus status,
425 int net_error,
426 const enterprise_management::DeviceManagementResponse& response) {
427 if (status == DM_STATUS_SUCCESS && !response.has_cert_upload_response()) {
428 LOG(WARNING) << "Empty upload certificate response.";
429 callback.Run(false);
430 return;
431 }
432
433 status_ = status;
434 if (status != DM_STATUS_SUCCESS) {
435 NotifyClientError();
436 callback.Run(false);
437 return;
438 }
439 callback.Run(true);
440 }
441
442 void CloudPolicyClient::NotifyPolicyFetched() {
443 FOR_EACH_OBSERVER(Observer, observers_, OnPolicyFetched(this));
444 }
445
446 void CloudPolicyClient::NotifyRegistrationStateChanged() {
447 FOR_EACH_OBSERVER(Observer, observers_, OnRegistrationStateChanged(this));
448 }
449
450 void CloudPolicyClient::NotifyRobotAuthCodesFetched() {
451 FOR_EACH_OBSERVER(Observer, observers_, OnRobotAuthCodesFetched(this));
452 }
453
454 void CloudPolicyClient::NotifyClientError() {
455 FOR_EACH_OBSERVER(Observer, observers_, OnClientError(this));
456 }
457
458 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698