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