blob: 2e85fd8ce2c44f4b9e6973d5ac03f519ac3bd534 [file] [log] [blame]
// 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/l2tp_ipsec_driver.h"
#include <utility>
#include <base/containers/contains.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/memory/ptr_util.h>
#include <base/memory/weak_ptr.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <gtest/gtest.h>
#include <libpasswordprovider/fake_password_provider.h>
#include <libpasswordprovider/password.h>
#include <libpasswordprovider/password_provider.h>
#include <vpn-manager/service_error.h>
#include "shill/ipconfig.h"
#include "shill/mock_adaptors.h"
#include "shill/mock_certificate_file.h"
#include "shill/mock_control.h"
#include "shill/mock_device_info.h"
#include "shill/mock_external_task.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_ppp_device.h"
#include "shill/mock_process_manager.h"
#include "shill/test_event_dispatcher.h"
#include "shill/vpn/mock_vpn_driver.h"
#include "shill/vpn/mock_vpn_provider.h"
using testing::_;
using testing::Mock;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;
namespace shill {
class L2TPIPsecDriverTest : public testing::Test, public RpcTaskDelegate {
public:
L2TPIPsecDriverTest()
: manager_(&control_, &dispatcher_, &metrics_),
device_info_(&manager_),
driver_(new L2TPIPsecDriver(&manager_, &process_manager_)),
certificate_file_(new MockCertificateFile()),
weak_factory_(this) {
manager_.set_mock_device_info(&device_info_);
driver_->certificate_file_.reset(certificate_file_); // Passes ownership.
}
~L2TPIPsecDriverTest() override = default;
void SetUp() override {
manager_.vpn_provider_ = std::make_unique<MockVPNProvider>();
manager_.vpn_provider_->manager_ = &manager_;
manager_.user_traffic_uids_.push_back(1000);
manager_.UpdateProviderMapping();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
void TearDown() override {
SetEventHandler(nullptr);
ASSERT_TRUE(temp_dir_.Delete());
// The ExternalTask instance initially held by |driver_->external_task_|
// could be scheduled to be destroyed after |driver_| is destroyed. To avoid
// leaking any ExternalTask instance when the test finishes, we explicitly
// destroy |driver_| here and in turn schedules the destruction of
// |driver_->external_task_| in the message loop. Then we run until the
// message loop becomes idle to exercise the destruction task of
// ExternalTask.
driver_ = nullptr;
dispatcher_.PostTask(
FROM_HERE,
base::Bind(&EventDispatcherForTest::QuitDispatchForever,
// dispatcher_ will not be deleted before RunLoop quits.
base::Unretained(&dispatcher_)));
dispatcher_.DispatchForever();
}
protected:
static const char kInterfaceName[];
static const int kInterfaceIndex;
void SetArg(const std::string& arg, const std::string& value) {
driver_->args()->Set<std::string>(arg, value);
}
void SetArgArray(const std::string& arg,
const std::vector<std::string>& value) {
driver_->args()->Set<Strings>(arg, value);
}
KeyValueStore* GetArgs() { return driver_->args(); }
std::string GetProviderType() { return driver_->GetProviderType(); }
void SetEventHandler(VPNDriver::EventHandler* handler) {
driver_->event_handler_ = handler;
}
bool IsPSKFileCleared(const base::FilePath& psk_file_path) const {
return !base::PathExists(psk_file_path) && GetPSKFile().empty();
}
bool IsXauthCredentialsFileCleared(
const base::FilePath& xauth_credentials_file_path) const {
return !base::PathExists(xauth_credentials_file_path) &&
GetXauthCredentialsFile().empty();
}
// Used to assert that a flag appears in the options.
void ExpectInFlags(const std::vector<std::string>& options,
const std::string& flag,
const std::string& value);
base::FilePath SetupPSKFile();
base::FilePath SetupXauthCredentialsFile();
base::FilePath GetPSKFile() const { return driver_->psk_file_; }
base::FilePath GetXauthCredentialsFile() const {
return driver_->xauth_credentials_file_;
}
void InvokeNotify(const std::string& reason,
const std::map<std::string, std::string>& dict) {
driver_->Notify(reason, dict);
}
void FakeUpConnect(base::FilePath* psk_file,
base::FilePath* xauth_credentials_file) {
*psk_file = SetupPSKFile();
*xauth_credentials_file = SetupXauthCredentialsFile();
SetEventHandler(&event_handler_);
}
void ExpectMetricsReported() {
Error unused_error;
PropertyStore store;
driver_->InitPropertyStore(&store);
store.SetStringProperty(kL2TPIPsecPskProperty, "x", &unused_error);
store.SetStringProperty(kL2TPIPsecPasswordProperty, "y", &unused_error);
store.SetStringProperty(kL2TPIPsecTunnelGroupProperty, "z", &unused_error);
EXPECT_CALL(metrics_, SendEnumToUMA(Metrics::kMetricVpnDriver,
Metrics::kVpnDriverL2tpIpsec,
Metrics::kMetricVpnDriverMax));
EXPECT_CALL(metrics_,
SendEnumToUMA(Metrics::kMetricVpnRemoteAuthenticationType,
Metrics::kVpnRemoteAuthenticationTypeL2tpIpsecPsk,
Metrics::kVpnRemoteAuthenticationTypeMax));
EXPECT_CALL(
metrics_,
SendEnumToUMA(
Metrics::kMetricVpnUserAuthenticationType,
Metrics::kVpnUserAuthenticationTypeL2tpIpsecUsernamePassword,
Metrics::kVpnUserAuthenticationTypeMax));
EXPECT_CALL(metrics_,
SendEnumToUMA(Metrics::kMetricVpnL2tpIpsecTunnelGroupUsage,
Metrics::kVpnL2tpIpsecTunnelGroupUsageYes,
Metrics::kVpnL2tpIpsecTunnelGroupUsageMax));
}
void SaveLoginPassword(const std::string& password_str) {
driver_->password_provider_ =
std::make_unique<password_provider::FakePasswordProvider>();
int fds[2];
base::CreateLocalNonBlockingPipe(fds);
base::ScopedFD read_dbus_fd(fds[0]);
base::ScopedFD write_scoped_fd(fds[1]);
size_t data_size = password_str.length();
base::WriteFileDescriptor(write_scoped_fd.get(), password_str);
auto password = password_provider::Password::CreateFromFileDescriptor(
read_dbus_fd.get(), data_size);
ASSERT_TRUE(password);
driver_->password_provider_->SavePassword(*password);
}
// Inherited from RpcTaskDelegate.
void GetLogin(std::string* user, std::string* password) override;
void Notify(const std::string& reason,
const std::map<std::string, std::string>& dict) override;
base::ScopedTempDir temp_dir_;
MockControl control_;
EventDispatcherForTest dispatcher_;
MockMetrics metrics_;
MockProcessManager process_manager_;
MockManager manager_;
NiceMock<MockDeviceInfo> device_info_;
MockVPNDriverEventHandler event_handler_;
std::unique_ptr<L2TPIPsecDriver> driver_;
MockCertificateFile* certificate_file_; // Owned by |driver_|.
base::WeakPtrFactory<L2TPIPsecDriverTest> weak_factory_;
};
const char L2TPIPsecDriverTest::kInterfaceName[] = "ppp0";
const int L2TPIPsecDriverTest::kInterfaceIndex = 123;
void L2TPIPsecDriverTest::GetLogin(std::string* /*user*/,
std::string* /*password*/) {}
void L2TPIPsecDriverTest::Notify(
const std::string& /*reason*/,
const std::map<std::string, std::string>& /*dict*/) {}
void L2TPIPsecDriverTest::ExpectInFlags(const std::vector<std::string>& options,
const std::string& flag,
const std::string& value) {
const auto flag_value =
base::StringPrintf("%s=%s", flag.c_str(), value.c_str());
EXPECT_TRUE(base::Contains(options, flag_value));
}
base::FilePath L2TPIPsecDriverTest::SetupPSKFile() {
base::FilePath psk_file;
EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &psk_file));
EXPECT_FALSE(psk_file.empty());
EXPECT_TRUE(base::PathExists(psk_file));
driver_->psk_file_ = psk_file;
return psk_file;
}
base::FilePath L2TPIPsecDriverTest::SetupXauthCredentialsFile() {
base::FilePath xauth_credentials_file;
EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(),
&xauth_credentials_file));
EXPECT_FALSE(xauth_credentials_file.empty());
EXPECT_TRUE(base::PathExists(xauth_credentials_file));
driver_->xauth_credentials_file_ = xauth_credentials_file;
return xauth_credentials_file;
}
TEST_F(L2TPIPsecDriverTest, GetProviderType) {
EXPECT_EQ(kProviderL2tpIpsec, GetProviderType());
}
TEST_F(L2TPIPsecDriverTest, Cleanup) {
driver_->Cleanup(); // Ensure no crash.
base::FilePath psk_file;
base::FilePath xauth_credentials_file;
FakeUpConnect(&psk_file, &xauth_credentials_file);
driver_->external_task_.reset(new MockExternalTask(
&control_, &process_manager_, weak_factory_.GetWeakPtr(),
base::Callback<void(pid_t, int)>()));
SetEventHandler(&event_handler_);
EXPECT_CALL(event_handler_,
OnDriverFailure(Service::kFailureBadPassphrase, _));
driver_->FailService(Service::kFailureBadPassphrase); // Trigger Cleanup.
EXPECT_TRUE(IsPSKFileCleared(psk_file));
EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file));
EXPECT_FALSE(driver_->event_handler_);
EXPECT_FALSE(driver_->external_task_);
SetEventHandler(&event_handler_);
driver_->Disconnect();
EXPECT_FALSE(driver_->event_handler_);
}
TEST_F(L2TPIPsecDriverTest, DeleteTemporaryFiles) {
base::FilePath psk_file = SetupPSKFile();
base::FilePath xauth_credentials_file = SetupXauthCredentialsFile();
driver_->DeleteTemporaryFiles();
EXPECT_TRUE(IsPSKFileCleared(psk_file));
EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file));
}
TEST_F(L2TPIPsecDriverTest, InitOptionsNoHost) {
Error error;
std::vector<std::string> options;
EXPECT_FALSE(driver_->InitOptions(&options, &error));
EXPECT_EQ(Error::kInvalidArguments, error.type());
EXPECT_TRUE(options.empty());
}
TEST_F(L2TPIPsecDriverTest, InitOptions) {
static const char kHost[] = "192.168.2.254";
static const char kPSK[] = "foobar";
static const char kXauthUser[] = "silly";
static const char kXauthPassword[] = "rabbit";
const std::vector<std::string> kCaCertPEM{"Insert PEM encoded data here"};
static const char kPEMCertfile[] = "/tmp/der-file-from-pem-cert";
base::FilePath pem_cert(kPEMCertfile);
SetArg(kProviderHostProperty, kHost);
SetArg(kL2TPIPsecPskProperty, kPSK);
SetArg(kL2TPIPsecXauthUserProperty, kXauthUser);
SetArg(kL2TPIPsecXauthPasswordProperty, kXauthPassword);
SetArgArray(kL2TPIPsecCaCertPemProperty, kCaCertPEM);
EXPECT_CALL(*certificate_file_, CreatePEMFromStrings(kCaCertPEM))
.WillOnce(Return(pem_cert));
const base::FilePath temp_dir(temp_dir_.GetPath());
// Once each for PSK and Xauth options.
EXPECT_CALL(manager_, run_path())
.WillOnce(ReturnRef(temp_dir))
.WillOnce(ReturnRef(temp_dir));
Error error;
std::vector<std::string> options;
EXPECT_TRUE(driver_->InitOptions(&options, &error));
EXPECT_TRUE(error.IsSuccess());
ExpectInFlags(options, "--remote_host", kHost);
ASSERT_FALSE(driver_->psk_file_.empty());
ExpectInFlags(options, "--psk_file", driver_->psk_file_.value());
ASSERT_FALSE(driver_->xauth_credentials_file_.empty());
ExpectInFlags(options, "--xauth_credentials_file",
driver_->xauth_credentials_file_.value());
ExpectInFlags(options, "--server_ca_file", kPEMCertfile);
}
TEST_F(L2TPIPsecDriverTest, InitPSKOptions) {
Error error;
std::vector<std::string> options;
static const char kPSK[] = "foobar";
const base::FilePath bad_dir("/non/existent/directory");
const base::FilePath temp_dir(temp_dir_.GetPath());
EXPECT_CALL(manager_, run_path())
.WillOnce(ReturnRef(bad_dir))
.WillOnce(ReturnRef(temp_dir));
EXPECT_TRUE(driver_->InitPSKOptions(&options, &error));
EXPECT_TRUE(options.empty());
EXPECT_TRUE(error.IsSuccess());
SetArg(kL2TPIPsecPskProperty, kPSK);
EXPECT_FALSE(driver_->InitPSKOptions(&options, &error));
EXPECT_TRUE(options.empty());
EXPECT_EQ(Error::kInternalError, error.type());
error.Reset();
EXPECT_TRUE(driver_->InitPSKOptions(&options, &error));
ASSERT_FALSE(driver_->psk_file_.empty());
ExpectInFlags(options, "--psk_file", driver_->psk_file_.value());
EXPECT_TRUE(error.IsSuccess());
std::string contents;
EXPECT_TRUE(base::ReadFileToString(driver_->psk_file_, &contents));
EXPECT_EQ(kPSK, contents);
struct stat buf;
ASSERT_EQ(0, stat(driver_->psk_file_.value().c_str(), &buf));
EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP, buf.st_mode);
}
TEST_F(L2TPIPsecDriverTest, InitPEMOptions) {
const std::vector<std::string> kCaCertPEM{"Insert PEM encoded data here"};
static const char kPEMCertfile[] = "/tmp/der-file-from-pem-cert";
base::FilePath empty_cert;
base::FilePath pem_cert(kPEMCertfile);
SetArgArray(kL2TPIPsecCaCertPemProperty, kCaCertPEM);
EXPECT_CALL(*certificate_file_, CreatePEMFromStrings(kCaCertPEM))
.WillOnce(Return(empty_cert))
.WillOnce(Return(pem_cert));
std::vector<std::string> options;
driver_->InitPEMOptions(&options);
EXPECT_TRUE(options.empty());
driver_->InitPEMOptions(&options);
ExpectInFlags(options, "--server_ca_file", kPEMCertfile);
}
TEST_F(L2TPIPsecDriverTest, InitXauthOptions) {
std::vector<std::string> options;
EXPECT_CALL(manager_, run_path()).Times(0);
{
Error error;
EXPECT_TRUE(driver_->InitXauthOptions(&options, &error));
EXPECT_TRUE(error.IsSuccess());
}
EXPECT_TRUE(options.empty());
static const char kUser[] = "foobar";
SetArg(kL2TPIPsecXauthUserProperty, kUser);
{
Error error;
EXPECT_FALSE(driver_->InitXauthOptions(&options, &error));
EXPECT_EQ(Error::kInvalidArguments, error.type());
}
EXPECT_TRUE(options.empty());
static const char kPassword[] = "foobar";
SetArg(kL2TPIPsecXauthUserProperty, "");
SetArg(kL2TPIPsecXauthPasswordProperty, kPassword);
{
Error error;
EXPECT_FALSE(driver_->InitXauthOptions(&options, &error));
EXPECT_EQ(Error::kInvalidArguments, error.type());
}
EXPECT_TRUE(options.empty());
Mock::VerifyAndClearExpectations(&manager_);
SetArg(kL2TPIPsecXauthUserProperty, kUser);
const base::FilePath bad_dir("/non/existent/directory");
const base::FilePath temp_dir(temp_dir_.GetPath());
EXPECT_CALL(manager_, run_path())
.WillOnce(ReturnRef(bad_dir))
.WillOnce(ReturnRef(temp_dir));
{
Error error;
EXPECT_FALSE(driver_->InitXauthOptions(&options, &error));
EXPECT_EQ(Error::kInternalError, error.type());
}
EXPECT_TRUE(options.empty());
{
Error error;
EXPECT_TRUE(driver_->InitXauthOptions(&options, &error));
EXPECT_TRUE(error.IsSuccess());
}
ASSERT_FALSE(driver_->xauth_credentials_file_.empty());
ExpectInFlags(options, "--xauth_credentials_file",
driver_->xauth_credentials_file_.value());
std::string contents;
EXPECT_TRUE(
base::ReadFileToString(driver_->xauth_credentials_file_, &contents));
std::string expected_contents(std::string(kUser) + "\n" + kPassword + "\n");
EXPECT_EQ(expected_contents, contents);
struct stat buf;
ASSERT_EQ(0, stat(driver_->xauth_credentials_file_.value().c_str(), &buf));
EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP, buf.st_mode);
}
TEST_F(L2TPIPsecDriverTest, AppendValueOption) {
static const char kOption[] = "--l2tpipsec-option";
static const char kProperty[] = "L2TPIPsec.SomeProperty";
static const char kValue[] = "some-property-value";
static const char kOption2[] = "--l2tpipsec-option2";
static const char kProperty2[] = "L2TPIPsec.SomeProperty2";
static const char kValue2[] = "some-property-value2";
std::vector<std::string> options;
EXPECT_FALSE(driver_->AppendValueOption("L2TPIPsec.UnknownProperty", kOption,
&options));
EXPECT_TRUE(options.empty());
SetArg(kProperty, "");
EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options));
EXPECT_TRUE(options.empty());
SetArg(kProperty, kValue);
SetArg(kProperty2, kValue2);
EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options));
EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options));
EXPECT_EQ(2, options.size());
EXPECT_EQ(base::StringPrintf("%s=%s", kOption, kValue), options[0]);
EXPECT_EQ(base::StringPrintf("%s=%s", kOption2, kValue2), options[1]);
}
TEST_F(L2TPIPsecDriverTest, AppendFlag) {
static const char kTrueOption[] = "--l2tpipsec-option";
static const char kFalseOption[] = "--nol2tpipsec-option";
static const char kProperty[] = "L2TPIPsec.SomeProperty";
static const char kTrueOption2[] = "--l2tpipsec-option2";
static const char kFalseOption2[] = "--nol2tpipsec-option2";
static const char kProperty2[] = "L2TPIPsec.SomeProperty2";
std::vector<std::string> options;
EXPECT_FALSE(driver_->AppendFlag("L2TPIPsec.UnknownProperty", kTrueOption,
kFalseOption, &options));
EXPECT_TRUE(options.empty());
SetArg(kProperty, "");
EXPECT_FALSE(
driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options));
EXPECT_TRUE(options.empty());
SetArg(kProperty, "true");
SetArg(kProperty2, "false");
EXPECT_TRUE(
driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options));
EXPECT_TRUE(
driver_->AppendFlag(kProperty2, kTrueOption2, kFalseOption2, &options));
EXPECT_EQ(2, options.size());
EXPECT_EQ(kTrueOption, options[0]);
EXPECT_EQ(kFalseOption2, options[1]);
}
TEST_F(L2TPIPsecDriverTest, GetLogin) {
static const char kUser[] = "joesmith";
static const char kPassword[] = "random-password";
std::string user, password;
SetArg(kL2TPIPsecUserProperty, kUser);
SetArg(kL2TPIPsecUseLoginPasswordProperty, "false");
driver_->GetLogin(&user, &password);
EXPECT_TRUE(user.empty());
EXPECT_TRUE(password.empty());
SetArg(kL2TPIPsecUserProperty, "");
SetArg(kL2TPIPsecPasswordProperty, kPassword);
driver_->GetLogin(&user, &password);
EXPECT_TRUE(user.empty());
EXPECT_TRUE(password.empty());
SetArg(kL2TPIPsecUserProperty, kUser);
driver_->GetLogin(&user, &password);
EXPECT_EQ(kUser, user);
EXPECT_EQ(kPassword, password);
}
TEST_F(L2TPIPsecDriverTest, UseLoginPassword) {
static const char kUser[] = "joesmith";
static const char kPassword[] = "random-password";
std::string user, password;
SetArg(kL2TPIPsecUserProperty, kUser);
SetArg(kL2TPIPsecUseLoginPasswordProperty, "true");
driver_->GetLogin(&user, &password);
EXPECT_TRUE(user.empty());
EXPECT_TRUE(password.empty());
SaveLoginPassword(kPassword);
driver_->GetLogin(&user, &password);
EXPECT_EQ(kUser, user);
EXPECT_EQ(kPassword, password);
}
TEST_F(L2TPIPsecDriverTest, OnL2TPIPsecVPNDied) {
const int kPID = 123456;
SetEventHandler(&event_handler_);
EXPECT_CALL(event_handler_, OnDriverFailure(Service::kFailureDNSLookup, _));
driver_->OnL2TPIPsecVPNDied(kPID,
vpn_manager::kServiceErrorResolveHostnameFailed);
EXPECT_FALSE(driver_->event_handler_);
}
TEST_F(L2TPIPsecDriverTest, SpawnL2TPIPsecVPN) {
Error error;
// Fail without sufficient arguments.
EXPECT_FALSE(driver_->SpawnL2TPIPsecVPN(&error));
EXPECT_TRUE(error.IsFailure());
// Provide the required arguments.
static const char kHost[] = "192.168.2.254";
SetArg(kProviderHostProperty, kHost);
EXPECT_CALL(process_manager_,
StartProcessInMinijail(_, _, _, _, _, _, _, _, true, _))
.WillOnce(Return(-1))
.WillOnce(Return(1));
EXPECT_FALSE(driver_->SpawnL2TPIPsecVPN(&error));
EXPECT_FALSE(driver_->external_task_);
EXPECT_TRUE(driver_->SpawnL2TPIPsecVPN(&error));
EXPECT_NE(nullptr, driver_->external_task_);
}
TEST_F(L2TPIPsecDriverTest, Connect) {
static const char kHost[] = "192.168.2.254";
SetArg(kProviderHostProperty, kHost);
EXPECT_CALL(process_manager_,
StartProcessInMinijail(_, _, _, _, _, _, _, _, true, _))
.WillOnce(Return(1));
base::TimeDelta timeout = driver_->ConnectAsync(&event_handler_);
EXPECT_NE(timeout, VPNDriver::kTimeoutNone);
}
TEST_F(L2TPIPsecDriverTest, Disconnect) {
SetEventHandler(&event_handler_);
driver_->Disconnect();
EXPECT_FALSE(driver_->event_handler_);
}
TEST_F(L2TPIPsecDriverTest, OnConnectTimeout) {
SetEventHandler(&event_handler_);
EXPECT_CALL(event_handler_, OnDriverFailure(Service::kFailureConnect, _));
driver_->OnConnectTimeout();
EXPECT_FALSE(driver_->event_handler_);
}
TEST_F(L2TPIPsecDriverTest, InitPropertyStore) {
// Quick test property store initialization.
PropertyStore store;
driver_->InitPropertyStore(&store);
const std::string kUser = "joe";
Error error;
EXPECT_TRUE(store.SetStringProperty(kL2TPIPsecUserProperty, kUser, &error));
EXPECT_TRUE(error.IsSuccess());
EXPECT_EQ(kUser, GetArgs()->Lookup<std::string>(kL2TPIPsecUserProperty, ""));
}
TEST_F(L2TPIPsecDriverTest, GetProvider) {
PropertyStore store;
driver_->InitPropertyStore(&store);
{
KeyValueStore props;
Error error;
SetArg(kL2TPIPsecClientCertIdProperty, "");
EXPECT_TRUE(
store.GetKeyValueStoreProperty(kProviderProperty, &props, &error));
EXPECT_TRUE(props.Lookup<bool>(kPassphraseRequiredProperty, false));
EXPECT_TRUE(props.Lookup<bool>(kL2TPIPsecPskRequiredProperty, false));
}
{
KeyValueStore props;
Error error;
SetArg(kL2TPIPsecClientCertIdProperty, "some-cert-id");
EXPECT_TRUE(
store.GetKeyValueStoreProperty(kProviderProperty, &props, &error));
EXPECT_TRUE(props.Lookup<bool>(kPassphraseRequiredProperty, false));
EXPECT_FALSE(props.Lookup<bool>(kL2TPIPsecPskRequiredProperty, true));
SetArg(kL2TPIPsecClientCertIdProperty, "");
}
{
KeyValueStore props;
SetArg(kL2TPIPsecPasswordProperty, "random-password");
SetArg(kL2TPIPsecPskProperty, "random-psk");
Error error;
EXPECT_TRUE(
store.GetKeyValueStoreProperty(kProviderProperty, &props, &error));
EXPECT_FALSE(props.Lookup<bool>(kPassphraseRequiredProperty, true));
EXPECT_FALSE(props.Lookup<bool>(kL2TPIPsecPskRequiredProperty, true));
EXPECT_FALSE(props.Contains<std::string>(kL2TPIPsecPasswordProperty));
}
}
TEST_F(L2TPIPsecDriverTest, Notify) {
std::map<std::string, std::string> config{
{kPPPInterfaceName, kInterfaceName}};
base::FilePath psk_file;
base::FilePath xauth_credentials_file;
FakeUpConnect(&psk_file, &xauth_credentials_file);
// Make sure that a notification of an intermediate state doesn't cause
// the driver to fail the connection.
EXPECT_CALL(event_handler_, OnDriverConnected(_, _)).Times(0);
EXPECT_CALL(event_handler_, OnDriverFailure(_, _)).Times(0);
EXPECT_TRUE(driver_->event_handler_);
InvokeNotify(kPPPReasonAuthenticating, config);
EXPECT_TRUE(driver_->event_handler_);
InvokeNotify(kPPPReasonAuthenticated, config);
EXPECT_TRUE(driver_->event_handler_);
ExpectMetricsReported();
EXPECT_CALL(event_handler_,
OnDriverConnected(kInterfaceName, kInterfaceIndex));
EXPECT_CALL(device_info_, GetIndex(kInterfaceName))
.WillOnce(Return(kInterfaceIndex));
InvokeNotify(kPPPReasonConnect, config);
EXPECT_TRUE(IsPSKFileCleared(psk_file));
EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file));
}
TEST_F(L2TPIPsecDriverTest, NotifyWithoutDeviceInfoReady) {
std::map<std::string, std::string> config{
{kPPPInterfaceName, kInterfaceName}};
base::FilePath psk_file;
base::FilePath xauth_credentials_file;
FakeUpConnect(&psk_file, &xauth_credentials_file);
DeviceInfo::LinkReadyCallback link_ready_callback;
EXPECT_CALL(event_handler_, OnDriverConnected(_, _)).Times(0);
EXPECT_CALL(device_info_, GetIndex(kInterfaceName)).WillOnce(Return(-1));
EXPECT_CALL(device_info_, AddVirtualInterfaceReadyCallback(kInterfaceName, _))
.WillOnce([&link_ready_callback](const std::string&,
DeviceInfo::LinkReadyCallback callback) {
link_ready_callback = std::move(callback);
});
InvokeNotify(kPPPReasonConnect, config);
EXPECT_CALL(event_handler_,
OnDriverConnected(kInterfaceName, kInterfaceIndex));
std::move(link_ready_callback).Run(kInterfaceName, kInterfaceIndex);
}
TEST_F(L2TPIPsecDriverTest, NotifyDisconnected) {
std::map<std::string, std::string> dict;
SetEventHandler(&event_handler_);
base::Callback<void(pid_t, int)> death_callback;
MockExternalTask* local_external_task = new MockExternalTask(
&control_, &process_manager_, weak_factory_.GetWeakPtr(), death_callback);
driver_->external_task_.reset(local_external_task); // passes ownership
EXPECT_CALL(event_handler_, OnDriverFailure(_, _));
EXPECT_CALL(*local_external_task, OnDelete());
driver_->Notify(kPPPReasonDisconnect, dict);
EXPECT_EQ(nullptr, driver_->external_task_);
}
} // namespace shill