| OLD | NEW |
| (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/chromeos/login/signed_settings.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/memory/ref_counted.h" | |
| 12 #include "base/threading/thread_restrictions.h" | |
| 13 #include "chrome/browser/browser_process.h" | |
| 14 #include "chrome/browser/chromeos/cros/cros_library.h" | |
| 15 #include "chrome/browser/chromeos/login/authenticator.h" | |
| 16 #include "chrome/browser/chromeos/login/ownership_service.h" | |
| 17 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" | |
| 18 #include "chrome/browser/policy/proto/device_management_backend.pb.h" | |
| 19 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 20 #include "chromeos/dbus/session_manager_client.h" | |
| 21 #include "content/public/browser/browser_thread.h" | |
| 22 | |
| 23 namespace em = enterprise_management; | |
| 24 | |
| 25 namespace chromeos { | |
| 26 using content::BrowserThread; | |
| 27 | |
| 28 const char kDevicePolicyType[] = "google/chromeos/device"; | |
| 29 | |
| 30 SignedSettings::SignedSettings() | |
| 31 : service_(OwnershipService::GetSharedInstance()) { | |
| 32 } | |
| 33 | |
| 34 SignedSettings::~SignedSettings() {} | |
| 35 | |
| 36 // static | |
| 37 bool SignedSettings::PolicyIsSane(const em::PolicyFetchResponse& value, | |
| 38 em::PolicyData* poldata) { | |
| 39 if (value.has_policy_data()) { | |
| 40 poldata->ParseFromString(value.policy_data()); | |
| 41 if (poldata->has_policy_type() && | |
| 42 poldata->policy_type() == kDevicePolicyType && | |
| 43 poldata->has_policy_value()) { | |
| 44 return true; | |
| 45 } | |
| 46 } | |
| 47 return false; | |
| 48 } | |
| 49 | |
| 50 // static | |
| 51 SignedSettings::ReturnCode SignedSettings::MapKeyOpCode( | |
| 52 OwnerManager::KeyOpCode return_code) { | |
| 53 return (return_code == OwnerManager::KEY_UNAVAILABLE ? | |
| 54 KEY_UNAVAILABLE : BAD_SIGNATURE); | |
| 55 } | |
| 56 | |
| 57 class StorePolicyOp : public SignedSettings { | |
| 58 public: | |
| 59 StorePolicyOp(em::PolicyFetchResponse* policy, | |
| 60 SignedSettings::Delegate<bool>* d); | |
| 61 void Succeed(bool value); | |
| 62 // Implementation of OwnerManager::Delegate | |
| 63 virtual void Execute() OVERRIDE; | |
| 64 virtual void Fail(SignedSettings::ReturnCode code) OVERRIDE; | |
| 65 virtual void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
| 66 const std::vector<uint8>& payload) OVERRIDE; | |
| 67 | |
| 68 protected: | |
| 69 virtual ~StorePolicyOp(); | |
| 70 | |
| 71 private: | |
| 72 void RequestStorePolicy(); | |
| 73 | |
| 74 void OnBoolComplete(bool success); | |
| 75 // Always call d_->OnSettingOpCompleted() via this call. | |
| 76 // It guarantees that the callback will not be triggered until _after_ | |
| 77 // Execute() returns, which is implicitly assumed by SignedSettingsHelper | |
| 78 // in some cases. | |
| 79 void PerformCallback(SignedSettings::ReturnCode code, bool value); | |
| 80 | |
| 81 em::PolicyFetchResponse* policy_; | |
| 82 SignedSettings::Delegate<bool>* d_; | |
| 83 }; | |
| 84 | |
| 85 class RetrievePolicyOp : public SignedSettings { | |
| 86 public: | |
| 87 explicit RetrievePolicyOp( | |
| 88 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d); | |
| 89 void Succeed(const em::PolicyFetchResponse& value); | |
| 90 // Implementation of OwnerManager::Delegate | |
| 91 virtual void Execute() OVERRIDE; | |
| 92 virtual void Fail(SignedSettings::ReturnCode code) OVERRIDE; | |
| 93 virtual void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
| 94 const std::vector<uint8>& payload) OVERRIDE; | |
| 95 | |
| 96 protected: | |
| 97 virtual ~RetrievePolicyOp(); | |
| 98 | |
| 99 private: | |
| 100 void OnStringComplete(const std::string& serialized_proto); | |
| 101 // Always call d_->OnSettingOpCompleted() via this call. | |
| 102 // It guarantees that the callback will not be triggered until _after_ | |
| 103 // Execute() returns, which is implicitly assumed by SignedSettingsHelper | |
| 104 // in some cases. | |
| 105 void PerformCallback(SignedSettings::ReturnCode code, | |
| 106 const em::PolicyFetchResponse& value); | |
| 107 | |
| 108 void ProcessPolicy(const std::string& serialized_proto); | |
| 109 | |
| 110 em::PolicyFetchResponse policy_; | |
| 111 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d_; | |
| 112 }; | |
| 113 | |
| 114 // static | |
| 115 SignedSettings* SignedSettings::CreateStorePolicyOp( | |
| 116 em::PolicyFetchResponse* policy, | |
| 117 SignedSettings::Delegate<bool>* d) { | |
| 118 DCHECK(d != NULL); | |
| 119 DCHECK(policy != NULL); | |
| 120 return new StorePolicyOp(policy, d); | |
| 121 } | |
| 122 | |
| 123 // static | |
| 124 SignedSettings* SignedSettings::CreateRetrievePolicyOp( | |
| 125 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) { | |
| 126 DCHECK(d != NULL); | |
| 127 return new RetrievePolicyOp(d); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 StorePolicyOp::StorePolicyOp(em::PolicyFetchResponse* policy, | |
| 132 SignedSettings::Delegate<bool>* d) | |
| 133 : policy_(policy), | |
| 134 d_(d) { | |
| 135 } | |
| 136 | |
| 137 void StorePolicyOp::Succeed(bool ignored) { | |
| 138 SignedSettings::ReturnCode code = SUCCESS; | |
| 139 bool to_ret = true; | |
| 140 em::PolicyData poldata; | |
| 141 if (SignedSettings::PolicyIsSane(*policy_, &poldata)) { | |
| 142 } else { | |
| 143 code = NOT_FOUND; | |
| 144 to_ret = false; | |
| 145 } | |
| 146 BrowserThread::PostTask( | |
| 147 BrowserThread::UI, FROM_HERE, | |
| 148 base::Bind(&StorePolicyOp::PerformCallback, this, code, to_ret)); | |
| 149 } | |
| 150 | |
| 151 void StorePolicyOp::Execute() { | |
| 152 // get protobuf contents to sign | |
| 153 if (!policy_->has_policy_data()) | |
| 154 Fail(OPERATION_FAILED); | |
| 155 else if (!policy_->has_policy_data_signature()) | |
| 156 service_->StartSigningAttempt(policy_->policy_data(), this); | |
| 157 else | |
| 158 RequestStorePolicy(); | |
| 159 } | |
| 160 | |
| 161 void StorePolicyOp::Fail(SignedSettings::ReturnCode code) { | |
| 162 BrowserThread::PostTask( | |
| 163 BrowserThread::UI, FROM_HERE, | |
| 164 base::Bind(&StorePolicyOp::PerformCallback, this, code, false)); | |
| 165 } | |
| 166 | |
| 167 void StorePolicyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, | |
| 168 const std::vector<uint8>& payload) { | |
| 169 // Ensure we're on the UI thread, due to the need to send DBus traffic. | |
| 170 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 171 BrowserThread::PostTask( | |
| 172 BrowserThread::UI, FROM_HERE, | |
| 173 base::Bind(&StorePolicyOp::OnKeyOpComplete, this, return_code, | |
| 174 payload)); | |
| 175 return; | |
| 176 } | |
| 177 VLOG(2) << "StorePolicyOp::OnKeyOpComplete return_code = " << return_code; | |
| 178 // Now, sure we're on the UI thread. | |
| 179 if (return_code == OwnerManager::SUCCESS) { | |
| 180 policy_->set_policy_data_signature(std::string(payload.begin(), | |
| 181 payload.end())); | |
| 182 RequestStorePolicy(); | |
| 183 return; | |
| 184 } | |
| 185 Fail(SignedSettings::MapKeyOpCode(return_code)); | |
| 186 } | |
| 187 | |
| 188 StorePolicyOp::~StorePolicyOp() {} | |
| 189 | |
| 190 void StorePolicyOp::RequestStorePolicy() { | |
| 191 std::string serialized; | |
| 192 if (policy_->SerializeToString(&serialized)) { | |
| 193 DBusThreadManager::Get()->GetSessionManagerClient()->StoreDevicePolicy( | |
| 194 serialized, | |
| 195 base::Bind(&StorePolicyOp::OnBoolComplete, this)); | |
| 196 } else { | |
| 197 Fail(OPERATION_FAILED); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 void StorePolicyOp::OnBoolComplete(bool success) { | |
| 202 if (success) | |
| 203 Succeed(true); | |
| 204 else | |
| 205 Fail(NOT_FOUND); | |
| 206 } | |
| 207 | |
| 208 void StorePolicyOp::PerformCallback(SignedSettings::ReturnCode code, | |
| 209 bool value) { | |
| 210 d_->OnSettingsOpCompleted(code, value); | |
| 211 } | |
| 212 | |
| 213 RetrievePolicyOp::RetrievePolicyOp( | |
| 214 SignedSettings::Delegate<const em::PolicyFetchResponse&>* d) | |
| 215 : d_(d) { | |
| 216 } | |
| 217 | |
| 218 void RetrievePolicyOp::Succeed(const em::PolicyFetchResponse& value) { | |
| 219 em::PolicyData poldata; | |
| 220 if (SignedSettings::PolicyIsSane(value, &poldata)) { | |
| 221 BrowserThread::PostTask( | |
| 222 BrowserThread::UI, FROM_HERE, | |
| 223 base::Bind(&RetrievePolicyOp::PerformCallback, this, SUCCESS, value)); | |
| 224 } else { | |
| 225 Fail(NOT_FOUND); | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 void RetrievePolicyOp::Execute() { | |
| 230 DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveDevicePolicy( | |
| 231 base::Bind(&RetrievePolicyOp::OnStringComplete, this)); | |
| 232 } | |
| 233 | |
| 234 void RetrievePolicyOp::Fail(SignedSettings::ReturnCode code) { | |
| 235 VLOG(2) << "RetrievePolicyOp::Execute() failed with " << code; | |
| 236 BrowserThread::PostTask( | |
| 237 BrowserThread::UI, FROM_HERE, | |
| 238 base::Bind(&RetrievePolicyOp::PerformCallback, this, code, | |
| 239 em::PolicyFetchResponse())); | |
| 240 } | |
| 241 | |
| 242 void RetrievePolicyOp::OnKeyOpComplete( | |
| 243 const OwnerManager::KeyOpCode return_code, | |
| 244 const std::vector<uint8>& payload) { | |
| 245 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 246 BrowserThread::PostTask( | |
| 247 BrowserThread::UI, FROM_HERE, | |
| 248 base::Bind(&RetrievePolicyOp::OnKeyOpComplete, this, return_code, | |
| 249 payload)); | |
| 250 return; | |
| 251 } | |
| 252 // Now, sure we're on the UI thread. | |
| 253 if (return_code == OwnerManager::SUCCESS) | |
| 254 Succeed(policy_); | |
| 255 else | |
| 256 Fail(SignedSettings::MapKeyOpCode(return_code)); | |
| 257 } | |
| 258 | |
| 259 RetrievePolicyOp::~RetrievePolicyOp() {} | |
| 260 | |
| 261 void RetrievePolicyOp::OnStringComplete(const std::string& serialized_proto) { | |
| 262 ProcessPolicy(serialized_proto); | |
| 263 } | |
| 264 | |
| 265 void RetrievePolicyOp::ProcessPolicy(const std::string& serialized_proto) { | |
| 266 if (serialized_proto.empty() || !policy_.ParseFromString(serialized_proto) || | |
| 267 (!policy_.has_policy_data() && !policy_.has_policy_data_signature())) { | |
| 268 Fail(NOT_FOUND); | |
| 269 return; | |
| 270 } | |
| 271 if (!policy_.has_policy_data()) { | |
| 272 Fail(OPERATION_FAILED); | |
| 273 return; | |
| 274 } | |
| 275 if (!policy_.has_policy_data_signature()) { | |
| 276 Fail(BAD_SIGNATURE); | |
| 277 return; | |
| 278 } | |
| 279 std::vector<uint8> sig; | |
| 280 const char* sig_ptr = policy_.policy_data_signature().c_str(); | |
| 281 sig.assign(sig_ptr, sig_ptr + policy_.policy_data_signature().length()); | |
| 282 service_->StartVerifyAttempt(policy_.policy_data(), sig, this); | |
| 283 } | |
| 284 | |
| 285 void RetrievePolicyOp::PerformCallback(SignedSettings::ReturnCode code, | |
| 286 const em::PolicyFetchResponse& value) { | |
| 287 d_->OnSettingsOpCompleted(code, value); | |
| 288 } | |
| 289 | |
| 290 } // namespace chromeos | |
| OLD | NEW |