| // 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 <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/stl_util.h> |
| #include <base/strings/string_util.h> |
| #include <base/strings/stringprintf.h> |
| #include <gtest/gtest.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_provider.h" |
| #include "shill/vpn/mock_vpn_service.h" |
| |
| using base::FilePath; |
| using std::map; |
| using std::string; |
| using std::vector; |
| 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_)), |
| service_(new MockVPNService(&manager_, base::WrapUnique(driver_))), |
| certificate_file_(new MockCertificateFile()), |
| weak_ptr_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 { |
| SetService(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 |service_| here, which indirectly destroys |driver_| |
| // 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. |
| service_ = 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 string& arg, const string& value) { |
| driver_->args()->Set<string>(arg, value); |
| } |
| |
| void SetArgArray(const string& arg, const vector<string>& value) { |
| driver_->args()->Set<Strings>(arg, value); |
| } |
| |
| KeyValueStore* GetArgs() { return driver_->args(); } |
| |
| string GetProviderType() { return driver_->GetProviderType(); } |
| |
| void SetService(const scoped_refptr<MockVPNService>& service) { |
| if (service) { |
| driver_->service_callback_ = service->GetCallback(); |
| } else { |
| driver_->service_callback_.Reset(); |
| } |
| } |
| |
| void OnConnectTimeout() { driver_->OnConnectTimeout(); } |
| |
| void StartConnectTimeout(int timeout_seconds) { |
| driver_->StartConnectTimeout(timeout_seconds); |
| } |
| |
| bool IsConnectTimeoutStarted() const { |
| return driver_->IsConnectTimeoutStarted(); |
| } |
| |
| bool IsPSKFileCleared(const FilePath& psk_file_path) const { |
| return !base::PathExists(psk_file_path) && GetPSKFile().empty(); |
| } |
| |
| bool IsXauthCredentialsFileCleared( |
| const 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 vector<string>& options, |
| const string& flag, |
| const string& value); |
| |
| FilePath SetupPSKFile(); |
| FilePath SetupXauthCredentialsFile(); |
| |
| FilePath GetPSKFile() const { return driver_->psk_file_; } |
| FilePath GetXauthCredentialsFile() const { |
| return driver_->xauth_credentials_file_; |
| } |
| |
| void InvokeNotify(const string& reason, const map<string, string>& dict) { |
| driver_->Notify(reason, dict); |
| } |
| |
| void FakeUpConnect(FilePath* psk_file, FilePath* xauth_credentials_file) { |
| *psk_file = SetupPSKFile(); |
| *xauth_credentials_file = SetupXauthCredentialsFile(); |
| SetService(service_); |
| StartConnectTimeout(0); |
| } |
| |
| void ExpectMetricsReported() { |
| Error unused_error; |
| PropertyStore store; |
| driver_->InitPropertyStore(&store); |
| store.SetStringProperty(kL2tpIpsecPskProperty, "x", &unused_error); |
| store.SetStringProperty(kL2tpIpsecPasswordProperty, "y", &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)); |
| } |
| |
| // Inherited from RpcTaskDelegate. |
| void GetLogin(string* user, string* password) override; |
| void Notify(const string& reason, const map<string, string>& dict) override; |
| |
| base::ScopedTempDir temp_dir_; |
| MockControl control_; |
| EventDispatcherForTest dispatcher_; |
| MockMetrics metrics_; |
| MockProcessManager process_manager_; |
| MockManager manager_; |
| NiceMock<MockDeviceInfo> device_info_; |
| L2TPIPSecDriver* driver_; // Owned by |service_|. |
| scoped_refptr<MockVPNService> service_; |
| MockCertificateFile* certificate_file_; // Owned by |driver_|. |
| base::WeakPtrFactory<L2TPIPSecDriverTest> weak_ptr_factory_; |
| }; |
| |
| const char L2TPIPSecDriverTest::kInterfaceName[] = "ppp0"; |
| const int L2TPIPSecDriverTest::kInterfaceIndex = 123; |
| |
| void L2TPIPSecDriverTest::GetLogin(string* /*user*/, string* /*password*/) {} |
| |
| void L2TPIPSecDriverTest::Notify(const string& /*reason*/, |
| const map<string, string>& /*dict*/) {} |
| |
| void L2TPIPSecDriverTest::ExpectInFlags(const vector<string>& options, |
| const string& flag, |
| const string& value) { |
| string flag_value = base::StringPrintf("%s=%s", flag.c_str(), value.c_str()); |
| EXPECT_TRUE(base::Contains(options, flag_value)); |
| } |
| |
| FilePath L2TPIPSecDriverTest::SetupPSKFile() { |
| 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; |
| } |
| |
| FilePath L2TPIPSecDriverTest::SetupXauthCredentialsFile() { |
| 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. |
| |
| FilePath psk_file; |
| FilePath xauth_credentials_file; |
| FakeUpConnect(&psk_file, &xauth_credentials_file); |
| driver_->external_task_.reset(new MockExternalTask( |
| &control_, &process_manager_, weak_ptr_factory_.GetWeakPtr(), |
| base::Callback<void(pid_t, int)>())); |
| SetService(service_); |
| EXPECT_CALL(*service_, OnDriverEvent(VPNService::kEventDriverFailure, |
| Service::kFailureBadPassphrase, _)); |
| driver_->FailService(Service::kFailureBadPassphrase); // Trigger Cleanup. |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file)); |
| EXPECT_FALSE(driver_->service_callback_); |
| EXPECT_FALSE(driver_->IsConnectTimeoutStarted()); |
| EXPECT_FALSE(driver_->external_task_); |
| |
| SetService(service_); |
| driver_->Disconnect(); |
| EXPECT_FALSE(driver_->service_callback_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, DeleteTemporaryFiles) { |
| FilePath psk_file = SetupPSKFile(); |
| FilePath xauth_credentials_file = SetupXauthCredentialsFile(); |
| driver_->DeleteTemporaryFiles(); |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file)); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitOptionsNoHost) { |
| Error error; |
| vector<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 vector<string> kCaCertPEM{"Insert PEM encoded data here"}; |
| static const char kPEMCertfile[] = "/tmp/der-file-from-pem-cert"; |
| 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 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; |
| vector<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; |
| vector<string> options; |
| static const char kPSK[] = "foobar"; |
| const FilePath bad_dir("/non/existent/directory"); |
| const 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()); |
| 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, buf.st_mode); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitPEMOptions) { |
| const vector<string> kCaCertPEM{"Insert PEM encoded data here"}; |
| static const char kPEMCertfile[] = "/tmp/der-file-from-pem-cert"; |
| FilePath empty_cert; |
| FilePath pem_cert(kPEMCertfile); |
| SetArgArray(kL2tpIpsecCaCertPemProperty, kCaCertPEM); |
| EXPECT_CALL(*certificate_file_, CreatePEMFromStrings(kCaCertPEM)) |
| .WillOnce(Return(empty_cert)) |
| .WillOnce(Return(pem_cert)); |
| |
| vector<string> options; |
| driver_->InitPEMOptions(&options); |
| EXPECT_TRUE(options.empty()); |
| driver_->InitPEMOptions(&options); |
| ExpectInFlags(options, "--server_ca_file", kPEMCertfile); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitXauthOptions) { |
| vector<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 FilePath bad_dir("/non/existent/directory"); |
| const 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()); |
| string contents; |
| EXPECT_TRUE( |
| base::ReadFileToString(driver_->xauth_credentials_file_, &contents)); |
| string expected_contents(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, 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"; |
| |
| vector<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"; |
| |
| vector<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"; |
| string user, password; |
| SetArg(kL2tpIpsecUserProperty, kUser); |
| 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, OnL2TPIPSecVPNDied) { |
| const int kPID = 123456; |
| SetService(service_); |
| EXPECT_CALL(*service_, OnDriverEvent(VPNService::kEventDriverFailure, |
| Service::kFailureDNSLookup, _)); |
| driver_->OnL2TPIPSecVPNDied(kPID, |
| vpn_manager::kServiceErrorResolveHostnameFailed); |
| EXPECT_FALSE(driver_->service_callback_); |
| } |
| |
| 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)); |
| driver_->ConnectAsync(service_->GetCallback()); |
| EXPECT_TRUE(driver_->IsConnectTimeoutStarted()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, Disconnect) { |
| SetService(service_); |
| driver_->Disconnect(); |
| EXPECT_FALSE(driver_->service_callback_); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, OnConnectTimeout) { |
| StartConnectTimeout(0); |
| SetService(service_); |
| EXPECT_CALL(*service_, OnDriverEvent(VPNService::kEventDriverFailure, |
| Service::kFailureConnect, _)); |
| OnConnectTimeout(); |
| EXPECT_FALSE(driver_->service_callback_); |
| EXPECT_FALSE(IsConnectTimeoutStarted()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, InitPropertyStore) { |
| // Sanity test property store initialization. |
| PropertyStore store; |
| driver_->InitPropertyStore(&store); |
| const string kUser = "joe"; |
| Error error; |
| EXPECT_TRUE(store.SetStringProperty(kL2tpIpsecUserProperty, kUser, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| EXPECT_EQ(kUser, GetArgs()->Lookup<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<string>(kL2tpIpsecPasswordProperty)); |
| } |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, Notify) { |
| map<string, string> config{{kPPPInterfaceName, kInterfaceName}}; |
| FilePath psk_file; |
| 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(*service_, OnDriverEvent(_, _, _)).Times(0); |
| EXPECT_TRUE(driver_->service_callback_); |
| InvokeNotify(kPPPReasonAuthenticating, config); |
| EXPECT_TRUE(driver_->service_callback_); |
| InvokeNotify(kPPPReasonAuthenticated, config); |
| EXPECT_TRUE(driver_->service_callback_); |
| |
| ExpectMetricsReported(); |
| EXPECT_CALL(*service_, |
| OnDriverEvent(VPNService::kEventConnectionSuccess, _, _)); |
| InvokeNotify(kPPPReasonConnect, config); |
| EXPECT_EQ(driver_->interface_name_, kInterfaceName); |
| EXPECT_TRUE(IsPSKFileCleared(psk_file)); |
| EXPECT_TRUE(IsXauthCredentialsFileCleared(xauth_credentials_file)); |
| EXPECT_FALSE(IsConnectTimeoutStarted()); |
| } |
| |
| TEST_F(L2TPIPSecDriverTest, NotifyDisconnected) { |
| map<string, string> dict; |
| SetService(service_); |
| base::Callback<void(pid_t, int)> death_callback; |
| MockExternalTask* local_external_task = |
| new MockExternalTask(&control_, &process_manager_, |
| weak_ptr_factory_.GetWeakPtr(), death_callback); |
| driver_->external_task_.reset(local_external_task); // passes ownership |
| EXPECT_CALL(*service_, OnDriverEvent(VPNService::kEventDriverFailure, _, _)); |
| EXPECT_CALL(*local_external_task, OnDelete()); |
| driver_->Notify(kPPPReasonDisconnect, dict); |
| EXPECT_EQ(nullptr, driver_->external_task_); |
| EXPECT_FALSE(IsConnectTimeoutStarted()); |
| } |
| |
| } // namespace shill |