• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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