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