blob: 8b366b9fda15babb310a1ccab7c945d064471494 [file] [log] [blame]
Chris Masone34af2182011-08-22 11:59:36 -07001// Copyright (c) 2011 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/wifi_service.h"
6
mukesh agrawald835b202011-10-07 15:26:47 -07007#include <map>
Chris Masone34af2182011-08-22 11:59:36 -07008#include <string>
9#include <vector>
10
11#include <base/string_util.h>
12#include <chromeos/dbus/service_constants.h>
13#include <gmock/gmock.h>
14#include <gtest/gtest.h>
15
Paul Stewart26b327e2011-10-19 11:38:09 -070016#include "shill/event_dispatcher.h"
Chris Masone34af2182011-08-22 11:59:36 -070017#include "shill/manager.h"
18#include "shill/mock_adaptors.h"
19#include "shill/mock_control.h"
20#include "shill/mock_service.h"
21#include "shill/mock_store.h"
mukesh agrawal6e277772011-09-29 15:04:23 -070022#include "shill/mock_wifi.h"
Chris Masone34af2182011-08-22 11:59:36 -070023#include "shill/property_store_unittest.h"
mukesh agrawal6e277772011-09-29 15:04:23 -070024#include "shill/wpa_supplicant.h"
Chris Masone34af2182011-08-22 11:59:36 -070025
mukesh agrawald835b202011-10-07 15:26:47 -070026using std::map;
Chris Masone34af2182011-08-22 11:59:36 -070027using std::string;
28using std::vector;
29
30namespace shill {
Paul Stewartd08f4432011-11-04 07:48:20 -070031using ::testing::_;
32using ::testing::DoAll;
mukesh agrawal6e277772011-09-29 15:04:23 -070033using ::testing::NiceMock;
Paul Stewartd08f4432011-11-04 07:48:20 -070034using ::testing::Return;
35using ::testing::SetArgumentPointee;
36using ::testing::StrEq;
Chris Masone34af2182011-08-22 11:59:36 -070037
38class WiFiServiceTest : public PropertyStoreTest {
39 public:
mukesh agrawal6e277772011-09-29 15:04:23 -070040 WiFiServiceTest() : wifi_(
41 new NiceMock<MockWiFi>(
42 control_interface(),
43 dispatcher(),
44 manager(),
45 "wifi",
46 fake_mac,
47 0)) {}
Chris Masone34af2182011-08-22 11:59:36 -070048 virtual ~WiFiServiceTest() {}
mukesh agrawal6e277772011-09-29 15:04:23 -070049
50 protected:
51 static const char fake_mac[];
52 scoped_refptr<MockWiFi> wifi() { return wifi_; }
53
54 private:
55 scoped_refptr<MockWiFi> wifi_;
Chris Masone34af2182011-08-22 11:59:36 -070056};
57
mukesh agrawal6e277772011-09-29 15:04:23 -070058// static
59const char WiFiServiceTest::fake_mac[] = "AaBBcCDDeeFF";
60
Paul Stewartd08f4432011-11-04 07:48:20 -070061class WiFiServiceSecurityTest : public WiFiServiceTest {
62 public:
63 WiFiServiceRefPtr CreateServiceWithSecurity(const string &security) {
Gaurav Shahda6218a2011-11-11 12:09:33 -080064 vector<uint8_t> ssid(5);
Paul Stewartd08f4432011-11-04 07:48:20 -070065 ssid.push_back(0xff);
66
67 return new WiFiService(control_interface(),
68 dispatcher(),
69 manager(),
70 wifi(),
71 ssid,
72 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -080073 security,
74 false);
Paul Stewartd08f4432011-11-04 07:48:20 -070075 }
76
77 bool TestStorageSecurityIs(WiFiServiceRefPtr wifi_service,
78 const string &security) {
79 string id = wifi_service->GetStorageIdentifier();
80 size_t mac_pos = id.find(StringToLowerASCII(string(fake_mac)));
81 EXPECT_NE(mac_pos, string::npos);
82 size_t mode_pos = id.find(string(flimflam::kModeManaged), mac_pos);
83 EXPECT_NE(mode_pos, string::npos);
84 return id.find(string(security), mode_pos) != string::npos;
85 }
86
87 // Test that a service that is created with security |from_security|
88 // gets by default a storage identifier with |to_security| as its
89 // security component.
90 bool TestStorageMapping(const string &from_security,
91 const string &to_security) {
92 WiFiServiceRefPtr wifi_service = CreateServiceWithSecurity(from_security);
93 return TestStorageSecurityIs(wifi_service, to_security);
94 }
95
96 // Test whether a service of type |service_security| can load from a
97 // storage interface containing an entry for |storage_security|.
98 // Make sure the result meets |expectation|. If |expectation| is
99 // true, also make sure the service storage identifier changes to
100 // match |storage_security|.
101 bool TestLoadMapping(const string &service_security,
102 const string &storage_security,
103 bool expectation) {
104 WiFiServiceRefPtr wifi_service =
105 CreateServiceWithSecurity(service_security);
106 NiceMock<MockStore> mock_store;
107 const string storage_id =
108 wifi_service->GetStorageIdentifierForSecurity(storage_security);
109 EXPECT_CALL(mock_store, ContainsGroup(_))
110 .WillRepeatedly(Return(false));
111 EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
112 .WillRepeatedly(Return(true));
113 bool is_loadable = wifi_service->IsLoadableFrom(&mock_store);
114 EXPECT_EQ(expectation, is_loadable);
115 bool is_loaded = wifi_service->Load(&mock_store);
116 EXPECT_EQ(expectation, is_loaded);
117
118 if (expectation != is_loadable || expectation != is_loaded) {
119 return false;
120 } else if (!expectation) {
121 return true;
122 } else {
123 return TestStorageSecurityIs(wifi_service, storage_security);
124 }
125 }
126};
127
Chris Masone34af2182011-08-22 11:59:36 -0700128TEST_F(WiFiServiceTest, StorageId) {
Gaurav Shahda6218a2011-11-11 12:09:33 -0800129 vector<uint8_t> ssid(5);
Chris Masone34af2182011-08-22 11:59:36 -0700130 ssid.push_back(0xff);
Chris Masone9d779932011-08-25 16:33:41 -0700131
Chris Masone2176a882011-09-14 22:29:15 -0700132 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
133 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700134 manager(),
mukesh agrawal6e277772011-09-29 15:04:23 -0700135 wifi(),
Chris Masone9d779932011-08-25 16:33:41 -0700136 ssid,
137 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800138 flimflam::kSecurityNone,
139 false);
Chris Masone9d779932011-08-25 16:33:41 -0700140 string id = wifi_service->GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700141 for (uint i = 0; i < id.length(); ++i) {
142 EXPECT_TRUE(id[i] == '_' ||
143 isxdigit(id[i]) ||
144 (isalpha(id[i]) && islower(id[i])));
145 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700146 EXPECT_TRUE(wifi_service->TechnologyIs(Technology::kWifi));
Chris Masone34af2182011-08-22 11:59:36 -0700147 size_t mac_pos = id.find(StringToLowerASCII(string(fake_mac)));
148 EXPECT_NE(mac_pos, string::npos);
149 EXPECT_NE(id.find(string(flimflam::kModeManaged), mac_pos), string::npos);
150}
151
Gaurav Shahda6218a2011-11-11 12:09:33 -0800152// Make sure the passphrase is registered as a write only property
153// by reading and comparing all string properties returned on the store.
154TEST_F(WiFiServiceTest, PassphraseWriteOnly) {
155 vector<uint8_t> ssid(5);
156 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
157 dispatcher(),
158 manager(),
159 wifi(),
160 ssid,
161 flimflam::kModeManaged,
162 flimflam::kSecurityWpa,
163 false);
164 ReadablePropertyConstIterator<string> it =
165 (wifi_service->store()).GetStringPropertiesIter();
166 for( ; !it.AtEnd(); it.Advance())
167 EXPECT_NE(it.Key(), flimflam::kPassphraseProperty);
168}
169
mukesh agrawald835b202011-10-07 15:26:47 -0700170TEST_F(WiFiServiceTest, NonUTF8SSID) {
171 vector<uint8_t> ssid;
172
173 ssid.push_back(0xff); // not a valid UTF-8 byte-sequence
174 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
175 dispatcher(),
176 manager(),
177 wifi(),
178 ssid,
179 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800180 flimflam::kSecurityNone,
181 false);
mukesh agrawald835b202011-10-07 15:26:47 -0700182 map<string, ::DBus::Variant> properties;
183 // if service doesn't propertly sanitize SSID, this will generate SIGABRT.
184 DBusAdaptor::GetProperties(wifi_service->store(), &properties, NULL);
185}
186
Gaurav Shahda6218a2011-11-11 12:09:33 -0800187MATCHER(WPASecurityArgs, "") {
188 return ContainsKey(arg, wpa_supplicant::kPropertySecurityProtocol) &&
189 ContainsKey(arg, wpa_supplicant::kPropertyPreSharedKey);
190}
191
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700192TEST_F(WiFiServiceTest, ConnectTaskWPA) {
Gaurav Shahda6218a2011-11-11 12:09:33 -0800193 vector<uint8_t> ssid(5);
mukesh agrawal6e277772011-09-29 15:04:23 -0700194 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
195 dispatcher(),
196 manager(),
197 wifi(),
198 ssid,
199 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800200 flimflam::kSecurityWpa,
201 false);
mukesh agrawal6e277772011-09-29 15:04:23 -0700202 EXPECT_CALL(*wifi(),
203 ConnectTo(wifi_service.get(), WPASecurityArgs()));
204 wifi_service->ConnectTask();
205}
206
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700207TEST_F(WiFiServiceTest, ConnectTaskRSN) {
Gaurav Shahda6218a2011-11-11 12:09:33 -0800208 vector<uint8_t> ssid(5);
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700209 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
210 dispatcher(),
211 manager(),
212 wifi(),
213 ssid,
214 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800215 flimflam::kSecurityRsn,
216 false);
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700217 EXPECT_CALL(*wifi(),
218 ConnectTo(wifi_service.get(), WPASecurityArgs()));
219 wifi_service->ConnectTask();
220}
221
Gaurav Shahf8721ee2011-11-07 09:12:46 -0800222TEST_F(WiFiServiceTest, ConnectTaskPSK) {
Gaurav Shahda6218a2011-11-11 12:09:33 -0800223 vector<uint8_t> ssid(5);
Gaurav Shahf8721ee2011-11-07 09:12:46 -0800224 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
225 dispatcher(),
226 manager(),
227 wifi(),
228 ssid,
229 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800230 flimflam::kSecurityPsk,
231 false);
Gaurav Shahf8721ee2011-11-07 09:12:46 -0800232 EXPECT_CALL(*wifi(),
233 ConnectTo(wifi_service.get(), WPASecurityArgs()));
234 wifi_service->ConnectTask();
235}
236
Thieu Lef4cbda92011-11-10 23:41:24 +0000237MATCHER(WEPSecurityArgsKeyIndex0, "") {
238 return ContainsKey(arg, wpa_supplicant::kPropertyAuthAlg) &&
239 ContainsKey(arg, wpa_supplicant::kPropertyWEPKey + std::string("0")) &&
240 ContainsKey(arg, wpa_supplicant::kPropertyWEPTxKeyIndex) &&
241 (arg.find(wpa_supplicant::kPropertyWEPTxKeyIndex)->second.
242 reader().get_uint32() == 0);
243}
244
245MATCHER(WEPSecurityArgsKeyIndex1, "") {
246 return ContainsKey(arg, wpa_supplicant::kPropertyAuthAlg) &&
247 ContainsKey(arg, wpa_supplicant::kPropertyWEPKey + std::string("1")) &&
248 ContainsKey(arg, wpa_supplicant::kPropertyWEPTxKeyIndex) &&
249 (arg.find(wpa_supplicant::kPropertyWEPTxKeyIndex)->second.
250 reader().get_uint32() == 1);
251}
252
253MATCHER(WEPSecurityArgsKeyIndex2, "") {
254 return ContainsKey(arg, wpa_supplicant::kPropertyAuthAlg) &&
255 ContainsKey(arg, wpa_supplicant::kPropertyWEPKey + std::string("2")) &&
256 ContainsKey(arg, wpa_supplicant::kPropertyWEPTxKeyIndex) &&
257 (arg.find(wpa_supplicant::kPropertyWEPTxKeyIndex)->second.
258 reader().get_uint32() == 2);
259}
260
261MATCHER(WEPSecurityArgsKeyIndex3, "") {
262 return ContainsKey(arg, wpa_supplicant::kPropertyAuthAlg) &&
263 ContainsKey(arg, wpa_supplicant::kPropertyWEPKey + std::string("3")) &&
264 ContainsKey(arg, wpa_supplicant::kPropertyWEPTxKeyIndex) &&
265 (arg.find(wpa_supplicant::kPropertyWEPTxKeyIndex)->second.
266 reader().get_uint32() == 3);
267}
268
269TEST_F(WiFiServiceTest, ConnectTaskWEP) {
270 vector<uint8_t> ssid(5);
271 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
272 dispatcher(),
273 manager(),
274 wifi(),
275 ssid,
276 flimflam::kModeManaged,
277 flimflam::kSecurityWep,
278 false);
279 Error error;
280 wifi_service->SetPassphrase("0:abcdefghijklm", &error);
281 EXPECT_CALL(*wifi(),
282 ConnectTo(wifi_service.get(), WEPSecurityArgsKeyIndex0()));
283 wifi_service->ConnectTask();
284
285 wifi_service->SetPassphrase("abcdefghijklm", &error);
286 EXPECT_CALL(*wifi(),
287 ConnectTo(wifi_service.get(), WEPSecurityArgsKeyIndex0()));
288 wifi_service->ConnectTask();
289
290 wifi_service->SetPassphrase("1:abcdefghijklm", &error);
291 EXPECT_CALL(*wifi(),
292 ConnectTo(wifi_service.get(), WEPSecurityArgsKeyIndex1()));
293 wifi_service->ConnectTask();
294
295 wifi_service->SetPassphrase("2:abcdefghijklm", &error);
296 EXPECT_CALL(*wifi(),
297 ConnectTo(wifi_service.get(), WEPSecurityArgsKeyIndex2()));
298 wifi_service->ConnectTask();
299
300 wifi_service->SetPassphrase("3:abcdefghijklm", &error);
301 EXPECT_CALL(*wifi(),
302 ConnectTo(wifi_service.get(), WEPSecurityArgsKeyIndex3()));
303 wifi_service->ConnectTask();
304}
305
Paul Stewartd08f4432011-11-04 07:48:20 -0700306TEST_F(WiFiServiceTest, LoadHidden) {
Gaurav Shahda6218a2011-11-11 12:09:33 -0800307 vector<uint8_t> ssid(5);
Paul Stewartd08f4432011-11-04 07:48:20 -0700308 ssid.push_back(0xff);
309
310 WiFiServiceRefPtr service = new WiFiService(control_interface(),
311 dispatcher(),
312 manager(),
313 wifi(),
314 ssid,
315 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800316 flimflam::kSecurityNone,
317 false);
Paul Stewartd08f4432011-11-04 07:48:20 -0700318 ASSERT_FALSE(service->hidden_ssid_);
319 NiceMock<MockStore> mock_store;
320 const string storage_id = service->GetStorageIdentifier();
321 EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
322 .WillRepeatedly(Return(true));
323 EXPECT_CALL(mock_store, GetBool(_, _, _))
324 .WillRepeatedly(Return(false));
325 EXPECT_CALL(mock_store,
326 GetBool(StrEq(storage_id), WiFiService::kStorageHiddenSSID, _))
327 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
328 EXPECT_TRUE(service->Load(&mock_store));
329 EXPECT_TRUE(service->hidden_ssid_);
330}
331
332TEST_F(WiFiServiceSecurityTest, WPAMapping) {
333 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityRsn,
334 flimflam::kSecurityPsk));
335 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWpa,
336 flimflam::kSecurityPsk));
337 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityPsk,
338 flimflam::kSecurityPsk));
339 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWep,
340 flimflam::kSecurityWep));
341 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityNone,
342 flimflam::kSecurityNone));
343 // TODO(pstew): 802.1x is in a NOTIMPLEMENTED block in wifi_service.cc
344 // EXPECT_TRUE(TestStorageMapping(flimflam::kSecurity8021x,
345 // flimflam::kSecurity8021x));
346}
347
348TEST_F(WiFiServiceSecurityTest, LoadMapping) {
349 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
350 flimflam::kSecurityPsk,
351 true));
352 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
353 flimflam::kSecurityRsn,
354 true));
355 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
356 flimflam::kSecurityWpa,
357 false));
358 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
359 flimflam::kSecurityPsk,
360 true));
361 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
362 flimflam::kSecurityWpa,
363 true));
364 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
365 flimflam::kSecurityRsn,
366 false));
367 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
368 flimflam::kSecurityWep,
369 true));
370 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
371 flimflam::kSecurityPsk,
372 false));
373}
374
Chris Masone34af2182011-08-22 11:59:36 -0700375} // namespace shill