• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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