1 // 2 // Copyright (C) 2012 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 "shill/vpn/vpn_provider.h" 18 19 #include <algorithm> 20 #include <memory> 21 22 #include <base/strings/string_util.h> 23 #if defined(__ANDROID__) 24 #include <dbus/service_constants.h> 25 #else 26 #include <chromeos/dbus/service_constants.h> 27 #endif // __ANDROID__ 28 29 #include "shill/error.h" 30 #include "shill/logging.h" 31 #include "shill/manager.h" 32 #include "shill/process_manager.h" 33 #include "shill/profile.h" 34 #include "shill/store_interface.h" 35 #include "shill/vpn/l2tp_ipsec_driver.h" 36 #include "shill/vpn/openvpn_driver.h" 37 #include "shill/vpn/third_party_vpn_driver.h" 38 #include "shill/vpn/vpn_service.h" 39 40 using std::set; 41 using std::string; 42 using std::vector; 43 44 namespace shill { 45 46 namespace Logging { 47 static auto kModuleLogScope = ScopeLogger::kVPN; 48 static string ObjectID(const VPNProvider* v) { return "(vpn_provider)"; } 49 } 50 51 VPNProvider::VPNProvider(ControlInterface* control_interface, 52 EventDispatcher* dispatcher, 53 Metrics* metrics, 54 Manager* manager) 55 : control_interface_(control_interface), 56 dispatcher_(dispatcher), 57 metrics_(metrics), 58 manager_(manager) {} 59 60 VPNProvider::~VPNProvider() {} 61 62 void VPNProvider::Start() {} 63 64 void VPNProvider::Stop() {} 65 66 // static 67 bool VPNProvider::GetServiceParametersFromArgs(const KeyValueStore& args, 68 string* type_ptr, 69 string* name_ptr, 70 string* host_ptr, 71 Error* error) { 72 SLOG(nullptr, 2) << __func__; 73 string type = args.LookupString(kProviderTypeProperty, ""); 74 if (type.empty()) { 75 Error::PopulateAndLog( 76 FROM_HERE, error, Error::kNotSupported, "Missing VPN type property."); 77 return false; 78 } 79 80 string host = args.LookupString(kProviderHostProperty, ""); 81 if (host.empty()) { 82 Error::PopulateAndLog( 83 FROM_HERE, error, Error::kNotSupported, "Missing VPN host property."); 84 return false; 85 } 86 87 *type_ptr = type, 88 *host_ptr = host, 89 *name_ptr = args.LookupString(kNameProperty, ""); 90 91 return true; 92 } 93 94 // static 95 bool VPNProvider::GetServiceParametersFromStorage(const StoreInterface* storage, 96 const string& entry_name, 97 string* vpn_type_ptr, 98 string* name_ptr, 99 string* host_ptr, 100 Error* error) { 101 string service_type; 102 if (!storage->GetString(entry_name, kTypeProperty, &service_type) || 103 service_type != kTypeVPN) { 104 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 105 "Unspecified or invalid network type"); 106 return false; 107 } 108 if (!storage->GetString(entry_name, kProviderTypeProperty, vpn_type_ptr) || 109 vpn_type_ptr->empty()) { 110 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 111 "VPN type not specified"); 112 return false; 113 } 114 if (!storage->GetString(entry_name, kNameProperty, name_ptr) || 115 name_ptr->empty()) { 116 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 117 "Network name not specified"); 118 return false; 119 } 120 if (!storage->GetString(entry_name, kProviderHostProperty, host_ptr) || 121 host_ptr->empty()) { 122 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 123 "Host not specified"); 124 return false; 125 } 126 return true; 127 } 128 129 ServiceRefPtr VPNProvider::GetService(const KeyValueStore& args, 130 Error* error) { 131 SLOG(this, 2) << __func__; 132 string type; 133 string name; 134 string host; 135 136 if (!GetServiceParametersFromArgs(args, &type, &name, &host, error)) { 137 return nullptr; 138 } 139 140 string storage_id = VPNService::CreateStorageIdentifier(args, error); 141 if (storage_id.empty()) { 142 return nullptr; 143 } 144 145 // Find a service in the provider list which matches these parameters. 146 VPNServiceRefPtr service = FindService(type, name, host); 147 if (service == nullptr) { 148 service = CreateService(type, name, storage_id, error); 149 } 150 return service; 151 } 152 153 ServiceRefPtr VPNProvider::FindSimilarService(const KeyValueStore& args, 154 Error* error) const { 155 SLOG(this, 2) << __func__; 156 string type; 157 string name; 158 string host; 159 160 if (!GetServiceParametersFromArgs(args, &type, &name, &host, error)) { 161 return nullptr; 162 } 163 164 // Find a service in the provider list which matches these parameters. 165 VPNServiceRefPtr service = FindService(type, name, host); 166 if (!service) { 167 error->Populate(Error::kNotFound, "Matching service was not found"); 168 } 169 170 return service; 171 } 172 173 bool VPNProvider::OnDeviceInfoAvailable(const string& link_name, 174 int interface_index) { 175 for (const auto& service : services_) { 176 if (service->driver()->ClaimInterface(link_name, interface_index)) { 177 return true; 178 } 179 } 180 181 return false; 182 } 183 184 void VPNProvider::RemoveService(VPNServiceRefPtr service) { 185 const auto it = std::find(services_.begin(), services_.end(), service); 186 if (it != services_.end()) { 187 services_.erase(it); 188 } 189 } 190 191 void VPNProvider::CreateServicesFromProfile(const ProfileRefPtr& profile) { 192 SLOG(this, 2) << __func__; 193 const StoreInterface* storage = profile->GetConstStorage(); 194 KeyValueStore args; 195 args.SetString(kTypeProperty, kTypeVPN); 196 for (const auto& group : storage->GetGroupsWithProperties(args)) { 197 string type; 198 string name; 199 string host; 200 if (!GetServiceParametersFromStorage(storage, 201 group, 202 &type, 203 &name, 204 &host, 205 nullptr)) { 206 continue; 207 } 208 209 VPNServiceRefPtr service = FindService(type, name, host); 210 if (service != nullptr) { 211 // If the service already exists, it does not need to be configured, 212 // since PushProfile would have already called ConfigureService on it. 213 SLOG(this, 2) << "Service already exists " << group; 214 continue; 215 } 216 217 Error error; 218 service = CreateService(type, name, group, &error); 219 220 if (service == nullptr) { 221 LOG(ERROR) << "Could not create service for " << group; 222 continue; 223 } 224 225 if (!profile->ConfigureService(service)) { 226 LOG(ERROR) << "Could not configure service for " << group; 227 continue; 228 } 229 } 230 } 231 232 VPNServiceRefPtr VPNProvider::CreateServiceInner(const string& type, 233 const string& name, 234 const string& storage_id, 235 Error* error) { 236 SLOG(this, 2) << __func__ << " type " << type << " name " << name 237 << " storage id " << storage_id; 238 #if defined(DISABLE_VPN) 239 240 Error::PopulateAndLog( 241 FROM_HERE, error, Error::kNotSupported, "VPN is not supported."); 242 return nullptr; 243 244 #else 245 246 std::unique_ptr<VPNDriver> driver; 247 if (type == kProviderOpenVpn) { 248 driver.reset(new OpenVPNDriver( 249 control_interface_, dispatcher_, metrics_, manager_, 250 manager_->device_info(), ProcessManager::GetInstance())); 251 } else if (type == kProviderL2tpIpsec) { 252 driver.reset(new L2TPIPSecDriver( 253 control_interface_, dispatcher_, metrics_, manager_, 254 manager_->device_info(), ProcessManager::GetInstance())); 255 } else if (type == kProviderThirdPartyVpn) { 256 // For third party VPN host contains extension ID 257 driver.reset(new ThirdPartyVpnDriver( 258 control_interface_, dispatcher_, metrics_, manager_, 259 manager_->device_info())); 260 } else { 261 Error::PopulateAndLog( 262 FROM_HERE, error, Error::kNotSupported, 263 "Unsupported VPN type: " + type); 264 return nullptr; 265 } 266 267 VPNServiceRefPtr service = new VPNService( 268 control_interface_, dispatcher_, metrics_, manager_, driver.release()); 269 service->set_storage_id(storage_id); 270 service->InitDriverPropertyStore(); 271 if (!name.empty()) { 272 service->set_friendly_name(name); 273 } 274 return service; 275 276 #endif // DISABLE_VPN 277 } 278 279 VPNServiceRefPtr VPNProvider::CreateService(const string& type, 280 const string& name, 281 const string& storage_id, 282 Error* error) { 283 VPNServiceRefPtr service = CreateServiceInner(type, name, storage_id, error); 284 if (service) { 285 services_.push_back(service); 286 manager_->RegisterService(service); 287 } 288 289 return service; 290 } 291 292 VPNServiceRefPtr VPNProvider::FindService(const string& type, 293 const string& name, 294 const string& host) const { 295 for (const auto& service : services_) { 296 if (type == service->driver()->GetProviderType() && 297 name == service->friendly_name() && 298 host == service->driver()->GetHost()) { 299 return service; 300 } 301 } 302 return nullptr; 303 } 304 305 ServiceRefPtr VPNProvider::CreateTemporaryService( 306 const KeyValueStore& args, Error* error) { 307 string type; 308 string name; 309 string host; 310 311 if (!GetServiceParametersFromArgs(args, &type, &name, &host, error)) { 312 return nullptr; 313 } 314 315 string storage_id = VPNService::CreateStorageIdentifier(args, error); 316 if (storage_id.empty()) { 317 return nullptr; 318 } 319 320 return CreateServiceInner(type, name, storage_id, error); 321 } 322 323 ServiceRefPtr VPNProvider::CreateTemporaryServiceFromProfile( 324 const ProfileRefPtr& profile, const std::string& entry_name, Error* error) { 325 string type; 326 string name; 327 string host; 328 if (!GetServiceParametersFromStorage(profile->GetConstStorage(), 329 entry_name, 330 &type, 331 &name, 332 &host, 333 error)) { 334 return nullptr; 335 } 336 337 return CreateServiceInner(type, name, entry_name, error); 338 } 339 340 bool VPNProvider::HasActiveService() const { 341 for (const auto& service : services_) { 342 if (service->IsConnecting() || service->IsConnected()) { 343 return true; 344 } 345 } 346 return false; 347 } 348 349 void VPNProvider::DisconnectAll() { 350 for (const auto& service : services_) { 351 if (service->IsConnecting() || service->IsConnected()) { 352 service->Disconnect(nullptr, "user selected new config"); 353 } 354 } 355 } 356 357 } // namespace shill 358