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