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