Home | History | Annotate | Download | only in vpn
      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;
     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 
     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 
     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 
    101 ThirdPartyVpnDriver::~ThirdPartyVpnDriver() {
    102   Cleanup(Service::kStateIdle, Service::kFailureUnknown,
    103           Service::kErrorDetailsNone);
    104 }
    105 
    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 
    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 
    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 
    136 void ThirdPartyVpnDriver::ClearExtensionId(Error* error) {
    137   error->Populate(Error::kNotSupported,
    138                   "Clearing extension id is not supported.");
    139 }
    140 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    509 std::string ThirdPartyVpnDriver::GetProviderType() const {
    510   return std::string(kProviderThirdPartyVpn);
    511 }
    512 
    513 void ThirdPartyVpnDriver::OnConnectionDisconnected() {
    514   Cleanup(Service::kStateFailure, Service::kFailureInternal,
    515           "Underlying network disconnected.");
    516 }
    517 
    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