• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
ObjectID(const VPNProvider * v)48 static string ObjectID(const VPNProvider* v) { return "(vpn_provider)"; }
49 }
50 
VPNProvider(ControlInterface * control_interface,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager)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 
~VPNProvider()60 VPNProvider::~VPNProvider() {}
61 
Start()62 void VPNProvider::Start() {}
63 
Stop()64 void VPNProvider::Stop() {}
65 
66 // static
GetServiceParametersFromArgs(const KeyValueStore & args,string * type_ptr,string * name_ptr,string * host_ptr,Error * error)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
GetServiceParametersFromStorage(const StoreInterface * storage,const string & entry_name,string * vpn_type_ptr,string * name_ptr,string * host_ptr,Error * error)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 
GetService(const KeyValueStore & args,Error * error)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 
FindSimilarService(const KeyValueStore & args,Error * error) const153 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 
OnDeviceInfoAvailable(const string & link_name,int interface_index)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 
RemoveService(VPNServiceRefPtr service)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 
CreateServicesFromProfile(const ProfileRefPtr & profile)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 
CreateServiceInner(const string & type,const string & name,const string & storage_id,Error * error)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 
CreateService(const string & type,const string & name,const string & storage_id,Error * error)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 
FindService(const string & type,const string & name,const string & host) const292 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 
CreateTemporaryService(const KeyValueStore & args,Error * error)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 
CreateTemporaryServiceFromProfile(const ProfileRefPtr & profile,const std::string & entry_name,Error * error)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 
HasActiveService() const340 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 
DisconnectAll()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