blob: 661e3e3e2c76652697efaef7cc21a17b405d4070 [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,
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
mukesh agrawal6e277772011-09-29 15:04:23 -0700128MATCHER(WPASecurityArgs, "") {
129 return ContainsKey(arg, wpa_supplicant::kPropertySecurityProtocol) &&
130 ContainsKey(arg, wpa_supplicant::kPropertyPreSharedKey);
131}
132
Chris Masone34af2182011-08-22 11:59:36 -0700133TEST_F(WiFiServiceTest, StorageId) {
134 vector<uint8_t> ssid(5, 0);
135 ssid.push_back(0xff);
Chris Masone9d779932011-08-25 16:33:41 -0700136
Chris Masone2176a882011-09-14 22:29:15 -0700137 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
138 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700139 manager(),
mukesh agrawal6e277772011-09-29 15:04:23 -0700140 wifi(),
Chris Masone9d779932011-08-25 16:33:41 -0700141 ssid,
142 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800143 flimflam::kSecurityNone,
144 false);
Chris Masone9d779932011-08-25 16:33:41 -0700145 string id = wifi_service->GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700146 for (uint i = 0; i < id.length(); ++i) {
147 EXPECT_TRUE(id[i] == '_' ||
148 isxdigit(id[i]) ||
149 (isalpha(id[i]) && islower(id[i])));
150 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700151 EXPECT_TRUE(wifi_service->TechnologyIs(Technology::kWifi));
Chris Masone34af2182011-08-22 11:59:36 -0700152 size_t mac_pos = id.find(StringToLowerASCII(string(fake_mac)));
153 EXPECT_NE(mac_pos, string::npos);
154 EXPECT_NE(id.find(string(flimflam::kModeManaged), mac_pos), string::npos);
155}
156
mukesh agrawald835b202011-10-07 15:26:47 -0700157TEST_F(WiFiServiceTest, NonUTF8SSID) {
158 vector<uint8_t> ssid;
159
160 ssid.push_back(0xff); // not a valid UTF-8 byte-sequence
161 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
162 dispatcher(),
163 manager(),
164 wifi(),
165 ssid,
166 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800167 flimflam::kSecurityNone,
168 false);
mukesh agrawald835b202011-10-07 15:26:47 -0700169 map<string, ::DBus::Variant> properties;
170 // if service doesn't propertly sanitize SSID, this will generate SIGABRT.
171 DBusAdaptor::GetProperties(wifi_service->store(), &properties, NULL);
172}
173
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700174TEST_F(WiFiServiceTest, ConnectTaskWPA) {
mukesh agrawal6e277772011-09-29 15:04:23 -0700175 vector<uint8_t> ssid(5, 0);
176 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
177 dispatcher(),
178 manager(),
179 wifi(),
180 ssid,
181 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800182 flimflam::kSecurityWpa,
183 false);
mukesh agrawal6e277772011-09-29 15:04:23 -0700184 EXPECT_CALL(*wifi(),
185 ConnectTo(wifi_service.get(), WPASecurityArgs()));
186 wifi_service->ConnectTask();
187}
188
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700189TEST_F(WiFiServiceTest, ConnectTaskRSN) {
190 vector<uint8_t> ssid(5, 0);
191 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
192 dispatcher(),
193 manager(),
194 wifi(),
195 ssid,
196 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800197 flimflam::kSecurityRsn,
198 false);
mukesh agrawalf2fd7452011-10-03 16:38:47 -0700199 EXPECT_CALL(*wifi(),
200 ConnectTo(wifi_service.get(), WPASecurityArgs()));
201 wifi_service->ConnectTask();
202}
203
Gaurav Shahf8721ee2011-11-07 09:12:46 -0800204TEST_F(WiFiServiceTest, ConnectTaskPSK) {
205 vector<uint8_t> ssid(5, 0);
206 WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
207 dispatcher(),
208 manager(),
209 wifi(),
210 ssid,
211 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800212 flimflam::kSecurityPsk,
213 false);
Gaurav Shahf8721ee2011-11-07 09:12:46 -0800214 EXPECT_CALL(*wifi(),
215 ConnectTo(wifi_service.get(), WPASecurityArgs()));
216 wifi_service->ConnectTask();
217}
218
Paul Stewartd08f4432011-11-04 07:48:20 -0700219TEST_F(WiFiServiceTest, LoadHidden) {
220 vector<uint8_t> ssid(5, 0);
221 ssid.push_back(0xff);
222
223 WiFiServiceRefPtr service = new WiFiService(control_interface(),
224 dispatcher(),
225 manager(),
226 wifi(),
227 ssid,
228 flimflam::kModeManaged,
Paul Stewartced6a0b2011-11-08 15:32:04 -0800229 flimflam::kSecurityNone,
230 false);
Paul Stewartd08f4432011-11-04 07:48:20 -0700231 ASSERT_FALSE(service->hidden_ssid_);
232 NiceMock<MockStore> mock_store;
233 const string storage_id = service->GetStorageIdentifier();
234 EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
235 .WillRepeatedly(Return(true));
236 EXPECT_CALL(mock_store, GetBool(_, _, _))
237 .WillRepeatedly(Return(false));
238 EXPECT_CALL(mock_store,
239 GetBool(StrEq(storage_id), WiFiService::kStorageHiddenSSID, _))
240 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
241 EXPECT_TRUE(service->Load(&mock_store));
242 EXPECT_TRUE(service->hidden_ssid_);
243}
244
245TEST_F(WiFiServiceSecurityTest, WPAMapping) {
246 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityRsn,
247 flimflam::kSecurityPsk));
248 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWpa,
249 flimflam::kSecurityPsk));
250 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityPsk,
251 flimflam::kSecurityPsk));
252 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityWep,
253 flimflam::kSecurityWep));
254 EXPECT_TRUE(TestStorageMapping(flimflam::kSecurityNone,
255 flimflam::kSecurityNone));
256 // TODO(pstew): 802.1x is in a NOTIMPLEMENTED block in wifi_service.cc
257 // EXPECT_TRUE(TestStorageMapping(flimflam::kSecurity8021x,
258 // flimflam::kSecurity8021x));
259}
260
261TEST_F(WiFiServiceSecurityTest, LoadMapping) {
262 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
263 flimflam::kSecurityPsk,
264 true));
265 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
266 flimflam::kSecurityRsn,
267 true));
268 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityRsn,
269 flimflam::kSecurityWpa,
270 false));
271 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
272 flimflam::kSecurityPsk,
273 true));
274 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
275 flimflam::kSecurityWpa,
276 true));
277 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWpa,
278 flimflam::kSecurityRsn,
279 false));
280 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
281 flimflam::kSecurityWep,
282 true));
283 EXPECT_TRUE(TestLoadMapping(flimflam::kSecurityWep,
284 flimflam::kSecurityPsk,
285 false));
286}
287
Chris Masone34af2182011-08-22 11:59:36 -0700288} // namespace shill