blob: 5c8e32e0bedff32749c3b34124b6b489d110ba64 [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) {
64 vector<uint8_t> ssid(5, 0);
65 ssid.push_back(0xff);
66
67 return new WiFiService(control_interface(),
68 dispatcher(),
69 manager(),
70 wifi(),
71 ssid,
72 flimflam::kModeManaged,
73 security);
74 }
75
76 bool TestStorageSecurityIs(WiFiServiceRefPtr wifi_service,
77 const string &security) {
78 string id = wifi_service->GetStorageIdentifier();
79 size_t mac_pos = id.find(StringToLowerASCII(string(fake_mac)));
80 EXPECT_NE(mac_pos, string::npos);
81 size_t mode_pos = id.find(string(flimflam::kModeManaged), mac_pos);
82 EXPECT_NE(mode_pos, string::npos);
83 return id.find(string(security), mode_pos) != string::npos;
84 }
85
86 // Test that a service that is created with security |from_security|
87 // gets by default a storage identifier with |to_security| as its
88 // security component.
89 bool TestStorageMapping(const string &from_security,
90 const string &to_security) {
91 WiFiServiceRefPtr wifi_service = CreateServiceWithSecurity(from_security);
92 return TestStorageSecurityIs(wifi_service, to_security);
93 }
94
95 // Test whether a service of type |service_security| can load from a
96 // storage interface containing an entry for |storage_security|.
97 // Make sure the result meets |expectation|. If |expectation| is
98 // true, also make sure the service storage identifier changes to
99 // match |storage_security|.
100 bool TestLoadMapping(const string &service_security,
101 const string &storage_security,
102 bool expectation) {
103 WiFiServiceRefPtr wifi_service =
104 CreateServiceWithSecurity(service_security);
105 NiceMock<MockStore> mock_store;
106 const string storage_id =
107 wifi_service->GetStorageIdentifierForSecurity(storage_security);
108 EXPECT_CALL(mock_store, ContainsGroup(_))
109 .WillRepeatedly(Return(false));
110 EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
111 .WillRepeatedly(Return(true));
112 bool is_loadable = wifi_service->IsLoadableFrom(&mock_store);
113 EXPECT_EQ(expectation, is_loadable);
114 bool is_loaded = wifi_service->Load(&mock_store);
115 EXPECT_EQ(expectation, is_loaded);
116
117 if (expectation != is_loadable || expectation != is_loaded) {
118 return false;
119 } else if (!expectation) {
120 return true;
121 } else {
122 return TestStorageSecurityIs(wifi_service, storage_security);
123 }
124 }
125};
126
mukesh agrawal6e277772011-09-29 15:04:23 -0700127MATCHER(WPASecurityArgs, "") {
128 return ContainsKey(arg, wpa_supplicant::kPropertySecurityProtocol) &&
129 ContainsKey(arg, wpa_supplicant::kPropertyPreSharedKey);
130}
131
Chris Masone34af2182011-08-22 11:59:36 -0700132TEST_F(WiFiServiceTest, StorageId) {
133 vector<uint8_t> ssid(5, 0);
134 ssid.push_back(0xff);
Chris Masone9d779932011-08-25 16:33:41 -0700135
Chris Masone2176a882011-09-14 22:29:15 -0700136 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
137 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700138 manager(),
mukesh agrawal6e277772011-09-29 15:04:23 -0700139 wifi(),
Chris Masone9d779932011-08-25 16:33:41 -0700140 ssid,
141 flimflam::kModeManaged,
Paul Stewartd08f4432011-11-04 07:48:20 -0700142 flimflam::kSecurityNone);
Chris Masone9d779932011-08-25 16:33:41 -0700143 string id = wifi_service->GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700144 for (uint i = 0; i < id.length(); ++i) {
145 EXPECT_TRUE(id[i] == '_' ||
146 isxdigit(id[i]) ||
147 (isalpha(id[i]) && islower(id[i])));
148 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700149 EXPECT_TRUE(wifi_service->TechnologyIs(Technology::kWifi));
Chris Masone34af2182011-08-22 11:59:36 -0700150 size_t mac_pos = id.find(StringToLowerASCII(string(fake_mac)));
151 EXPECT_NE(mac_pos, string::npos);
152 EXPECT_NE(id.find(string(flimflam::kModeManaged), mac_pos), string::npos);
153}
154
mukesh agrawald835b202011-10-07 15:26:47 -0700155TEST_F(WiFiServiceTest, NonUTF8SSID) {
156 vector<uint8_t> ssid;
157
158 ssid.push_back(0xff); // not a valid UTF-8 byte-sequence
159 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
160 dispatcher(),
161 manager(),
162 wifi(),
163 ssid,
164 flimflam::kModeManaged,
Paul Stewartd08f4432011-11-04 07:48:20 -0700165 flimflam::kSecurityNone);
mukesh agrawald835b202011-10-07 15:26:47 -0700166 map<string, ::DBus::Variant> properties;
167 // if service doesn't propertly sanitize SSID, this will generate SIGABRT.
168 DBusAdaptor::GetProperties(wifi_service->store(), &properties, NULL);
169}
170
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700171TEST_F(WiFiServiceTest, ConnectTaskWPA) {
mukesh agrawal6e277772011-09-29 15:04:23 -0700172 vector<uint8_t> ssid(5, 0);
173 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
174 dispatcher(),
175 manager(),
176 wifi(),
177 ssid,
178 flimflam::kModeManaged,
179 flimflam::kSecurityWpa);
180 EXPECT_CALL(*wifi(),
181 ConnectTo(wifi_service.get(), WPASecurityArgs()));
182 wifi_service->ConnectTask();
183}
184
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700185TEST_F(WiFiServiceTest, ConnectTaskRSN) {
186 vector<uint8_t> ssid(5, 0);
187 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
188 dispatcher(),
189 manager(),
190 wifi(),
191 ssid,
192 flimflam::kModeManaged,
193 flimflam::kSecurityRsn);
194 EXPECT_CALL(*wifi(),
195 ConnectTo(wifi_service.get(), WPASecurityArgs()));
196 wifi_service->ConnectTask();
197}
198
Gaurav Shahf8721ee2011-11-07 09:12:46 -0800199TEST_F(WiFiServiceTest, ConnectTaskPSK) {
200 vector<uint8_t> ssid(5, 0);
201 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
202 dispatcher(),
203 manager(),
204 wifi(),
205 ssid,
206 flimflam::kModeManaged,
207 flimflam::kSecurityPsk);
208 EXPECT_CALL(*wifi(),
209 ConnectTo(wifi_service.get(), WPASecurityArgs()));
210 wifi_service->ConnectTask();
211}
212
Paul Stewartd08f4432011-11-04 07:48:20 -0700213TEST_F(WiFiServiceTest, LoadHidden) {
214 vector<uint8_t> ssid(5, 0);
215 ssid.push_back(0xff);
216
217 WiFiServiceRefPtr service = new WiFiService(control_interface(),
218 dispatcher(),
219 manager(),
220 wifi(),
221 ssid,
222 flimflam::kModeManaged,
223 flimflam::kSecurityNone);
224 ASSERT_FALSE(service->hidden_ssid_);
225 NiceMock<MockStore> mock_store;
226 const string storage_id = service->GetStorageIdentifier();
227 EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
228 .WillRepeatedly(Return(true));
229 EXPECT_CALL(mock_store, GetBool(_, _, _))
230 .WillRepeatedly(Return(false));
231 EXPECT_CALL(mock_store,
232 GetBool(StrEq(storage_id), WiFiService::kStorageHiddenSSID, _))
233 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
234 EXPECT_TRUE(service->Load(&mock_store));
235 EXPECT_TRUE(service->hidden_ssid_);
236}
237
238TEST_F(WiFiServiceSecurityTest, WPAMapping) {
239 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityRsn,
240 flimflam::kSecurityPsk));
241 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWpa,
242 flimflam::kSecurityPsk));
243 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityPsk,
244 flimflam::kSecurityPsk));
245 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWep,
246 flimflam::kSecurityWep));
247 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityNone,
248 flimflam::kSecurityNone));
249 // TODO(pstew): 802.1x is in a NOTIMPLEMENTED block in wifi_service.cc
250 // EXPECT_TRUE(TestStorageMapping(flimflam::kSecurity8021x,
251 // flimflam::kSecurity8021x));
252}
253
254TEST_F(WiFiServiceSecurityTest, LoadMapping) {
255 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
256 flimflam::kSecurityPsk,
257 true));
258 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
259 flimflam::kSecurityRsn,
260 true));
261 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
262 flimflam::kSecurityWpa,
263 false));
264 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
265 flimflam::kSecurityPsk,
266 true));
267 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
268 flimflam::kSecurityWpa,
269 true));
270 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
271 flimflam::kSecurityRsn,
272 false));
273 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
274 flimflam::kSecurityWep,
275 true));
276 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
277 flimflam::kSecurityPsk,
278 false));
279}
280
Chris Masone34af2182011-08-22 11:59:36 -0700281} // namespace shill