device_policy_decoder_chromeos.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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_deprecated_public_session_id()) {
145        // Deprecated public session specification.
146        entry_dict->SetStringWithoutPathExpansion(
147            chromeos::kAccountsPrefDeviceLocalAccountsKeyId,
148            entry->deprecated_public_session_id());
149        entry_dict->SetIntegerWithoutPathExpansion(
150            chromeos::kAccountsPrefDeviceLocalAccountsKeyType,
151            chromeos::DEVICE_LOCAL_ACCOUNT_TYPE_PUBLIC_SESSION);
152      }
153      account_list->Append(entry_dict.release());
154    }
155    policies->Set(key::kDeviceLocalAccounts,
156                  POLICY_LEVEL_MANDATORY,
157                  POLICY_SCOPE_MACHINE,
158                  account_list.release());
159    if (container.has_auto_login_id()) {
160      policies->Set(key::kDeviceLocalAccountAutoLoginId,
161                    POLICY_LEVEL_MANDATORY,
162                    POLICY_SCOPE_MACHINE,
163                    Value::CreateStringValue(container.auto_login_id()));
164    }
165    if (container.has_auto_login_delay()) {
166      policies->Set(key::kDeviceLocalAccountAutoLoginDelay,
167                    POLICY_LEVEL_MANDATORY,
168                    POLICY_SCOPE_MACHINE,
169                    DecodeIntegerValue(container.auto_login_delay()));
170    }
171    if (container.has_enable_auto_login_bailout()) {
172      policies->Set(key::kDeviceLocalAccountAutoLoginBailoutEnabled,
173                    POLICY_LEVEL_MANDATORY,
174                    POLICY_SCOPE_MACHINE,
175                    Value::CreateBooleanValue(
176                        container.enable_auto_login_bailout()));
177    }
178  }
179}
180
181void DecodeKioskPolicies(const em::ChromeDeviceSettingsProto& policy,
182                         PolicyMap* policies,
183                         EnterpriseInstallAttributes* install_attributes) {
184  // No policies if this is not KIOSK.
185  if (install_attributes->GetMode() != DEVICE_MODE_KIOSK)
186    return;
187
188  if (policy.has_forced_logout_timeouts()) {
189    const em::ForcedLogoutTimeoutsProto& container(
190        policy.forced_logout_timeouts());
191    if (container.has_idle_logout_timeout()) {
192      policies->Set(key::kDeviceIdleLogoutTimeout,
193                    POLICY_LEVEL_MANDATORY,
194                    POLICY_SCOPE_MACHINE,
195                    DecodeIntegerValue(container.idle_logout_timeout()));
196    }
197    if (container.has_idle_logout_warning_duration()) {
198      policies->Set(key::kDeviceIdleLogoutWarningDuration,
199                    POLICY_LEVEL_MANDATORY,
200                    POLICY_SCOPE_MACHINE,
201                    DecodeIntegerValue(
202                        container.idle_logout_warning_duration()));
203    }
204  }
205
206  if (policy.has_login_screen_saver()) {
207    const em::ScreenSaverProto& container(
208        policy.login_screen_saver());
209    if (container.has_screen_saver_extension_id()) {
210      policies->Set(key::kDeviceLoginScreenSaverId,
211                    POLICY_LEVEL_MANDATORY,
212                    POLICY_SCOPE_MACHINE,
213                    Value::CreateStringValue(
214                        container.screen_saver_extension_id()));
215    }
216    if (container.has_screen_saver_timeout()) {
217      policies->Set(key::kDeviceLoginScreenSaverTimeout,
218                    POLICY_LEVEL_MANDATORY,
219                    POLICY_SCOPE_MACHINE,
220                    DecodeIntegerValue(container.screen_saver_timeout()));
221    }
222  }
223
224  if (policy.has_app_pack()) {
225    const em::AppPackProto& container(policy.app_pack());
226    base::ListValue* app_pack_list = new base::ListValue();
227    for (int i = 0; i < container.app_pack_size(); ++i) {
228      const em::AppPackEntryProto& entry(container.app_pack(i));
229      if (entry.has_extension_id() && entry.has_update_url()) {
230        base::DictionaryValue* dict = new base::DictionaryValue();
231        dict->SetString(chromeos::kAppPackKeyExtensionId, entry.extension_id());
232        dict->SetString(chromeos::kAppPackKeyUpdateUrl, entry.update_url());
233        app_pack_list->Append(dict);
234      }
235    }
236    policies->Set(key::kDeviceAppPack,
237                  POLICY_LEVEL_MANDATORY,
238                  POLICY_SCOPE_MACHINE,
239                  app_pack_list);
240  }
241
242  if (policy.has_pinned_apps()) {
243    const em::PinnedAppsProto& container(policy.pinned_apps());
244    base::ListValue* pinned_apps_list = new base::ListValue();
245    for (int i = 0; i < container.app_id_size(); ++i)
246      pinned_apps_list->Append(Value::CreateStringValue(container.app_id(i)));
247
248    policies->Set(key::kPinnedLauncherApps,
249                  POLICY_LEVEL_RECOMMENDED,
250                  POLICY_SCOPE_MACHINE,
251                  pinned_apps_list);
252  }
253}
254
255void DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto& policy,
256                           PolicyMap* policies,
257                           EnterpriseInstallAttributes* install_attributes) {
258  if (policy.has_device_proxy_settings()) {
259    const em::DeviceProxySettingsProto& container(
260        policy.device_proxy_settings());
261    scoped_ptr<DictionaryValue> proxy_settings(new DictionaryValue);
262    if (container.has_proxy_mode())
263      proxy_settings->SetString(key::kProxyMode, container.proxy_mode());
264    if (container.has_proxy_server())
265      proxy_settings->SetString(key::kProxyServer, container.proxy_server());
266    if (container.has_proxy_pac_url())
267      proxy_settings->SetString(key::kProxyPacUrl, container.proxy_pac_url());
268    if (container.has_proxy_bypass_list()) {
269      proxy_settings->SetString(key::kProxyBypassList,
270                                container.proxy_bypass_list());
271    }
272
273    // Figure out the level. Proxy policy is mandatory in kiosk mode.
274    PolicyLevel level = POLICY_LEVEL_RECOMMENDED;
275    if (install_attributes->GetMode() == DEVICE_MODE_KIOSK)
276      level = POLICY_LEVEL_MANDATORY;
277
278    if (!proxy_settings->empty()) {
279      policies->Set(key::kProxySettings,
280                    level,
281                    POLICY_SCOPE_MACHINE,
282                    proxy_settings.release());
283    }
284  }
285
286  if (policy.has_data_roaming_enabled()) {
287    const em::DataRoamingEnabledProto& container(policy.data_roaming_enabled());
288    if (container.has_data_roaming_enabled()) {
289      policies->Set(key::kDeviceDataRoamingEnabled,
290                    POLICY_LEVEL_MANDATORY,
291                    POLICY_SCOPE_MACHINE,
292                    Value::CreateBooleanValue(
293                        container.data_roaming_enabled()));
294    }
295  }
296
297  if (policy.has_open_network_configuration() &&
298      policy.open_network_configuration().has_open_network_configuration()) {
299    std::string config(
300        policy.open_network_configuration().open_network_configuration());
301    policies->Set(key::kDeviceOpenNetworkConfiguration,
302                  POLICY_LEVEL_MANDATORY,
303                  POLICY_SCOPE_MACHINE,
304                  Value::CreateStringValue(config));
305  }
306}
307
308void DecodeReportingPolicies(const em::ChromeDeviceSettingsProto& policy,
309                             PolicyMap* policies) {
310  if (policy.has_device_reporting()) {
311    const em::DeviceReportingProto& container(policy.device_reporting());
312    if (container.has_report_version_info()) {
313      policies->Set(key::kReportDeviceVersionInfo,
314                    POLICY_LEVEL_MANDATORY,
315                    POLICY_SCOPE_MACHINE,
316                    Value::CreateBooleanValue(container.report_version_info()));
317    }
318    if (container.has_report_activity_times()) {
319      policies->Set(key::kReportDeviceActivityTimes,
320                    POLICY_LEVEL_MANDATORY,
321                    POLICY_SCOPE_MACHINE,
322                    Value::CreateBooleanValue(
323                        container.report_activity_times()));
324    }
325    if (container.has_report_boot_mode()) {
326      policies->Set(key::kReportDeviceBootMode,
327                    POLICY_LEVEL_MANDATORY,
328                    POLICY_SCOPE_MACHINE,
329                    Value::CreateBooleanValue(container.report_boot_mode()));
330    }
331    if (container.has_report_location()) {
332      policies->Set(key::kReportDeviceLocation,
333                    POLICY_LEVEL_MANDATORY,
334                    POLICY_SCOPE_MACHINE,
335                    Value::CreateBooleanValue(container.report_location()));
336    }
337  }
338}
339
340void DecodeAutoUpdatePolicies(const em::ChromeDeviceSettingsProto& policy,
341                              PolicyMap* policies) {
342  if (policy.has_release_channel()) {
343    const em::ReleaseChannelProto& container(policy.release_channel());
344    if (container.has_release_channel()) {
345      std::string channel(container.release_channel());
346      policies->Set(key::kChromeOsReleaseChannel,
347                    POLICY_LEVEL_MANDATORY,
348                    POLICY_SCOPE_MACHINE,
349                    Value::CreateStringValue(channel));
350      // TODO(dubroy): Once http://crosbug.com/17015 is implemented, we won't
351      // have to pass the channel in here, only ping the update engine to tell
352      // it to fetch the channel from the policy.
353      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
354          SetReleaseTrack(channel);
355    }
356    if (container.has_release_channel_delegated()) {
357      policies->Set(key::kChromeOsReleaseChannelDelegated,
358                    POLICY_LEVEL_MANDATORY,
359                    POLICY_SCOPE_MACHINE,
360                    Value::CreateBooleanValue(
361                        container.release_channel_delegated()));
362    }
363  }
364
365  if (policy.has_auto_update_settings()) {
366    const em::AutoUpdateSettingsProto& container(policy.auto_update_settings());
367    if (container.has_update_disabled()) {
368      policies->Set(key::kDeviceAutoUpdateDisabled,
369                    POLICY_LEVEL_MANDATORY,
370                    POLICY_SCOPE_MACHINE,
371                    Value::CreateBooleanValue(container.update_disabled()));
372    }
373
374    if (container.has_target_version_prefix()) {
375      policies->Set(key::kDeviceTargetVersionPrefix,
376                    POLICY_LEVEL_MANDATORY,
377                    POLICY_SCOPE_MACHINE,
378                    Value::CreateStringValue(
379                        container.target_version_prefix()));
380    }
381
382    // target_version_display_name is not actually a policy, but a display
383    // string for target_version_prefix, so we ignore it.
384
385    if (container.has_scatter_factor_in_seconds()) {
386      policies->Set(key::kDeviceUpdateScatterFactor,
387                    POLICY_LEVEL_MANDATORY,
388                    POLICY_SCOPE_MACHINE,
389                    Value::CreateIntegerValue(
390                        container.scatter_factor_in_seconds()));
391    }
392
393    if (container.allowed_connection_types_size()) {
394      ListValue* allowed_connection_types = new ListValue();
395      RepeatedField<int>::const_iterator entry;
396      for (entry = container.allowed_connection_types().begin();
397           entry != container.allowed_connection_types().end();
398           ++entry) {
399        base::Value* value = DecodeConnectionType(*entry);
400        if (value)
401          allowed_connection_types->Append(value);
402      }
403      policies->Set(key::kDeviceUpdateAllowedConnectionTypes,
404                    POLICY_LEVEL_MANDATORY,
405                    POLICY_SCOPE_MACHINE,
406                    allowed_connection_types);
407    }
408
409    if (container.has_reboot_after_update()) {
410      policies->Set(key::kRebootAfterUpdate,
411                    POLICY_LEVEL_MANDATORY,
412                    POLICY_SCOPE_MACHINE,
413                    Value::CreateBooleanValue(container.reboot_after_update()));
414    }
415  }
416}
417
418void DecodeGenericPolicies(const em::ChromeDeviceSettingsProto& policy,
419                           PolicyMap* policies) {
420  if (policy.has_device_policy_refresh_rate()) {
421    const em::DevicePolicyRefreshRateProto& container(
422        policy.device_policy_refresh_rate());
423    if (container.has_device_policy_refresh_rate()) {
424      policies->Set(key::kDevicePolicyRefreshRate,
425                    POLICY_LEVEL_MANDATORY,
426                    POLICY_SCOPE_MACHINE,
427                    DecodeIntegerValue(container.device_policy_refresh_rate()));
428    }
429  }
430
431  if (policy.has_metrics_enabled()) {
432    const em::MetricsEnabledProto& container(policy.metrics_enabled());
433    if (container.has_metrics_enabled()) {
434      policies->Set(key::kDeviceMetricsReportingEnabled,
435                    POLICY_LEVEL_MANDATORY,
436                    POLICY_SCOPE_MACHINE,
437                    Value::CreateBooleanValue(container.metrics_enabled()));
438    }
439  }
440
441  if (policy.has_start_up_urls()) {
442    const em::StartUpUrlsProto& container(policy.start_up_urls());
443    ListValue* urls = new ListValue();
444    RepeatedPtrField<std::string>::const_iterator entry;
445    for (entry = container.start_up_urls().begin();
446         entry != container.start_up_urls().end();
447         ++entry) {
448      urls->Append(Value::CreateStringValue(*entry));
449    }
450    policies->Set(key::kDeviceStartUpUrls,
451                  POLICY_LEVEL_MANDATORY,
452                  POLICY_SCOPE_MACHINE,
453                  urls);
454  }
455
456  if (policy.has_system_timezone()) {
457    if (policy.system_timezone().has_timezone()) {
458      policies->Set(key::kSystemTimezone,
459                    POLICY_LEVEL_MANDATORY,
460                    POLICY_SCOPE_MACHINE,
461                    Value::CreateStringValue(
462                        policy.system_timezone().timezone()));
463    }
464  }
465
466  if (policy.has_allow_redeem_offers()) {
467    const em::AllowRedeemChromeOsRegistrationOffersProto& container(
468        policy.allow_redeem_offers());
469    if (container.has_allow_redeem_offers()) {
470      policies->Set(key::kDeviceAllowRedeemChromeOsRegistrationOffers,
471                    POLICY_LEVEL_MANDATORY,
472                    POLICY_SCOPE_MACHINE,
473                    Value::CreateBooleanValue(
474                        container.allow_redeem_offers()));
475    }
476  }
477
478  if (policy.has_uptime_limit()) {
479    const em::UptimeLimitProto& container(policy.uptime_limit());
480    if (container.has_uptime_limit()) {
481      policies->Set(key::kUptimeLimit,
482                    POLICY_LEVEL_MANDATORY,
483                    POLICY_SCOPE_MACHINE,
484                    DecodeIntegerValue(container.uptime_limit()));
485    }
486  }
487
488  if (policy.has_start_up_flags()) {
489    const em::StartUpFlagsProto& container(policy.start_up_flags());
490    ListValue* flags = new ListValue();
491    RepeatedPtrField<std::string>::const_iterator entry;
492    for (entry = container.flags().begin();
493         entry != container.flags().end();
494         ++entry) {
495      flags->Append(Value::CreateStringValue(*entry));
496    }
497    policies->Set(key::kDeviceStartUpFlags,
498                  POLICY_LEVEL_MANDATORY,
499                  POLICY_SCOPE_MACHINE,
500                  flags);
501  }
502
503  if (policy.has_variations_parameter()) {
504    if (policy.variations_parameter().has_parameter()) {
505      policies->Set(key::kDeviceVariationsRestrictParameter,
506                    POLICY_LEVEL_MANDATORY,
507                    POLICY_SCOPE_MACHINE,
508                    Value::CreateStringValue(
509                        policy.variations_parameter().parameter()));
510    }
511  }
512
513  if (policy.has_attestation_settings()) {
514    if (policy.attestation_settings().has_attestation_enabled()) {
515      policies->Set(key::kAttestationEnabledForDevice,
516                    POLICY_LEVEL_MANDATORY,
517                    POLICY_SCOPE_MACHINE,
518                    Value::CreateBooleanValue(
519                        policy.attestation_settings().attestation_enabled()));
520    }
521  }
522}
523
524}  // namespace
525
526void DecodeDevicePolicy(const em::ChromeDeviceSettingsProto& policy,
527                        PolicyMap* policies,
528                        EnterpriseInstallAttributes* install_attributes) {
529  // Decode the various groups of policies.
530  DecodeLoginPolicies(policy, policies);
531  DecodeKioskPolicies(policy, policies, install_attributes);
532  DecodeNetworkPolicies(policy, policies, install_attributes);
533  DecodeReportingPolicies(policy, policies);
534  DecodeAutoUpdatePolicies(policy, policies);
535  DecodeGenericPolicies(policy, policies);
536}
537
538}  // namespace policy
539