1 // 2 // Copyright (C) 2012 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/openvpn_driver.h" 18 19 #include <arpa/inet.h> 20 21 #include <base/files/file_util.h> 22 #include <base/strings/string_number_conversions.h> 23 #include <base/strings/string_split.h> 24 #include <base/strings/string_util.h> 25 #if defined(__ANDROID__) 26 #include <dbus/service_constants.h> 27 #else 28 #include <chromeos/dbus/service_constants.h> 29 #endif // __ANDROID__ 30 31 #include "shill/certificate_file.h" 32 #include "shill/connection.h" 33 #include "shill/device_info.h" 34 #include "shill/error.h" 35 #include "shill/ipconfig.h" 36 #include "shill/logging.h" 37 #include "shill/manager.h" 38 #include "shill/net/sockets.h" 39 #include "shill/process_manager.h" 40 #include "shill/rpc_task.h" 41 #include "shill/virtual_device.h" 42 #include "shill/vpn/openvpn_management_server.h" 43 #include "shill/vpn/vpn_service.h" 44 45 using base::Closure; 46 using base::FilePath; 47 using base::SplitString; 48 using base::Unretained; 49 using base::WeakPtr; 50 using std::map; 51 using std::string; 52 using std::vector; 53 54 namespace shill { 55 56 namespace Logging { 57 static auto kModuleLogScope = ScopeLogger::kVPN; 58 static string ObjectID(const OpenVPNDriver* o) { 59 return o->GetServiceRpcIdentifier(); 60 } 61 } 62 63 namespace { 64 65 const char kChromeOSReleaseName[] = "CHROMEOS_RELEASE_NAME"; 66 const char kChromeOSReleaseVersion[] = "CHROMEOS_RELEASE_VERSION"; 67 const char kOpenVPNEnvVarPlatformName[] = "IV_PLAT"; 68 const char kOpenVPNEnvVarPlatformVersion[] = "IV_PLAT_REL"; 69 const char kOpenVPNForeignOptionPrefix[] = "foreign_option_"; 70 const char kOpenVPNIfconfigBroadcast[] = "ifconfig_broadcast"; 71 const char kOpenVPNIfconfigLocal[] = "ifconfig_local"; 72 const char kOpenVPNIfconfigNetmask[] = "ifconfig_netmask"; 73 const char kOpenVPNIfconfigRemote[] = "ifconfig_remote"; 74 const char kOpenVPNRedirectGateway[] = "redirect_gateway"; 75 const char kOpenVPNRedirectPrivate[] = "redirect_private"; 76 const char kOpenVPNRouteOptionPrefix[] = "route_"; 77 const char kOpenVPNRouteVPNGateway[] = "route_vpn_gateway"; 78 const char kOpenVPNTrustedIP[] = "trusted_ip"; 79 const char kOpenVPNTunMTU[] = "tun_mtu"; 80 81 const char kDefaultPKCS11Provider[] = "libchaps.so"; 82 83 // Some configurations pass the netmask in the ifconfig_remote property. 84 // This is due to some servers not explicitly indicating that they are using 85 // a "broadcast mode" network instead of peer-to-peer. See 86 // http://crbug.com/241264 for an example of this issue. 87 const char kSuspectedNetmaskPrefix[] = "255."; 88 89 void DoNothingWithExitStatus(int exit_status) { 90 } 91 92 } // namespace 93 94 // static 95 const char OpenVPNDriver::kDefaultCACertificates[] = 96 "/etc/ssl/certs/ca-certificates.crt"; 97 // static 98 const char OpenVPNDriver::kOpenVPNPath[] = "/usr/sbin/openvpn"; 99 // static 100 const char OpenVPNDriver::kOpenVPNScript[] = SHIMDIR "/openvpn-script"; 101 // static 102 const VPNDriver::Property OpenVPNDriver::kProperties[] = { 103 { kOpenVPNAuthNoCacheProperty, 0 }, 104 { kOpenVPNAuthProperty, 0 }, 105 { kOpenVPNAuthRetryProperty, 0 }, 106 { kOpenVPNAuthUserPassProperty, 0 }, 107 { kOpenVPNCaCertNSSProperty, 0 }, 108 { kOpenVPNCaCertProperty, 0 }, 109 { kOpenVPNCipherProperty, 0 }, 110 { kOpenVPNClientCertIdProperty, Property::kCredential }, 111 { kOpenVPNCompLZOProperty, 0 }, 112 { kOpenVPNCompNoAdaptProperty, 0 }, 113 { kOpenVPNIgnoreDefaultRouteProperty, 0 }, 114 { kOpenVPNKeyDirectionProperty, 0 }, 115 { kOpenVPNNsCertTypeProperty, 0 }, 116 { kOpenVPNOTPProperty, 117 Property::kEphemeral | Property::kCredential | Property::kWriteOnly }, 118 { kOpenVPNPasswordProperty, Property::kCredential | Property::kWriteOnly }, 119 { kOpenVPNPinProperty, Property::kCredential }, 120 { kOpenVPNPortProperty, 0 }, 121 { kOpenVPNProtoProperty, 0 }, 122 { kOpenVPNProviderProperty, 0 }, 123 { kOpenVPNPushPeerInfoProperty, 0 }, 124 { kOpenVPNRemoteCertEKUProperty, 0 }, 125 { kOpenVPNRemoteCertKUProperty, 0 }, 126 { kOpenVPNRemoteCertTLSProperty, 0 }, 127 { kOpenVPNRenegSecProperty, 0 }, 128 { kOpenVPNServerPollTimeoutProperty, 0 }, 129 { kOpenVPNShaperProperty, 0 }, 130 { kOpenVPNStaticChallengeProperty, 0 }, 131 { kOpenVPNTLSAuthContentsProperty, 0 }, 132 { kOpenVPNTLSRemoteProperty, 0 }, 133 { kOpenVPNTokenProperty, 134 Property::kEphemeral | Property::kCredential | Property::kWriteOnly }, 135 { kOpenVPNUserProperty, 0 }, 136 { kProviderHostProperty, 0 }, 137 { kProviderTypeProperty, 0 }, 138 { kOpenVPNCaCertPemProperty, Property::kArray }, 139 { kOpenVPNCertProperty, 0 }, 140 { kOpenVPNExtraCertPemProperty, Property::kArray }, 141 { kOpenVPNKeyProperty, 0 }, 142 { kOpenVPNPingExitProperty, 0 }, 143 { kOpenVPNPingProperty, 0 }, 144 { kOpenVPNPingRestartProperty, 0 }, 145 { kOpenVPNTLSAuthProperty, 0 }, 146 { kOpenVPNVerbProperty, 0 }, 147 { kOpenVPNVerifyHashProperty, 0 }, 148 { kOpenVPNVerifyX509NameProperty, 0 }, 149 { kOpenVPNVerifyX509TypeProperty, 0 }, 150 { kVPNMTUProperty, 0 }, 151 }; 152 153 const char OpenVPNDriver::kLSBReleaseFile[] = "/etc/lsb-release"; 154 155 // Directory where OpenVPN configuration files are exported while the 156 // process is running. 157 const char OpenVPNDriver::kDefaultOpenVPNConfigurationDirectory[] = 158 RUNDIR "/openvpn_config"; 159 160 const int OpenVPNDriver::kReconnectOfflineTimeoutSeconds = 2 * 60; 161 const int OpenVPNDriver::kReconnectTLSErrorTimeoutSeconds = 20; 162 163 OpenVPNDriver::OpenVPNDriver(ControlInterface* control, 164 EventDispatcher* dispatcher, 165 Metrics* metrics, 166 Manager* manager, 167 DeviceInfo* device_info, 168 ProcessManager* process_manager) 169 : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)), 170 control_(control), 171 metrics_(metrics), 172 device_info_(device_info), 173 process_manager_(process_manager), 174 management_server_(new OpenVPNManagementServer(this)), 175 certificate_file_(new CertificateFile()), 176 extra_certificates_file_(new CertificateFile()), 177 lsb_release_file_(kLSBReleaseFile), 178 openvpn_config_directory_(kDefaultOpenVPNConfigurationDirectory), 179 pid_(0), 180 default_service_callback_tag_(0) {} 181 182 OpenVPNDriver::~OpenVPNDriver() { 183 IdleService(); 184 } 185 186 void OpenVPNDriver::IdleService() { 187 Cleanup(Service::kStateIdle, 188 Service::kFailureUnknown, 189 Service::kErrorDetailsNone); 190 } 191 192 void OpenVPNDriver::FailService(Service::ConnectFailure failure, 193 const string& error_details) { 194 Cleanup(Service::kStateFailure, failure, error_details); 195 } 196 197 void OpenVPNDriver::Cleanup(Service::ConnectState state, 198 Service::ConnectFailure failure, 199 const string& error_details) { 200 SLOG(this, 2) << __func__ << "(" << Service::ConnectStateToString(state) 201 << ", " << error_details << ")"; 202 StopConnectTimeout(); 203 // Disconnecting the management interface will terminate the openvpn 204 // process. Ensure this is handled robustly by first unregistering 205 // the callback for OnOpenVPNDied, and then terminating and reaping 206 // the process with StopProcess(). 207 if (pid_) { 208 process_manager_->UpdateExitCallback( 209 pid_, base::Bind(DoNothingWithExitStatus)); 210 } 211 management_server_->Stop(); 212 if (!tls_auth_file_.empty()) { 213 base::DeleteFile(tls_auth_file_, false); 214 tls_auth_file_.clear(); 215 } 216 if (!openvpn_config_file_.empty()) { 217 base::DeleteFile(openvpn_config_file_, false); 218 openvpn_config_file_.clear(); 219 } 220 if (default_service_callback_tag_) { 221 manager()->DeregisterDefaultServiceCallback(default_service_callback_tag_); 222 default_service_callback_tag_ = 0; 223 } 224 rpc_task_.reset(); 225 int interface_index = -1; 226 if (device_) { 227 interface_index = device_->interface_index(); 228 device_->DropConnection(); 229 device_->SetEnabled(false); 230 device_ = nullptr; 231 } 232 if (pid_) { 233 if (interface_index >= 0) { 234 // NB: |callback| must be bound to a static method, as 235 // |callback| may be called after our dtor completes. 236 const auto callback( 237 Bind(OnOpenVPNExited, device_info_->AsWeakPtr(), interface_index)); 238 interface_index = -1; 239 process_manager_->UpdateExitCallback(pid_, callback); 240 } 241 process_manager_->StopProcess(pid_); 242 pid_ = 0; 243 } 244 if (interface_index >= 0) { 245 device_info_->DeleteInterface(interface_index); 246 } 247 tunnel_interface_.clear(); 248 if (service_) { 249 if (state == Service::kStateFailure) { 250 service_->SetErrorDetails(error_details); 251 service_->SetFailure(failure); 252 } else { 253 service_->SetState(state); 254 } 255 service_ = nullptr; 256 } 257 ip_properties_ = IPConfig::Properties(); 258 } 259 260 // static 261 string OpenVPNDriver::JoinOptions(const vector<vector<string>>& options, 262 char separator) { 263 vector<string> option_strings; 264 for (const auto& option : options) { 265 vector<string> quoted_option; 266 for (const auto& argument : option) { 267 if (argument.find(' ') != string::npos || 268 argument.find('\t') != string::npos || 269 argument.find('"') != string::npos || 270 argument.find(separator) != string::npos) { 271 string quoted_argument(argument); 272 const char separator_chars[] = { separator, '\0' }; 273 base::ReplaceChars(argument, separator_chars, " ", "ed_argument); 274 base::ReplaceChars(quoted_argument, "\\", "\\\\", "ed_argument); 275 base::ReplaceChars(quoted_argument, "\"", "\\\"", "ed_argument); 276 quoted_option.push_back("\"" + quoted_argument + "\""); 277 } else { 278 quoted_option.push_back(argument); 279 } 280 } 281 option_strings.push_back(base::JoinString(quoted_option, " ")); 282 } 283 return base::JoinString(option_strings, string{separator}); 284 } 285 286 bool OpenVPNDriver::WriteConfigFile( 287 const vector<vector<string>>& options, 288 FilePath* config_file) { 289 if (!base::DirectoryExists(openvpn_config_directory_)) { 290 if (!base::CreateDirectory(openvpn_config_directory_)) { 291 LOG(ERROR) << "Unable to create configuration directory " 292 << openvpn_config_directory_.value(); 293 return false; 294 } 295 if (chmod(openvpn_config_directory_.value().c_str(), S_IRWXU)) { 296 LOG(ERROR) << "Failed to set permissions on " 297 << openvpn_config_directory_.value(); 298 base::DeleteFile(openvpn_config_directory_, true); 299 return false; 300 } 301 } 302 303 string contents = JoinOptions(options, '\n'); 304 contents.push_back('\n'); 305 if (!base::CreateTemporaryFileInDir(openvpn_config_directory_, config_file) || 306 base::WriteFile(*config_file, contents.data(), contents.size()) != 307 static_cast<int>(contents.size())) { 308 LOG(ERROR) << "Unable to setup OpenVPN config file."; 309 return false; 310 } 311 return true; 312 } 313 314 bool OpenVPNDriver::SpawnOpenVPN() { 315 SLOG(this, 2) << __func__ << "(" << tunnel_interface_ << ")"; 316 317 vector<vector<string>> options; 318 Error error; 319 InitOptions(&options, &error); 320 if (error.IsFailure()) { 321 return false; 322 } 323 LOG(INFO) << "OpenVPN process options: " << JoinOptions(options, ','); 324 if (!WriteConfigFile(options, &openvpn_config_file_)) { 325 return false; 326 } 327 328 // TODO(quiche): This should be migrated to use ExternalTask. 329 // (crbug.com/246263). 330 CHECK(!pid_); 331 pid_t pid = process_manager_->StartProcess( 332 FROM_HERE, FilePath(kOpenVPNPath), 333 vector<string>{"--config", openvpn_config_file_.value()}, 334 GetEnvironment(), 335 false, // Do not terminate with parent. 336 base::Bind(&OpenVPNDriver::OnOpenVPNDied, base::Unretained(this))); 337 if (pid < 0) { 338 LOG(ERROR) << "Unable to spawn: " << kOpenVPNPath; 339 return false; 340 } 341 342 pid_ = pid; 343 return true; 344 } 345 346 void OpenVPNDriver::OnOpenVPNDied(int exit_status) { 347 SLOG(nullptr, 2) << __func__ << "(" << pid_ << ", " << exit_status << ")"; 348 pid_ = 0; 349 FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 350 // TODO(petkov): Figure if we need to restart the connection. 351 } 352 353 // static 354 void OpenVPNDriver::OnOpenVPNExited(const WeakPtr<DeviceInfo>& device_info, 355 int interface_index, 356 int /* exit_status */) { 357 if (device_info) { 358 LOG(INFO) << "Deleting interface " << interface_index; 359 device_info->DeleteInterface(interface_index); 360 } 361 } 362 363 bool OpenVPNDriver::ClaimInterface(const string& link_name, 364 int interface_index) { 365 if (link_name != tunnel_interface_) { 366 return false; 367 } 368 369 SLOG(this, 2) << "Claiming " << link_name << " for OpenVPN tunnel"; 370 371 CHECK(!device_); 372 device_ = new VirtualDevice(control_, dispatcher(), metrics_, manager(), 373 link_name, interface_index, Technology::kVPN); 374 device_->SetEnabled(true); 375 376 rpc_task_.reset(new RPCTask(control_, this)); 377 if (SpawnOpenVPN()) { 378 default_service_callback_tag_ = 379 manager()->RegisterDefaultServiceCallback( 380 Bind(&OpenVPNDriver::OnDefaultServiceChanged, Unretained(this))); 381 } else { 382 FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 383 } 384 return true; 385 } 386 387 void OpenVPNDriver::GetLogin(string* /*user*/, string* /*password*/) { 388 NOTREACHED(); 389 } 390 391 void OpenVPNDriver::Notify(const string& reason, 392 const map<string, string>& dict) { 393 LOG(INFO) << "IP configuration received: " << reason; 394 if (reason != "up") { 395 device_->DropConnection(); 396 return; 397 } 398 // On restart/reconnect, update the existing IP configuration. 399 ParseIPConfiguration(dict, &ip_properties_); 400 device_->SelectService(service_); 401 device_->UpdateIPConfig(ip_properties_); 402 ReportConnectionMetrics(); 403 StopConnectTimeout(); 404 } 405 406 void OpenVPNDriver::ParseIPConfiguration( 407 const map<string, string>& configuration, 408 IPConfig::Properties* properties) const { 409 ForeignOptions foreign_options; 410 RouteOptions routes; 411 bool is_gateway_route_required = false; 412 413 properties->address_family = IPAddress::kFamilyIPv4; 414 if (!properties->subnet_prefix) { 415 properties->subnet_prefix = 416 IPAddress::GetMaxPrefixLength(properties->address_family); 417 } 418 for (const auto& configuration_map : configuration) { 419 const string& key = configuration_map.first; 420 const string& value = configuration_map.second; 421 SLOG(this, 2) << "Processing: " << key << " -> " << value; 422 if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigLocal)) { 423 properties->address = value; 424 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigBroadcast)) { 425 properties->broadcast_address = value; 426 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigNetmask)) { 427 properties->subnet_prefix = 428 IPAddress::GetPrefixLengthFromMask(properties->address_family, value); 429 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigRemote)) { 430 if (base::StartsWith(value, kSuspectedNetmaskPrefix, 431 base::CompareCase::INSENSITIVE_ASCII)) { 432 LOG(WARNING) << "Option " << key << " value " << value 433 << " looks more like a netmask than a peer address; " 434 << "assuming it is the former."; 435 // In this situation, the "peer_address" value will be left 436 // unset and Connection::UpdateFromIPConfig() will treat the 437 // interface as if it were a broadcast-style network. The 438 // kernel will, automatically set the peer address equal to 439 // the local address. 440 properties->subnet_prefix = 441 IPAddress::GetPrefixLengthFromMask(properties->address_family, 442 value); 443 } else { 444 properties->peer_address = value; 445 } 446 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNRedirectGateway) || 447 base::LowerCaseEqualsASCII(key, kOpenVPNRedirectPrivate)) { 448 is_gateway_route_required = true; 449 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNRouteVPNGateway)) { 450 properties->gateway = value; 451 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNTrustedIP)) { 452 size_t prefix = IPAddress::GetMaxPrefixLength(properties->address_family); 453 properties->exclusion_list.push_back(value + "/" + 454 base::SizeTToString(prefix)); 455 456 } else if (base::LowerCaseEqualsASCII(key, kOpenVPNTunMTU)) { 457 int mtu = 0; 458 if (base::StringToInt(value, &mtu) && mtu >= IPConfig::kMinIPv4MTU) { 459 properties->mtu = mtu; 460 } else { 461 LOG(ERROR) << "MTU " << value << " ignored."; 462 } 463 } else if (base::StartsWith(key, kOpenVPNForeignOptionPrefix, 464 base::CompareCase::INSENSITIVE_ASCII)) { 465 const string suffix = key.substr(strlen(kOpenVPNForeignOptionPrefix)); 466 int order = 0; 467 if (base::StringToInt(suffix, &order)) { 468 foreign_options[order] = value; 469 } else { 470 LOG(ERROR) << "Ignored unexpected foreign option suffix: " << suffix; 471 } 472 } else if (base::StartsWith(key, kOpenVPNRouteOptionPrefix, 473 base::CompareCase::INSENSITIVE_ASCII)) { 474 ParseRouteOption(key.substr(strlen(kOpenVPNRouteOptionPrefix)), 475 value, &routes); 476 } else { 477 SLOG(this, 2) << "Key ignored."; 478 } 479 } 480 ParseForeignOptions(foreign_options, properties); 481 SetRoutes(routes, properties); 482 483 if (const_args()->ContainsString(kOpenVPNIgnoreDefaultRouteProperty)) { 484 if (is_gateway_route_required) { 485 LOG(INFO) << "Configuration request to ignore default route is " 486 << "overridden by the remote server."; 487 } else { 488 SLOG(this, 2) << "Ignoring default route parameter as requested by " 489 << "configuration."; 490 properties->gateway.clear(); 491 } 492 } 493 } 494 495 // static 496 void OpenVPNDriver::ParseForeignOptions(const ForeignOptions& options, 497 IPConfig::Properties* properties) { 498 vector<string> domain_search; 499 vector<string> dns_servers; 500 for (const auto& option_map : options) { 501 ParseForeignOption(option_map.second, &domain_search, &dns_servers); 502 } 503 if (!domain_search.empty()) { 504 properties->domain_search.swap(domain_search); 505 } 506 LOG_IF(WARNING, properties->domain_search.empty()) 507 << "No search domains provided."; 508 if (!dns_servers.empty()) { 509 properties->dns_servers.swap(dns_servers); 510 } 511 LOG_IF(WARNING, properties->dns_servers.empty()) 512 << "No DNS servers provided."; 513 } 514 515 // static 516 void OpenVPNDriver::ParseForeignOption(const string& option, 517 vector<string>* domain_search, 518 vector<string>* dns_servers) { 519 SLOG(nullptr, 2) << __func__ << "(" << option << ")"; 520 vector<string> tokens = SplitString(option, " ", base::TRIM_WHITESPACE, 521 base::SPLIT_WANT_ALL); 522 if (tokens.size() != 3 || 523 !base::LowerCaseEqualsASCII(tokens[0], "dhcp-option")) { 524 return; 525 } 526 if (base::LowerCaseEqualsASCII(tokens[1], "domain")) { 527 domain_search->push_back(tokens[2]); 528 } else if (base::LowerCaseEqualsASCII(tokens[1], "dns")) { 529 dns_servers->push_back(tokens[2]); 530 } 531 } 532 533 // static 534 IPConfig::Route* OpenVPNDriver::GetRouteOptionEntry( 535 const string& prefix, const string& key, RouteOptions* routes) { 536 int order = 0; 537 if (!base::StartsWith(key, prefix, base::CompareCase::INSENSITIVE_ASCII) || 538 !base::StringToInt(key.substr(prefix.size()), &order)) { 539 return nullptr; 540 } 541 return&(*routes)[order]; 542 } 543 544 // static 545 void OpenVPNDriver::ParseRouteOption( 546 const string& key, const string& value, RouteOptions* routes) { 547 IPConfig::Route* route = GetRouteOptionEntry("network_", key, routes); 548 if (route) { 549 route->host = value; 550 return; 551 } 552 route = GetRouteOptionEntry("netmask_", key, routes); 553 if (route) { 554 route->netmask = value; 555 return; 556 } 557 route = GetRouteOptionEntry("gateway_", key, routes); 558 if (route) { 559 route->gateway = value; 560 return; 561 } 562 LOG(WARNING) << "Unknown route option ignored: " << key; 563 } 564 565 // static 566 void OpenVPNDriver::SetRoutes(const RouteOptions& routes, 567 IPConfig::Properties* properties) { 568 vector<IPConfig::Route> new_routes; 569 for (const auto& route_map : routes) { 570 const IPConfig::Route& route = route_map.second; 571 if (route.host.empty() || route.netmask.empty() || route.gateway.empty()) { 572 LOG(WARNING) << "Ignoring incomplete route: " << route_map.first; 573 continue; 574 } 575 new_routes.push_back(route); 576 } 577 if (!new_routes.empty()) { 578 properties->routes.swap(new_routes); 579 } 580 LOG_IF(WARNING, properties->routes.empty()) << "No routes provided."; 581 } 582 583 // static 584 bool OpenVPNDriver::SplitPortFromHost( 585 const string& host, string* name, string* port) { 586 vector<string> tokens = SplitString(host, ":", base::TRIM_WHITESPACE, 587 base::SPLIT_WANT_ALL); 588 int port_number = 0; 589 if (tokens.size() != 2 || tokens[0].empty() || tokens[1].empty() || 590 !base::IsAsciiDigit(tokens[1][0]) || 591 !base::StringToInt(tokens[1], &port_number) || 592 port_number > std::numeric_limits<uint16_t>::max()) { 593 return false; 594 } 595 *name = tokens[0]; 596 *port = tokens[1]; 597 return true; 598 } 599 600 void OpenVPNDriver::Connect(const VPNServiceRefPtr& service, Error* error) { 601 StartConnectTimeout(kDefaultConnectTimeoutSeconds); 602 service_ = service; 603 service_->SetState(Service::kStateConfiguring); 604 if (!device_info_->CreateTunnelInterface(&tunnel_interface_)) { 605 Error::PopulateAndLog( 606 FROM_HERE, error, Error::kInternalError, 607 "Could not create tunnel interface."); 608 FailService(Service::kFailureInternal, Service::kErrorDetailsNone); 609 } 610 // Wait for the ClaimInterface callback to continue the connection process. 611 } 612 613 void OpenVPNDriver::InitOptions(vector<vector<string>>* options, Error* error) { 614 string vpnhost = args()->LookupString(kProviderHostProperty, ""); 615 if (vpnhost.empty()) { 616 Error::PopulateAndLog( 617 FROM_HERE, error, Error::kInvalidArguments, "VPN host not specified."); 618 return; 619 } 620 AppendOption("client", options); 621 AppendOption("tls-client", options); 622 623 string host_name, host_port; 624 if (SplitPortFromHost(vpnhost, &host_name, &host_port)) { 625 DCHECK(!host_name.empty()); 626 DCHECK(!host_port.empty()); 627 AppendOption("remote", host_name, host_port, options); 628 } else { 629 AppendOption("remote", vpnhost, options); 630 } 631 632 AppendOption("nobind", options); 633 AppendOption("persist-key", options); 634 AppendOption("persist-tun", options); 635 636 CHECK(!tunnel_interface_.empty()); 637 AppendOption("dev", tunnel_interface_, options); 638 AppendOption("dev-type", "tun", options); 639 640 InitLoggingOptions(options); 641 642 AppendValueOption(kVPNMTUProperty, "mtu", options); 643 AppendValueOption(kOpenVPNProtoProperty, "proto", options); 644 AppendValueOption(kOpenVPNPortProperty, "port", options); 645 AppendValueOption(kOpenVPNTLSAuthProperty, "tls-auth", options); 646 { 647 string contents = 648 args()->LookupString(kOpenVPNTLSAuthContentsProperty, ""); 649 if (!contents.empty()) { 650 if (!base::CreateTemporaryFile(&tls_auth_file_) || 651 base::WriteFile(tls_auth_file_, contents.data(), contents.size()) != 652 static_cast<int>(contents.size())) { 653 Error::PopulateAndLog( 654 FROM_HERE, error, Error::kInternalError, 655 "Unable to setup tls-auth file."); 656 return; 657 } 658 AppendOption("tls-auth", tls_auth_file_.value(), options); 659 } 660 } 661 AppendValueOption(kOpenVPNTLSRemoteProperty, "tls-remote", options); 662 AppendValueOption(kOpenVPNCipherProperty, "cipher", options); 663 AppendValueOption(kOpenVPNAuthProperty, "auth", options); 664 AppendFlag(kOpenVPNAuthNoCacheProperty, "auth-nocache", options); 665 AppendValueOption(kOpenVPNAuthRetryProperty, "auth-retry", options); 666 AppendFlag(kOpenVPNCompLZOProperty, "comp-lzo", options); 667 AppendFlag(kOpenVPNCompNoAdaptProperty, "comp-noadapt", options); 668 AppendFlag(kOpenVPNPushPeerInfoProperty, "push-peer-info", options); 669 AppendValueOption(kOpenVPNRenegSecProperty, "reneg-sec", options); 670 AppendValueOption(kOpenVPNShaperProperty, "shaper", options); 671 AppendValueOption(kOpenVPNServerPollTimeoutProperty, 672 "server-poll-timeout", options); 673 674 if (!InitCAOptions(options, error)) { 675 return; 676 } 677 678 // Additional remote certificate verification options. 679 InitCertificateVerifyOptions(options); 680 if (!InitExtraCertOptions(options, error)) { 681 return; 682 } 683 684 // Client-side ping support. 685 AppendValueOption(kOpenVPNPingProperty, "ping", options); 686 AppendValueOption(kOpenVPNPingExitProperty, "ping-exit", options); 687 AppendValueOption(kOpenVPNPingRestartProperty, "ping-restart", options); 688 689 AppendValueOption(kOpenVPNNsCertTypeProperty, "ns-cert-type", options); 690 691 InitClientAuthOptions(options); 692 InitPKCS11Options(options); 693 694 // TLS suport. 695 string remote_cert_tls = 696 args()->LookupString(kOpenVPNRemoteCertTLSProperty, ""); 697 if (remote_cert_tls.empty()) { 698 remote_cert_tls = "server"; 699 } 700 if (remote_cert_tls != "none") { 701 AppendOption("remote-cert-tls", remote_cert_tls, options); 702 } 703 704 // This is an undocumented command line argument that works like a .cfg file 705 // entry. TODO(sleffler): Maybe roll this into the "tls-auth" option? 706 AppendValueOption(kOpenVPNKeyDirectionProperty, "key-direction", options); 707 AppendValueOption(kOpenVPNRemoteCertEKUProperty, "remote-cert-eku", options); 708 AppendDelimitedValueOption(kOpenVPNRemoteCertKUProperty, 709 "remote-cert-ku", ' ', options); 710 711 if (!InitManagementChannelOptions(options, error)) { 712 return; 713 } 714 715 // Setup openvpn-script options and RPC information required to send back 716 // Layer 3 configuration. 717 AppendOption("setenv", kRPCTaskServiceVariable, 718 rpc_task_->GetRpcConnectionIdentifier(), options); 719 AppendOption("setenv", kRPCTaskServiceVariable, 720 rpc_task_->GetRpcConnectionIdentifier(), options); 721 AppendOption("setenv", kRPCTaskPathVariable, rpc_task_->GetRpcIdentifier(), 722 options); 723 AppendOption("script-security", "2", options); 724 AppendOption("up", kOpenVPNScript, options); 725 AppendOption("up-restart", options); 726 727 // Disable openvpn handling since we do route+ifconfig work. 728 AppendOption("route-noexec", options); 729 AppendOption("ifconfig-noexec", options); 730 731 // Drop root privileges on connection and enable callback scripts to send 732 // notify messages. 733 AppendOption("user", "openvpn", options); 734 AppendOption("group", "openvpn", options); 735 } 736 737 bool OpenVPNDriver::InitCAOptions( 738 vector<vector<string>>* options, Error* error) { 739 string ca_cert = 740 args()->LookupString(kOpenVPNCaCertProperty, ""); 741 vector<string> ca_cert_pem; 742 if (args()->ContainsStrings(kOpenVPNCaCertPemProperty)) { 743 ca_cert_pem = args()->GetStrings(kOpenVPNCaCertPemProperty); 744 } 745 746 int num_ca_cert_types = 0; 747 if (!ca_cert.empty()) 748 num_ca_cert_types++; 749 if (!ca_cert_pem.empty()) 750 num_ca_cert_types++; 751 if (num_ca_cert_types == 0) { 752 // Use default CAs if no CA certificate is provided. 753 AppendOption("ca", kDefaultCACertificates, options); 754 return true; 755 } else if (num_ca_cert_types > 1) { 756 Error::PopulateAndLog( 757 FROM_HERE, error, Error::kInvalidArguments, 758 "Can't specify more than one of CACert and CACertPEM."); 759 return false; 760 } 761 string cert_file; 762 if (!ca_cert_pem.empty()) { 763 DCHECK(ca_cert.empty()); 764 FilePath certfile = certificate_file_->CreatePEMFromStrings(ca_cert_pem); 765 if (certfile.empty()) { 766 Error::PopulateAndLog( 767 FROM_HERE, 768 error, 769 Error::kInvalidArguments, 770 "Unable to extract PEM CA certificates."); 771 return false; 772 } 773 AppendOption("ca", certfile.value(), options); 774 return true; 775 } 776 DCHECK(!ca_cert.empty() && ca_cert_pem.empty()); 777 AppendOption("ca", ca_cert, options); 778 return true; 779 } 780 781 void OpenVPNDriver::InitCertificateVerifyOptions( 782 std::vector<std::vector<std::string>>* options) { 783 AppendValueOption(kOpenVPNVerifyHashProperty, "verify-hash", options); 784 string x509_name = args()->LookupString(kOpenVPNVerifyX509NameProperty, ""); 785 if (!x509_name.empty()) { 786 string x509_type = args()->LookupString(kOpenVPNVerifyX509TypeProperty, ""); 787 if (x509_type.empty()) { 788 AppendOption("verify-x509-name", x509_name, options); 789 } else { 790 AppendOption("verify-x509-name", x509_name, x509_type, options); 791 } 792 } 793 } 794 795 bool OpenVPNDriver::InitExtraCertOptions( 796 vector<vector<string>>* options, Error* error) { 797 if (!args()->ContainsStrings(kOpenVPNExtraCertPemProperty)) { 798 // It's okay for this parameter to be unspecified. 799 return true; 800 } 801 802 vector<string> extra_certs = args()->GetStrings(kOpenVPNExtraCertPemProperty); 803 if (extra_certs.empty()) { 804 // It's okay for this parameter to be empty. 805 return true; 806 } 807 808 FilePath certfile = 809 extra_certificates_file_->CreatePEMFromStrings(extra_certs); 810 if (certfile.empty()) { 811 Error::PopulateAndLog( 812 FROM_HERE, 813 error, 814 Error::kInvalidArguments, 815 "Unable to extract extra PEM CA certificates."); 816 return false; 817 } 818 819 AppendOption("extra-certs", certfile.value(), options); 820 return true; 821 } 822 823 void OpenVPNDriver::InitPKCS11Options(vector<vector<string>>* options) { 824 string id = args()->LookupString(kOpenVPNClientCertIdProperty, ""); 825 if (!id.empty()) { 826 string provider = 827 args()->LookupString(kOpenVPNProviderProperty, ""); 828 if (provider.empty()) { 829 provider = kDefaultPKCS11Provider; 830 } 831 AppendOption("pkcs11-providers", provider, options); 832 AppendOption("pkcs11-id", id, options); 833 } 834 } 835 836 void OpenVPNDriver::InitClientAuthOptions(vector<vector<string>>* options) { 837 bool has_cert = AppendValueOption(kOpenVPNCertProperty, "cert", options) || 838 !args()->LookupString(kOpenVPNClientCertIdProperty, "").empty(); 839 bool has_key = AppendValueOption(kOpenVPNKeyProperty, "key", options); 840 // If the AuthUserPass property is set, or the User property is non-empty, or 841 // there's neither a key, nor a cert available, specify user-password client 842 // authentication. 843 if (args()->ContainsString(kOpenVPNAuthUserPassProperty) || 844 !args()->LookupString(kOpenVPNUserProperty, "").empty() || 845 (!has_cert && !has_key)) { 846 AppendOption("auth-user-pass", options); 847 } 848 } 849 850 bool OpenVPNDriver::InitManagementChannelOptions( 851 vector<vector<string>>* options, Error* error) { 852 if (!management_server_->Start(dispatcher(), &sockets_, options)) { 853 Error::PopulateAndLog( 854 FROM_HERE, error, Error::kInternalError, 855 "Unable to setup management channel."); 856 return false; 857 } 858 // If there's a connected default service already, allow the openvpn client to 859 // establish connection as soon as it's started. Otherwise, hold the client 860 // until an underlying service connects and OnDefaultServiceChanged is 861 // invoked. 862 if (manager()->IsConnected()) { 863 management_server_->ReleaseHold(); 864 } 865 return true; 866 } 867 868 void OpenVPNDriver::InitLoggingOptions(vector<vector<string>>* options) { 869 AppendOption("syslog", options); 870 871 string verb = args()->LookupString(kOpenVPNVerbProperty, ""); 872 if (verb.empty() && SLOG_IS_ON(VPN, 0)) { 873 verb = "3"; 874 } 875 if (!verb.empty()) { 876 AppendOption("verb", verb, options); 877 } 878 } 879 880 void OpenVPNDriver::AppendOption( 881 const string& option, vector<vector<string>>* options) { 882 options->push_back(vector<string>{ option }); 883 } 884 885 void OpenVPNDriver::AppendOption( 886 const string& option, 887 const string& value, 888 vector<vector<string>>* options) { 889 options->push_back(vector<string>{ option, value }); 890 } 891 892 void OpenVPNDriver::AppendOption( 893 const string& option, 894 const string& value0, 895 const string& value1, 896 vector<vector<string>>* options) { 897 options->push_back(vector<string>{ option, value0, value1 }); 898 } 899 900 bool OpenVPNDriver::AppendValueOption( 901 const string& property, 902 const string& option, 903 vector<vector<string>>* options) { 904 string value = args()->LookupString(property, ""); 905 if (!value.empty()) { 906 AppendOption(option, value, options); 907 return true; 908 } 909 return false; 910 } 911 912 bool OpenVPNDriver::AppendDelimitedValueOption( 913 const string& property, 914 const string& option, 915 char delimiter, 916 vector<vector<string>>* options) { 917 string value = args()->LookupString(property, ""); 918 if (!value.empty()) { 919 vector<string> parts = SplitString( 920 value, std::string{delimiter}, base::TRIM_WHITESPACE, 921 base::SPLIT_WANT_ALL); 922 parts.insert(parts.begin(), option); 923 options->push_back(parts); 924 return true; 925 } 926 return false; 927 } 928 929 bool OpenVPNDriver::AppendFlag( 930 const string& property, 931 const string& option, 932 vector<vector<string>>* options) { 933 if (args()->ContainsString(property)) { 934 AppendOption(option, options); 935 return true; 936 } 937 return false; 938 } 939 940 string OpenVPNDriver::GetServiceRpcIdentifier() const { 941 if (service_ == nullptr) 942 return "(openvpn_driver)"; 943 return service_->GetRpcIdentifier(); 944 } 945 946 void OpenVPNDriver::Disconnect() { 947 SLOG(this, 2) << __func__; 948 IdleService(); 949 } 950 951 void OpenVPNDriver::OnConnectionDisconnected() { 952 LOG(INFO) << "Underlying connection disconnected."; 953 // Restart the OpenVPN client forcing a reconnect attempt. 954 management_server_->Restart(); 955 // Indicate reconnect state right away to drop the VPN connection and start 956 // the connect timeout. This ensures that any miscommunication between shill 957 // and openvpn will not lead to a permanently stale connectivity state. Note 958 // that a subsequent invocation of OnReconnecting due to a RECONNECTING 959 // message will essentially be a no-op. 960 OnReconnecting(kReconnectReasonOffline); 961 } 962 963 void OpenVPNDriver::OnConnectTimeout() { 964 VPNDriver::OnConnectTimeout(); 965 Service::ConnectFailure failure = 966 management_server_->state() == OpenVPNManagementServer::kStateResolve ? 967 Service::kFailureDNSLookup : Service::kFailureConnect; 968 FailService(failure, Service::kErrorDetailsNone); 969 } 970 971 void OpenVPNDriver::OnReconnecting(ReconnectReason reason) { 972 LOG(INFO) << __func__ << "(" << reason << ")"; 973 int timeout_seconds = GetReconnectTimeoutSeconds(reason); 974 if (reason == kReconnectReasonTLSError && 975 timeout_seconds < connect_timeout_seconds()) { 976 // Reconnect due to TLS error happens during connect so we need to cancel 977 // the original connect timeout first and then reduce the time limit. 978 StopConnectTimeout(); 979 } 980 StartConnectTimeout(timeout_seconds); 981 // On restart/reconnect, drop the VPN connection, if any. The openvpn client 982 // might be in hold state if the VPN connection was previously established 983 // successfully. The hold will be released by OnDefaultServiceChanged when a 984 // new default service connects. This ensures that the client will use a fully 985 // functional underlying connection to reconnect. 986 if (device_) { 987 device_->DropConnection(); 988 } 989 if (service_) { 990 service_->SetState(Service::kStateAssociating); 991 } 992 } 993 994 // static 995 int OpenVPNDriver::GetReconnectTimeoutSeconds(ReconnectReason reason) { 996 switch (reason) { 997 case kReconnectReasonOffline: 998 return kReconnectOfflineTimeoutSeconds; 999 case kReconnectReasonTLSError: 1000 return kReconnectTLSErrorTimeoutSeconds; 1001 default: 1002 break; 1003 } 1004 return kDefaultConnectTimeoutSeconds; 1005 } 1006 1007 string OpenVPNDriver::GetProviderType() const { 1008 return kProviderOpenVpn; 1009 } 1010 1011 KeyValueStore OpenVPNDriver::GetProvider(Error* error) { 1012 SLOG(this, 2) << __func__; 1013 KeyValueStore props = VPNDriver::GetProvider(error); 1014 props.SetBool(kPassphraseRequiredProperty, 1015 args()->LookupString(kOpenVPNPasswordProperty, "").empty() && 1016 args()->LookupString(kOpenVPNTokenProperty, "").empty()); 1017 return props; 1018 } 1019 1020 map<string, string> OpenVPNDriver::GetEnvironment() { 1021 SLOG(this, 2) << __func__ << "(" << lsb_release_file_.value() << ")"; 1022 map<string, string> environment; 1023 string contents; 1024 if (!base::ReadFileToString(lsb_release_file_, &contents)) { 1025 LOG(ERROR) << "Unable to read the lsb-release file: " 1026 << lsb_release_file_.value(); 1027 return environment; 1028 } 1029 vector<string> lines = SplitString(contents, "\n", base::TRIM_WHITESPACE, 1030 base::SPLIT_WANT_ALL); 1031 for (const auto& line : lines) { 1032 const size_t assign = line.find('='); 1033 if (assign == string::npos) { 1034 continue; 1035 } 1036 const string key = line.substr(0, assign); 1037 const string value = line.substr(assign + 1); 1038 if (key == kChromeOSReleaseName) { 1039 environment[kOpenVPNEnvVarPlatformName] = value; 1040 } else if (key == kChromeOSReleaseVersion) { 1041 environment[kOpenVPNEnvVarPlatformVersion] = value; 1042 } 1043 // Other LSB release values are irrelevant. 1044 } 1045 return environment; 1046 } 1047 1048 void OpenVPNDriver::OnDefaultServiceChanged(const ServiceRefPtr& service) { 1049 SLOG(this, 2) << __func__ 1050 << "(" << (service ? service->unique_name() : "-") << ")"; 1051 // Allow the openvpn client to connect/reconnect only over a connected 1052 // underlying default service. If there's no default connected service, hold 1053 // the openvpn client until an underlying connection is established. If the 1054 // default service is our VPN service, hold the openvpn client on reconnect so 1055 // that the VPN connection can be torn down fully before a new connection 1056 // attempt is made over the underlying service. 1057 if (service && service != service_ && service->IsConnected()) { 1058 management_server_->ReleaseHold(); 1059 } else { 1060 management_server_->Hold(); 1061 } 1062 } 1063 1064 void OpenVPNDriver::ReportConnectionMetrics() { 1065 metrics_->SendEnumToUMA( 1066 Metrics::kMetricVpnDriver, 1067 Metrics::kVpnDriverOpenVpn, 1068 Metrics::kMetricVpnDriverMax); 1069 1070 if (args()->LookupString(kOpenVPNCaCertProperty, "") != "" || 1071 (args()->ContainsStrings(kOpenVPNCaCertPemProperty) && 1072 !args()->GetStrings(kOpenVPNCaCertPemProperty).empty())) { 1073 metrics_->SendEnumToUMA( 1074 Metrics::kMetricVpnRemoteAuthenticationType, 1075 Metrics::kVpnRemoteAuthenticationTypeOpenVpnCertificate, 1076 Metrics::kMetricVpnRemoteAuthenticationTypeMax); 1077 } else { 1078 metrics_->SendEnumToUMA( 1079 Metrics::kMetricVpnRemoteAuthenticationType, 1080 Metrics::kVpnRemoteAuthenticationTypeOpenVpnDefault, 1081 Metrics::kMetricVpnRemoteAuthenticationTypeMax); 1082 } 1083 1084 bool has_user_authentication = false; 1085 if (args()->LookupString(kOpenVPNTokenProperty, "") != "") { 1086 metrics_->SendEnumToUMA( 1087 Metrics::kMetricVpnUserAuthenticationType, 1088 Metrics::kVpnUserAuthenticationTypeOpenVpnUsernameToken, 1089 Metrics::kMetricVpnUserAuthenticationTypeMax); 1090 has_user_authentication = true; 1091 } 1092 if (args()->LookupString(kOpenVPNOTPProperty, "") != "") { 1093 metrics_->SendEnumToUMA( 1094 Metrics::kMetricVpnUserAuthenticationType, 1095 Metrics::kVpnUserAuthenticationTypeOpenVpnUsernamePasswordOtp, 1096 Metrics::kMetricVpnUserAuthenticationTypeMax); 1097 has_user_authentication = true; 1098 } 1099 if (args()->LookupString(kOpenVPNAuthUserPassProperty, "") != "" || 1100 args()->LookupString(kOpenVPNUserProperty, "") != "") { 1101 metrics_->SendEnumToUMA( 1102 Metrics::kMetricVpnUserAuthenticationType, 1103 Metrics::kVpnUserAuthenticationTypeOpenVpnUsernamePassword, 1104 Metrics::kMetricVpnUserAuthenticationTypeMax); 1105 has_user_authentication = true; 1106 } 1107 if (args()->LookupString(kOpenVPNClientCertIdProperty, "") != "" || 1108 args()->LookupString(kOpenVPNCertProperty, "") != "") { 1109 metrics_->SendEnumToUMA( 1110 Metrics::kMetricVpnUserAuthenticationType, 1111 Metrics::kVpnUserAuthenticationTypeOpenVpnCertificate, 1112 Metrics::kMetricVpnUserAuthenticationTypeMax); 1113 has_user_authentication = true; 1114 } 1115 if (!has_user_authentication) { 1116 metrics_->SendEnumToUMA( 1117 Metrics::kMetricVpnUserAuthenticationType, 1118 Metrics::kVpnUserAuthenticationTypeOpenVpnNone, 1119 Metrics::kMetricVpnUserAuthenticationTypeMax); 1120 } 1121 } 1122 1123 } // namespace shill 1124