blob: aab42ce34c069cf3cee5ec0348990ac24afde58c [file] [log] [blame]
mukesh agrawal16bc1b82012-02-09 18:38:26 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
mukesh agrawal6e277772011-09-29 15:04:23 -07002// 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_endpoint.h"
6
7#include <map>
8#include <set>
9#include <string>
10#include <vector>
11
Eric Shienbrood3e20a232012-02-16 11:35:56 -050012#include <base/stl_util.h>
mukesh agrawal6e277772011-09-29 15:04:23 -070013#include <chromeos/dbus/service_constants.h>
mukesh agrawalb20776f2012-02-10 16:00:36 -080014#include <gmock/gmock.h>
mukesh agrawal6e277772011-09-29 15:04:23 -070015#include <gtest/gtest.h>
16
Thieu Le1df7f4e2012-02-10 15:21:45 -080017#include "shill/ieee80211.h"
Paul Stewart72b2fdc2012-06-02 08:58:51 -070018#include "shill/mock_log.h"
mukesh agrawalb20776f2012-02-10 16:00:36 -080019#include "shill/mock_wifi.h"
20#include "shill/property_store_unittest.h"
mukesh agrawal16bc1b82012-02-09 18:38:26 -080021#include "shill/refptr_types.h"
mukesh agrawal6e277772011-09-29 15:04:23 -070022#include "shill/wpa_supplicant.h"
23
24using std::map;
25using std::set;
26using std::string;
27using std::vector;
mukesh agrawalb20776f2012-02-10 16:00:36 -080028using ::testing::_;
Paul Stewart72b2fdc2012-06-02 08:58:51 -070029using testing::HasSubstr;
mukesh agrawalb20776f2012-02-10 16:00:36 -080030using ::testing::NiceMock;
mukesh agrawal6e277772011-09-29 15:04:23 -070031
32namespace shill {
33
mukesh agrawalb20776f2012-02-10 16:00:36 -080034class WiFiEndpointTest : public PropertyStoreTest {
mukesh agrawal6e277772011-09-29 15:04:23 -070035 public:
mukesh agrawalb20776f2012-02-10 16:00:36 -080036 WiFiEndpointTest() : wifi_(
37 new NiceMock<MockWiFi>(
38 control_interface(),
39 dispatcher(),
40 metrics(),
41 manager(),
42 "wifi",
43 "aabbccddeeff", // fake mac
44 0)) {}
mukesh agrawal6e277772011-09-29 15:04:23 -070045 virtual ~WiFiEndpointTest() {}
46
47 protected:
48 vector<string> make_string_vector1(const string &str1) {
49 vector<string> strvec;
50 strvec.push_back(str1);
51 return strvec;
52 }
53
54 vector<string> make_string_vector2(const string &str1, const string &str2) {
55 vector<string> strvec;
56 strvec.push_back(str1);
57 strvec.push_back(str2);
58 return strvec;
59 }
60
61 map<string, ::DBus::Variant> make_key_management_args(
62 vector<string> key_management_method_strings) {
63 map<string, ::DBus::Variant> args;
64 ::DBus::MessageIter writer;
65 writer =
66 args[wpa_supplicant::kSecurityMethodPropertyKeyManagement].writer();
67 writer << key_management_method_strings;
68 return args;
69 }
70
71 map<string, ::DBus::Variant> make_security_args(
72 const string &security_protocol,
73 const string &key_management_method) {
74 map<string, ::DBus::Variant> args;
75 ::DBus::MessageIter writer;
76 writer = args[security_protocol].writer();
77 writer <<
78 make_key_management_args(make_string_vector1(key_management_method));
79 return args;
80 }
81
82 const char *ParseSecurity(
83 const map<string, ::DBus::Variant> &properties) {
84 return WiFiEndpoint::ParseSecurity(properties);
85 }
Thieu Le1df7f4e2012-02-10 15:21:45 -080086
87 void AddIE(uint8_t type, vector<uint8_t> *ies) {
88 ies->push_back(type); // type
Paul Stewart72b2fdc2012-06-02 08:58:51 -070089 ies->push_back(1); // length
Thieu Le1df7f4e2012-02-10 15:21:45 -080090 ies->push_back(0); // data
91 }
mukesh agrawalb20776f2012-02-10 16:00:36 -080092
Paul Stewart72b2fdc2012-06-02 08:58:51 -070093 void AddVendorIE(uint32_t oui, uint8_t vendor_type,
94 const vector<uint8_t> &data,
95 vector<uint8_t> *ies) {
96 ies->push_back(IEEE_80211::kElemIdVendor); // type
97 ies->push_back(4 + data.size()); // length
98 ies->push_back((oui >> 16) & 0xff); // OUI MSByte
99 ies->push_back((oui >> 8) & 0xff); // OUI middle octet
100 ies->push_back(oui & 0xff); // OUI LSByte
101 ies->push_back(vendor_type); // OUI Type
102 ies->insert(ies->end(), data.begin(), data.end());
103 }
104
105 void AddWPSElement(uint16_t type, const string &value,
106 vector<uint8_t> *wps) {
107 wps->push_back(type >> 8); // type MSByte
108 wps->push_back(type); // type LSByte
109 CHECK(value.size() < kuint16max);
110 wps->push_back((value.size() >> 8) & 0xff); // length MSByte
111 wps->push_back(value.size() & 0xff); // length LSByte
112 wps->insert(wps->end(), value.begin(), value.end());
113 }
114
115 map<string, ::DBus::Variant> MakeBSSPropertiesWithIEs(
116 const vector<uint8_t> &ies) {
117 map<string, ::DBus::Variant> properties;
118 ::DBus::MessageIter writer =
119 properties[wpa_supplicant::kBSSPropertyIEs].writer();
120 writer << ies;
121 return properties;
122 }
123
mukesh agrawalb20776f2012-02-10 16:00:36 -0800124 WiFiEndpoint *MakeOpenEndpoint(ProxyFactory *proxy_factory,
125 const WiFiRefPtr &wifi,
126 const std::string &ssid,
127 const std::string &bssid) {
mukesh agrawale1d90e92012-02-15 17:36:08 -0800128 return WiFiEndpoint::MakeOpenEndpoint(
129 proxy_factory, wifi, ssid, bssid, 0, 0);
mukesh agrawalb20776f2012-02-10 16:00:36 -0800130 }
131
132 scoped_refptr<MockWiFi> wifi() { return wifi_; }
133
134 private:
135 scoped_refptr<MockWiFi> wifi_;
mukesh agrawal6e277772011-09-29 15:04:23 -0700136};
137
138TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsEAP) {
139 set<WiFiEndpoint::KeyManagement> parsed_methods;
140 WiFiEndpoint::ParseKeyManagementMethods(
141 make_key_management_args(make_string_vector1("something-eap")),
142 &parsed_methods);
143 EXPECT_TRUE(
144 ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagement802_1x));
145 EXPECT_FALSE(
146 ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagementPSK));
147}
148
149TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsPSK) {
150 set<WiFiEndpoint::KeyManagement> parsed_methods;
151 WiFiEndpoint::ParseKeyManagementMethods(
152 make_key_management_args(make_string_vector1("something-psk")),
153 &parsed_methods);
154 EXPECT_TRUE(
155 ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagementPSK));
156 EXPECT_FALSE(
157 ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagement802_1x));
158}
159
160TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsEAPAndPSK) {
161 set<WiFiEndpoint::KeyManagement> parsed_methods;
162 WiFiEndpoint::ParseKeyManagementMethods(
163 make_key_management_args(
164 make_string_vector2("something-eap", "something-psk")),
165 &parsed_methods);
166 EXPECT_TRUE(
167 ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagement802_1x));
168 EXPECT_TRUE(
169 ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagementPSK));
170}
171
172TEST_F(WiFiEndpointTest, ParseSecurityRSN802_1x) {
173 EXPECT_STREQ(flimflam::kSecurity8021x,
174 ParseSecurity(make_security_args("RSN", "something-eap")));
175}
176
177TEST_F(WiFiEndpointTest, ParseSecurityWPA802_1x) {
178 EXPECT_STREQ(flimflam::kSecurity8021x,
179 ParseSecurity(make_security_args("WPA", "something-eap")));
180}
181
182TEST_F(WiFiEndpointTest, ParseSecurityRSNPSK) {
183 EXPECT_STREQ(flimflam::kSecurityRsn,
184 ParseSecurity(make_security_args("RSN", "something-psk")));
185}
186
187TEST_F(WiFiEndpointTest, ParseSecurityWPAPSK) {
188 EXPECT_STREQ(flimflam::kSecurityWpa,
189 ParseSecurity(make_security_args("WPA", "something-psk")));
190}
191
192TEST_F(WiFiEndpointTest, ParseSecurityWEP) {
193 map<string, ::DBus::Variant> top_params;
194 top_params[wpa_supplicant::kPropertyPrivacy].writer().append_bool(true);
195 EXPECT_STREQ(flimflam::kSecurityWep, ParseSecurity(top_params));
196}
197
198TEST_F(WiFiEndpointTest, ParseSecurityNone) {
199 map<string, ::DBus::Variant> top_params;
200 EXPECT_STREQ(flimflam::kSecurityNone, ParseSecurity(top_params));
201}
202
mukesh agrawal16bc1b82012-02-09 18:38:26 -0800203TEST_F(WiFiEndpointTest, SSIDWithNull) {
204 WiFiEndpointRefPtr endpoint =
mukesh agrawalb20776f2012-02-10 16:00:36 -0800205 MakeOpenEndpoint(NULL, NULL, string(1, 0), "00:00:00:00:00:01");
mukesh agrawal16bc1b82012-02-09 18:38:26 -0800206 EXPECT_EQ("?", endpoint->ssid_string());
207}
208
Paul Stewart72b2fdc2012-06-02 08:58:51 -0700209TEST_F(WiFiEndpointTest, DeterminePhyModeFromFrequency) {
Thieu Le1df7f4e2012-02-10 15:21:45 -0800210 {
211 map<string, ::DBus::Variant> properties;
212 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11a,
Paul Stewart72b2fdc2012-06-02 08:58:51 -0700213 WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 3200));
Thieu Le1df7f4e2012-02-10 15:21:45 -0800214 }
215 {
216 map<string, ::DBus::Variant> properties;
217 vector<uint32_t> rates(1, 22000000);
218 ::DBus::MessageIter writer =
219 properties[wpa_supplicant::kBSSPropertyRates].writer();
220 writer << rates;
221 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11b,
Paul Stewart72b2fdc2012-06-02 08:58:51 -0700222 WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 2400));
Thieu Le1df7f4e2012-02-10 15:21:45 -0800223 }
224 {
225 map<string, ::DBus::Variant> properties;
226 vector<uint32_t> rates(1, 54000000);
227 ::DBus::MessageIter writer =
228 properties[wpa_supplicant::kBSSPropertyRates].writer();
229 writer << rates;
230 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11g,
Paul Stewart72b2fdc2012-06-02 08:58:51 -0700231 WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 2400));
232 }
233}
234
235TEST_F(WiFiEndpointTest, ParseIEs) {
236 {
237 vector<uint8_t> ies;
238 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
239 WiFiEndpoint::VendorInformation vendor_information;
240 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
241 &phy_mode, &vendor_information);
242 EXPECT_EQ(Metrics::kWiFiNetworkPhyModeUndef, phy_mode);
243 }
244 {
245 vector<uint8_t> ies;
246 AddIE(IEEE_80211::kElemIdErp, &ies);
247 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
248 WiFiEndpoint::VendorInformation vendor_information;
249 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
250 &phy_mode, &vendor_information);
251 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11g, phy_mode);
252 }
253 {
254 vector<uint8_t> ies;
255 AddIE(IEEE_80211::kElemIdHTCap, &ies);
256 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
257 WiFiEndpoint::VendorInformation vendor_information;
258 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
259 &phy_mode, &vendor_information);
260 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, phy_mode);
261 }
262 {
263 vector<uint8_t> ies;
264 AddIE(IEEE_80211::kElemIdHTInfo, &ies);
265 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
266 WiFiEndpoint::VendorInformation vendor_information;
267 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
268 &phy_mode, &vendor_information);
269 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, phy_mode);
270 }
271 {
272 vector<uint8_t> ies;
273 AddIE(IEEE_80211::kElemIdErp, &ies);
274 AddIE(IEEE_80211::kElemIdHTCap, &ies);
275 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
276 WiFiEndpoint::VendorInformation vendor_information;
277 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
278 &phy_mode, &vendor_information);
279 EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, phy_mode);
280 }
281}
282
283TEST_F(WiFiEndpointTest, ParseVendorIEs) {
284 {
285 ScopedMockLog log;
286 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
287 HasSubstr("no room in IE for OUI and type field.")))
288 .Times(1);
289 vector<uint8_t> ies;
290 AddIE(IEEE_80211::kElemIdVendor, &ies);
291 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
292 WiFiEndpoint::VendorInformation vendor_information;
293 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
294 &phy_mode, &vendor_information);
295 }
296 {
297 vector<uint8_t> ies;
298 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
299 WiFiEndpoint::VendorInformation vendor_information;
300 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
301 &phy_mode, &vendor_information);
302 EXPECT_EQ("", vendor_information.wps_manufacturer);
303 EXPECT_EQ("", vendor_information.wps_model_name);
304 EXPECT_EQ("", vendor_information.wps_model_number);
305 EXPECT_EQ("", vendor_information.wps_device_name);
306 EXPECT_EQ(0, vendor_information.oui_list.size());
307 }
308 {
309 ScopedMockLog log;
310 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
311 HasSubstr("IE extends past containing PDU"))).Times(1);
312 vector<uint8_t> ies;
313 AddVendorIE(0, 0, vector<uint8_t>(), &ies);
314 ies.resize(ies.size() - 1); // Cause an underrun in the data.
315 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
316 WiFiEndpoint::VendorInformation vendor_information;
317 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
318 &phy_mode, &vendor_information);
319 }
320 {
321 vector<uint8_t> ies;
322 const uint32_t kVendorOUI = 0xaabbcc;
323 AddVendorIE(kVendorOUI, 0, vector<uint8_t>(), &ies);
324 AddVendorIE(IEEE_80211::kOUIVendorMicrosoft, 0, vector<uint8_t>(), &ies);
325 AddVendorIE(IEEE_80211::kOUIVendorEpigram, 0, vector<uint8_t>(), &ies);
326 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
327 WiFiEndpoint::VendorInformation vendor_information;
328 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
329 &phy_mode, &vendor_information);
330 EXPECT_EQ("", vendor_information.wps_manufacturer);
331 EXPECT_EQ("", vendor_information.wps_model_name);
332 EXPECT_EQ("", vendor_information.wps_model_number);
333 EXPECT_EQ("", vendor_information.wps_device_name);
334 EXPECT_EQ(1, vendor_information.oui_list.size());
335 EXPECT_FALSE(vendor_information.oui_list.find(kVendorOUI) ==
336 vendor_information.oui_list.end());
337
338 WiFiEndpointRefPtr endpoint =
339 MakeOpenEndpoint(NULL, NULL, string(1, 0), "00:00:00:00:00:01");
340 endpoint->vendor_information_ = vendor_information;
341 map<string, string> vendor_stringmap(endpoint->GetVendorInformation());
342 EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSManufacturerProperty));
343 EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSModelNameProperty));
344 EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSModelNumberProperty));
345 EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSDeviceNameProperty));
346 EXPECT_EQ("aa-bb-cc", vendor_stringmap[kVendorOUIListProperty]);
347 }
348 {
349 ScopedMockLog log;
350 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
351 HasSubstr("WPS element extends past containing PDU")))
352 .Times(1);
353 vector<uint8_t> ies;
354 vector<uint8_t> wps;
355 AddWPSElement(IEEE_80211::kWPSElementManufacturer, "foo", &wps);
356 wps.resize(wps.size() - 1); // Cause an underrun in the data.
357 AddVendorIE(IEEE_80211::kOUIVendorMicrosoft,
358 IEEE_80211::kOUIMicrosoftWPS, wps, &ies);
359 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
360 WiFiEndpoint::VendorInformation vendor_information;
361 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
362 &phy_mode, &vendor_information);
363 EXPECT_EQ("", vendor_information.wps_manufacturer);
364 }
365 {
366 vector<uint8_t> ies;
367 vector<uint8_t> wps;
368 const string kManufacturer("manufacturer");
369 const string kModelName("modelname");
370 const string kModelNumber("modelnumber");
371 const string kDeviceName("devicename");
372 AddWPSElement(IEEE_80211::kWPSElementManufacturer, kManufacturer, &wps);
373 AddWPSElement(IEEE_80211::kWPSElementModelName, kModelName, &wps);
374 AddWPSElement(IEEE_80211::kWPSElementModelNumber, kModelNumber, &wps);
375 AddWPSElement(IEEE_80211::kWPSElementDeviceName, kDeviceName, &wps);
376 AddVendorIE(IEEE_80211::kOUIVendorMicrosoft,
377 IEEE_80211::kOUIMicrosoftWPS, wps, &ies);
378 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
379 WiFiEndpoint::VendorInformation vendor_information;
380 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
381 &phy_mode, &vendor_information);
382 EXPECT_EQ(kManufacturer, vendor_information.wps_manufacturer);
383 EXPECT_EQ(kModelName, vendor_information.wps_model_name);
384 EXPECT_EQ(kModelNumber, vendor_information.wps_model_number);
385 EXPECT_EQ(kDeviceName, vendor_information.wps_device_name);
386
387 WiFiEndpointRefPtr endpoint =
388 MakeOpenEndpoint(NULL, NULL, string(1, 0), "00:00:00:00:00:01");
389 endpoint->vendor_information_ = vendor_information;
390 map<string, string> vendor_stringmap(endpoint->GetVendorInformation());
391 EXPECT_EQ(kManufacturer, vendor_stringmap[kVendorWPSManufacturerProperty]);
392 EXPECT_EQ(kModelName, vendor_stringmap[kVendorWPSModelNameProperty]);
393 EXPECT_EQ(kModelNumber, vendor_stringmap[kVendorWPSModelNumberProperty]);
394 EXPECT_EQ(kDeviceName, vendor_stringmap[kVendorWPSDeviceNameProperty]);
395 EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorOUIListProperty));
396 }
397 {
398 vector<uint8_t> ies;
399 vector<uint8_t> wps;
400 const string kManufacturer("manufacturer");
401 const string kModelName("modelname");
402 AddWPSElement(IEEE_80211::kWPSElementManufacturer, kManufacturer, &wps);
403 wps.resize(wps.size() - 1); // Insert a non-ASCII character in the WPS.
404 wps.push_back(0x80);
405 AddWPSElement(IEEE_80211::kWPSElementModelName, kModelName, &wps);
406 AddVendorIE(IEEE_80211::kOUIVendorMicrosoft,
407 IEEE_80211::kOUIMicrosoftWPS, wps, &ies);
408 Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
409 WiFiEndpoint::VendorInformation vendor_information;
410 WiFiEndpoint::ParseIEs(MakeBSSPropertiesWithIEs(ies),
411 &phy_mode, &vendor_information);
412 EXPECT_EQ("", vendor_information.wps_manufacturer);
413 EXPECT_EQ(kModelName, vendor_information.wps_model_name);
Thieu Le1df7f4e2012-02-10 15:21:45 -0800414 }
415}
416
mukesh agrawalb20776f2012-02-10 16:00:36 -0800417TEST_F(WiFiEndpointTest, PropertiesChanged) {
418 WiFiEndpointRefPtr endpoint =
419 MakeOpenEndpoint(NULL, wifi(), "ssid", "00:00:00:00:00:01");
420 map<string, ::DBus::Variant> changed_properties;
421 ::DBus::MessageIter writer;
422 int16_t signal_strength = 10;
423
424 EXPECT_NE(signal_strength, endpoint->signal_strength());
425 writer =
426 changed_properties[wpa_supplicant::kBSSPropertySignal].writer();
427 writer << signal_strength;
428
429 EXPECT_CALL(*wifi(), NotifyEndpointChanged(_));
430 endpoint->PropertiesChanged(changed_properties);
431 EXPECT_EQ(signal_strength, endpoint->signal_strength());
432}
433
mukesh agrawal6e277772011-09-29 15:04:23 -0700434} // namespace shill