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
41using std::string;
42using std::vector;
43using testing::_;
44using testing::AnyNumber;
45using testing::NiceMock;
46using testing::Return;
47using testing::SetArgumentPointee;
48using testing::StrictMock;
49using testing::Test;
50
51namespace shill {
52
53namespace {
54
55const char kVPNHostProperty[] = "VPN.Host";
56const char kOTPProperty[] = "VPN.OTP";
57const char kPINProperty[] = "VPN.PIN";
58const char kPSKProperty[] = "VPN.PSK";
59const char kPasswordProperty[] = "VPN.Password";
60const char kPortProperty[] = "VPN.Port";
61
62const char kPIN[] = "5555";
63const char kPassword[] = "random-password";
64const char kPort[] = "1234";
65const char kStorageID[] = "vpn_service_id";
66
67}  // namespace
68
69class VPNDriverUnderTest : public VPNDriver {
70 public:
71  VPNDriverUnderTest(EventDispatcher* dispatcher, Manager* manager);
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
89const 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
101VPNDriverUnderTest::VPNDriverUnderTest(
102    EventDispatcher* dispatcher, Manager* manager)
103    : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)) {}
104
105class VPNDriverTest : public Test {
106 public:
107  VPNDriverTest()
108      : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
109        metrics_(&dispatcher_),
110        manager_(&control_, &dispatcher_, &metrics_),
111        driver_(&dispatcher_, &manager_) {}
112
113  virtual ~VPNDriverTest() {}
114
115 protected:
116  EventDispatcher* dispatcher() { return driver_.dispatcher_; }
117  void set_dispatcher(EventDispatcher* dispatcher) {
118    driver_.dispatcher_ = dispatcher;
119  }
120
121  const base::CancelableClosure& connect_timeout_callback() {
122    return driver_.connect_timeout_callback_;
123  }
124
125  bool IsConnectTimeoutStarted() { return driver_.IsConnectTimeoutStarted(); }
126  int connect_timeout_seconds() { return driver_.connect_timeout_seconds(); }
127
128  void StartConnectTimeout(int timeout_seconds) {
129    driver_.StartConnectTimeout(timeout_seconds);
130  }
131
132  void StopConnectTimeout() { driver_.StopConnectTimeout(); }
133
134  void SetArg(const string& arg, const string& value) {
135    driver_.args()->SetString(arg, value);
136  }
137
138  void SetArgArray(const string& arg, const vector<string>& value) {
139    driver_.args()->SetStrings(arg, value);
140  }
141
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
160bool 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
176bool 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
192TEST_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
232TEST_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
266TEST_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
280TEST_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
290TEST_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
416TEST_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
430TEST_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