1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "update_engine/update_manager/real_device_policy_provider.h"
18 
19 #include <stdint.h>
20 
21 #include <base/location.h>
22 #include <base/logging.h>
23 #include <base/time/time.h>
24 #include <policy/device_policy.h>
25 
26 #include "update_engine/common/utils.h"
27 #include "update_engine/connection_utils.h"
28 #include "update_engine/update_manager/generic_variables.h"
29 
30 using base::TimeDelta;
31 using brillo::MessageLoop;
32 using chromeos_update_engine::ConnectionType;
33 using policy::DevicePolicy;
34 using std::set;
35 using std::string;
36 
37 namespace {
38 
39 const int kDevicePolicyRefreshRateInMinutes = 60;
40 
41 }  // namespace
42 
43 namespace chromeos_update_manager {
44 
~RealDevicePolicyProvider()45 RealDevicePolicyProvider::~RealDevicePolicyProvider() {
46   MessageLoop::current()->CancelTask(scheduled_refresh_);
47 }
48 
Init()49 bool RealDevicePolicyProvider::Init() {
50   CHECK(policy_provider_ != nullptr);
51 
52   // On Init() we try to get the device policy and keep updating it.
53   RefreshDevicePolicyAndReschedule();
54 
55 #if USE_DBUS
56   // We also listen for signals from the session manager to force a device
57   // policy refresh.
58   session_manager_proxy_->RegisterPropertyChangeCompleteSignalHandler(
59       base::Bind(&RealDevicePolicyProvider::OnPropertyChangedCompletedSignal,
60                  base::Unretained(this)),
61       base::Bind(&RealDevicePolicyProvider::OnSignalConnected,
62                  base::Unretained(this)));
63 #endif  // USE_DBUS
64   return true;
65 }
66 
OnPropertyChangedCompletedSignal(const string & success)67 void RealDevicePolicyProvider::OnPropertyChangedCompletedSignal(
68     const string& success) {
69   if (success != "success") {
70     LOG(WARNING) << "Received device policy updated signal with a failure.";
71   }
72   // We refresh the policy file even if the payload string is kSignalFailure.
73   LOG(INFO) << "Reloading and re-scheduling device policy due to signal "
74                "received.";
75   MessageLoop::current()->CancelTask(scheduled_refresh_);
76   scheduled_refresh_ = MessageLoop::kTaskIdNull;
77   RefreshDevicePolicyAndReschedule();
78 }
79 
OnSignalConnected(const string & interface_name,const string & signal_name,bool successful)80 void RealDevicePolicyProvider::OnSignalConnected(const string& interface_name,
81                                                  const string& signal_name,
82                                                  bool successful) {
83   if (!successful) {
84     LOG(WARNING) << "We couldn't connect to SessionManager signal for updates "
85                     "on the device policy blob. We will reload the policy file "
86                     "periodically.";
87   }
88   // We do a one-time refresh of the DevicePolicy just in case we missed a
89   // signal between the first refresh and the time the signal handler was
90   // actually connected.
91   RefreshDevicePolicy();
92 }
93 
RefreshDevicePolicyAndReschedule()94 void RealDevicePolicyProvider::RefreshDevicePolicyAndReschedule() {
95   RefreshDevicePolicy();
96   scheduled_refresh_ = MessageLoop::current()->PostDelayedTask(
97       FROM_HERE,
98       base::Bind(&RealDevicePolicyProvider::RefreshDevicePolicyAndReschedule,
99                  base::Unretained(this)),
100       TimeDelta::FromMinutes(kDevicePolicyRefreshRateInMinutes));
101 }
102 
103 template<typename T>
UpdateVariable(AsyncCopyVariable<T> * var,bool (DevicePolicy::* getter_method)(T *)const)104 void RealDevicePolicyProvider::UpdateVariable(
105     AsyncCopyVariable<T>* var,
106     bool (DevicePolicy::*getter_method)(T*) const) {
107   T new_value;
108   if (policy_provider_->device_policy_is_loaded() &&
109       (policy_provider_->GetDevicePolicy().*getter_method)(&new_value)) {
110     var->SetValue(new_value);
111   } else {
112     var->UnsetValue();
113   }
114 }
115 
116 template<typename T>
UpdateVariable(AsyncCopyVariable<T> * var,bool (RealDevicePolicyProvider::* getter_method)(T *)const)117 void RealDevicePolicyProvider::UpdateVariable(
118     AsyncCopyVariable<T>* var,
119     bool (RealDevicePolicyProvider::*getter_method)(T*) const) {
120   T new_value;
121   if (policy_provider_->device_policy_is_loaded() &&
122       (this->*getter_method)(&new_value)) {
123     var->SetValue(new_value);
124   } else {
125     var->UnsetValue();
126   }
127 }
128 
ConvertAllowedConnectionTypesForUpdate(set<ConnectionType> * allowed_types) const129 bool RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate(
130       set<ConnectionType>* allowed_types) const {
131   set<string> allowed_types_str;
132   if (!policy_provider_->GetDevicePolicy()
133       .GetAllowedConnectionTypesForUpdate(&allowed_types_str)) {
134     return false;
135   }
136   allowed_types->clear();
137   for (auto& type_str : allowed_types_str) {
138     ConnectionType type =
139         chromeos_update_engine::connection_utils::ParseConnectionType(type_str);
140     if (type != ConnectionType::kUnknown) {
141       allowed_types->insert(type);
142     } else {
143       LOG(WARNING) << "Policy includes unknown connection type: " << type_str;
144     }
145   }
146   return true;
147 }
148 
ConvertScatterFactor(TimeDelta * scatter_factor) const149 bool RealDevicePolicyProvider::ConvertScatterFactor(
150     TimeDelta* scatter_factor) const {
151   int64_t scatter_factor_in_seconds;
152   if (!policy_provider_->GetDevicePolicy().GetScatterFactorInSeconds(
153       &scatter_factor_in_seconds)) {
154     return false;
155   }
156   if (scatter_factor_in_seconds < 0) {
157     LOG(WARNING) << "Ignoring negative scatter factor: "
158                  << scatter_factor_in_seconds;
159     return false;
160   }
161   *scatter_factor = TimeDelta::FromSeconds(scatter_factor_in_seconds);
162   return true;
163 }
164 
RefreshDevicePolicy()165 void RealDevicePolicyProvider::RefreshDevicePolicy() {
166   if (!policy_provider_->Reload()) {
167     LOG(INFO) << "No device policies/settings present.";
168   }
169 
170   var_device_policy_is_loaded_.SetValue(
171       policy_provider_->device_policy_is_loaded());
172 
173   UpdateVariable(&var_release_channel_, &DevicePolicy::GetReleaseChannel);
174   UpdateVariable(&var_release_channel_delegated_,
175                  &DevicePolicy::GetReleaseChannelDelegated);
176   UpdateVariable(&var_update_disabled_, &DevicePolicy::GetUpdateDisabled);
177   UpdateVariable(&var_target_version_prefix_,
178                  &DevicePolicy::GetTargetVersionPrefix);
179   UpdateVariable(&var_scatter_factor_,
180                  &RealDevicePolicyProvider::ConvertScatterFactor);
181   UpdateVariable(
182       &var_allowed_connection_types_for_update_,
183       &RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate);
184   UpdateVariable(&var_owner_, &DevicePolicy::GetOwner);
185   UpdateVariable(&var_http_downloads_enabled_,
186                  &DevicePolicy::GetHttpDownloadsEnabled);
187   UpdateVariable(&var_au_p2p_enabled_, &DevicePolicy::GetAuP2PEnabled);
188   UpdateVariable(&var_allow_kiosk_app_control_chrome_version_,
189                  &DevicePolicy::GetAllowKioskAppControlChromeVersion);
190 }
191 
192 }  // namespace chromeos_update_manager
193