1 //
2 // Copyright (C) 2014 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/third_party_vpn_driver.h"
18
19 #include <algorithm>
20
21 #include <fcntl.h>
22 #include <unistd.h>
23
24 #include <base/posix/eintr_wrapper.h>
25 #include <base/strings/string_number_conversions.h>
26 #include <base/strings/string_split.h>
27 #if defined(__ANDROID__)
28 #include <dbus/service_constants.h>
29 #else
30 #include <chromeos/dbus/service_constants.h>
31 #endif // __ANDROID__
32
33 #include "shill/connection.h"
34 #include "shill/control_interface.h"
35 #include "shill/device_info.h"
36 #include "shill/error.h"
37 #include "shill/file_io.h"
38 #include "shill/ipconfig.h"
39 #include "shill/logging.h"
40 #include "shill/manager.h"
41 #include "shill/property_accessor.h"
42 #include "shill/store_interface.h"
43 #include "shill/virtual_device.h"
44 #include "shill/vpn/vpn_service.h"
45
46 namespace shill {
47
48 namespace Logging {
49
50 static auto kModuleLogScope = ScopeLogger::kVPN;
ObjectID(const ThirdPartyVpnDriver * v)51 static std::string ObjectID(const ThirdPartyVpnDriver* v) {
52 return "(third_party_vpn_driver)";
53 }
54
55 } // namespace Logging
56
57 namespace {
58
59 const int32_t kConstantMaxMtu = (1 << 16) - 1;
60 const int32_t kConnectTimeoutSeconds = 60*5;
61
IPAddressFingerprint(const IPAddress & address)62 std::string IPAddressFingerprint(const IPAddress& address) {
63 static const std::string hex_to_bin[] = {
64 "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
65 "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
66 std::string fingerprint;
67 const size_t address_length = address.address().GetLength();
68 const uint8_t* raw_address = address.address().GetConstData();
69 for (size_t i = 0; i < address_length; ++i) {
70 fingerprint += hex_to_bin[raw_address[i] >> 4];
71 fingerprint += hex_to_bin[raw_address[i] & 0xf];
72 }
73 return fingerprint.substr(0, address.prefix());
74 }
75
76 } // namespace
77
78 const VPNDriver::Property ThirdPartyVpnDriver::kProperties[] = {
79 { kProviderHostProperty, 0 },
80 { kProviderTypeProperty, 0 },
81 { kExtensionNameProperty, 0 },
82 { kConfigurationNameProperty, 0 }
83 };
84
85 ThirdPartyVpnDriver* ThirdPartyVpnDriver::active_client_ = nullptr;
86
ThirdPartyVpnDriver(ControlInterface * control,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager,DeviceInfo * device_info)87 ThirdPartyVpnDriver::ThirdPartyVpnDriver(ControlInterface* control,
88 EventDispatcher* dispatcher,
89 Metrics* metrics, Manager* manager,
90 DeviceInfo* device_info)
91 : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)),
92 control_(control),
93 dispatcher_(dispatcher),
94 metrics_(metrics),
95 device_info_(device_info),
96 tun_fd_(-1),
97 parameters_expected_(false) {
98 file_io_ = FileIO::GetInstance();
99 }
100
~ThirdPartyVpnDriver()101 ThirdPartyVpnDriver::~ThirdPartyVpnDriver() {
102 Cleanup(Service::kStateIdle, Service::kFailureUnknown,
103 Service::kErrorDetailsNone);
104 }
105
InitPropertyStore(PropertyStore * store)106 void ThirdPartyVpnDriver::InitPropertyStore(PropertyStore* store) {
107 VPNDriver::InitPropertyStore(store);
108 store->RegisterDerivedString(
109 kObjectPathSuffixProperty,
110 StringAccessor(
111 new CustomWriteOnlyAccessor<ThirdPartyVpnDriver, std::string>(
112 this, &ThirdPartyVpnDriver::SetExtensionId,
113 &ThirdPartyVpnDriver::ClearExtensionId, nullptr)));
114 }
115
Load(StoreInterface * storage,const std::string & storage_id)116 bool ThirdPartyVpnDriver::Load(StoreInterface* storage,
117 const std::string& storage_id) {
118 bool return_value = VPNDriver::Load(storage, storage_id);
119 if (adaptor_interface_ == nullptr) {
120 storage->GetString(storage_id, kObjectPathSuffixProperty,
121 &object_path_suffix_);
122 adaptor_interface_.reset(control_->CreateThirdPartyVpnAdaptor(this));
123 }
124 return return_value;
125 }
126
Save(StoreInterface * storage,const std::string & storage_id,bool save_credentials)127 bool ThirdPartyVpnDriver::Save(StoreInterface* storage,
128 const std::string& storage_id,
129 bool save_credentials) {
130 bool return_value = VPNDriver::Save(storage, storage_id, save_credentials);
131 storage->SetString(storage_id, kObjectPathSuffixProperty,
132 object_path_suffix_);
133 return return_value;
134 }
135
ClearExtensionId(Error * error)136 void ThirdPartyVpnDriver::ClearExtensionId(Error* error) {
137 error->Populate(Error::kNotSupported,
138 "Clearing extension id is not supported.");
139 }
140
SetExtensionId(const std::string & value,Error * error)141 bool ThirdPartyVpnDriver::SetExtensionId(const std::string& value,
142 Error* error) {
143 if (adaptor_interface_ == nullptr) {
144 object_path_suffix_ = value;
145 adaptor_interface_.reset(control_->CreateThirdPartyVpnAdaptor(this));
146 return true;
147 }
148 error->Populate(Error::kAlreadyExists, "Extension ID is set");
149 return false;
150 }
151
UpdateConnectionState(Service::ConnectState connection_state,std::string * error_message)152 void ThirdPartyVpnDriver::UpdateConnectionState(
153 Service::ConnectState connection_state, std::string* error_message) {
154 if (active_client_ != this) {
155 error_message->append("Unexpected call");
156 return;
157 }
158 if (service_ && connection_state == Service::kStateFailure) {
159 service_->SetState(connection_state);
160 Cleanup(Service::kStateFailure, Service::kFailureUnknown,
161 Service::kErrorDetailsNone);
162 } else if (!service_ || connection_state != Service::kStateOnline) {
163 // We expect "failure" and "connected" messages from the client, but we
164 // only set state for these "failure" messages. "connected" message (which
165 // is corresponding to kStateOnline here) will simply be ignored.
166 error_message->append("Invalid argument");
167 }
168 }
169
SendPacket(const std::vector<uint8_t> & ip_packet,std::string * error_message)170 void ThirdPartyVpnDriver::SendPacket(const std::vector<uint8_t>& ip_packet,
171 std::string* error_message) {
172 if (active_client_ != this) {
173 error_message->append("Unexpected call");
174 return;
175 } else if (tun_fd_ < 0) {
176 error_message->append("Device not open");
177 return;
178 } else if (file_io_->Write(tun_fd_, ip_packet.data(), ip_packet.size()) !=
179 static_cast<ssize_t>(ip_packet.size())) {
180 error_message->append("Partial write");
181 adaptor_interface_->EmitPlatformMessage(
182 static_cast<uint32_t>(PlatformMessage::kError));
183 }
184 }
185
ProcessIp(const std::map<std::string,std::string> & parameters,const char * key,std::string * target,bool mandatory,std::string * error_message)186 void ThirdPartyVpnDriver::ProcessIp(
187 const std::map<std::string, std::string>& parameters, const char* key,
188 std::string* target, bool mandatory, std::string* error_message) {
189 // TODO(kaliamoorthi): Add IPV6 support.
190 auto it = parameters.find(key);
191 if (it != parameters.end()) {
192 if (IPAddress(parameters.at(key)).family() == IPAddress::kFamilyIPv4) {
193 *target = parameters.at(key);
194 } else {
195 error_message->append(key).append(" is not a valid IP;");
196 }
197 } else if (mandatory) {
198 error_message->append(key).append(" is missing;");
199 }
200 }
201
ProcessIPArray(const std::map<std::string,std::string> & parameters,const char * key,char delimiter,std::vector<std::string> * target,bool mandatory,std::string * error_message,std::string * warning_message)202 void ThirdPartyVpnDriver::ProcessIPArray(
203 const std::map<std::string, std::string>& parameters, const char* key,
204 char delimiter, std::vector<std::string>* target, bool mandatory,
205 std::string* error_message, std::string* warning_message) {
206 std::vector<std::string> string_array;
207 auto it = parameters.find(key);
208 if (it != parameters.end()) {
209 string_array = base::SplitString(
210 parameters.at(key), std::string{delimiter}, base::TRIM_WHITESPACE,
211 base::SPLIT_WANT_ALL);
212
213 // Eliminate invalid IPs
214 for (auto value = string_array.begin(); value != string_array.end();) {
215 if (IPAddress(*value).family() != IPAddress::kFamilyIPv4) {
216 warning_message->append(*value + " for " + key + " is invalid;");
217 value = string_array.erase(value);
218 } else {
219 ++value;
220 }
221 }
222
223 if (!string_array.empty()) {
224 target->swap(string_array);
225 } else {
226 error_message->append(key).append(" has no valid values or is empty;");
227 }
228 } else if (mandatory) {
229 error_message->append(key).append(" is missing;");
230 }
231 }
232
ProcessIPArrayCIDR(const std::map<std::string,std::string> & parameters,const char * key,char delimiter,std::vector<std::string> * target,bool mandatory,std::string * error_message,std::string * warning_message)233 void ThirdPartyVpnDriver::ProcessIPArrayCIDR(
234 const std::map<std::string, std::string>& parameters, const char* key,
235 char delimiter, std::vector<std::string>* target, bool mandatory,
236 std::string* error_message, std::string* warning_message) {
237 std::vector<std::string> string_array;
238 IPAddress address(IPAddress::kFamilyIPv4);
239 auto it = parameters.find(key);
240 if (it != parameters.end()) {
241 string_array = base::SplitString(
242 parameters.at(key), std::string{delimiter}, base::TRIM_WHITESPACE,
243 base::SPLIT_WANT_ALL);
244
245 // Eliminate invalid IPs
246 for (auto value = string_array.begin(); value != string_array.end();) {
247 if (!address.SetAddressAndPrefixFromString(*value)) {
248 warning_message->append(*value + " for " + key + " is invalid;");
249 value = string_array.erase(value);
250 continue;
251 }
252 const std::string cidr_key = IPAddressFingerprint(address);
253 if (known_cidrs_.find(cidr_key) != known_cidrs_.end()) {
254 warning_message->append("Duplicate entry for " + *value + " in " + key +
255 " found;");
256 value = string_array.erase(value);
257 } else {
258 known_cidrs_.insert(cidr_key);
259 ++value;
260 }
261 }
262
263 if (!string_array.empty()) {
264 target->swap(string_array);
265 } else {
266 error_message->append(key).append(" has no valid values or is empty;");
267 }
268 } else if (mandatory) {
269 error_message->append(key).append(" is missing;");
270 }
271 }
272
ProcessSearchDomainArray(const std::map<std::string,std::string> & parameters,const char * key,char delimiter,std::vector<std::string> * target,bool mandatory,std::string * error_message)273 void ThirdPartyVpnDriver::ProcessSearchDomainArray(
274 const std::map<std::string, std::string>& parameters, const char* key,
275 char delimiter, std::vector<std::string>* target, bool mandatory,
276 std::string* error_message) {
277 std::vector<std::string> string_array;
278 auto it = parameters.find(key);
279 if (it != parameters.end()) {
280 string_array = base::SplitString(
281 parameters.at(key), std::string{delimiter}, base::TRIM_WHITESPACE,
282 base::SPLIT_WANT_ALL);
283
284 if (!string_array.empty()) {
285 target->swap(string_array);
286 } else {
287 error_message->append(key).append(" has no valid values or is empty;");
288 }
289 } else if (mandatory) {
290 error_message->append(key).append(" is missing;");
291 }
292 }
293
ProcessInt32(const std::map<std::string,std::string> & parameters,const char * key,int32_t * target,int32_t min_value,int32_t max_value,bool mandatory,std::string * error_message)294 void ThirdPartyVpnDriver::ProcessInt32(
295 const std::map<std::string, std::string>& parameters, const char* key,
296 int32_t* target, int32_t min_value, int32_t max_value, bool mandatory,
297 std::string* error_message) {
298 int32_t value = 0;
299 auto it = parameters.find(key);
300 if (it != parameters.end()) {
301 if (base::StringToInt(parameters.at(key), &value) && value >= min_value &&
302 value <= max_value) {
303 *target = value;
304 } else {
305 error_message->append(key).append(" not in expected range;");
306 }
307 } else if (mandatory) {
308 error_message->append(key).append(" is missing;");
309 }
310 }
311
SetParameters(const std::map<std::string,std::string> & parameters,std::string * error_message,std::string * warning_message)312 void ThirdPartyVpnDriver::SetParameters(
313 const std::map<std::string, std::string>& parameters,
314 std::string* error_message, std::string* warning_message) {
315 // TODO(kaliamoorthi): Add IPV6 support.
316 if (!parameters_expected_ || active_client_ != this) {
317 error_message->append("Unexpected call");
318 return;
319 }
320
321 ip_properties_ = IPConfig::Properties();
322 ip_properties_.address_family = IPAddress::kFamilyIPv4;
323
324 ProcessIp(parameters, kAddressParameterThirdPartyVpn, &ip_properties_.address,
325 true, error_message);
326 ProcessIp(parameters, kBroadcastAddressParameterThirdPartyVpn,
327 &ip_properties_.broadcast_address, false, error_message);
328
329 ip_properties_.gateway = ip_properties_.address;
330
331 ProcessInt32(parameters, kSubnetPrefixParameterThirdPartyVpn,
332 &ip_properties_.subnet_prefix, 0, 32, true, error_message);
333 ProcessInt32(parameters, kMtuParameterThirdPartyVpn, &ip_properties_.mtu,
334 IPConfig::kMinIPv4MTU, kConstantMaxMtu, false, error_message);
335
336 ProcessSearchDomainArray(parameters, kDomainSearchParameterThirdPartyVpn,
337 kNonIPDelimiter, &ip_properties_.domain_search,
338 false, error_message);
339 ProcessIPArray(parameters, kDnsServersParameterThirdPartyVpn, kIPDelimiter,
340 &ip_properties_.dns_servers, true, error_message,
341 warning_message);
342
343 known_cidrs_.clear();
344
345 ProcessIPArrayCIDR(parameters, kExclusionListParameterThirdPartyVpn,
346 kIPDelimiter, &ip_properties_.exclusion_list, true,
347 error_message, warning_message);
348 if (!ip_properties_.exclusion_list.empty()) {
349 // The first excluded IP is used to find the default gateway. The logic that
350 // finds the default gateway does not work for default route "0.0.0.0/0".
351 // Hence, this code ensures that the first IP is not default.
352 IPAddress address(ip_properties_.address_family);
353 address.SetAddressAndPrefixFromString(ip_properties_.exclusion_list[0]);
354 if (address.IsDefault() && !address.prefix()) {
355 if (ip_properties_.exclusion_list.size() > 1) {
356 swap(ip_properties_.exclusion_list[0],
357 ip_properties_.exclusion_list[1]);
358 } else {
359 // When there is only a single entry which is a default address, it can
360 // be cleared since the default behavior is to not route any traffic to
361 // the tunnel interface.
362 ip_properties_.exclusion_list.clear();
363 }
364 }
365 }
366
367 std::vector<std::string> inclusion_list;
368 ProcessIPArrayCIDR(parameters, kInclusionListParameterThirdPartyVpn,
369 kIPDelimiter, &inclusion_list, true, error_message,
370 warning_message);
371
372 IPAddress ip_address(ip_properties_.address_family);
373 IPConfig::Route route;
374 route.gateway = ip_properties_.gateway;
375 for (auto value = inclusion_list.begin(); value != inclusion_list.end();
376 ++value) {
377 ip_address.SetAddressAndPrefixFromString(*value);
378 ip_address.IntoString(&route.host);
379 IPAddress::GetAddressMaskFromPrefix(
380 ip_address.family(), ip_address.prefix()).IntoString(&route.netmask);
381 ip_properties_.routes.push_back(route);
382 }
383
384 if (error_message->empty()) {
385 ip_properties_.user_traffic_only = true;
386 ip_properties_.default_route = false;
387 ip_properties_.blackhole_ipv6 = true;
388 device_->SelectService(service_);
389 device_->UpdateIPConfig(ip_properties_);
390 device_->SetLooseRouting(true);
391 StopConnectTimeout();
392 parameters_expected_ = false;
393 }
394 }
395
OnInput(InputData * data)396 void ThirdPartyVpnDriver::OnInput(InputData* data) {
397 // TODO(kaliamoorthi): This is not efficient, transfer the descriptor over to
398 // chrome browser or use a pipe in between. Avoid using DBUS for packet
399 // transfer.
400 std::vector<uint8_t> ip_packet(data->buf, data->buf + data->len);
401 adaptor_interface_->EmitPacketReceived(ip_packet);
402 }
403
OnInputError(const std::string & error)404 void ThirdPartyVpnDriver::OnInputError(const std::string& error) {
405 LOG(ERROR) << error;
406 CHECK_EQ(active_client_, this);
407 adaptor_interface_->EmitPlatformMessage(
408 static_cast<uint32_t>(PlatformMessage::kError));
409 }
410
Cleanup(Service::ConnectState state,Service::ConnectFailure failure,const std::string & error_details)411 void ThirdPartyVpnDriver::Cleanup(Service::ConnectState state,
412 Service::ConnectFailure failure,
413 const std::string& error_details) {
414 SLOG(this, 2) << __func__ << "(" << Service::ConnectStateToString(state)
415 << ", " << error_details << ")";
416 StopConnectTimeout();
417 int interface_index = -1;
418 if (device_) {
419 interface_index = device_->interface_index();
420 device_->DropConnection();
421 device_->SetEnabled(false);
422 device_ = nullptr;
423 }
424 if (interface_index >= 0) {
425 device_info_->DeleteInterface(interface_index);
426 }
427 tunnel_interface_.clear();
428 if (service_) {
429 if (state == Service::kStateFailure) {
430 service_->SetErrorDetails(error_details);
431 service_->SetFailure(failure);
432 } else {
433 service_->SetState(state);
434 }
435 service_ = nullptr;
436 }
437 if (tun_fd_ > 0) {
438 file_io_->Close(tun_fd_);
439 tun_fd_ = -1;
440 }
441 io_handler_.reset();
442 if (active_client_ == this) {
443 adaptor_interface_->EmitPlatformMessage(
444 static_cast<uint32_t>(PlatformMessage::kDisconnected));
445 active_client_ = nullptr;
446 }
447 parameters_expected_ = false;
448 }
449
Connect(const VPNServiceRefPtr & service,Error * error)450 void ThirdPartyVpnDriver::Connect(const VPNServiceRefPtr& service,
451 Error* error) {
452 SLOG(this, 2) << __func__;
453 CHECK(adaptor_interface_);
454 CHECK(!active_client_);
455 StartConnectTimeout(kConnectTimeoutSeconds);
456 ip_properties_ = IPConfig::Properties();
457 service_ = service;
458 service_->SetState(Service::kStateConfiguring);
459 if (!device_info_->CreateTunnelInterface(&tunnel_interface_)) {
460 Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
461 "Could not create tunnel interface.");
462 Cleanup(Service::kStateFailure, Service::kFailureInternal,
463 "Unable to create tun interface");
464 }
465 // Wait for the ClaimInterface callback to continue the connection process.
466 }
467
ClaimInterface(const std::string & link_name,int interface_index)468 bool ThirdPartyVpnDriver::ClaimInterface(const std::string& link_name,
469 int interface_index) {
470 if (link_name != tunnel_interface_) {
471 return false;
472 }
473 CHECK(!active_client_);
474
475 SLOG(this, 2) << "Claiming " << link_name << " for third party VPN tunnel";
476
477 CHECK(!device_);
478 device_ = new VirtualDevice(control_, dispatcher(), metrics_, manager(),
479 link_name, interface_index, Technology::kVPN);
480 device_->SetEnabled(true);
481
482 tun_fd_ = device_info_->OpenTunnelInterface(tunnel_interface_);
483 if (tun_fd_ < 0) {
484 Cleanup(Service::kStateFailure, Service::kFailureInternal,
485 "Unable to open tun interface");
486 } else {
487 io_handler_.reset(dispatcher_->CreateInputHandler(
488 tun_fd_,
489 base::Bind(&ThirdPartyVpnDriver::OnInput, base::Unretained(this)),
490 base::Bind(&ThirdPartyVpnDriver::OnInputError,
491 base::Unretained(this))));
492 active_client_ = this;
493 parameters_expected_ = true;
494 adaptor_interface_->EmitPlatformMessage(
495 static_cast<uint32_t>(PlatformMessage::kConnected));
496 }
497 return true;
498 }
499
Disconnect()500 void ThirdPartyVpnDriver::Disconnect() {
501 SLOG(this, 2) << __func__;
502 CHECK(adaptor_interface_);
503 if (active_client_ == this) {
504 Cleanup(Service::kStateIdle, Service::kFailureUnknown,
505 Service::kErrorDetailsNone);
506 }
507 }
508
GetProviderType() const509 std::string ThirdPartyVpnDriver::GetProviderType() const {
510 return std::string(kProviderThirdPartyVpn);
511 }
512
OnConnectionDisconnected()513 void ThirdPartyVpnDriver::OnConnectionDisconnected() {
514 Cleanup(Service::kStateFailure, Service::kFailureInternal,
515 "Underlying network disconnected.");
516 }
517
OnConnectTimeout()518 void ThirdPartyVpnDriver::OnConnectTimeout() {
519 SLOG(this, 2) << __func__;
520 VPNDriver::OnConnectTimeout();
521 adaptor_interface_->EmitPlatformMessage(
522 static_cast<uint32_t>(PlatformMessage::kError));
523 Cleanup(Service::kStateFailure, Service::kFailureConnect,
524 "Connection timed out");
525 }
526
527 } // namespace shill
528