blob: 929766c9a948e4361c629098aae2d8b27e6381cd [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
Paul Stewartd08f4432011-11-04 07:48:20 -0700237TEST_F(WiFiServiceTest, LoadHidden) {
Gaurav Shahda6218a2011-11-11 12:09:33 -0800238 vector<uint8_t> ssid(5);
Paul Stewartd08f4432011-11-04 07:48:20 -0700239 ssid.push_back(0xff);
240
241 WiFiServiceRefPtr service = new WiFiService(control_interface(),
242 dispatcher(),
243 manager(),
244 wifi(),
245 ssid,
246 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800247 flimflam::kSecurityNone,
248 false);
Paul Stewartd08f4432011-11-04 07:48:20 -0700249 ASSERT_FALSE(service->hidden_ssid_);
250 NiceMock<MockStore> mock_store;
251 const string storage_id = service->GetStorageIdentifier();
252 EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
253 .WillRepeatedly(Return(true));
254 EXPECT_CALL(mock_store, GetBool(_, _, _))
255 .WillRepeatedly(Return(false));
256 EXPECT_CALL(mock_store,
257 GetBool(StrEq(storage_id), WiFiService::kStorageHiddenSSID, _))
258 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
259 EXPECT_TRUE(service->Load(&mock_store));
260 EXPECT_TRUE(service->hidden_ssid_);
261}
262
263TEST_F(WiFiServiceSecurityTest, WPAMapping) {
264 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityRsn,
265 flimflam::kSecurityPsk));
266 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWpa,
267 flimflam::kSecurityPsk));
268 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityPsk,
269 flimflam::kSecurityPsk));
270 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWep,
271 flimflam::kSecurityWep));
272 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityNone,
273 flimflam::kSecurityNone));
274 // TODO(pstew): 802.1x is in a NOTIMPLEMENTED block in wifi_service.cc
275 // EXPECT_TRUE(TestStorageMapping(flimflam::kSecurity8021x,
276 // flimflam::kSecurity8021x));
277}
278
279TEST_F(WiFiServiceSecurityTest, LoadMapping) {
280 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
281 flimflam::kSecurityPsk,
282 true));
283 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
284 flimflam::kSecurityRsn,
285 true));
286 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
287 flimflam::kSecurityWpa,
288 false));
289 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
290 flimflam::kSecurityPsk,
291 true));
292 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
293 flimflam::kSecurityWpa,
294 true));
295 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
296 flimflam::kSecurityRsn,
297 false));
298 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
299 flimflam::kSecurityWep,
300 true));
301 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
302 flimflam::kSecurityPsk,
303 false));
304}
305
Chris Masone34af2182011-08-22 11:59:36 -0700306} // namespace shill