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
45using base::Closure;
46using base::FilePath;
47using base::SplitString;
48using base::Unretained;
49using base::WeakPtr;
50using std::map;
51using std::string;
52using std::vector;
53
54namespace shill {
55
56namespace Logging {
57static auto kModuleLogScope = ScopeLogger::kVPN;
58static string ObjectID(const OpenVPNDriver* o) {
59  return o->GetServiceRpcIdentifier();
60}
61}
62
63namespace {
64
65const char kChromeOSReleaseName[] = "CHROMEOS_RELEASE_NAME";
66const char kChromeOSReleaseVersion[] = "CHROMEOS_RELEASE_VERSION";
67const char kOpenVPNEnvVarPlatformName[] = "IV_PLAT";
68const char kOpenVPNEnvVarPlatformVersion[] = "IV_PLAT_REL";
69const char kOpenVPNForeignOptionPrefix[] = "foreign_option_";
70const char kOpenVPNIfconfigBroadcast[] = "ifconfig_broadcast";
71const char kOpenVPNIfconfigLocal[] = "ifconfig_local";
72const char kOpenVPNIfconfigNetmask[] = "ifconfig_netmask";
73const char kOpenVPNIfconfigRemote[] = "ifconfig_remote";
74const char kOpenVPNRedirectGateway[] = "redirect_gateway";
75const char kOpenVPNRedirectPrivate[] = "redirect_private";
76const char kOpenVPNRouteOptionPrefix[] = "route_";
77const char kOpenVPNRouteVPNGateway[] = "route_vpn_gateway";
78const char kOpenVPNTrustedIP[] = "trusted_ip";
79const char kOpenVPNTunMTU[] = "tun_mtu";
80
81const 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.
87const char kSuspectedNetmaskPrefix[] = "255.";
88
89void DoNothingWithExitStatus(int exit_status) {
90}
91
92}  // namespace
93
94// static
95const char OpenVPNDriver::kDefaultCACertificates[] =
96    "/etc/ssl/certs/ca-certificates.crt";
97// static
98const char OpenVPNDriver::kOpenVPNPath[] = "/usr/sbin/openvpn";
99// static
100const char OpenVPNDriver::kOpenVPNScript[] = SHIMDIR "/openvpn-script";
101// static
102const 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
153const char OpenVPNDriver::kLSBReleaseFile[] = "/etc/lsb-release";
154
155// Directory where OpenVPN configuration files are exported while the
156// process is running.
157const char OpenVPNDriver::kDefaultOpenVPNConfigurationDirectory[] =
158    RUNDIR "/openvpn_config";
159
160const int OpenVPNDriver::kReconnectOfflineTimeoutSeconds = 2 * 60;
161const int OpenVPNDriver::kReconnectTLSErrorTimeoutSeconds = 20;
162
163OpenVPNDriver::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
182OpenVPNDriver::~OpenVPNDriver() {
183  IdleService();
184}
185
186void OpenVPNDriver::IdleService() {
187  Cleanup(Service::kStateIdle,
188          Service::kFailureUnknown,
189          Service::kErrorDetailsNone);
190}
191
192void OpenVPNDriver::FailService(Service::ConnectFailure failure,
193                                const string& error_details) {
194  Cleanup(Service::kStateFailure, failure, error_details);
195}
196
197void 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
261string 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, " ", &quoted_argument);
274        base::ReplaceChars(quoted_argument, "\\", "\\\\", &quoted_argument);
275        base::ReplaceChars(quoted_argument, "\"", "\\\"", &quoted_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
286bool 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
314bool 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
346void 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
354void 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
363bool 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
387void OpenVPNDriver::GetLogin(string* /*user*/, string* /*password*/) {
388  NOTREACHED();
389}
390
391void 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
406void 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
496void 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
516void 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
534IPConfig::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
545void 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
566void 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
584bool 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
600void 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
613void 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
737bool 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
781void 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
795bool 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
823void 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
836void 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
850bool 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
868void 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
880void OpenVPNDriver::AppendOption(
881    const string& option, vector<vector<string>>* options) {
882  options->push_back(vector<string>{ option });
883}
884
885void 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
892void 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
900bool 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
912bool 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
929bool 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
940string OpenVPNDriver::GetServiceRpcIdentifier() const {
941  if (service_ == nullptr)
942    return "(openvpn_driver)";
943  return service_->GetRpcIdentifier();
944}
945
946void OpenVPNDriver::Disconnect() {
947  SLOG(this, 2) << __func__;
948  IdleService();
949}
950
951void 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
963void 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
971void 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
995int 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
1007string OpenVPNDriver::GetProviderType() const {
1008  return kProviderOpenVpn;
1009}
1010
1011KeyValueStore 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
1020map<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
1048void 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
1064void 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