device_policy_decoder_chromeos.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/policy/device_policy_decoder_chromeos.h"
6
7#include <limits>
8
9#include "base/logging.h"
10#include "base/values.h"
11#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
12#include "chrome/browser/chromeos/settings/cros_settings_names.h"
13#include "chrome/browser/policy/policy_map.h"
14#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
15#include "chromeos/dbus/dbus_thread_manager.h"
16#include "chromeos/dbus/update_engine_client.h"
17#include "policy/policy_constants.h"
18#include "third_party/cros_system_api/dbus/service_constants.h"
19
20using google::protobuf::RepeatedField;
21using google::protobuf::RepeatedPtrField;
22
23namespace em = enterprise_management;
24
25namespace policy {
26
27namespace {
28
29// Decodes a protobuf integer to an IntegerValue. The caller assumes ownership
30// of the return Value*. Returns NULL in case the input value is out of bounds.
31Value* DecodeIntegerValue(google::protobuf::int64 value) {
32  if (value < std::numeric_limits<int>::min() ||
33      value > std::numeric_limits<int>::max()) {
34    LOG(WARNING) << "Integer value " << value
35                 << " out of numeric limits, ignoring.";
36    return NULL;
37  }
38
39  return Value::CreateIntegerValue(static_cast<int>(value));
40}
41
42Value* DecodeConnectionType(int value) {
43  static const char* const kConnectionTypes[] = {
44    flimflam::kTypeEthernet,
45    flimflam::kTypeWifi,
46    flimflam::kTypeWimax,
47    flimflam::kTypeBluetooth,
48    flimflam::kTypeCellular,
49  };
50
51  if (value < 0 || value >= static_cast<int>(arraysize(kConnectionTypes)))
52    return NULL;
53
54  return Value::CreateStringValue(kConnectionTypes[value]);
55}
56
57void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy,
58                         PolicyMap* policies) {
59  if (policy.has_guest_mode_enabled()) {
60    const em::GuestModeEnabledProto& container(policy.guest_mode_enabled());
61    if (container.has_guest_mode_enabled()) {
62      policies->Set(key::kDeviceGuestModeEnabled,
63                    POLICY_LEVEL_MANDATORY,
64                    POLICY_SCOPE_MACHINE,
65                    Value::CreateBooleanValue(container.guest_mode_enabled()));
66    }
67  }
68
69  if (policy.has_show_user_names()) {
70    const em::ShowUserNamesOnSigninProto& container(policy.show_user_names());
71    if (container.has_show_user_names()) {
72      policies->Set(key::kDeviceShowUserNamesOnSignin,
73                    POLICY_LEVEL_MANDATORY,
74                    POLICY_SCOPE_MACHINE,
75                    Value::CreateBooleanValue(container.show_user_names()));
76    }
77  }
78
79  if (policy.has_allow_new_users()) {
80    const em::AllowNewUsersProto& container(policy.allow_new_users());
81    if (container.has_allow_new_users()) {
82      policies->Set(key::kDeviceAllowNewUsers,
83                    POLICY_LEVEL_MANDATORY,
84                    POLICY_SCOPE_MACHINE,
85                    Value::CreateBooleanValue(container.allow_new_users()));
86    }
87  }
88
89  if (policy.has_user_whitelist()) {
90    const em::UserWhitelistProto& container(policy.user_whitelist());
91    ListValue* whitelist = new ListValue();
92    RepeatedPtrField<std::string>::const_iterator entry;
93    for (entry = container.user_whitelist().begin();
94         entry != container.user_whitelist().end();
95         ++entry) {
96      whitelist->Append(Value::CreateStringValue(*entry));
97    }
98    policies->Set(key::kDeviceUserWhitelist,
99                  POLICY_LEVEL_MANDATORY,
100                  POLICY_SCOPE_MACHINE,
101                  whitelist);
102  }
103
104  if (policy.has_ephemeral_users_enabled()) {
105    const em::EphemeralUsersEnabledProto& container(
106        policy.ephemeral_users_enabled());
107    if (container.has_ephemeral_users_enabled()) {
108      policies->Set(key::kDeviceEphemeralUsersEnabled,
109                    POLICY_LEVEL_MANDATORY,
110                    POLICY_SCOPE_MACHINE,
111                    Value::CreateBooleanValue(
112                        container.ephemeral_users_enabled()));
113    }
114  }
115
116  if (policy.has_device_local_accounts()) {
117    const em::DeviceLocalAccountsProto& container(
118        policy.device_local_accounts());
119    const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts =
120        container.account();
121    scoped_ptr<base::ListValue> account_list(new base::ListValue());
122    RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry;
123    for (entry = accounts.begin(); entry != accounts.end(); ++entry) {
124      scoped_ptr<base::DictionaryValue> entry_dict(
125          new base::DictionaryValue());
126      if (entry->has_type()) {
127        if (entry->has_account_id()) {
128          entry_dict->SetStringWithoutPathExpansion(
129              chromeos::kAccountsPrefDeviceLocalAccountsKeyId,
130              entry->account_id());
131        }
132        entry_dict->SetIntegerWithoutPathExpansion(
133            chromeos::kAccountsPrefDeviceLocalAccountsKeyType, entry->type());
134        if (entry->kiosk_app().has_app_id()) {
135          entry_dict->SetStringWithoutPathExpansion(
136              chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
137              entry->kiosk_app().app_id());
138        }
139        if (entry->kiosk_app().has_update_url()) {
140          entry_dict->SetStringWithoutPathExpansion(
141              chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL,
142              entry->kiosk_app().update_url());
143        }
144      } else if (entry->has_id()) {
145        // Deprecated public session specification.
146        entry_dict->SetStringWithoutPathExpansion(
147            chromeos::kAccountsPrefDeviceLocalAccountsKeyId, entry->id());
148        entry_dict->SetIntegerWithoutPathExpansion(
149            chromeos::kAccountsPrefDeviceLocalAccountsKeyType,
150            chromeos::DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION);
151      }
152      account_list->Append(entry_dict.release());
153    }
154    policies->Set(key::kDeviceLocalAccounts,
155                  POLICY_LEVEL_MANDATORY,
156                  POLICY_SCOPE_MACHINE,
157                  account_list.release());
158    if (container.has_auto_login_id()) {
159      policies->Set(key::kDeviceLocalAccountAutoLoginId,
160                    POLICY_LEVEL_MANDATORY,
161                    POLICY_SCOPE_MACHINE,
162                    Value::CreateStringValue(container.auto_login_id()));
163    }
164    if (container.has_auto_login_delay()) {
165      policies->Set(key::kDeviceLocalAccountAutoLoginDelay,
166                    POLICY_LEVEL_MANDATORY,
167                    POLICY_SCOPE_MACHINE,
168                    DecodeIntegerValue(container.auto_login_delay()));
169    }
170    if (container.has_enable_auto_login_bailout()) {
171      policies->Set(key::kDeviceLocalAccountAutoLoginBailoutEnabled,
172                    POLICY_LEVEL_MANDATORY,
173                    POLICY_SCOPE_MACHINE,
174                    Value::CreateBooleanValue(
175                        container.enable_auto_login_bailout()));
176    }
177  }
178}
179
180void DecodeKioskPolicies(const em::ChromeDeviceSettingsProto& policy,
181                         PolicyMap* policies,
182                         EnterpriseInstallAttributes* install_attributes) {
183  // No policies if this is not KIOSK.
184  if (install_attributes->GetMode() != DEVICE_MODE_KIOSK)
185    return;
186
187  if (policy.has_forced_logout_timeouts()) {
188    const em::ForcedLogoutTimeoutsProto& container(
189        policy.forced_logout_timeouts());
190    if (container.has_idle_logout_timeout()) {
191      policies->Set(key::kDeviceIdleLogoutTimeout,
192                    POLICY_LEVEL_MANDATORY,
193                    POLICY_SCOPE_MACHINE,
194                    DecodeIntegerValue(container.idle_logout_timeout()));
195    }
196    if (container.has_idle_logout_warning_duration()) {
197      policies->Set(key::kDeviceIdleLogoutWarningDuration,
198                    POLICY_LEVEL_MANDATORY,
199                    POLICY_SCOPE_MACHINE,
200                    DecodeIntegerValue(
201                        container.idle_logout_warning_duration()));
202    }
203  }
204
205  if (policy.has_login_screen_saver()) {
206    const em::ScreenSaverProto& container(
207        policy.login_screen_saver());
208    if (container.has_screen_saver_extension_id()) {
209      policies->Set(key::kDeviceLoginScreenSaverId,
210                    POLICY_LEVEL_MANDATORY,
211                    POLICY_SCOPE_MACHINE,
212                    Value::CreateStringValue(
213                        container.screen_saver_extension_id()));
214    }
215    if (container.has_screen_saver_timeout()) {
216      policies->Set(key::kDeviceLoginScreenSaverTimeout,
217                    POLICY_LEVEL_MANDATORY,
218                    POLICY_SCOPE_MACHINE,
219                    DecodeIntegerValue(container.screen_saver_timeout()));
220    }
221  }
222
223  if (policy.has_app_pack()) {
224    const em::AppPackProto& container(policy.app_pack());
225    base::ListValue* app_pack_list = new base::ListValue();
226    for (int i = 0; i < container.app_pack_size(); ++i) {
227      const em::AppPackEntryProto& entry(container.app_pack(i));
228      if (entry.has_extension_id() && entry.has_update_url()) {
229        base::DictionaryValue* dict = new base::DictionaryValue();
230        dict->SetString(chromeos::kAppPackKeyExtensionId, entry.extension_id());
231        dict->SetString(chromeos::kAppPackKeyUpdateUrl, entry.update_url());
232        app_pack_list->Append(dict);
233      }
234    }
235    policies->Set(key::kDeviceAppPack,
236                  POLICY_LEVEL_MANDATORY,
237                  POLICY_SCOPE_MACHINE,
238                  app_pack_list);
239  }
240
241  if (policy.has_pinned_apps()) {
242    const em::PinnedAppsProto& container(policy.pinned_apps());
243    base::ListValue* pinned_apps_list = new base::ListValue();
244    for (int i = 0; i < container.app_id_size(); ++i)
245      pinned_apps_list->Append(Value::CreateStringValue(container.app_id(i)));
246
247    policies->Set(key::kPinnedLauncherApps,
248                  POLICY_LEVEL_RECOMMENDED,
249                  POLICY_SCOPE_MACHINE,
250                  pinned_apps_list);
251  }
252}
253
254void DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto& policy,
255                           PolicyMap* policies,
256                           EnterpriseInstallAttributes* install_attributes) {
257  if (policy.has_device_proxy_settings()) {
258    const em::DeviceProxySettingsProto& container(
259        policy.device_proxy_settings());
260    scoped_ptr<DictionaryValue> proxy_settings(new DictionaryValue);
261    if (container.has_proxy_mode())
262      proxy_settings->SetString(key::kProxyMode, container.proxy_mode());
263    if (container.has_proxy_server())
264      proxy_settings->SetString(key::kProxyServer, container.proxy_server());
265    if (container.has_proxy_pac_url())
266      proxy_settings->SetString(key::kProxyPacUrl, container.proxy_pac_url());
267    if (container.has_proxy_bypass_list()) {
268      proxy_settings->SetString(key::kProxyBypassList,
269                                container.proxy_bypass_list());
270    }
271
272    // Figure out the level. Proxy policy is mandatory in kiosk mode.
273    PolicyLevel level = POLICY_LEVEL_RECOMMENDED;
274    if (install_attributes->GetMode() == DEVICE_MODE_KIOSK)
275      level = POLICY_LEVEL_MANDATORY;
276
277    if (!proxy_settings->empty()) {
278      policies->Set(key::kProxySettings,
279                    level,
280                    POLICY_SCOPE_MACHINE,
281                    proxy_settings.release());
282    }
283  }
284
285  if (policy.has_data_roaming_enabled()) {
286    const em::DataRoamingEnabledProto& container(policy.data_roaming_enabled());
287    if (container.has_data_roaming_enabled()) {
288      policies->Set(key::kDeviceDataRoamingEnabled,
289                    POLICY_LEVEL_MANDATORY,
290                    POLICY_SCOPE_MACHINE,
291                    Value::CreateBooleanValue(
292                        container.data_roaming_enabled()));
293    }
294  }
295
296  if (policy.has_open_network_configuration() &&
297      policy.open_network_configuration().has_open_network_configuration()) {
298    std::string config(
299        policy.open_network_configuration().open_network_configuration());
300    policies->Set(key::kDeviceOpenNetworkConfiguration,
301                  POLICY_LEVEL_MANDATORY,
302                  POLICY_SCOPE_MACHINE,
303                  Value::CreateStringValue(config));
304  }
305}
306
307void DecodeReportingPolicies(const em::ChromeDeviceSettingsProto& policy,
308                             PolicyMap* policies) {
309  if (policy.has_device_reporting()) {
310    const em::DeviceReportingProto& container(policy.device_reporting());
311    if (container.has_report_version_info()) {
312      policies->Set(key::kReportDeviceVersionInfo,
313                    POLICY_LEVEL_MANDATORY,
314                    POLICY_SCOPE_MACHINE,
315                    Value::CreateBooleanValue(container.report_version_info()));
316    }
317    if (container.has_report_activity_times()) {
318      policies->Set(key::kReportDeviceActivityTimes,
319                    POLICY_LEVEL_MANDATORY,
320                    POLICY_SCOPE_MACHINE,
321                    Value::CreateBooleanValue(
322                        container.report_activity_times()));
323    }
324    if (container.has_report_boot_mode()) {
325      policies->Set(key::kReportDeviceBootMode,
326                    POLICY_LEVEL_MANDATORY,
327                    POLICY_SCOPE_MACHINE,
328                    Value::CreateBooleanValue(container.report_boot_mode()));
329    }
330    if (container.has_report_location()) {
331      policies->Set(key::kReportDeviceLocation,
332                    POLICY_LEVEL_MANDATORY,
333                    POLICY_SCOPE_MACHINE,
334                    Value::CreateBooleanValue(container.report_location()));
335    }
336  }
337}
338
339void DecodeAutoUpdatePolicies(const em::ChromeDeviceSettingsProto& policy,
340                              PolicyMap* policies) {
341  if (policy.has_release_channel()) {
342    const em::ReleaseChannelProto& container(policy.release_channel());
343    if (container.has_release_channel()) {
344      std::string channel(container.release_channel());
345      policies->Set(key::kChromeOsReleaseChannel,
346                    POLICY_LEVEL_MANDATORY,
347                    POLICY_SCOPE_MACHINE,
348                    Value::CreateStringValue(channel));
349      // TODO(dubroy): Once http://crosbug.com/17015 is implemented, we won't
350      // have to pass the channel in here, only ping the update engine to tell
351      // it to fetch the channel from the policy.
352      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
353          SetReleaseTrack(channel);
354    }
355    if (container.has_release_channel_delegated()) {
356      policies->Set(key::kChromeOsReleaseChannelDelegated,
357                    POLICY_LEVEL_MANDATORY,
358                    POLICY_SCOPE_MACHINE,
359                    Value::CreateBooleanValue(
360                        container.release_channel_delegated()));
361    }
362  }
363
364  if (policy.has_auto_update_settings()) {
365    const em::AutoUpdateSettingsProto& container(policy.auto_update_settings());
366    if (container.has_update_disabled()) {
367      policies->Set(key::kDeviceAutoUpdateDisabled,
368                    POLICY_LEVEL_MANDATORY,
369                    POLICY_SCOPE_MACHINE,
370                    Value::CreateBooleanValue(container.update_disabled()));
371    }
372
373    if (container.has_target_version_prefix()) {
374      policies->Set(key::kDeviceTargetVersionPrefix,
375                    POLICY_LEVEL_MANDATORY,
376                    POLICY_SCOPE_MACHINE,
377                    Value::CreateStringValue(
378                        container.target_version_prefix()));
379    }
380
381    // target_version_display_name is not actually a policy, but a display
382    // string for target_version_prefix, so we ignore it.
383
384    if (container.has_scatter_factor_in_seconds()) {
385      policies->Set(key::kDeviceUpdateScatterFactor,
386                    POLICY_LEVEL_MANDATORY,
387                    POLICY_SCOPE_MACHINE,
388                    Value::CreateIntegerValue(
389                        container.scatter_factor_in_seconds()));
390    }
391
392    if (container.allowed_connection_types_size()) {
393      ListValue* allowed_connection_types = new ListValue();
394      RepeatedField<int>::const_iterator entry;
395      for (entry = container.allowed_connection_types().begin();
396           entry != container.allowed_connection_types().end();
397           ++entry) {
398        base::Value* value = DecodeConnectionType(*entry);
399        if (value)
400          allowed_connection_types->Append(value);
401      }
402      policies->Set(key::kDeviceUpdateAllowedConnectionTypes,
403                    POLICY_LEVEL_MANDATORY,
404                    POLICY_SCOPE_MACHINE,
405                    allowed_connection_types);
406    }
407
408    if (container.has_reboot_after_update()) {
409      policies->Set(key::kRebootAfterUpdate,
410                    POLICY_LEVEL_MANDATORY,
411                    POLICY_SCOPE_MACHINE,
412                    Value::CreateBooleanValue(container.reboot_after_update()));
413    }
414  }
415}
416
417void DecodeGenericPolicies(const em::ChromeDeviceSettingsProto& policy,
418                           PolicyMap* policies) {
419  if (policy.has_device_policy_refresh_rate()) {
420    const em::DevicePolicyRefreshRateProto& container(
421        policy.device_policy_refresh_rate());
422    if (container.has_device_policy_refresh_rate()) {
423      policies->Set(key::kDevicePolicyRefreshRate,
424                    POLICY_LEVEL_MANDATORY,
425                    POLICY_SCOPE_MACHINE,
426                    DecodeIntegerValue(container.device_policy_refresh_rate()));
427    }
428  }
429
430  if (policy.has_metrics_enabled()) {
431    const em::MetricsEnabledProto& container(policy.metrics_enabled());
432    if (container.has_metrics_enabled()) {
433      policies->Set(key::kDeviceMetricsReportingEnabled,
434                    POLICY_LEVEL_MANDATORY,
435                    POLICY_SCOPE_MACHINE,
436                    Value::CreateBooleanValue(container.metrics_enabled()));
437    }
438  }
439
440  if (policy.has_start_up_urls()) {
441    const em::StartUpUrlsProto& container(policy.start_up_urls());
442    ListValue* urls = new ListValue();
443    RepeatedPtrField<std::string>::const_iterator entry;
444    for (entry = container.start_up_urls().begin();
445         entry != container.start_up_urls().end();
446         ++entry) {
447      urls->Append(Value::CreateStringValue(*entry));
448    }
449    policies->Set(key::kDeviceStartUpUrls,
450                  POLICY_LEVEL_MANDATORY,
451                  POLICY_SCOPE_MACHINE,
452                  urls);
453  }
454
455  if (policy.has_system_timezone()) {
456    if (policy.system_timezone().has_timezone()) {
457      policies->Set(key::kSystemTimezone,
458                    POLICY_LEVEL_MANDATORY,
459                    POLICY_SCOPE_MACHINE,
460                    Value::CreateStringValue(
461                        policy.system_timezone().timezone()));
462    }
463  }
464
465  if (policy.has_allow_redeem_offers()) {
466    const em::AllowRedeemChromeOsRegistrationOffersProto& container(
467        policy.allow_redeem_offers());
468    if (container.has_allow_redeem_offers()) {
469      policies->Set(key::kDeviceAllowRedeemChromeOsRegistrationOffers,
470                    POLICY_LEVEL_MANDATORY,
471                    POLICY_SCOPE_MACHINE,
472                    Value::CreateBooleanValue(
473                        container.allow_redeem_offers()));
474    }
475  }
476
477  if (policy.has_uptime_limit()) {
478    const em::UptimeLimitProto& container(policy.uptime_limit());
479    if (container.has_uptime_limit()) {
480      policies->Set(key::kUptimeLimit,
481                    POLICY_LEVEL_MANDATORY,
482                    POLICY_SCOPE_MACHINE,
483                    DecodeIntegerValue(container.uptime_limit()));
484    }
485  }
486
487  if (policy.has_start_up_flags()) {
488    const em::StartUpFlagsProto& container(policy.start_up_flags());
489    ListValue* flags = new ListValue();
490    RepeatedPtrField<std::string>::const_iterator entry;
491    for (entry = container.flags().begin();
492         entry != container.flags().end();
493         ++entry) {
494      flags->Append(Value::CreateStringValue(*entry));
495    }
496    policies->Set(key::kDeviceStartUpFlags,
497                  POLICY_LEVEL_MANDATORY,
498                  POLICY_SCOPE_MACHINE,
499                  flags);
500  }
501
502  if (policy.has_variations_parameter()) {
503    if (policy.variations_parameter().has_parameter()) {
504      policies->Set(key::kDeviceVariationsRestrictParameter,
505                    POLICY_LEVEL_MANDATORY,
506                    POLICY_SCOPE_MACHINE,
507                    Value::CreateStringValue(
508                        policy.variations_parameter().parameter()));
509    }
510  }
511}
512
513}  // namespace
514
515void DecodeDevicePolicy(const em::ChromeDeviceSettingsProto& policy,
516                        PolicyMap* policies,
517                        EnterpriseInstallAttributes* install_attributes) {
518  // Decode the various groups of policies.
519  DecodeLoginPolicies(policy, policies);
520  DecodeKioskPolicies(policy, policies, install_attributes);
521  DecodeNetworkPolicies(policy, policies, install_attributes);
522  DecodeReportingPolicies(policy, policies);
523  DecodeAutoUpdatePolicies(policy, policies);
524  DecodeGenericPolicies(policy, policies);
525}
526
527}  // namespace policy
528