// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/vpn/openvpn_driver.h"

#include <arpa/inet.h>

#include <limits>

#include <base/files/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/certificate_file.h"
#include "shill/connection.h"
#include "shill/device_info.h"
#include "shill/error.h"
#include "shill/ipconfig.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/net/sockets.h"
#include "shill/process_manager.h"
#include "shill/rpc_task.h"
#include "shill/virtual_device.h"
#include "shill/vpn/openvpn_management_server.h"
#include "shill/vpn/vpn_provider.h"
#include "shill/vpn/vpn_service.h"

using base::FilePath;
using base::SplitString;
using base::Unretained;
using std::map;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kVPN;
static string ObjectID(const OpenVPNDriver* o) {
  return o->GetServiceRpcIdentifier();
}
}

namespace {

const char kChromeOSReleaseName[] = "CHROMEOS_RELEASE_NAME";
const char kChromeOSReleaseVersion[] = "CHROMEOS_RELEASE_VERSION";
const char kOpenVPNForeignOptionPrefix[] = "foreign_option_";
const char kOpenVPNIfconfigBroadcast[] = "ifconfig_broadcast";
const char kOpenVPNIfconfigLocal[] = "ifconfig_local";
const char kOpenVPNIfconfigNetmask[] = "ifconfig_netmask";
const char kOpenVPNIfconfigRemote[] = "ifconfig_remote";
const char kOpenVPNRedirectGateway[] = "redirect_gateway";
const char kOpenVPNRouteOptionPrefix[] = "route_";
const char kOpenVPNRouteNetGateway[] = "route_net_gateway";
const char kOpenVPNRouteVPNGateway[] = "route_vpn_gateway";
const char kOpenVPNTrustedIP[] = "trusted_ip";
const char kOpenVPNTunMTU[] = "tun_mtu";

// Typically OpenVPN will set environment variables like:
//   route_net_gateway=<existing default LAN gateway>
//   route_vpn_gateway=10.8.0.1
//   route_gateway_1=10.8.0.1
//   route_netmask_1=255.255.255.0
//   route_network_1=192.168.10.0
// This example shows a split include route of 192.168.10.0/24, and
// 10.8.0.1 is the ifconfig_remote (remote peer) address.
const char kOpenVPNRouteNetworkPrefix[] = "network_";
const char kOpenVPNRouteNetmaskPrefix[] = "netmask_";
const char kOpenVPNRouteGatewayPrefix[] = "gateway_";

const char kDefaultPKCS11Provider[] = "libchaps.so";

// Some configurations pass the netmask in the ifconfig_remote property.
// This is due to some servers not explicitly indicating that they are using
// a "broadcast mode" network instead of peer-to-peer.  See
// http://crbug.com/241264 for an example of this issue.
const char kSuspectedNetmaskPrefix[] = "255.";

void DoNothingWithExitStatus(int exit_status) {
}

}  // namespace

// static
const char OpenVPNDriver::kDefaultCACertificates[] =
    "/etc/ssl/certs/ca-certificates.crt";
// static
const char OpenVPNDriver::kOpenVPNPath[] = "/usr/sbin/openvpn";
// static
const char OpenVPNDriver::kOpenVPNScript[] = SHIMDIR "/openvpn-script";
// static
const VPNDriver::Property OpenVPNDriver::kProperties[] = {
  { kOpenVPNAuthNoCacheProperty, 0 },
  { kOpenVPNAuthProperty, 0 },
  { kOpenVPNAuthRetryProperty, 0 },
  { kOpenVPNAuthUserPassProperty, 0 },
  { kOpenVPNCipherProperty, 0 },
  { kOpenVPNClientCertIdProperty, Property::kCredential },
  { kOpenVPNCompLZOProperty, 0 },
  { kOpenVPNCompNoAdaptProperty, 0 },
  { kOpenVPNExtraHostsProperty, Property::kArray },
  { kOpenVPNIgnoreDefaultRouteProperty, 0 },
  { kOpenVPNKeyDirectionProperty, 0 },
  { kOpenVPNNsCertTypeProperty, 0 },
  { kOpenVPNOTPProperty,
    Property::kEphemeral | Property::kCredential | Property::kWriteOnly },
  { kOpenVPNPasswordProperty, Property::kCredential | Property::kWriteOnly },
  { kOpenVPNPinProperty, Property::kCredential },
  { kOpenVPNPortProperty, 0 },
  { kOpenVPNProtoProperty, 0 },
  { kOpenVPNPushPeerInfoProperty, 0 },
  { kOpenVPNRemoteCertEKUProperty, 0 },
  { kOpenVPNRemoteCertKUProperty, 0 },
  { kOpenVPNRemoteCertTLSProperty, 0 },
  { kOpenVPNRenegSecProperty, 0 },
  { kOpenVPNServerPollTimeoutProperty, 0 },
  { kOpenVPNShaperProperty, 0 },
  { kOpenVPNStaticChallengeProperty, 0 },
  { kOpenVPNTLSAuthContentsProperty, 0 },
  { kOpenVPNTLSRemoteProperty, 0 },
  { kOpenVPNTLSVersionMinProperty, 0 },
  { kOpenVPNTokenProperty,
    Property::kEphemeral | Property::kCredential | Property::kWriteOnly },
  { kOpenVPNUserProperty, 0 },
  { kProviderHostProperty, 0 },
  { kProviderTypeProperty, 0 },
  { kOpenVPNCaCertPemProperty, Property::kArray },
  { kOpenVPNExtraCertPemProperty, Property::kArray },
  { kOpenVPNPingExitProperty, 0 },
  { kOpenVPNPingProperty, 0 },
  { kOpenVPNPingRestartProperty, 0 },
  { kOpenVPNTLSAuthProperty, 0 },
  { kOpenVPNVerbProperty, 0 },
  { kOpenVPNVerifyHashProperty, 0 },
  { kOpenVPNVerifyX509NameProperty, 0 },
  { kOpenVPNVerifyX509TypeProperty, 0 },
  { kVPNMTUProperty, 0 },
};

const char OpenVPNDriver::kLSBReleaseFile[] = "/etc/lsb-release";

// Directory where OpenVPN configuration files are exported while the
// process is running.
const char OpenVPNDriver::kDefaultOpenVPNConfigurationDirectory[] =
    RUNDIR "/openvpn_config";

const int OpenVPNDriver::kReconnectOfflineTimeoutSeconds = 2 * 60;
const int OpenVPNDriver::kReconnectTLSErrorTimeoutSeconds = 20;

OpenVPNDriver::OpenVPNDriver(Manager* manager,
                             DeviceInfo* device_info,
                             ProcessManager* process_manager)
    : VPNDriver(manager, kProperties, arraysize(kProperties)),
      device_info_(device_info),
      process_manager_(process_manager),
      management_server_(new OpenVPNManagementServer(this)),
      certificate_file_(new CertificateFile()),
      extra_certificates_file_(new CertificateFile()),
      lsb_release_file_(kLSBReleaseFile),
      openvpn_config_directory_(kDefaultOpenVPNConfigurationDirectory),
      pid_(0),
      default_service_callback_tag_(0),
      link_down_(false) {}

OpenVPNDriver::~OpenVPNDriver() {
  IdleService();
}

void OpenVPNDriver::IdleService() {
  Cleanup(Service::kStateIdle,
          Service::kFailureNone,
          Service::kErrorDetailsNone);
}

void OpenVPNDriver::FailService(Service::ConnectFailure failure,
                                const string& error_details) {
  Cleanup(Service::kStateFailure, failure, error_details);
}

void OpenVPNDriver::Cleanup(Service::ConnectState state,
                            Service::ConnectFailure failure,
                            const string& error_details) {
  SLOG(this, 2) << __func__ << "(" << Service::ConnectStateToString(state)
                << ", " << error_details << ")";
  StopConnectTimeout();
  // Disconnecting the management interface will terminate the openvpn
  // process. Ensure this is handled robustly by first unregistering
  // the callback for OnOpenVPNDied, and then terminating and reaping
  // the process with StopProcess().
  if (pid_) {
    process_manager_->UpdateExitCallback(
        pid_, base::Bind(DoNothingWithExitStatus));
  }
  management_server_->Stop();
  if (!tls_auth_file_.empty()) {
    base::DeleteFile(tls_auth_file_, false);
    tls_auth_file_.clear();
  }
  if (!openvpn_config_file_.empty()) {
    base::DeleteFile(openvpn_config_file_, false);
    openvpn_config_file_.clear();
  }
  if (default_service_callback_tag_) {
    manager()->DeregisterDefaultServiceCallback(default_service_callback_tag_);
    default_service_callback_tag_ = 0;
  }
  rpc_task_.reset();
  int interface_index = -1;
  if (device_) {
    interface_index = device_->interface_index();
    device_->DropConnection();
    device_->SetEnabled(false);
    device_ = nullptr;
  }
  if (pid_) {
    process_manager_->StopProcessAndBlock(pid_);
    pid_ = 0;
  }
  if (interface_index >= 0) {
    device_info_->DeleteInterface(interface_index);
  }
  tunnel_interface_.clear();
  if (service_) {
    if (state == Service::kStateFailure) {
      service_->SetErrorDetails(error_details);
      service_->SetFailure(failure);
    } else {
      service_->SetState(state);
    }
    service_ = nullptr;
  }
  ip_properties_ = IPConfig::Properties();
}

// static
string OpenVPNDriver::JoinOptions(const vector<vector<string>>& options,
                                  char separator) {
  vector<string> option_strings;
  for (const auto& option : options) {
    vector<string> quoted_option;
    for (const auto& argument : option) {
      if (argument.find(' ') != string::npos ||
          argument.find('\t') != string::npos ||
          argument.find('"') != string::npos ||
          argument.find(separator) != string::npos) {
        string quoted_argument(argument);
        const char separator_chars[] = { separator, '\0' };
        base::ReplaceChars(argument, separator_chars, " ", &quoted_argument);
        base::ReplaceChars(quoted_argument, "\\", "\\\\", &quoted_argument);
        base::ReplaceChars(quoted_argument, "\"", "\\\"", &quoted_argument);
        quoted_option.push_back("\"" + quoted_argument + "\"");
      } else {
        quoted_option.push_back(argument);
      }
    }
    option_strings.push_back(base::JoinString(quoted_option, " "));
  }
  return base::JoinString(option_strings, string{separator});
}

bool OpenVPNDriver::WriteConfigFile(
    const vector<vector<string>>& options,
    FilePath* config_file) {
  if (!base::DirectoryExists(openvpn_config_directory_)) {
    if (!base::CreateDirectory(openvpn_config_directory_)) {
      LOG(ERROR) << "Unable to create configuration directory  "
                 << openvpn_config_directory_.value();
      return false;
    }
    // OpenVPN running as user 'openvpn' needs access to the config directory,
    // and openvpn user is not member of shill group so make the dir
    // world-readable. We'd rather not have openvpn belong to shill group since
    // shill is more privileged than openvpn, hence the idea of 'dropping'
    // UID/GID from shill to openvpn. Moreover since shill no longer runs with
    // CAP_CHOWN, we can't chown the dir to shill:openvpn.
    if (chmod(openvpn_config_directory_.value().c_str(),
              S_IRWXU | S_IRWXG | S_IROTH)) {
      LOG(ERROR) << "Failed to set permissions on "
                 << openvpn_config_directory_.value();
      base::DeleteFile(openvpn_config_directory_, true);
      return false;
    }
  }

  string contents = JoinOptions(options, '\n');
  contents.push_back('\n');
  if (!base::CreateTemporaryFileInDir(openvpn_config_directory_, config_file) ||
      base::WriteFile(*config_file, contents.data(), contents.size()) !=
          static_cast<int>(contents.size()) ||
      chmod(config_file->value().c_str(), S_IRWXU | S_IRWXG | S_IROTH)) {
    // Make the config file world-readable. Same rationale as listed above for
    // the config directory.
    LOG(ERROR) << "Unable to setup OpenVPN config file.";
    return false;
  }
  return true;
}

bool OpenVPNDriver::SpawnOpenVPN() {
  SLOG(this, 2) << __func__ << "(" << tunnel_interface_ << ")";

  vector<vector<string>> options;
  Error error;
  pid_t openvpn_pid;
  InitOptions(&options, &error);
  if (error.IsFailure()) {
    return false;
  }
  LOG(INFO) << "OpenVPN process options: " << JoinOptions(options, ',');
  if (!WriteConfigFile(options, &openvpn_config_file_)) {
    return false;
  }

  // TODO(quiche): This should be migrated to use ExternalTask.
  // (crbug.com/246263).
  CHECK(!pid_);

  vector<string> args = GetCommandLineArgs();
  LOG(INFO) << "OpenVPN command line args: " << base::JoinString(args, " ");

  if (manager()->GetJailVpnClients()) {
    uint64_t capmask = CAP_TO_MASK(CAP_NET_ADMIN) | CAP_TO_MASK(CAP_NET_RAW) |
                       CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID);
    openvpn_pid = process_manager_->StartProcessInMinijail(
        FROM_HERE, base::FilePath(kOpenVPNPath), args, "shill", "shill",
        capmask, true, true,
        base::Bind(&OpenVPNDriver::OnOpenVPNDied, base::Unretained(this)));
    if (openvpn_pid == -1) {
      LOG(ERROR) << "Minijail couldn't run our child process";
      return false;
    }
  } else {
    openvpn_pid = process_manager_->StartProcess(
        FROM_HERE, FilePath(kOpenVPNPath), args,
        map<string, string>(),  // No env vars passed.
        false,                  // Do not terminate with parent.
        base::Bind(&OpenVPNDriver::OnOpenVPNDied, base::Unretained(this)));
    if (openvpn_pid < 0) {
      LOG(ERROR) << "Unable to spawn: " << kOpenVPNPath;
      return false;
    }
  }
  pid_ = openvpn_pid;
  return true;
}

void OpenVPNDriver::OnOpenVPNDied(int exit_status) {
  SLOG(nullptr, 2) << __func__ << "(" << pid_ << ", "  << exit_status << ")";
  pid_ = 0;
  FailService(Service::kFailureInternal, Service::kErrorDetailsNone);
  // TODO(petkov): Figure if we need to restart the connection.
}

bool OpenVPNDriver::ClaimInterface(const string& link_name,
                                   int interface_index) {
  if (link_name != tunnel_interface_) {
    return false;
  }

  SLOG(this, 2) << "Claiming " << link_name << " for OpenVPN tunnel";

  CHECK(!device_);
  device_ = new VirtualDevice(manager(), link_name, interface_index,
                              Technology::kVPN);
  device_->SetEnabled(true);

  rpc_task_.reset(new RpcTask(control_interface(), this));
  if (SpawnOpenVPN()) {
    default_service_callback_tag_ =
        manager()->RegisterDefaultServiceCallback(
            Bind(&OpenVPNDriver::OnDefaultServiceChanged, Unretained(this)));
  } else {
    FailService(Service::kFailureInternal, Service::kErrorDetailsNone);
  }
  return true;
}

void OpenVPNDriver::GetLogin(string* /*user*/, string* /*password*/) {
  NOTREACHED();
}

void OpenVPNDriver::Notify(const string& reason,
                           const map<string, string>& dict) {
  LOG(INFO) << "IP configuration received: " << reason;
  if (reason != "up") {
    device_->DropConnection();
    return;
  }
  // On restart/reconnect, update the existing IP configuration.
  ParseIPConfiguration(dict, &ip_properties_);
  device_->SelectService(service_);
  device_->UpdateIPConfig(ip_properties_);
  ReportConnectionMetrics();
  StopConnectTimeout();
}

void OpenVPNDriver::ParseIPConfiguration(
    const map<string, string>& configuration,
    IPConfig::Properties* properties) const {
  ForeignOptions foreign_options;
  RouteOptions routes;
  bool redirect_gateway = false;

  properties->address_family = IPAddress::kFamilyIPv4;
  if (!properties->subnet_prefix) {
    properties->subnet_prefix =
        IPAddress::GetMaxPrefixLength(properties->address_family);
  }
  for (const auto& configuration_map : configuration) {
    const string& key = configuration_map.first;
    const string& value = configuration_map.second;
    SLOG(this, 2) << "Processing: " << key << " -> " << value;
    if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigLocal)) {
      properties->address = value;
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigBroadcast)) {
      properties->broadcast_address = value;
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigNetmask)) {
      properties->subnet_prefix =
          IPAddress::GetPrefixLengthFromMask(properties->address_family, value);
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNIfconfigRemote)) {
      if (base::StartsWith(value, kSuspectedNetmaskPrefix,
                           base::CompareCase::INSENSITIVE_ASCII)) {
        LOG(WARNING) << "Option " << key << " value " << value
                     << " looks more like a netmask than a peer address; "
                     << "assuming it is the former.";
        // In this situation, the "peer_address" value will be left
        // unset and Connection::UpdateFromIPConfig() will treat the
        // interface as if it were a broadcast-style network.  The
        // kernel will, automatically set the peer address equal to
        // the local address.
        properties->subnet_prefix =
            IPAddress::GetPrefixLengthFromMask(properties->address_family,
                                               value);
      } else {
        // This creates an explicit route to the peer address in SetRoutes().
        properties->peer_address = value;
      }
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNRedirectGateway)) {
      redirect_gateway = true;
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNTrustedIP)) {
      size_t prefix = IPAddress::GetMaxPrefixLength(properties->address_family);
      properties->exclusion_list.push_back(value + "/" +
                                           base::SizeTToString(prefix));
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNTunMTU)) {
      int mtu = 0;
      if (base::StringToInt(value, &mtu) && mtu >= IPConfig::kMinIPv4MTU) {
        properties->mtu = mtu;
      } else {
        LOG(ERROR) << "MTU " << value << " ignored.";
      }
    } else if (base::StartsWith(key, kOpenVPNForeignOptionPrefix,
                                base::CompareCase::INSENSITIVE_ASCII)) {
      const string suffix = key.substr(strlen(kOpenVPNForeignOptionPrefix));
      int order = 0;
      if (base::StringToInt(suffix, &order)) {
        foreign_options[order] = value;
      } else {
        LOG(ERROR) << "Ignored unexpected foreign option suffix: " << suffix;
      }
    } else if (base::LowerCaseEqualsASCII(key, kOpenVPNRouteNetGateway) ||
               base::LowerCaseEqualsASCII(key, kOpenVPNRouteVPNGateway)) {
      // These options are unused.  Catch them here so that they don't
      // get passed to ParseRouteOption().
    } else if (base::StartsWith(key, kOpenVPNRouteOptionPrefix,
                                base::CompareCase::INSENSITIVE_ASCII)) {
      ParseRouteOption(key.substr(strlen(kOpenVPNRouteOptionPrefix)),
                       value, &routes);
    } else {
      SLOG(this, 2) << "Key ignored.";
    }
  }
  ParseForeignOptions(foreign_options, properties);

  manager()->vpn_provider()->SetDefaultRoutingPolicy(properties);

  // Since we use persist-tun, we expect that a reconnection will use the same
  // routes *and* that OpenVPN will not re-provide us with all the needed
  // routing information. Simply re-use the routing information we attained from
  // the initial connection.
  if (!properties->routes.empty())
    return;

  // Ignore the route_vpn_gateway parameter as VPNs don't need gateway IPs.
  // This guarantees that we will pass the various sanity checks in
  // connection.cc.
  properties->gateway = properties->address;

  if (redirect_gateway &&
      const_args()->ContainsString(kOpenVPNIgnoreDefaultRouteProperty)) {
    LOG(INFO) << "Ignoring default route parameter as requested by "
              << "configuration.";
    redirect_gateway = false;
  }
  properties->default_route = properties->blackhole_ipv6 = redirect_gateway;
  SetRoutes(routes, properties);
}

// static
void OpenVPNDriver::ParseForeignOptions(const ForeignOptions& options,
                                        IPConfig::Properties* properties) {
  vector<string> domain_search;
  vector<string> dns_servers;
  for (const auto& option_map : options) {
    ParseForeignOption(option_map.second, &domain_search, &dns_servers);
  }
  if (!domain_search.empty()) {
    properties->domain_search.swap(domain_search);
  }
  LOG_IF(INFO, properties->domain_search.empty())
      << "No search domains provided.";
  if (!dns_servers.empty()) {
    properties->dns_servers.swap(dns_servers);
  }
  LOG_IF(WARNING, properties->dns_servers.empty())
      << "No DNS servers provided.";
}

// static
void OpenVPNDriver::ParseForeignOption(const string& option,
                                       vector<string>* domain_search,
                                       vector<string>* dns_servers) {
  SLOG(nullptr, 2) << __func__ << "(" << option << ")";
  vector<string> tokens = SplitString(option, " ", base::TRIM_WHITESPACE,
                                      base::SPLIT_WANT_ALL);
  if (tokens.size() != 3 ||
      !base::LowerCaseEqualsASCII(tokens[0], "dhcp-option")) {
    return;
  }
  if (base::LowerCaseEqualsASCII(tokens[1], "domain")) {
    domain_search->push_back(tokens[2]);
  } else if (base::LowerCaseEqualsASCII(tokens[1], "dns")) {
    dns_servers->push_back(tokens[2]);
  }
}

// static
IPConfig::Route* OpenVPNDriver::GetRouteOptionEntry(
    const string& prefix, const string& key, RouteOptions* routes) {
  int order = 0;
  if (!base::StartsWith(key, prefix, base::CompareCase::INSENSITIVE_ASCII) ||
      !base::StringToInt(key.substr(prefix.size()), &order)) {
    return nullptr;
  }
  return&(*routes)[order];
}

// static
void OpenVPNDriver::ParseRouteOption(
    const string& key, const string& value, RouteOptions* routes) {
  // IPv4 uses route_{network,netmask,gateway}_<index>
  // IPv6 uses route_ipv6_{network,gateway}_<index>
  IPConfig::Route* route =
      GetRouteOptionEntry(kOpenVPNRouteNetworkPrefix, key, routes);
  if (route) {
    route->host = value;
    return;
  }
  route = GetRouteOptionEntry(kOpenVPNRouteNetmaskPrefix, key, routes);
  if (route) {
    route->prefix = IPAddress::GetPrefixLengthFromMask(IPAddress::kFamilyIPv4,
                                                       value);
    return;
  }
  route = GetRouteOptionEntry(kOpenVPNRouteGatewayPrefix, key, routes);
  if (route) {
    route->gateway = value;
    return;
  }
  LOG(WARNING) << "Unknown route option ignored: " << key;
}

// static
void OpenVPNDriver::SetRoutes(const RouteOptions& routes,
                              IPConfig::Properties* properties) {
  vector<IPConfig::Route> new_routes;
  int32_t max_prefix =
      IPAddress::GetMaxPrefixLength(properties->address_family);
  if (!properties->peer_address.empty()) {
    // --topology net30 or p2p will set ifconfig_remote

    // Setting a point-to-point address in the kernel will create a route
    // in RT_TABLE_MAIN instead of our per-device table.  To avoid this,
    // create an explicit host route here, and clear
    // |properties->peer_address.|
    IPConfig::Route route(
        properties->peer_address, max_prefix, properties->address);
    new_routes.push_back(route);
    properties->peer_address.clear();
  } else if (properties->subnet_prefix != max_prefix) {
    // --topology subnet will set ifconfig_netmask instead
    IPAddress network_addr(properties->address);
    if (network_addr.family() != properties->address_family) {
      LOG(WARNING) << "Error obtaining network address for "
                   << properties->address;
    } else {
      network_addr.set_prefix(properties->subnet_prefix);

      IPConfig::Route route(network_addr.GetNetworkPart().ToString(),
                            properties->subnet_prefix,
                            properties->address);
      new_routes.push_back(route);
    }
  }

  // Ignore |route.gateway|.  If it's wrong, it can cause the kernel to
  // refuse to add the route.  If it's correct, it has no effect anyway.
  for (const auto& route_map : routes) {
    const IPConfig::Route& route = route_map.second;
    if (route.host.empty() || route.gateway.empty()) {
      LOG(WARNING) << "Ignoring incomplete route: " << route_map.first;
      continue;
    }
    IPConfig::Route new_route(route.host, route.prefix, properties->address);
    new_routes.push_back(new_route);
  }

  if (!new_routes.empty()) {
    properties->routes.swap(new_routes);
  } else if (!properties->default_route) {
    LOG(WARNING) << "No routes provided.";
  }
}

// static
bool OpenVPNDriver::SplitPortFromHost(
    const string& host, string* name, string* port) {
  vector<string> tokens = SplitString(host, ":", base::TRIM_WHITESPACE,
                                      base::SPLIT_WANT_ALL);
  int port_number = 0;
  if (tokens.size() != 2 || tokens[0].empty() || tokens[1].empty() ||
      !base::IsAsciiDigit(tokens[1][0]) ||
      !base::StringToInt(tokens[1], &port_number) ||
      port_number > std::numeric_limits<uint16_t>::max()) {
    return false;
  }
  *name = tokens[0];
  *port = tokens[1];
  return true;
}

void OpenVPNDriver::Connect(const VPNServiceRefPtr& service, Error* error) {
  StartConnectTimeout(kDefaultConnectTimeoutSeconds);
  service_ = service;
  service_->SetState(Service::kStateConfiguring);
  if (!device_info_->CreateTunnelInterface(&tunnel_interface_)) {
    Error::PopulateAndLog(
        FROM_HERE, error, Error::kInternalError,
        "Could not create tunnel interface.");
    FailService(Service::kFailureInternal, Service::kErrorDetailsNone);
  }
  // Wait for the ClaimInterface callback to continue the connection process.
}

void OpenVPNDriver::InitOptions(vector<vector<string>>* options, Error* error) {
  string vpnhost = args()->LookupString(kProviderHostProperty, "");
  if (vpnhost.empty()) {
    Error::PopulateAndLog(
        FROM_HERE, error, Error::kInvalidArguments, "VPN host not specified.");
    return;
  }
  AppendOption("client", options);
  AppendOption("tls-client", options);

  AppendRemoteOption(vpnhost, options);
  if (args()->ContainsStrings(kOpenVPNExtraHostsProperty)) {
    for (const auto& host : args()->GetStrings(kOpenVPNExtraHostsProperty)) {
      AppendRemoteOption(host, options);
    }
  }

  AppendOption("nobind", options);
  AppendOption("persist-key", options);
  AppendOption("persist-tun", options);

  CHECK(!tunnel_interface_.empty());
  AppendOption("dev", tunnel_interface_, options);
  AppendOption("dev-type", "tun", options);

  InitLoggingOptions(options);

  AppendValueOption(kVPNMTUProperty, "mtu", options);
  AppendValueOption(kOpenVPNProtoProperty, "proto", options);
  AppendValueOption(kOpenVPNPortProperty, "port", options);
  AppendValueOption(kOpenVPNTLSAuthProperty, "tls-auth", options);
  {
    string contents =
        args()->LookupString(kOpenVPNTLSAuthContentsProperty, "");
    if (!contents.empty()) {
      if (!base::CreateTemporaryFile(&tls_auth_file_) ||
          base::WriteFile(tls_auth_file_, contents.data(), contents.size()) !=
              static_cast<int>(contents.size())) {
        Error::PopulateAndLog(
            FROM_HERE, error, Error::kInternalError,
            "Unable to setup tls-auth file.");
        return;
      }
      AppendOption("tls-auth", tls_auth_file_.value(), options);
    }
  }

  if (args()->ContainsString(kOpenVPNTLSVersionMinProperty)) {
    AppendOption("tls-version-min",
                 args()->GetString(kOpenVPNTLSVersionMinProperty),
                 options);
  }

  string tls_remote = args()->LookupString(kOpenVPNTLSRemoteProperty, "");
  if (!tls_remote.empty()) {
    AppendOption("verify-x509-name", tls_remote, "name-prefix", options);
  }

  AppendValueOption(kOpenVPNCipherProperty, "cipher", options);
  AppendValueOption(kOpenVPNAuthProperty, "auth", options);
  AppendFlag(kOpenVPNAuthNoCacheProperty, "auth-nocache", options);
  AppendValueOption(kOpenVPNAuthRetryProperty, "auth-retry", options);
  AppendFlag(kOpenVPNCompLZOProperty, "comp-lzo", options);
  AppendFlag(kOpenVPNCompNoAdaptProperty, "comp-noadapt", options);
  AppendFlag(kOpenVPNPushPeerInfoProperty, "push-peer-info", options);
  AppendValueOption(kOpenVPNRenegSecProperty, "reneg-sec", options);
  AppendValueOption(kOpenVPNShaperProperty, "shaper", options);
  AppendValueOption(kOpenVPNServerPollTimeoutProperty,
                    "server-poll-timeout", options);

  if (!InitCAOptions(options, error)) {
    return;
  }

  // Additional remote certificate verification options.
  InitCertificateVerifyOptions(options);
  if (!InitExtraCertOptions(options, error)) {
    return;
  }

  // Client-side ping support.
  AppendValueOption(kOpenVPNPingProperty, "ping", options);
  AppendValueOption(kOpenVPNPingExitProperty, "ping-exit", options);
  AppendValueOption(kOpenVPNPingRestartProperty, "ping-restart", options);

  AppendValueOption(kOpenVPNNsCertTypeProperty, "ns-cert-type", options);

  InitClientAuthOptions(options);
  InitPKCS11Options(options);

  // TLS suport.
  string remote_cert_tls =
      args()->LookupString(kOpenVPNRemoteCertTLSProperty, "");
  if (remote_cert_tls.empty()) {
    remote_cert_tls = "server";
  }
  if (remote_cert_tls != "none") {
    AppendOption("remote-cert-tls", remote_cert_tls, options);
  }

  AppendValueOption(kOpenVPNKeyDirectionProperty, "key-direction", options);
  AppendValueOption(kOpenVPNRemoteCertEKUProperty, "remote-cert-eku", options);
  AppendDelimitedValueOption(kOpenVPNRemoteCertKUProperty,
                             "remote-cert-ku", ' ', options);

  if (!InitManagementChannelOptions(options, error)) {
    return;
  }

  // Setup openvpn-script options and RPC information required to send back
  // Layer 3 configuration.
  AppendOption("setenv", kRpcTaskServiceVariable,
               rpc_task_->GetRpcConnectionIdentifier(), options);
  AppendOption("setenv", kRpcTaskServiceVariable,
               rpc_task_->GetRpcConnectionIdentifier(), options);
  AppendOption("setenv", kRpcTaskPathVariable, rpc_task_->GetRpcIdentifier(),
               options);
  AppendOption("script-security", "2", options);
  AppendOption("up", kOpenVPNScript, options);
  AppendOption("up-restart", options);

  // Disable openvpn handling since we do route+ifconfig work.
  AppendOption("route-noexec", options);
  AppendOption("ifconfig-noexec", options);

  // Drop root privileges on connection and enable callback scripts to send
  // notify messages.
  AppendOption("user", "openvpn", options);
  AppendOption("group", "openvpn", options);
}

bool OpenVPNDriver::InitCAOptions(
    vector<vector<string>>* options, Error* error) {
  vector<string> ca_cert_pem;
  if (args()->ContainsStrings(kOpenVPNCaCertPemProperty)) {
    ca_cert_pem = args()->GetStrings(kOpenVPNCaCertPemProperty);
  }
  if (ca_cert_pem.empty()) {
    // Use default CAs if no CA certificate is provided.
    AppendOption("ca", kDefaultCACertificates, options);
    return true;
  }

  FilePath certfile = certificate_file_->CreatePEMFromStrings(ca_cert_pem);
  if (certfile.empty()) {
    Error::PopulateAndLog(FROM_HERE,
                          error,
                          Error::kInvalidArguments,
                          "Unable to extract PEM CA certificates.");
    return false;
  }
  AppendOption("ca", certfile.value(), options);
  return true;
}

void OpenVPNDriver::InitCertificateVerifyOptions(
    std::vector<std::vector<std::string>>* options) {
  AppendValueOption(kOpenVPNVerifyHashProperty, "verify-hash", options);
  string x509_name = args()->LookupString(kOpenVPNVerifyX509NameProperty, "");
  if (!x509_name.empty()) {
    string x509_type = args()->LookupString(kOpenVPNVerifyX509TypeProperty, "");
    if (x509_type.empty()) {
      AppendOption("verify-x509-name", x509_name, options);
    } else {
      AppendOption("verify-x509-name", x509_name, x509_type, options);
    }
  }
}

bool OpenVPNDriver::InitExtraCertOptions(
    vector<vector<string>>* options, Error* error) {
  if (!args()->ContainsStrings(kOpenVPNExtraCertPemProperty)) {
    // It's okay for this parameter to be unspecified.
    return true;
  }

  vector<string> extra_certs = args()->GetStrings(kOpenVPNExtraCertPemProperty);
  if (extra_certs.empty()) {
    // It's okay for this parameter to be empty.
    return true;
  }

  FilePath certfile =
      extra_certificates_file_->CreatePEMFromStrings(extra_certs);
  if (certfile.empty()) {
    Error::PopulateAndLog(
        FROM_HERE,
        error,
        Error::kInvalidArguments,
        "Unable to extract extra PEM CA certificates.");
    return false;
  }

  AppendOption("extra-certs", certfile.value(), options);
  return true;
}

void OpenVPNDriver::InitPKCS11Options(vector<vector<string>>* options) {
  string id = args()->LookupString(kOpenVPNClientCertIdProperty, "");
  if (!id.empty()) {
    AppendOption("pkcs11-providers", kDefaultPKCS11Provider, options);
    AppendOption("pkcs11-id", id, options);
  }
}

void OpenVPNDriver::InitClientAuthOptions(vector<vector<string>>* options) {
  // If the AuthUserPass property is set, or the User property is non-empty, or
  // a client cert was not provided, specify user-password client
  // authentication.
  if (args()->ContainsString(kOpenVPNAuthUserPassProperty) ||
      !args()->LookupString(kOpenVPNUserProperty, "").empty() ||
      args()->LookupString(kOpenVPNClientCertIdProperty, "").empty()) {
    AppendOption("auth-user-pass", options);
  }
}

bool OpenVPNDriver::InitManagementChannelOptions(
    vector<vector<string>>* options, Error* error) {
  if (!management_server_->Start(&sockets_, options)) {
    Error::PopulateAndLog(
        FROM_HERE, error, Error::kInternalError,
        "Unable to setup management channel.");
    return false;
  }
  // If there's a connected default service already, allow the openvpn client to
  // establish connection as soon as it's started. Otherwise, hold the client
  // until an underlying service connects and OnDefaultServiceChanged is
  // invoked.
  if (manager()->IsConnected()) {
    management_server_->ReleaseHold();
  }
  return true;
}

void OpenVPNDriver::InitLoggingOptions(vector<vector<string>>* options) {
  AppendOption("syslog", options);

  string verb = args()->LookupString(kOpenVPNVerbProperty, "");
  if (!verb.empty()) {
    AppendOption("verb", verb, options);
    return;
  }

  if (SLOG_IS_ON(VPN, 6)) {
    // Maximum output:
    // --verb 9 enables PKCS11 debug, TCP stream, link read/write
    // --verb 8 enables event waits, scheduler, tls_session
    AppendOption("verb", "9", options);
  } else if (SLOG_IS_ON(VPN, 5)) {
    // --verb 7 enables data channel encryption keys, routing,
    // pkcs11 actions, pings, push/pull debug
    AppendOption("verb", "7", options);
  } else if (SLOG_IS_ON(VPN, 4)) {
    // --verb 6 enables tcp/udp reads/writes (short), tun/tap reads/writes
    // --verb 5 enables printing 'R' or 'W' per packet to stdout
    AppendOption("verb", "6", options);
  } else if (SLOG_IS_ON(VPN, 3)) {
    // --verb 4 enables logging packet drops, options
    AppendOption("verb", "4", options);
  } else if (SLOG_IS_ON(VPN, 0)) {
    // --verb 3 is the old default for `ff_debug +vpn`
    AppendOption("verb", "3", options);
  }
}

void OpenVPNDriver::AppendOption(
    const string& option, vector<vector<string>>* options) {
  options->push_back(vector<string>{ option });
}

void OpenVPNDriver::AppendOption(
    const string& option,
    const string& value,
    vector<vector<string>>* options) {
  options->push_back(vector<string>{ option, value });
}

void OpenVPNDriver::AppendOption(
    const string& option,
    const string& value0,
    const string& value1,
    vector<vector<string>>* options) {
  options->push_back(vector<string>{ option, value0, value1 });
}

void OpenVPNDriver::AppendRemoteOption(const string& host,
                                       vector<vector<string>>* options) {
  string host_name, host_port;
  if (SplitPortFromHost(host, &host_name, &host_port)) {
    DCHECK(!host_name.empty());
    DCHECK(!host_port.empty());
    AppendOption("remote", host_name, host_port, options);
  } else {
    AppendOption("remote", host, options);
  }
}

bool OpenVPNDriver::AppendValueOption(
    const string& property,
    const string& option,
    vector<vector<string>>* options) {
  string value = args()->LookupString(property, "");
  if (!value.empty()) {
    AppendOption(option, value, options);
    return true;
  }
  return false;
}

bool OpenVPNDriver::AppendDelimitedValueOption(
    const string& property,
    const string& option,
    char delimiter,
    vector<vector<string>>* options) {
  string value = args()->LookupString(property, "");
  if (!value.empty()) {
    vector<string> parts = SplitString(
        value, std::string{delimiter}, base::TRIM_WHITESPACE,
        base::SPLIT_WANT_ALL);
    parts.insert(parts.begin(), option);
    options->push_back(parts);
    return true;
  }
  return false;
}

bool OpenVPNDriver::AppendFlag(
    const string& property,
    const string& option,
    vector<vector<string>>* options) {
  if (args()->ContainsString(property)) {
    AppendOption(option, options);
    return true;
  }
  return false;
}

RpcIdentifier OpenVPNDriver::GetServiceRpcIdentifier() const {
  if (service_ == nullptr)
    return RpcIdentifier("(openvpn_driver)");
  return service_->GetRpcIdentifier();
}

void OpenVPNDriver::Disconnect() {
  SLOG(this, 2) << __func__;
  IdleService();
}

void OpenVPNDriver::OnConnectionDisconnected() {
  LOG(INFO) << "Underlying connection disconnected.";
}

void OpenVPNDriver::OnConnectTimeout() {
  VPNDriver::OnConnectTimeout();
  Service::ConnectFailure failure =
      management_server_->state() == OpenVPNManagementServer::kStateResolve ?
      Service::kFailureDNSLookup : Service::kFailureConnect;
  FailService(failure, Service::kErrorDetailsNone);
}

void OpenVPNDriver::OnReconnecting(ReconnectReason reason) {
  LOG(INFO) << __func__ << "(" << reason << ")";
  int timeout_seconds = GetReconnectTimeoutSeconds(reason);
  if (reason == kReconnectReasonTLSError &&
      timeout_seconds < connect_timeout_seconds()) {
    // Reconnect due to TLS error happens during connect so we need to cancel
    // the original connect timeout first and then reduce the time limit.
    StopConnectTimeout();
  }
  StartConnectTimeout(timeout_seconds);
  // On restart/reconnect, drop the VPN connection, if any. The openvpn client
  // might be in hold state if the VPN connection was previously established
  // successfully. The hold will be released by OnDefaultServiceChanged when a
  // new default service connects. This ensures that the client will use a fully
  // functional underlying connection to reconnect.
  if (device_) {
    device_->SetServiceState(Service::kStateConfiguring);
    device_->ResetConnection();
  }
}

// static
int OpenVPNDriver::GetReconnectTimeoutSeconds(ReconnectReason reason) {
  switch (reason) {
    case kReconnectReasonOffline:
      return kReconnectOfflineTimeoutSeconds;
    case kReconnectReasonTLSError:
      return kReconnectTLSErrorTimeoutSeconds;
    default:
      break;
  }
  return kDefaultConnectTimeoutSeconds;
}

string OpenVPNDriver::GetProviderType() const {
  return kProviderOpenVpn;
}

KeyValueStore OpenVPNDriver::GetProvider(Error* error) {
  SLOG(this, 2) << __func__;
  KeyValueStore props = VPNDriver::GetProvider(error);
  props.SetBool(kPassphraseRequiredProperty,
                args()->LookupString(kOpenVPNPasswordProperty, "").empty() &&
                args()->LookupString(kOpenVPNTokenProperty, "").empty());
  return props;
}

vector<string> OpenVPNDriver::GetCommandLineArgs() {
  SLOG(this, 2) << __func__ << "(" << lsb_release_file_.value() << ")";
  vector<string> args =
      vector<string>{"--config", openvpn_config_file_.value()};
  string contents;
  if (!base::ReadFileToString(lsb_release_file_, &contents)) {
    LOG(ERROR) << "Unable to read the lsb-release file: "
               << lsb_release_file_.value();
    return args;
  }
  vector<string> lines = SplitString(contents, "\n", base::TRIM_WHITESPACE,
                                     base::SPLIT_WANT_ALL);
  for (const auto& line : lines) {
    const size_t assign = line.find('=');
    if (assign == string::npos) {
      continue;
    }
    const string key = line.substr(0, assign);
    const string value = line.substr(assign + 1);
    if (key == kChromeOSReleaseName) {
      args.push_back("--setenv");
      args.push_back("UV_PLAT");
      args.push_back(value);
    } else if (key == kChromeOSReleaseVersion) {
      args.push_back("--setenv");
      args.push_back("UV_PLAT_REL");
      args.push_back(value);
    }
    // Other LSB release values are irrelevant.
  }
  return args;
}

void OpenVPNDriver::OnDefaultServiceChanged(const ServiceRefPtr& service) {
  SLOG(this, 2) << __func__
                << "(" << (service ? service->unique_name() : "-") << ")";
  if (!device_)
    return;

  // Inform the user that the VPN is reconnecting.
  device_->SetServiceState(Service::kStateConfiguring);
  device_->ResetConnection();
  StopConnectTimeout();

  if (service && service->state() == Service::kStateOnline) {
    // The original service is no longer the default, but manager was able
    // to find another physical service that is already Online.
    // Ask the management server to reconnect immediately.
    management_server_->ReleaseHold();
    management_server_->Restart();
    StartConnectTimeout(GetReconnectTimeoutSeconds(kReconnectReasonOffline));
  } else {
    // The default physical service went away, and nothing else is available
    // right now.  All we can do is wait.
    if (link_down_)
      return;
    SLOG(this, 2) << __func__
                  << " - physical connection lost";
    link_down_ = true;

    management_server_->Hold();
    management_server_->Restart();
  }
}

void OpenVPNDriver::OnDefaultServiceStateChanged(
    const ServiceRefPtr& service) {
  if (link_down_ && service->state() == Service::kStateOnline) {
    link_down_ = false;
    management_server_->ReleaseHold();
    StartConnectTimeout(GetReconnectTimeoutSeconds(kReconnectReasonOffline));
  }
}

void OpenVPNDriver::ReportConnectionMetrics() {
  metrics()->SendEnumToUMA(
      Metrics::kMetricVpnDriver,
      Metrics::kVpnDriverOpenVpn,
      Metrics::kMetricVpnDriverMax);

  if (args()->ContainsStrings(kOpenVPNCaCertPemProperty) &&
      !args()->GetStrings(kOpenVPNCaCertPemProperty).empty()) {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnRemoteAuthenticationType,
        Metrics::kVpnRemoteAuthenticationTypeOpenVpnCertificate,
        Metrics::kMetricVpnRemoteAuthenticationTypeMax);
  } else {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnRemoteAuthenticationType,
        Metrics::kVpnRemoteAuthenticationTypeOpenVpnDefault,
        Metrics::kMetricVpnRemoteAuthenticationTypeMax);
  }

  bool has_user_authentication = false;
  if (args()->LookupString(kOpenVPNTokenProperty, "") != "") {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnUserAuthenticationType,
        Metrics::kVpnUserAuthenticationTypeOpenVpnUsernameToken,
        Metrics::kMetricVpnUserAuthenticationTypeMax);
    has_user_authentication = true;
  }
  if (args()->LookupString(kOpenVPNOTPProperty, "") != "") {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnUserAuthenticationType,
        Metrics::kVpnUserAuthenticationTypeOpenVpnUsernamePasswordOtp,
        Metrics::kMetricVpnUserAuthenticationTypeMax);
    has_user_authentication = true;
  }
  if (args()->LookupString(kOpenVPNAuthUserPassProperty, "") != "" ||
      args()->LookupString(kOpenVPNUserProperty, "") != "")  {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnUserAuthenticationType,
        Metrics::kVpnUserAuthenticationTypeOpenVpnUsernamePassword,
        Metrics::kMetricVpnUserAuthenticationTypeMax);
    has_user_authentication = true;
  }
  if (args()->LookupString(kOpenVPNClientCertIdProperty, "") != "") {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnUserAuthenticationType,
        Metrics::kVpnUserAuthenticationTypeOpenVpnCertificate,
        Metrics::kMetricVpnUserAuthenticationTypeMax);
    has_user_authentication = true;
  }
  if (!has_user_authentication) {
    metrics()->SendEnumToUMA(
        Metrics::kMetricVpnUserAuthenticationType,
        Metrics::kVpnUserAuthenticationTypeOpenVpnNone,
        Metrics::kMetricVpnUserAuthenticationTypeMax);
  }
}

}  // namespace shill
