Home | History | Annotate | Download | only in vpn
      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