blob: e231d929d89d8042452c7d3db1e8e741fac4c358 [file] [log] [blame]
Darin Petkov7476a262012-04-12 16:30:46 +02001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/l2tp_ipsec_driver.h"
6
Darin Petkovf7ef50a2012-04-16 20:54:31 +02007#include <base/file_util.h>
8#include <base/scoped_temp_dir.h>
Darin Petkov209e6292012-04-20 11:33:32 +02009#include <base/string_util.h>
Darin Petkov7476a262012-04-12 16:30:46 +020010#include <gtest/gtest.h>
11
12#include "shill/event_dispatcher.h"
13#include "shill/nice_mock_control.h"
Darin Petkov209e6292012-04-20 11:33:32 +020014#include "shill/mock_adaptors.h"
Darin Petkov7476a262012-04-12 16:30:46 +020015#include "shill/mock_glib.h"
16#include "shill/mock_manager.h"
17#include "shill/mock_metrics.h"
Darin Petkovf7ef50a2012-04-16 20:54:31 +020018#include "shill/mock_nss.h"
Darin Petkov7476a262012-04-12 16:30:46 +020019#include "shill/mock_vpn_service.h"
20
Darin Petkovf7ef50a2012-04-16 20:54:31 +020021using std::find;
Darin Petkov209e6292012-04-20 11:33:32 +020022using std::map;
Darin Petkovf7ef50a2012-04-16 20:54:31 +020023using std::string;
24using std::vector;
25using testing::_;
26using testing::ElementsAreArray;
27using testing::Return;
28using testing::ReturnRef;
Darin Petkov209e6292012-04-20 11:33:32 +020029using testing::SetArgumentPointee;
Darin Petkovf7ef50a2012-04-16 20:54:31 +020030
Darin Petkov7476a262012-04-12 16:30:46 +020031namespace shill {
32
Darin Petkov209e6292012-04-20 11:33:32 +020033class L2TPIPSecDriverTest : public testing::Test,
34 public RPCTaskDelegate {
Darin Petkov7476a262012-04-12 16:30:46 +020035 public:
36 L2TPIPSecDriverTest()
37 : manager_(&control_, &dispatcher_, &metrics_, &glib_),
Darin Petkov209e6292012-04-20 11:33:32 +020038 driver_(new L2TPIPSecDriver(&control_, &manager_, &glib_)),
Darin Petkov7476a262012-04-12 16:30:46 +020039 service_(new MockVPNService(&control_, &dispatcher_, &metrics_,
Darin Petkovf7ef50a2012-04-16 20:54:31 +020040 &manager_, driver_)) {
41 driver_->nss_ = &nss_;
42 }
Darin Petkov7476a262012-04-12 16:30:46 +020043
44 virtual ~L2TPIPSecDriverTest() {}
45
Darin Petkovf7ef50a2012-04-16 20:54:31 +020046 virtual void SetUp() {
47 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
48 }
49
50 virtual void TearDown() {
Darin Petkov209e6292012-04-20 11:33:32 +020051 driver_->child_watch_tag_ = 0;
52 driver_->pid_ = 0;
53 driver_->service_ = NULL;
Darin Petkovf7ef50a2012-04-16 20:54:31 +020054 ASSERT_TRUE(temp_dir_.Delete());
55 }
56
Darin Petkov7476a262012-04-12 16:30:46 +020057 protected:
Darin Petkovf7ef50a2012-04-16 20:54:31 +020058 void SetArg(const string &arg, const string &value) {
59 driver_->args_.SetString(arg, value);
60 }
61
Darin Petkovd4325392012-04-23 15:48:22 +020062 KeyValueStore *GetArgs() {
63 return driver_->args();
64 }
65
Darin Petkovf7ef50a2012-04-16 20:54:31 +020066 // Used to assert that a flag appears in the options.
67 void ExpectInFlags(const vector<string> &options, const string &flag,
68 const string &value);
69
Darin Petkov209e6292012-04-20 11:33:32 +020070 // Inherited from RPCTaskDelegate.
71 virtual void GetLogin(string *user, string *password);
72 virtual void Notify(const string &reason, const map<string, string> &dict);
73
Darin Petkovf7ef50a2012-04-16 20:54:31 +020074 ScopedTempDir temp_dir_;
Darin Petkov7476a262012-04-12 16:30:46 +020075 NiceMockControl control_;
76 EventDispatcher dispatcher_;
77 MockMetrics metrics_;
78 MockGLib glib_;
79 MockManager manager_;
80 L2TPIPSecDriver *driver_; // Owned by |service_|.
81 scoped_refptr<MockVPNService> service_;
Darin Petkovf7ef50a2012-04-16 20:54:31 +020082 MockNSS nss_;
Darin Petkov7476a262012-04-12 16:30:46 +020083};
84
Darin Petkov209e6292012-04-20 11:33:32 +020085void L2TPIPSecDriverTest::GetLogin(string */*user*/, string */*password*/) {}
86
87void L2TPIPSecDriverTest::Notify(
88 const string &/*reason*/, const map<string, string> &/*dict*/) {}
89
Darin Petkovf7ef50a2012-04-16 20:54:31 +020090void L2TPIPSecDriverTest::ExpectInFlags(
91 const vector<string> &options, const string &flag, const string &value) {
92 vector<string>::const_iterator it =
93 find(options.begin(), options.end(), flag);
94
95 EXPECT_TRUE(it != options.end());
96 if (it != options.end())
97 return; // Don't crash below.
98 it++;
99 EXPECT_TRUE(it != options.end());
100 if (it != options.end())
101 return; // Don't crash below.
102 EXPECT_EQ(value, *it);
103}
104
Darin Petkov7476a262012-04-12 16:30:46 +0200105TEST_F(L2TPIPSecDriverTest, GetProviderType) {
106 EXPECT_EQ(flimflam::kProviderL2tpIpsec, driver_->GetProviderType());
107}
108
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200109TEST_F(L2TPIPSecDriverTest, Cleanup) {
Darin Petkov209e6292012-04-20 11:33:32 +0200110 driver_->Cleanup(Service::kStateIdle); // Ensure no crash.
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200111
Darin Petkov209e6292012-04-20 11:33:32 +0200112 const unsigned int kTag = 123;
113 driver_->child_watch_tag_ = kTag;
114 EXPECT_CALL(glib_, SourceRemove(kTag));
115 const int kPID = 123456;
116 driver_->pid_ = kPID;
117 EXPECT_CALL(glib_, SpawnClosePID(kPID));
118 driver_->service_ = service_;
119 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
120 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200121 FilePath psk_file;
122 EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &psk_file));
123 EXPECT_FALSE(psk_file.empty());
124 EXPECT_TRUE(file_util::PathExists(psk_file));
125 driver_->psk_file_ = psk_file;
Darin Petkov209e6292012-04-20 11:33:32 +0200126 driver_->Cleanup(Service::kStateFailure);
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200127 EXPECT_FALSE(file_util::PathExists(psk_file));
128 EXPECT_TRUE(driver_->psk_file_.empty());
Darin Petkov209e6292012-04-20 11:33:32 +0200129 EXPECT_EQ(0, driver_->child_watch_tag_);
130 EXPECT_EQ(0, driver_->pid_);
131 EXPECT_FALSE(driver_->rpc_task_.get());
132 EXPECT_FALSE(driver_->service_);
133}
134
135TEST_F(L2TPIPSecDriverTest, InitEnvironment) {
136 vector<string> env;
137 driver_->rpc_task_.reset(new RPCTask(&control_, this));
138 driver_->InitEnvironment(&env);
139 ASSERT_EQ(3, env.size());
140 EXPECT_EQ(string("CONNMAN_BUSNAME=") + RPCTaskMockAdaptor::kRpcConnId,
141 env[0]);
142 EXPECT_EQ(string("CONNMAN_INTERFACE=") + RPCTaskMockAdaptor::kRpcInterfaceId,
143 env[1]);
144 EXPECT_EQ(string("CONNMAN_PATH=") + RPCTaskMockAdaptor::kRpcId, env[2]);
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200145}
146
147TEST_F(L2TPIPSecDriverTest, InitOptionsNoHost) {
148 Error error;
149 vector<string> options;
Darin Petkov209e6292012-04-20 11:33:32 +0200150 EXPECT_FALSE(driver_->InitOptions(&options, &error));
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200151 EXPECT_EQ(Error::kInvalidArguments, error.type());
152 EXPECT_TRUE(options.empty());
153}
154
155TEST_F(L2TPIPSecDriverTest, InitOptions) {
156 static const char kHost[] = "192.168.2.254";
157 static const char kCaCertNSS[] = "{1234}";
158 static const char kPSK[] = "foobar";
159
160 SetArg(flimflam::kProviderHostProperty, kHost);
161 SetArg(flimflam::kL2tpIpsecCaCertNssProperty, kCaCertNSS);
162 SetArg(flimflam::kL2tpIpsecPskProperty, kPSK);
163
164 FilePath empty_cert;
165 EXPECT_CALL(nss_, GetDERCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert));
166
167 const FilePath temp_dir(temp_dir_.path());
168 EXPECT_CALL(manager_, run_path()).WillOnce(ReturnRef(temp_dir));
169
170 Error error;
171 vector<string> options;
Darin Petkov209e6292012-04-20 11:33:32 +0200172 EXPECT_TRUE(driver_->InitOptions(&options, &error));
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200173 EXPECT_TRUE(error.IsSuccess());
174
175 ExpectInFlags(options, "--remote_host", kHost);
176 ASSERT_FALSE(driver_->psk_file_.empty());
177 ExpectInFlags(options, "--psk_file", driver_->psk_file_.value());
178}
179
180TEST_F(L2TPIPSecDriverTest, InitPSKOptions) {
181 Error error;
182 vector<string> options;
183 static const char kPSK[] = "foobar";
184 const FilePath bad_dir("/non/existent/directory");
185 const FilePath temp_dir(temp_dir_.path());
186 EXPECT_CALL(manager_, run_path())
187 .WillOnce(ReturnRef(bad_dir))
188 .WillOnce(ReturnRef(temp_dir));
189
190 EXPECT_TRUE(driver_->InitPSKOptions(&options, &error));
191 EXPECT_TRUE(options.empty());
192 EXPECT_TRUE(error.IsSuccess());
193
194 SetArg(flimflam::kL2tpIpsecPskProperty, kPSK);
195
196 EXPECT_FALSE(driver_->InitPSKOptions(&options, &error));
197 EXPECT_TRUE(options.empty());
198 EXPECT_EQ(Error::kInternalError, error.type());
199 error.Reset();
200
201 EXPECT_TRUE(driver_->InitPSKOptions(&options, &error));
202 ASSERT_FALSE(driver_->psk_file_.empty());
203 ExpectInFlags(options, "--psk_file", driver_->psk_file_.value());
204 EXPECT_TRUE(error.IsSuccess());
205 string contents;
206 EXPECT_TRUE(
207 file_util::ReadFileToString(driver_->psk_file_, &contents));
208 EXPECT_EQ(kPSK, contents);
209 struct stat buf;
210 ASSERT_EQ(0, stat(driver_->psk_file_.value().c_str(), &buf));
211 EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR, buf.st_mode);
212}
213
214TEST_F(L2TPIPSecDriverTest, InitNSSOptions) {
215 static const char kHost[] = "192.168.2.254";
216 static const char kCaCertNSS[] = "{1234}";
217 static const char kNSSCertfile[] = "/tmp/nss-cert";
218 FilePath empty_cert;
219 FilePath nss_cert(kNSSCertfile);
220 SetArg(flimflam::kProviderHostProperty, kHost);
221 SetArg(flimflam::kL2tpIpsecCaCertNssProperty, kCaCertNSS);
222 EXPECT_CALL(nss_,
223 GetDERCertfile(kCaCertNSS,
224 ElementsAreArray(kHost, arraysize(kHost) - 1)))
225 .WillOnce(Return(empty_cert))
226 .WillOnce(Return(nss_cert));
227
228 vector<string> options;
229 driver_->InitNSSOptions(&options);
230 EXPECT_TRUE(options.empty());
231 driver_->InitNSSOptions(&options);
232 ExpectInFlags(options, "--server_ca_file", kNSSCertfile);
233}
234
235TEST_F(L2TPIPSecDriverTest, AppendValueOption) {
236 static const char kOption[] = "--l2tpipsec-option";
237 static const char kProperty[] = "L2TPIPSec.SomeProperty";
238 static const char kValue[] = "some-property-value";
239 static const char kOption2[] = "--l2tpipsec-option2";
240 static const char kProperty2[] = "L2TPIPSec.SomeProperty2";
241 static const char kValue2[] = "some-property-value2";
242
243 vector<string> options;
244 EXPECT_FALSE(
245 driver_->AppendValueOption(
246 "L2TPIPSec.UnknownProperty", kOption, &options));
247 EXPECT_TRUE(options.empty());
248
249 SetArg(kProperty, "");
250 EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options));
251 EXPECT_TRUE(options.empty());
252
253 SetArg(kProperty, kValue);
254 SetArg(kProperty2, kValue2);
255 EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options));
256 EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options));
257 EXPECT_EQ(4, options.size());
258 EXPECT_EQ(kOption, options[0]);
259 EXPECT_EQ(kValue, options[1]);
260 EXPECT_EQ(kOption2, options[2]);
261 EXPECT_EQ(kValue2, options[3]);
262}
263
264TEST_F(L2TPIPSecDriverTest, AppendFlag) {
265 static const char kTrueOption[] = "--l2tpipsec-option";
266 static const char kFalseOption[] = "--nol2tpipsec-option";
267 static const char kProperty[] = "L2TPIPSec.SomeProperty";
268 static const char kTrueOption2[] = "--l2tpipsec-option2";
269 static const char kFalseOption2[] = "--nol2tpipsec-option2";
270 static const char kProperty2[] = "L2TPIPSec.SomeProperty2";
271
272 vector<string> options;
273 EXPECT_FALSE(driver_->AppendFlag("L2TPIPSec.UnknownProperty",
274 kTrueOption, kFalseOption, &options));
275 EXPECT_TRUE(options.empty());
276
277 SetArg(kProperty, "");
278 EXPECT_FALSE(
279 driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options));
280 EXPECT_TRUE(options.empty());
281
282 SetArg(kProperty, "true");
283 SetArg(kProperty2, "false");
284 EXPECT_TRUE(
285 driver_->AppendFlag(kProperty, kTrueOption, kFalseOption, &options));
286 EXPECT_TRUE(
287 driver_->AppendFlag(kProperty2, kTrueOption2, kFalseOption2, &options));
288 EXPECT_EQ(2, options.size());
289 EXPECT_EQ(kTrueOption, options[0]);
290 EXPECT_EQ(kFalseOption2, options[1]);
291}
292
Darin Petkov209e6292012-04-20 11:33:32 +0200293TEST_F(L2TPIPSecDriverTest, GetLogin) {
294 static const char kUser[] = "joesmith";
295 static const char kPassword[] = "random-password";
296 string user, password;
297 SetArg(flimflam::kL2tpIpsecUserProperty, kUser);
298 driver_->GetLogin(&user, &password);
299 EXPECT_TRUE(user.empty());
300 EXPECT_TRUE(password.empty());
301 SetArg(flimflam::kL2tpIpsecUserProperty, "");
302 SetArg(flimflam::kL2tpIpsecPasswordProperty, kPassword);
303 driver_->GetLogin(&user, &password);
304 EXPECT_TRUE(user.empty());
305 EXPECT_TRUE(password.empty());
306 SetArg(flimflam::kL2tpIpsecUserProperty, kUser);
307 driver_->GetLogin(&user, &password);
308 EXPECT_EQ(kUser, user);
309 EXPECT_EQ(kPassword, password);
310}
311
312TEST_F(L2TPIPSecDriverTest, OnL2TPIPSecVPNDied) {
313 const int kPID = 99999;
314 driver_->child_watch_tag_ = 333;
315 driver_->pid_ = kPID;
316 EXPECT_CALL(glib_, SpawnClosePID(kPID));
317 L2TPIPSecDriver::OnL2TPIPSecVPNDied(kPID, 2, driver_);
318 EXPECT_EQ(0, driver_->child_watch_tag_);
319 EXPECT_EQ(0, driver_->pid_);
320}
321
322namespace {
323MATCHER(CheckEnv, "") {
324 if (!arg || !arg[0] || !arg[1] || !arg[2] || arg[3]) {
325 return false;
326 }
327 return StartsWithASCII(arg[0], "CONNMAN_", true);
328}
329} // namespace
330
331TEST_F(L2TPIPSecDriverTest, SpawnL2TPIPSecVPN) {
332 Error error;
333 EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error));
334 EXPECT_TRUE(error.IsFailure());
335
336 static const char kHost[] = "192.168.2.254";
337 SetArg(flimflam::kProviderHostProperty, kHost);
338 driver_->rpc_task_.reset(new RPCTask(&control_, this));
339
340 const int kPID = 234678;
341 EXPECT_CALL(glib_,
342 SpawnAsyncWithPipesCWD(_, CheckEnv(), _, _, _, _, _, _, _, _))
343 .WillOnce(Return(false))
344 .WillOnce(DoAll(SetArgumentPointee<5>(kPID), Return(true)));
345 const int kTag = 6;
346 EXPECT_CALL(glib_, ChildWatchAdd(kPID, &driver_->OnL2TPIPSecVPNDied, driver_))
347 .WillOnce(Return(kTag));
348 error.Reset();
349 EXPECT_FALSE(driver_->SpawnL2TPIPSecVPN(&error));
350 EXPECT_EQ(Error::kInternalError, error.type());
351 error.Reset();
352 EXPECT_TRUE(driver_->SpawnL2TPIPSecVPN(&error));
353 EXPECT_TRUE(error.IsSuccess());
354 EXPECT_EQ(kPID, driver_->pid_);
355 EXPECT_EQ(kTag, driver_->child_watch_tag_);
356}
357
358TEST_F(L2TPIPSecDriverTest, Connect) {
359 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
360 static const char kHost[] = "192.168.2.254";
361 SetArg(flimflam::kProviderHostProperty, kHost);
362 EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
363 .WillOnce(Return(true));
364 EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).WillOnce(Return(1));
365 Error error;
366 driver_->Connect(service_, &error);
367 EXPECT_TRUE(error.IsSuccess());
368}
369
Darin Petkovd4325392012-04-23 15:48:22 +0200370TEST_F(L2TPIPSecDriverTest, InitPropertyStore) {
371 // Sanity test property store initialization.
372 PropertyStore store;
373 driver_->InitPropertyStore(&store);
374 const string kUser = "joe";
375 Error error;
376 EXPECT_TRUE(
377 store.SetStringProperty(flimflam::kL2tpIpsecUserProperty, kUser, &error));
378 EXPECT_TRUE(error.IsSuccess());
379 EXPECT_EQ(kUser, GetArgs()->GetString(flimflam::kL2tpIpsecUserProperty));
380}
381
Darin Petkov7476a262012-04-12 16:30:46 +0200382} // namespace shill