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
46namespace shill {
47
48namespace Logging {
49
50static auto kModuleLogScope = ScopeLogger::kVPN;
51static std::string ObjectID(const ThirdPartyVpnDriver* v) {
52  return "(third_party_vpn_driver)";
53}
54
55}  // namespace Logging
56
57namespace {
58
59const int32_t kConstantMaxMtu = (1 << 16) - 1;
60const int32_t kConnectTimeoutSeconds = 60*5;
61
62std::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
78const VPNDriver::Property ThirdPartyVpnDriver::kProperties[] = {
79  { kProviderHostProperty, 0 },
80  { kProviderTypeProperty, 0 },
81  { kExtensionNameProperty, 0 },
82  { kConfigurationNameProperty, 0 }
83};
84
85ThirdPartyVpnDriver* ThirdPartyVpnDriver::active_client_ = nullptr;
86
87ThirdPartyVpnDriver::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
101ThirdPartyVpnDriver::~ThirdPartyVpnDriver() {
102  Cleanup(Service::kStateIdle, Service::kFailureUnknown,
103          Service::kErrorDetailsNone);
104}
105
106void 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
116bool 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
127bool 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
136void ThirdPartyVpnDriver::ClearExtensionId(Error* error) {
137  error->Populate(Error::kNotSupported,
138                  "Clearing extension id is not supported.");
139}
140
141bool 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
152void 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
170void 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
186void 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
202void 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
233void 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
273void 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
294void 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
312void 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
396void 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
404void 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
411void 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
450void 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
468bool 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
500void 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
509std::string ThirdPartyVpnDriver::GetProviderType() const {
510  return std::string(kProviderThirdPartyVpn);
511}
512
513void ThirdPartyVpnDriver::OnConnectionDisconnected() {
514  Cleanup(Service::kStateFailure, Service::kFailureInternal,
515          "Underlying network disconnected.");
516}
517
518void 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