blob: c9afe768175c264fb4dfa206f3727361c8214be1 [file] [log] [blame]
Bartosz Fabianowskic4ee8bf2012-01-25 16:31:26 +01001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Julian Pastarmov2638fbc2011-07-20 14:30:46 +02002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "device_policy_impl.h"
6
7#include <openssl/evp.h>
8#include <openssl/x509.h>
9
10#include <string>
11
12#include "base/basictypes.h"
13#include "base/file_path.h"
14#include "base/file_util.h"
15#include "base/logging.h"
16#include "bindings/chrome_device_policy.pb.h"
17#include "bindings/device_management_backend.pb.h"
18
19namespace policy {
20
21namespace {
22const char kPolicyPath[] = "/var/lib/whitelist/policy";
23const char kPublicKeyPath[] = "/var/lib/whitelist/owner.key";
24
25// Reads the public key used to sign the policy from |key_file| and stores it
26// in |public_key|. Returns true on success.
27bool ReadPublicKeyFromFile(const FilePath& key_file, std::string* public_key) {
28 if (!file_util::PathExists(key_file))
29 return false;
30 public_key->clear();
31 if (!file_util::ReadFileToString(key_file, public_key) ||
32 public_key->empty()) {
33 LOG(ERROR) << "Could not read public key off disk";
34 return false;
35 }
36 return true;
37}
38
39// Verifies that the |signed_data| has correct |signature| with |public_key|.
40bool VerifySignature(std::string& signed_data,
41 std::string& signature,
42 std::string& public_key) {
43 EVP_MD_CTX ctx;
44 EVP_MD_CTX_init(&ctx);
45
46 const EVP_MD* digest = EVP_sha1();
47
48 char* key = const_cast<char*>(public_key.data());
49 BIO* bio = BIO_new_mem_buf(key, public_key.length());
50 if (!bio) {
51 EVP_MD_CTX_cleanup(&ctx);
52 return false;
53 }
54
55 EVP_PKEY* public_key_ssl = d2i_PUBKEY_bio(bio, NULL);
56 if (!public_key_ssl) {
57 BIO_free_all(bio);
58 EVP_MD_CTX_cleanup(&ctx);
59 return false;
60 }
61
62 const unsigned char* sig =
63 reinterpret_cast<const unsigned char*>(signature.data());
64 int rv = EVP_VerifyInit_ex(&ctx, digest, NULL);
65 if (rv == 1) {
66 EVP_VerifyUpdate(&ctx, signed_data.data(), signed_data.length());
67 rv = EVP_VerifyFinal(&ctx,
68 sig, signature.length(),
69 public_key_ssl);
70 }
71
72 EVP_PKEY_free(public_key_ssl);
73 BIO_free_all(bio);
74 EVP_MD_CTX_cleanup(&ctx);
75
76 return rv == 1;
77}
78
79} // namespace
80
81DevicePolicyImpl::DevicePolicyImpl()
82 : policy_path_(kPolicyPath),
83 keyfile_path_(kPublicKeyPath) {
84}
85
86DevicePolicyImpl::~DevicePolicyImpl() {
87}
88
89bool DevicePolicyImpl::LoadPolicy() {
90 if (!VerifyPolicyFiles()) {
Julian Pastarmov2638fbc2011-07-20 14:30:46 +020091 return false;
92 }
93
94 std::string polstr;
95 if (!file_util::ReadFileToString(policy_path_, &polstr) || polstr.empty()) {
96 LOG(ERROR) << "Could not read policy off disk";
97 return false;
98 }
99 if (!policy_.ParseFromString(polstr) || !policy_.has_policy_data()) {
100 LOG(ERROR) << "Policy on disk could not be parsed!";
101 return false;
102 }
Bartosz Fabianowskic4ee8bf2012-01-25 16:31:26 +0100103 policy_data_.ParseFromString(policy_.policy_data());
104 if (!policy_data_.has_policy_value()) {
Julian Pastarmov2638fbc2011-07-20 14:30:46 +0200105 LOG(ERROR) << "Policy on disk could not be parsed!";
106 return false;
107 }
108
109 // Make sure the signature is still valid.
110 if (!VerifyPolicySignature()) {
111 LOG(ERROR) << "Policy signature verification failed!";
112 return false;
113 }
114
Bartosz Fabianowskic4ee8bf2012-01-25 16:31:26 +0100115 device_policy_.ParseFromString(policy_data_.policy_value());
Julian Pastarmov2638fbc2011-07-20 14:30:46 +0200116 return true;
117}
118
119// Writes the value of the PolicyRefreshRate policy in |rate|. Returns
120// true on success.
121bool DevicePolicyImpl::GetPolicyRefreshRate(int* rate) const {
122 if (!device_policy_.has_device_policy_refresh_rate())
123 return false;
124 *rate = static_cast<int>(
125 device_policy_.device_policy_refresh_rate().device_policy_refresh_rate());
126 return true;
127}
128
129// Writes the value of the UserWhitelist policy in |user_whitelist|. Returns
130// true on success.
131bool DevicePolicyImpl::GetUserWhitelist(
132 std::vector<std::string>* user_whitelist) const {
133 if (!device_policy_.has_user_whitelist())
134 return false;
135 const enterprise_management::UserWhitelistProto& proto =
136 device_policy_.user_whitelist();
137 user_whitelist->clear();
138 for (int i = 0; i < proto.user_whitelist_size(); i++)
139 user_whitelist->push_back(proto.user_whitelist(i));
140 return true;
141}
142
143// Writes the value of the GuestModeEnabled policy in |guest_mode_enabled|.
144// Returns true on success.
145bool DevicePolicyImpl::GetGuestModeEnabled(bool* guest_mode_enabled) const {
146 if (!device_policy_.has_guest_mode_enabled())
147 return false;
148 *guest_mode_enabled =
149 device_policy_.guest_mode_enabled().guest_mode_enabled();
150 return true;
151}
152
153// Writes the value of the CameraEnabled policy in |camera_enabled|. Returns
154// true on success.
155bool DevicePolicyImpl::GetCameraEnabled(bool* camera_enabled) const {
156 if (!device_policy_.has_camera_enabled())
157 return false;
158 *camera_enabled = device_policy_.camera_enabled().camera_enabled();
159 return true;
160}
161
162// Writes the value of the ShowUserNamesOnSignIn policy in |show_usernames|.
163// Returns true on success.
164bool DevicePolicyImpl::GetShowUserNames(bool* show_user_names) const {
165 if (!device_policy_.has_show_user_names())
166 return false;
167 *show_user_names = device_policy_.show_user_names().show_user_names();
168 return true;
169}
170
171// Writes the value of the DataRoamingEnabled policy in |data_roaming_enabled|
172// Returns true on success.
173bool DevicePolicyImpl::GetDataRoamingEnabled(bool* data_roaming_enabled) const {
174 if (!device_policy_.has_data_roaming_enabled())
175 return false;
176 *data_roaming_enabled =
177 device_policy_.data_roaming_enabled().data_roaming_enabled();
178 return true;
179}
180
181// Writes the value of the AllowNewUSer policy in |allow_new_user|. Returns
182// true on success.
183bool DevicePolicyImpl::GetAllowNewUsers(bool* allow_new_users) const {
184 if (!device_policy_.has_allow_new_users())
185 return false;
186 *allow_new_users = device_policy_.allow_new_users().allow_new_users();
187 return true;
188}
189
190// Writes the value of the MetricsEnabled policy in |metrics_enabled|. Returns
191// true on success.
192bool DevicePolicyImpl::GetMetricsEnabled(bool* metrics_enabled) const {
193 if (!device_policy_.has_metrics_enabled())
194 return false;
195 *metrics_enabled = device_policy_.metrics_enabled().metrics_enabled();
196 return true;
197}
198
199// Writes the value of the ProxyMode policy in |proxy_mode|. Returns true on
200// success.
201bool DevicePolicyImpl::GetProxyMode(std::string* proxy_mode) const {
202 if (!device_policy_.has_device_proxy_settings())
203 return false;
204
205 const enterprise_management::DeviceProxySettingsProto& proto =
206 device_policy_.device_proxy_settings();
207 if (!proto.has_proxy_mode())
208 return false;
209
210 *proxy_mode = proto.proxy_mode();
211 return true;
212}
213
214// Writes the value of the ProxyServer policy in |proxy_server|. Returns true
215// on success.
216bool DevicePolicyImpl::GetProxyServer(std::string* proxy_server) const {
217 if (!device_policy_.has_device_proxy_settings())
218 return false;
219
220 const enterprise_management::DeviceProxySettingsProto& proto =
221 device_policy_.device_proxy_settings();
222 if (!proto.has_proxy_server())
223 return false;
224
225 *proxy_server = proto.proxy_server();
226 return true;
227}
228
229// Writes the value of the ProxyPacUrl policy in |proxy_pac|. Returns true on
230// success.
231bool DevicePolicyImpl::GetProxyPacUrl(std::string* proxy_pac) const {
232 if (!device_policy_.has_device_proxy_settings())
233 return false;
234
235 const enterprise_management::DeviceProxySettingsProto& proto =
236 device_policy_.device_proxy_settings();
237 if (!proto.has_proxy_pac_url())
238 return false;
239
240 *proxy_pac = proto.proxy_pac_url();
241 return true;
242}
243
244// Writes the value of the ProxyBypassList policy in |proxy_bypass_list|.
245// Returns true on success.
246bool DevicePolicyImpl::GetProxyBypassList(
247 std::string* proxy_bypass_list) const {
248 if (!device_policy_.has_device_proxy_settings())
249 return false;
250
251 const enterprise_management::DeviceProxySettingsProto& proto =
252 device_policy_.device_proxy_settings();
253 if (!proto.has_proxy_bypass_list())
254 return false;
255
256 *proxy_bypass_list = proto.proxy_bypass_list();
257 return true;
258}
259
Patrick Dubroy9d979cb2011-08-01 15:52:35 +0200260// Writes the value of the release channel policy in |release_channel|.
261// Returns true on success.
262bool DevicePolicyImpl::GetReleaseChannel(
263 std::string* release_channel) const {
264 if (!device_policy_.has_release_channel())
265 return false;
266
267 const enterprise_management::ReleaseChannelProto& proto =
268 device_policy_.release_channel();
269 if (!proto.has_release_channel())
270 return false;
271
272 *release_channel = proto.release_channel();
273 return true;
274}
275
Bartosz Fabianowskic4ee8bf2012-01-25 16:31:26 +0100276// Writes the name of the device owner in |owner|. For enterprise enrolled
277// devices, this will be an empty string.
278// Returns true on success.
279bool DevicePolicyImpl::GetOwner(std::string* owner) const {
280 // The device is enterprise enrolled iff a request token exists.
281 if (policy_data_.has_request_token()) {
282 *owner = "";
283 return true;
284 }
285 if (!policy_data_.has_username())
286 return false;
287 *owner = policy_data_.username();
288 return true;
289}
290
Julian Pastarmov2638fbc2011-07-20 14:30:46 +0200291bool DevicePolicyImpl::VerifyPolicyFiles() {
292 // Both the policy and its signature have to exist.
293 if (!file_util::PathExists(policy_path_) ||
294 !file_util::PathExists(keyfile_path_)) {
Julian Pastarmov2638fbc2011-07-20 14:30:46 +0200295 return false;
296 }
297
298 // Check if the policy and signature file is owned by root.
299 struct stat file_stat;
300 stat(policy_path_.value().c_str(), &file_stat);
301 if (file_stat.st_uid != 0) {
302 LOG(ERROR) << "Policy file is not owned by root!";
303 return false;
304 }
305 stat(keyfile_path_.value().c_str(), &file_stat);
306 if (file_stat.st_uid != 0) {
307 LOG(ERROR) << "Policy signature file is not owned by root!";
308 return false;
309 }
310 return true;
311}
312
313bool DevicePolicyImpl::VerifyPolicySignature() {
314 if (policy_.has_policy_data_signature()) {
315 std::string policy_data = policy_.policy_data();
316 std::string policy_data_signature = policy_.policy_data_signature();
317 std::string public_key;
318 if (!ReadPublicKeyFromFile(FilePath(keyfile_path_), &public_key)) {
319 LOG(ERROR) << "Could not read owner key off disk";
320 return false;
321 }
322 if (!VerifySignature(policy_data, policy_data_signature, public_key)) {
323 LOG(ERROR) << "Signature does not match the data or can not be verified!";
324 return false;
325 }
326 return true;
327 }
328 LOG(ERROR) << "The policy blob is not signed!";
329 return false;
330}
331
332} // namespace policy
333