1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
16d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
174348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan#include "update_engine/connection_manager.h"
18d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
19d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko#include <set>
20d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes#include <string>
21d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
224348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan#include <base/stl_util.h>
2375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h>
241f84723f499b3b309efac11324ed4e6c937341b6Gilad Arnold#include <policy/device_policy.h>
25d6deb1d0357f47d5525bfaeffa6c201b19abd3e7Alex Deymo#include <shill/dbus-constants.h>
26d6deb1d0357f47d5525bfaeffa6c201b19abd3e7Alex Deymo#include <shill/dbus-proxies.h>
27d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
2839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/prefs.h"
2939910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
30255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang#include "update_engine/connection_utils.h"
31f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang#include "update_engine/shill_proxy.h"
324348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan#include "update_engine/system_state.h"
33d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
34305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ManagerProxyInterface;
35305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ServiceProxyInterface;
364348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasanusing std::set;
37d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyesusing std::string;
38d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
39d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyesnamespace chromeos_update_engine {
40d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
41f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiangnamespace connection_manager {
42f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiangstd::unique_ptr<ConnectionManagerInterface> CreateConnectionManager(
43f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang    SystemState* system_state) {
44f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang  return std::unique_ptr<ConnectionManagerInterface>(
45f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang      new ConnectionManager(new ShillProxy(), system_state));
46f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang}
47f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang}
48f5bebaef8dd12ff71baaf6fb4d4543db3615a6b4Sen Jiang
49305345001d85ca2282112c2a30fe75c7a4773491Alex DeymoConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy,
50305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                     SystemState* system_state)
51305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    : shill_proxy_(shill_proxy), system_state_(system_state) {}
524348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
53255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiangbool ConnectionManager::IsUpdateAllowedOver(
54255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    ConnectionType type, ConnectionTethering tethering) const {
554348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan  switch (type) {
56255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    case ConnectionType::kBluetooth:
574348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      return false;
584348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
59255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    case ConnectionType::kCellular: {
604348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      set<string> allowed_types;
614348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      const policy::DevicePolicy* device_policy =
626f6ea00aa8c4cf54b6842be32ca1226854c24f78Jay Srinivasan          system_state_->device_policy();
63f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
64f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      // A device_policy is loaded in a lazy way right before an update check,
65f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      // so the device_policy should be already loaded at this point. If it's
66f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      // not, return a safe value for this setting.
674348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      if (!device_policy) {
68f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        LOG(INFO) << "Disabling updates over cellular networks as there's no "
69f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                     "device policy loaded yet.";
704348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan        return false;
714348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      }
724348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
73f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
74f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        // The update setting is enforced by the device policy.
75f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
769a423ff19e3a7503cd8128998b3a10d65c499fdcGilad Arnold        if (!ContainsKey(allowed_types, shill::kTypeCellular)) {
77f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          LOG(INFO) << "Disabling updates over cellular connection as it's not "
78f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                       "allowed in the device policy.";
79f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
80f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        }
81f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
82f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        LOG(INFO) << "Allowing updates over cellular per device policy.";
83f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        return true;
84f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      } else {
85f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        // There's no update setting in the device policy, using the local user
86f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        // setting.
87f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        PrefsInterface* prefs = system_state_->prefs();
88f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
89f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        if (!prefs || !prefs->Exists(kPrefsUpdateOverCellularPermission)) {
90f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          LOG(INFO) << "Disabling updates over cellular connection as there's "
91f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                       "no device policy setting nor user preference present.";
92f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
93f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        }
94f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
95efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo        bool stored_value;
96efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo        if (!prefs->GetBoolean(kPrefsUpdateOverCellularPermission,
97efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo                               &stored_value)) {
98f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
99efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo        }
100f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
101f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        if (!stored_value) {
102f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          LOG(INFO) << "Disabling updates over cellular connection per user "
103f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                       "setting.";
104f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
105f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        }
106f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        LOG(INFO) << "Allowing updates over cellular per user setting.";
107f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        return true;
1084348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      }
1094348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan    }
1104348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
1114348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan    default:
112255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang      if (tethering == ConnectionTethering::kConfirmed) {
1136ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo        // Treat this connection as if it is a cellular connection.
1146ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo        LOG(INFO) << "Current connection is confirmed tethered, using Cellular "
1156ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo                     "setting.";
116255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang        return IsUpdateAllowedOver(ConnectionType::kCellular,
117255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang                                   ConnectionTethering::kUnknown);
1186ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo      }
1194348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      return true;
1204348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan  }
1214348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan}
1224348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
1236ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymobool ConnectionManager::GetConnectionProperties(
124255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    ConnectionType* out_type, ConnectionTethering* out_tethering) {
125758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  dbus::ObjectPath default_service_path;
126305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
127758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  if (!default_service_path.IsValid())
128305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
1291fbaac8c911ee484de521e8302d28543ad33cfe1Alex Deymo  // Shill uses the "/" service path to indicate that it is not connected.
1301fbaac8c911ee484de521e8302d28543ad33cfe1Alex Deymo  if (default_service_path.value() == "/")
1311fbaac8c911ee484de521e8302d28543ad33cfe1Alex Deymo    return false;
132305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(
133305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      GetServicePathProperties(default_service_path, out_type, out_tethering));
134305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  return true;
135305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo}
136305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
137758dd53cf503adbcb049909f25f54603d411be09Alex Deymobool ConnectionManager::GetDefaultServicePath(dbus::ObjectPath* out_path) {
1383f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::VariantDictionary properties;
1393f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::ErrorPtr error;
140305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
141305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!manager_proxy)
142305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
143305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(manager_proxy->GetProperties(&properties, &error));
144305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
145305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_default_service =
146305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      properties.find(shill::kDefaultServiceProperty);
147305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_default_service == properties.end())
148305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
149305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
150758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  *out_path = prop_default_service->second.TryGet<dbus::ObjectPath>();
151758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  return out_path->IsValid();
152305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo}
153305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
154305345001d85ca2282112c2a30fe75c7a4773491Alex Deymobool ConnectionManager::GetServicePathProperties(
155758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    const dbus::ObjectPath& path,
156255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    ConnectionType* out_type,
157255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    ConnectionTethering* out_tethering) {
158305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // We create and dispose the ServiceProxyInterface on every request.
159305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  std::unique_ptr<ServiceProxyInterface> service =
160305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      shill_proxy_->GetServiceForPath(path);
161305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
1623f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::VariantDictionary properties;
1633f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::ErrorPtr error;
164305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(service->GetProperties(&properties, &error));
165305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
166305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Populate the out_tethering.
167305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
168305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_tethering == properties.end()) {
169305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // Set to Unknown if not present.
170255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    *out_tethering = ConnectionTethering::kUnknown;
171305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
172305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // If the property doesn't contain a string value, the empty string will
173305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // become kUnknown.
174255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    *out_tethering = connection_utils::ParseConnectionTethering(
175255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang        prop_tethering->second.TryGet<string>());
176305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
177305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
178305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Populate the out_type property.
179305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_type = properties.find(shill::kTypeProperty);
180305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_type == properties.end()) {
181305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // Set to Unknown if not present.
182255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    *out_type = ConnectionType::kUnknown;
183305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
184305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
185305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
186305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  string type_str = prop_type->second.TryGet<string>();
187305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (type_str == shill::kTypeVPN) {
188305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    const auto& prop_physical =
189305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        properties.find(shill::kPhysicalTechnologyProperty);
190305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    if (prop_physical == properties.end()) {
191305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
192758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                    " connection (service: "
193758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                 << path.value() << "). Returning default kUnknown value.";
194255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang      *out_type = ConnectionType::kUnknown;
195305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    } else {
196255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang      *out_type = connection_utils::ParseConnectionType(
197255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang          prop_physical->second.TryGet<string>());
198305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    }
199305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
200255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang    *out_type = connection_utils::ParseConnectionType(type_str);
201305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
202d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes  return true;
203d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes}
204d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
205d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes}  // namespace chromeos_update_engine
206