1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/vpn/vpn_driver.h"
18
19 #include <vector>
20
21 #include <base/stl_util.h>
22 #include <base/strings/string_number_conversions.h>
23 #if defined(__ANDROID__)
24 #include <dbus/service_constants.h>
25 #else
26 #include <chromeos/dbus/service_constants.h>
27 #endif // __ANDROID__
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30
31 #include "shill/mock_connection.h"
32 #include "shill/mock_device_info.h"
33 #include "shill/mock_manager.h"
34 #include "shill/mock_metrics.h"
35 #include "shill/mock_service.h"
36 #include "shill/mock_store.h"
37 #include "shill/nice_mock_control.h"
38 #include "shill/property_store.h"
39 #include "shill/test_event_dispatcher.h"
40
41 using std::string;
42 using std::vector;
43 using testing::_;
44 using testing::AnyNumber;
45 using testing::NiceMock;
46 using testing::Return;
47 using testing::SetArgumentPointee;
48 using testing::StrictMock;
49 using testing::Test;
50
51 namespace shill {
52
53 namespace {
54
55 const char kVPNHostProperty[] = "VPN.Host";
56 const char kOTPProperty[] = "VPN.OTP";
57 const char kPINProperty[] = "VPN.PIN";
58 const char kPSKProperty[] = "VPN.PSK";
59 const char kPasswordProperty[] = "VPN.Password";
60 const char kPortProperty[] = "VPN.Port";
61
62 const char kPIN[] = "5555";
63 const char kPassword[] = "random-password";
64 const char kPort[] = "1234";
65 const char kStorageID[] = "vpn_service_id";
66
67 } // namespace
68
69 class VPNDriverUnderTest : public VPNDriver {
70 public:
71 VPNDriverUnderTest(EventDispatcher* dispatcher, Manager* manager);
~VPNDriverUnderTest()72 virtual ~VPNDriverUnderTest() {}
73
74 // Inherited from VPNDriver.
75 MOCK_METHOD2(ClaimInterface, bool(const string& link_name,
76 int interface_index));
77 MOCK_METHOD2(Connect, void(const VPNServiceRefPtr& service, Error* error));
78 MOCK_METHOD0(Disconnect, void());
79 MOCK_METHOD0(OnConnectionDisconnected, void());
80 MOCK_CONST_METHOD0(GetProviderType, string());
81
82 private:
83 static const Property kProperties[];
84
85 DISALLOW_COPY_AND_ASSIGN(VPNDriverUnderTest);
86 };
87
88 // static
89 const VPNDriverUnderTest::Property VPNDriverUnderTest::kProperties[] = {
90 { kEapCaCertPemProperty, Property::kArray },
91 { kVPNHostProperty, 0 },
92 { kL2tpIpsecCaCertPemProperty, Property::kArray },
93 { kOTPProperty, Property::kEphemeral },
94 { kPINProperty, Property::kWriteOnly },
95 { kPSKProperty, Property::kCredential },
96 { kPasswordProperty, Property::kCredential },
97 { kPortProperty, 0 },
98 { kProviderTypeProperty, 0 },
99 };
100
VPNDriverUnderTest(EventDispatcher * dispatcher,Manager * manager)101 VPNDriverUnderTest::VPNDriverUnderTest(
102 EventDispatcher* dispatcher, Manager* manager)
103 : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)) {}
104
105 class VPNDriverTest : public Test {
106 public:
VPNDriverTest()107 VPNDriverTest()
108 : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
109 metrics_(&dispatcher_),
110 manager_(&control_, &dispatcher_, &metrics_),
111 driver_(&dispatcher_, &manager_) {}
112
~VPNDriverTest()113 virtual ~VPNDriverTest() {}
114
115 protected:
dispatcher()116 EventDispatcher* dispatcher() { return driver_.dispatcher_; }
set_dispatcher(EventDispatcher * dispatcher)117 void set_dispatcher(EventDispatcher* dispatcher) {
118 driver_.dispatcher_ = dispatcher;
119 }
120
connect_timeout_callback()121 const base::CancelableClosure& connect_timeout_callback() {
122 return driver_.connect_timeout_callback_;
123 }
124
IsConnectTimeoutStarted()125 bool IsConnectTimeoutStarted() { return driver_.IsConnectTimeoutStarted(); }
connect_timeout_seconds()126 int connect_timeout_seconds() { return driver_.connect_timeout_seconds(); }
127
StartConnectTimeout(int timeout_seconds)128 void StartConnectTimeout(int timeout_seconds) {
129 driver_.StartConnectTimeout(timeout_seconds);
130 }
131
StopConnectTimeout()132 void StopConnectTimeout() { driver_.StopConnectTimeout(); }
133
SetArg(const string & arg,const string & value)134 void SetArg(const string& arg, const string& value) {
135 driver_.args()->SetString(arg, value);
136 }
137
SetArgArray(const string & arg,const vector<string> & value)138 void SetArgArray(const string& arg, const vector<string>& value) {
139 driver_.args()->SetStrings(arg, value);
140 }
141
GetArgs()142 KeyValueStore* GetArgs() { return driver_.args(); }
143
144 bool GetProviderPropertyString(const PropertyStore& store,
145 const string& key,
146 string* value);
147
148 bool GetProviderPropertyStrings(const PropertyStore& store,
149 const string& key,
150 vector<string>* value);
151
152 NiceMockControl control_;
153 NiceMock<MockDeviceInfo> device_info_;
154 EventDispatcherForTest dispatcher_;
155 MockMetrics metrics_;
156 MockManager manager_;
157 VPNDriverUnderTest driver_;
158 };
159
GetProviderPropertyString(const PropertyStore & store,const string & key,string * value)160 bool VPNDriverTest::GetProviderPropertyString(const PropertyStore& store,
161 const string& key,
162 string* value) {
163 KeyValueStore provider_properties;
164 Error error;
165 EXPECT_TRUE(store.GetKeyValueStoreProperty(
166 kProviderProperty, &provider_properties, &error));
167 if (!provider_properties.ContainsString(key)) {
168 return false;
169 }
170 if (value != nullptr) {
171 *value = provider_properties.GetString(key);
172 }
173 return true;
174 }
175
GetProviderPropertyStrings(const PropertyStore & store,const string & key,vector<string> * value)176 bool VPNDriverTest::GetProviderPropertyStrings(const PropertyStore& store,
177 const string& key,
178 vector<string>* value) {
179 KeyValueStore provider_properties;
180 Error error;
181 EXPECT_TRUE(store.GetKeyValueStoreProperty(
182 kProviderProperty, &provider_properties, &error));
183 if (!provider_properties.ContainsStrings(key)) {
184 return false;
185 }
186 if (value != nullptr) {
187 *value = provider_properties.GetStrings(key);
188 }
189 return true;
190 }
191
TEST_F(VPNDriverTest,Load)192 TEST_F(VPNDriverTest, Load) {
193 MockStore storage;
194 GetArgs()->SetString(kVPNHostProperty, "1.2.3.4");
195 GetArgs()->SetString(kPSKProperty, "1234");
196 GetArgs()->SetStrings(kL2tpIpsecCaCertPemProperty,
197 vector<string>{ "cleared-cert0", "cleared-cert1" });
198 EXPECT_CALL(storage, GetString(kStorageID, _, _))
199 .WillRepeatedly(Return(false));
200 EXPECT_CALL(storage, GetStringList(kStorageID, _, _))
201 .WillRepeatedly(Return(false));
202 EXPECT_CALL(storage, GetString(_, kEapCaCertPemProperty, _)).Times(0);
203 EXPECT_CALL(storage, GetString(_, kOTPProperty, _)).Times(0);
204 EXPECT_CALL(storage, GetCryptedString(_, kOTPProperty, _)).Times(0);
205 EXPECT_CALL(storage, GetStringList(_, kOTPProperty, _)).Times(0);
206 vector<string> kCaCerts{ "cert0", "cert1" };
207 EXPECT_CALL(storage, GetStringList(kStorageID, kEapCaCertPemProperty, _))
208 .WillOnce(DoAll(SetArgumentPointee<2>(kCaCerts), Return(true)));
209 EXPECT_CALL(storage, GetString(kStorageID, kPortProperty, _))
210 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPort)), Return(true)));
211 EXPECT_CALL(storage, GetString(kStorageID, kPINProperty, _))
212 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPIN)), Return(true)));
213 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPSKProperty, _))
214 .WillOnce(Return(false));
215 EXPECT_CALL(storage, GetCryptedString(kStorageID, kPasswordProperty, _))
216 .WillOnce(DoAll(SetArgumentPointee<2>(string(kPassword)), Return(true)));
217 EXPECT_TRUE(driver_.Load(&storage, kStorageID));
218 EXPECT_TRUE(GetArgs()->ContainsStrings(kEapCaCertPemProperty));
219 if (GetArgs()->ContainsStrings(kEapCaCertPemProperty)) {
220 EXPECT_EQ(kCaCerts, GetArgs()->GetStrings(kEapCaCertPemProperty));
221 }
222 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
223 EXPECT_EQ(kPIN, GetArgs()->LookupString(kPINProperty, ""));
224 EXPECT_EQ(kPassword, GetArgs()->LookupString(kPasswordProperty, ""));
225
226 // Properties missing from the persistent store should be deleted.
227 EXPECT_FALSE(GetArgs()->ContainsString(kVPNHostProperty));
228 EXPECT_FALSE(GetArgs()->ContainsStrings(kL2tpIpsecCaCertPemProperty));
229 EXPECT_FALSE(GetArgs()->ContainsString(kPSKProperty));
230 }
231
TEST_F(VPNDriverTest,Save)232 TEST_F(VPNDriverTest, Save) {
233 SetArg(kProviderTypeProperty, "");
234 SetArg(kPINProperty, kPIN);
235 SetArg(kPortProperty, kPort);
236 SetArg(kPasswordProperty, kPassword);
237 SetArg(kOTPProperty, "987654");
238 const vector<string> kCaCerts{ "cert0", "cert1" };
239 SetArgArray(kEapCaCertPemProperty, kCaCerts);
240 MockStore storage;
241 EXPECT_CALL(storage,
242 SetStringList(kStorageID, kEapCaCertPemProperty, kCaCerts))
243 .WillOnce(Return(true));
244 EXPECT_CALL(storage,
245 SetString(kStorageID, kProviderTypeProperty, ""))
246 .WillOnce(Return(true));
247 EXPECT_CALL(storage, SetString(kStorageID, kPortProperty, kPort))
248 .WillOnce(Return(true));
249 EXPECT_CALL(storage, SetString(kStorageID, kPINProperty, kPIN))
250 .WillOnce(Return(true));
251 EXPECT_CALL(storage,
252 SetCryptedString(kStorageID, kPasswordProperty, kPassword))
253 .WillOnce(Return(true));
254 EXPECT_CALL(storage, SetCryptedString(_, kOTPProperty, _)).Times(0);
255 EXPECT_CALL(storage, SetString(_, kOTPProperty, _)).Times(0);
256 EXPECT_CALL(storage, SetString(_, kEapCaCertPemProperty, _)).Times(0);
257 EXPECT_CALL(storage, DeleteKey(kStorageID, kEapCaCertPemProperty)).Times(0);
258 EXPECT_CALL(storage, DeleteKey(kStorageID, kProviderTypeProperty))
259 .Times(0);
260 EXPECT_CALL(storage, DeleteKey(kStorageID, kL2tpIpsecCaCertPemProperty));
261 EXPECT_CALL(storage, DeleteKey(kStorageID, kPSKProperty));
262 EXPECT_CALL(storage, DeleteKey(kStorageID, kVPNHostProperty));
263 EXPECT_TRUE(driver_.Save(&storage, kStorageID, true));
264 }
265
TEST_F(VPNDriverTest,SaveNoCredentials)266 TEST_F(VPNDriverTest, SaveNoCredentials) {
267 SetArg(kPasswordProperty, kPassword);
268 SetArg(kPSKProperty, "");
269 MockStore storage;
270 EXPECT_CALL(storage, SetString(_, kPasswordProperty, _)).Times(0);
271 EXPECT_CALL(storage, SetCryptedString(_, kPasswordProperty, _)).Times(0);
272 EXPECT_CALL(storage, DeleteKey(kStorageID, _)).Times(AnyNumber());
273 EXPECT_CALL(storage, DeleteKey(kStorageID, kPasswordProperty));
274 EXPECT_CALL(storage, DeleteKey(kStorageID, kPSKProperty));
275 EXPECT_CALL(storage, DeleteKey(kStorageID, kEapCaCertPemProperty));
276 EXPECT_CALL(storage, DeleteKey(kStorageID, kL2tpIpsecCaCertPemProperty));
277 EXPECT_TRUE(driver_.Save(&storage, kStorageID, false));
278 }
279
TEST_F(VPNDriverTest,UnloadCredentials)280 TEST_F(VPNDriverTest, UnloadCredentials) {
281 SetArg(kOTPProperty, "654321");
282 SetArg(kPasswordProperty, kPassword);
283 SetArg(kPortProperty, kPort);
284 driver_.UnloadCredentials();
285 EXPECT_FALSE(GetArgs()->ContainsString(kOTPProperty));
286 EXPECT_FALSE(GetArgs()->ContainsString(kPasswordProperty));
287 EXPECT_EQ(kPort, GetArgs()->LookupString(kPortProperty, ""));
288 }
289
TEST_F(VPNDriverTest,InitPropertyStore)290 TEST_F(VPNDriverTest, InitPropertyStore) {
291 // Figure out if the store is actually hooked up to the driver argument
292 // KeyValueStore.
293 PropertyStore store;
294 driver_.InitPropertyStore(&store);
295
296 // An un-set property should not be readable.
297 {
298 Error error;
299 EXPECT_FALSE(store.GetStringProperty(kPortProperty, nullptr, &error));
300 EXPECT_EQ(Error::kInvalidArguments, error.type());
301 }
302 {
303 Error error;
304 EXPECT_FALSE(
305 store.GetStringsProperty(kEapCaCertPemProperty, nullptr, &error));
306 EXPECT_EQ(Error::kInvalidArguments, error.type());
307 }
308 EXPECT_FALSE(GetProviderPropertyString(store, kPortProperty, nullptr));
309 EXPECT_FALSE(
310 GetProviderPropertyStrings(store, kEapCaCertPemProperty, nullptr));
311
312 const string kProviderType = "boo";
313 SetArg(kPortProperty, kPort);
314 SetArg(kPasswordProperty, kPassword);
315 SetArg(kProviderTypeProperty, kProviderType);
316 SetArg(kVPNHostProperty, "");
317 const vector<string> kCaCerts{ "cert1" };
318 SetArgArray(kEapCaCertPemProperty, kCaCerts);
319 SetArgArray(kL2tpIpsecCaCertPemProperty, vector<string>());
320
321 // We should not be able to read a property out of the driver args using the
322 // key to the args directly.
323 {
324 Error error;
325 EXPECT_FALSE(store.GetStringProperty(kPortProperty, nullptr, &error));
326 EXPECT_EQ(Error::kInvalidArguments, error.type());
327 }
328 {
329 Error error;
330 EXPECT_FALSE(
331 store.GetStringsProperty(kEapCaCertPemProperty, nullptr, &error));
332 EXPECT_EQ(Error::kInvalidArguments, error.type());
333 }
334
335 // We should instead be able to find it within the "Provider" stringmap.
336 {
337 string value;
338 EXPECT_TRUE(GetProviderPropertyString(store, kPortProperty, &value));
339 EXPECT_EQ(kPort, value);
340 }
341 {
342 vector<string> value;
343 EXPECT_TRUE(GetProviderPropertyStrings(store, kEapCaCertPemProperty,
344 &value));
345 EXPECT_EQ(kCaCerts, value);
346 }
347
348 // We should be able to read empty properties from the "Provider" stringmap.
349 {
350 string value;
351 EXPECT_TRUE(GetProviderPropertyString(store, kVPNHostProperty, &value));
352 EXPECT_TRUE(value.empty());
353 }
354 {
355 vector<string> value;
356 EXPECT_TRUE(GetProviderPropertyStrings(store, kL2tpIpsecCaCertPemProperty,
357 &value));
358 EXPECT_TRUE(value.empty());
359 }
360
361 // Properties that start with the prefix "Provider." should be mapped to the
362 // name in the Properties dict with the prefix removed.
363 {
364 string value;
365 EXPECT_TRUE(GetProviderPropertyString(store, kTypeProperty,
366 &value));
367 EXPECT_EQ(kProviderType, value);
368 }
369
370 // If we clear a property, we should no longer be able to find it.
371 {
372 Error error;
373 EXPECT_TRUE(store.ClearProperty(kPortProperty, &error));
374 EXPECT_TRUE(error.IsSuccess());
375 EXPECT_FALSE(GetProviderPropertyString(store, kPortProperty, nullptr));
376 }
377 {
378 Error error;
379 EXPECT_TRUE(store.ClearProperty(kEapCaCertPemProperty, &error));
380 EXPECT_TRUE(error.IsSuccess());
381 EXPECT_FALSE(GetProviderPropertyStrings(store, kEapCaCertPemProperty,
382 nullptr));
383 }
384
385 // A second attempt to clear this property should return an error.
386 {
387 Error error;
388 EXPECT_FALSE(store.ClearProperty(kPortProperty, &error));
389 EXPECT_EQ(Error::kNotFound, error.type());
390 }
391 {
392 Error error;
393 EXPECT_FALSE(store.ClearProperty(kEapCaCertPemProperty, &error));
394 EXPECT_EQ(Error::kNotFound, error.type());
395 }
396
397 // Test write only properties.
398 EXPECT_FALSE(GetProviderPropertyString(store, kPINProperty, nullptr));
399
400 // Write properties to the driver args using the PropertyStore interface.
401 {
402 const string kValue = "some-value";
403 Error error;
404 EXPECT_TRUE(store.SetStringProperty(kPINProperty, kValue, &error));
405 EXPECT_EQ(kValue, GetArgs()->GetString(kPINProperty));
406 }
407 {
408 const vector<string> kValue{ "some-value" };
409 Error error;
410 EXPECT_TRUE(store.SetStringsProperty(kEapCaCertPemProperty, kValue,
411 &error));
412 EXPECT_EQ(kValue, GetArgs()->GetStrings(kEapCaCertPemProperty));
413 }
414 }
415
TEST_F(VPNDriverTest,ConnectTimeout)416 TEST_F(VPNDriverTest, ConnectTimeout) {
417 EXPECT_EQ(&dispatcher_, dispatcher());
418 EXPECT_TRUE(connect_timeout_callback().IsCancelled());
419 EXPECT_FALSE(IsConnectTimeoutStarted());
420 StartConnectTimeout(0);
421 EXPECT_FALSE(connect_timeout_callback().IsCancelled());
422 EXPECT_TRUE(IsConnectTimeoutStarted());
423 set_dispatcher(nullptr);
424 StartConnectTimeout(0); // Expect no crash.
425 dispatcher_.DispatchPendingEvents();
426 EXPECT_TRUE(connect_timeout_callback().IsCancelled());
427 EXPECT_FALSE(IsConnectTimeoutStarted());
428 }
429
TEST_F(VPNDriverTest,StartStopConnectTimeout)430 TEST_F(VPNDriverTest, StartStopConnectTimeout) {
431 EXPECT_FALSE(IsConnectTimeoutStarted());
432 EXPECT_EQ(0, connect_timeout_seconds());
433 const int kTimeout = 123;
434 StartConnectTimeout(kTimeout);
435 EXPECT_TRUE(IsConnectTimeoutStarted());
436 EXPECT_EQ(kTimeout, connect_timeout_seconds());
437 StartConnectTimeout(kTimeout - 20);
438 EXPECT_EQ(kTimeout, connect_timeout_seconds());
439 StopConnectTimeout();
440 EXPECT_FALSE(IsConnectTimeoutStarted());
441 EXPECT_EQ(0, connect_timeout_seconds());
442 }
443
444 } // namespace shill
445