1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/wifi/wifi_endpoint.h"
18
19#include <map>
20#include <set>
21#include <string>
22#include <vector>
23
24#include <base/stl_util.h>
25#if defined(__ANDROID__)
26#include <dbus/service_constants.h>
27#else
28#include <chromeos/dbus/service_constants.h>
29#endif  // __ANDROID__
30#include <gmock/gmock.h>
31#include <gtest/gtest.h>
32
33#include "shill/mock_log.h"
34#include "shill/net/ieee80211.h"
35#include "shill/property_store_unittest.h"
36#include "shill/refptr_types.h"
37#include "shill/supplicant/wpa_supplicant.h"
38#include "shill/tethering.h"
39#include "shill/wifi/mock_wifi.h"
40
41using std::map;
42using std::set;
43using std::string;
44using std::vector;
45using ::testing::_;
46using ::testing::HasSubstr;
47using ::testing::Mock;
48using ::testing::NiceMock;
49
50namespace shill {
51
52class WiFiEndpointTest : public PropertyStoreTest {
53 public:
54  WiFiEndpointTest() : wifi_(
55      new NiceMock<MockWiFi>(
56          control_interface(),
57          dispatcher(),
58          metrics(),
59          manager(),
60          "wifi",
61          "aabbccddeeff",  // fake mac
62          0)) {}
63  virtual ~WiFiEndpointTest() {}
64
65 protected:
66  vector<string> make_string_vector1(const string& str1) {
67    vector<string> strvec;
68    strvec.push_back(str1);
69    return strvec;
70  }
71
72  vector<string> make_string_vector2(const string& str1, const string& str2) {
73    vector<string> strvec;
74    strvec.push_back(str1);
75    strvec.push_back(str2);
76    return strvec;
77  }
78
79  KeyValueStore make_key_management_args(
80      vector<string> key_management_method_strings) {
81    KeyValueStore args;
82    args.SetStrings(WPASupplicant::kSecurityMethodPropertyKeyManagement,
83                    key_management_method_strings);
84    return args;
85  }
86
87  KeyValueStore make_privacy_args(bool is_private) {
88    KeyValueStore props;
89    props.SetBool(WPASupplicant::kPropertyPrivacy, is_private);
90    return props;
91  }
92
93  KeyValueStore make_security_args(
94      const string& security_protocol,
95      const string& key_management_method) {
96    KeyValueStore args;
97    vector<string> key_management_method_vector;
98    if (!key_management_method.empty()) {
99      key_management_method_vector = make_string_vector1(key_management_method);
100    }
101    args.SetKeyValueStore(
102        security_protocol,
103        make_key_management_args(key_management_method_vector));
104    return args;
105  }
106
107  const char* ParseSecurity(
108    const KeyValueStore& properties) {
109    WiFiEndpoint::SecurityFlags security_flags;
110    return WiFiEndpoint::ParseSecurity(properties, &security_flags);
111  }
112
113  void AddIEWithData(uint8_t type, vector<uint8_t> data, vector<uint8_t>* ies) {
114    ies->push_back(type);           // type
115    ies->push_back(data.size());    // length
116    ies->insert(ies->end(), data.begin(), data.end());
117  }
118
119  void AddIE(uint8_t type, vector<uint8_t>* ies) {
120    AddIEWithData(type, vector<uint8_t>(1), ies);
121  }
122
123  void AddVendorIE(uint32_t oui, uint8_t vendor_type,
124                   const vector<uint8_t>& data,
125                   vector<uint8_t>* ies) {
126    ies->push_back(IEEE_80211::kElemIdVendor);  // type
127    ies->push_back(4 + data.size());            // length
128    ies->push_back((oui >> 16) & 0xff);         // OUI MSByte
129    ies->push_back((oui >> 8) & 0xff);          // OUI middle octet
130    ies->push_back(oui & 0xff);                 // OUI LSByte
131    ies->push_back(vendor_type);                // OUI Type
132    ies->insert(ies->end(), data.begin(), data.end());
133  }
134
135  void AddWPSElement(uint16_t type, const string& value,
136                     vector<uint8_t>* wps) {
137    wps->push_back(type >> 8);                   // type MSByte
138    wps->push_back(type);                        // type LSByte
139    CHECK(value.size() < std::numeric_limits<uint16_t>::max());
140    wps->push_back((value.size() >> 8) & 0xff);  // length MSByte
141    wps->push_back(value.size() & 0xff);         // length LSByte
142    wps->insert(wps->end(), value.begin(), value.end());
143  }
144
145  KeyValueStore MakeBSSPropertiesWithIEs(const vector<uint8_t>& ies) {
146    KeyValueStore properties;
147    properties.SetUint8s(WPASupplicant::kBSSPropertyIEs, ies);
148    return properties;
149  }
150
151  // Creates the RSN properties string (which still requires an information
152  // element prefix).
153  vector<uint8_t> MakeRSNProperties(uint16_t pairwise_count,
154                                    uint16_t authkey_count,
155                                    uint16_t capabilities) {
156    vector<uint8_t> rsn(IEEE_80211::kRSNIECipherCountOffset +
157                        IEEE_80211::kRSNIECipherCountLen * 2 +
158                        IEEE_80211::kRSNIESelectorLen *
159                        (pairwise_count + authkey_count) +
160                        IEEE_80211::kRSNIECapabilitiesLen);
161
162    // Set both cipher counts in little endian.
163    rsn[IEEE_80211::kRSNIECipherCountOffset] = pairwise_count & 0xff;
164    rsn[IEEE_80211::kRSNIECipherCountOffset + 1] = pairwise_count >> 8;
165    size_t authkey_offset = IEEE_80211::kRSNIECipherCountOffset +
166        IEEE_80211::kRSNIECipherCountLen +
167        pairwise_count * IEEE_80211::kRSNIESelectorLen;
168    rsn[authkey_offset] = authkey_count & 0xff;
169    rsn[authkey_offset + 1] = authkey_count >> 8;
170
171    // Set the little-endian capabilities field.
172    size_t capabilities_offset = rsn.size() - 2;
173    rsn[capabilities_offset] = capabilities & 0xff;
174    rsn[capabilities_offset + 1] = capabilities >> 8;
175
176    return rsn;
177  }
178
179  bool ParseIEs(const KeyValueStore& properties,
180                Metrics::WiFiNetworkPhyMode* phy_mode,
181                WiFiEndpoint::VendorInformation* vendor_information,
182                bool* ieee80211w_required, std::string* country_code) {
183    return WiFiEndpoint::ParseIEs(properties, phy_mode, vendor_information,
184                                  ieee80211w_required, country_code);
185  }
186
187  void SetVendorInformation(
188      const WiFiEndpointRefPtr& endpoint,
189      const WiFiEndpoint::VendorInformation& vendor_information) {
190    endpoint->vendor_information_ = vendor_information;
191  }
192
193  WiFiEndpoint* MakeEndpoint(ControlInterface* control_interface,
194                             const WiFiRefPtr& wifi,
195                             const std::string& ssid,
196                             const std::string& bssid,
197                             bool has_wpa_property,
198                             bool has_rsn_property) {
199    return WiFiEndpoint::MakeEndpoint(
200        control_interface, wifi, ssid, bssid,
201        WPASupplicant::kNetworkModeInfrastructure, 0, 0, has_wpa_property,
202        has_rsn_property);
203  }
204
205  WiFiEndpoint* MakeOpenEndpoint(ControlInterface* control_interface,
206                                 const WiFiRefPtr& wifi,
207                                 const std::string& ssid,
208                                 const std::string& bssid) {
209    return WiFiEndpoint::MakeOpenEndpoint(
210        control_interface, wifi, ssid, bssid,
211        WPASupplicant::kNetworkModeInfrastructure, 0, 0);
212  }
213
214  scoped_refptr<MockWiFi> wifi() { return wifi_; }
215
216 private:
217  scoped_refptr<MockWiFi> wifi_;
218};
219
220TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsEAP) {
221  set<WiFiEndpoint::KeyManagement> parsed_methods;
222  WiFiEndpoint::ParseKeyManagementMethods(
223      make_key_management_args(make_string_vector1("something-eap")),
224      &parsed_methods);
225  EXPECT_TRUE(
226      ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagement802_1x));
227  EXPECT_FALSE(
228      ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagementPSK));
229}
230
231TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsPSK) {
232  set<WiFiEndpoint::KeyManagement> parsed_methods;
233  WiFiEndpoint::ParseKeyManagementMethods(
234      make_key_management_args(make_string_vector1("something-psk")),
235      &parsed_methods);
236  EXPECT_TRUE(
237      ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagementPSK));
238  EXPECT_FALSE(
239      ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagement802_1x));
240}
241
242TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsEAPAndPSK) {
243  set<WiFiEndpoint::KeyManagement> parsed_methods;
244  WiFiEndpoint::ParseKeyManagementMethods(
245      make_key_management_args(
246          make_string_vector2("something-eap", "something-psk")),
247      &parsed_methods);
248  EXPECT_TRUE(
249      ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagement802_1x));
250  EXPECT_TRUE(
251      ContainsKey(parsed_methods, WiFiEndpoint::kKeyManagementPSK));
252}
253
254TEST_F(WiFiEndpointTest, ParseSecurityRSN802_1x) {
255  EXPECT_STREQ(kSecurity8021x,
256               ParseSecurity(make_security_args("RSN", "something-eap")));
257}
258
259TEST_F(WiFiEndpointTest, ParseSecurityWPA802_1x) {
260  EXPECT_STREQ(kSecurity8021x,
261               ParseSecurity(make_security_args("WPA", "something-eap")));
262}
263
264TEST_F(WiFiEndpointTest, ParseSecurityRSNPSK) {
265  EXPECT_STREQ(kSecurityRsn,
266               ParseSecurity(make_security_args("RSN", "something-psk")));
267}
268
269TEST_F(WiFiEndpointTest, ParseSecurityWPAPSK) {
270  EXPECT_STREQ(kSecurityWpa,
271               ParseSecurity(make_security_args("WPA", "something-psk")));
272}
273
274TEST_F(WiFiEndpointTest, ParseSecurityWEP) {
275  EXPECT_STREQ(kSecurityWep, ParseSecurity(make_privacy_args(true)));
276}
277
278TEST_F(WiFiEndpointTest, ParseSecurityNone) {
279  KeyValueStore top_params;
280  EXPECT_STREQ(kSecurityNone, ParseSecurity(top_params));
281}
282
283TEST_F(WiFiEndpointTest, SSIDAndBSSIDString) {
284  const char kSSID[] = "The SSID";
285  const char kBSSID[] = "00:01:02:03:04:05";
286
287  // The MakeOpenEndpoint method translates both of the above parameters into
288  // binary equivalents before calling the Endpoint constructor.  Let's make
289  // sure the Endpoint can translate them back losslessly to strings.
290  WiFiEndpointRefPtr endpoint =
291      MakeOpenEndpoint(nullptr, nullptr, kSSID, kBSSID);
292  EXPECT_EQ(kSSID, endpoint->ssid_string());
293  EXPECT_EQ(kBSSID, endpoint->bssid_string());
294}
295
296TEST_F(WiFiEndpointTest, SSIDWithNull) {
297  WiFiEndpointRefPtr endpoint =
298      MakeOpenEndpoint(nullptr, nullptr, string(1, 0), "00:00:00:00:00:01");
299  EXPECT_EQ("?", endpoint->ssid_string());
300}
301
302TEST_F(WiFiEndpointTest, DeterminePhyModeFromFrequency) {
303  {
304    KeyValueStore properties;
305    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11a,
306              WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 3200));
307  }
308  {
309    KeyValueStore properties;
310    vector<uint32_t> rates(1, 22000000);
311    properties.SetUint32s(WPASupplicant::kBSSPropertyRates, rates);
312    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11b,
313              WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 2400));
314  }
315  {
316    KeyValueStore properties;
317    vector<uint32_t> rates(1, 54000000);
318    properties.SetUint32s(WPASupplicant::kBSSPropertyRates, rates);
319    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11g,
320              WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 2400));
321  }
322  {
323    KeyValueStore properties;
324    vector<uint32_t> rates;
325    properties.SetUint32s(WPASupplicant::kBSSPropertyRates, rates);
326    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11b,
327              WiFiEndpoint::DeterminePhyModeFromFrequency(properties, 2400));
328  }
329}
330
331TEST_F(WiFiEndpointTest, ParseIEs) {
332  {
333    vector<uint8_t> ies;
334    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
335    WiFiEndpoint::VendorInformation vendor_information;
336    EXPECT_FALSE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
337                          &vendor_information, nullptr, nullptr));
338    EXPECT_EQ(Metrics::kWiFiNetworkPhyModeUndef, phy_mode);
339  }
340  {
341    vector<uint8_t> ies;
342    AddIE(IEEE_80211::kElemIdErp, &ies);
343    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
344    WiFiEndpoint::VendorInformation vendor_information;
345    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
346                         &vendor_information, nullptr, nullptr));
347    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11g, phy_mode);
348  }
349  {
350    vector<uint8_t> ies;
351    AddIE(IEEE_80211::kElemIdHTCap, &ies);
352    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
353    WiFiEndpoint::VendorInformation vendor_information;
354    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
355                         &vendor_information, nullptr, nullptr));
356    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, phy_mode);
357  }
358  {
359    vector<uint8_t> ies;
360    AddIE(IEEE_80211::kElemIdHTInfo, &ies);
361    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
362    WiFiEndpoint::VendorInformation vendor_information;
363    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
364                         &vendor_information, nullptr, nullptr));
365    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, phy_mode);
366  }
367  {
368    vector<uint8_t> ies;
369    AddIE(IEEE_80211::kElemIdErp, &ies);
370    AddIE(IEEE_80211::kElemIdHTCap, &ies);
371    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
372    WiFiEndpoint::VendorInformation vendor_information;
373    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
374                         &vendor_information, nullptr, nullptr));
375    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, phy_mode);
376  }
377  {
378    vector<uint8_t> ies;
379    AddIE(IEEE_80211::kElemIdVHTCap, &ies);
380    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
381    WiFiEndpoint::VendorInformation vendor_information;
382    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
383                         &vendor_information, nullptr, nullptr));
384    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11ac, phy_mode);
385  }
386  {
387    vector<uint8_t> ies;
388    AddIE(IEEE_80211::kElemIdVHTOperation, &ies);
389    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
390    WiFiEndpoint::VendorInformation vendor_information;
391    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
392                         &vendor_information, nullptr, nullptr));
393    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11ac, phy_mode);
394  }
395  {
396    vector<uint8_t> ies;
397    AddIE(IEEE_80211::kElemIdErp, &ies);
398    AddIE(IEEE_80211::kElemIdHTCap, &ies);
399    AddIE(IEEE_80211::kElemIdVHTCap, &ies);
400    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
401    WiFiEndpoint::VendorInformation vendor_information;
402    EXPECT_TRUE(ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode,
403                         &vendor_information, nullptr, nullptr));
404    EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11ac, phy_mode);
405  }
406}
407
408TEST_F(WiFiEndpointTest, ParseVendorIEs) {
409  {
410    ScopedMockLog log;
411    EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
412                         HasSubstr("no room in IE for OUI and type field.")))
413        .Times(1);
414    vector<uint8_t> ies;
415    AddIE(IEEE_80211::kElemIdVendor, &ies);
416    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
417    WiFiEndpoint::VendorInformation vendor_information;
418    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
419             nullptr, nullptr);
420  }
421  {
422    vector<uint8_t> ies;
423    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
424    WiFiEndpoint::VendorInformation vendor_information;
425    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
426             nullptr, nullptr);
427    EXPECT_EQ("", vendor_information.wps_manufacturer);
428    EXPECT_EQ("", vendor_information.wps_model_name);
429    EXPECT_EQ("", vendor_information.wps_model_number);
430    EXPECT_EQ("", vendor_information.wps_device_name);
431    EXPECT_EQ(0, vendor_information.oui_set.size());
432  }
433  {
434    ScopedMockLog log;
435    EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
436                         HasSubstr("IE extends past containing PDU"))).Times(1);
437    vector<uint8_t> ies;
438    AddVendorIE(0, 0, vector<uint8_t>(), &ies);
439    ies.resize(ies.size() - 1);  // Cause an underrun in the data.
440    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
441    WiFiEndpoint::VendorInformation vendor_information;
442    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
443             nullptr, nullptr);
444  }
445  {
446    vector<uint8_t> ies;
447    const uint32_t kVendorOUI = 0xaabbcc;
448    AddVendorIE(kVendorOUI, 0, vector<uint8_t>(), &ies);
449    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft, 0, vector<uint8_t>(), &ies);
450    AddVendorIE(IEEE_80211::kOUIVendorEpigram, 0, vector<uint8_t>(), &ies);
451    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
452    WiFiEndpoint::VendorInformation vendor_information;
453    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
454             nullptr, nullptr);
455    EXPECT_EQ("", vendor_information.wps_manufacturer);
456    EXPECT_EQ("", vendor_information.wps_model_name);
457    EXPECT_EQ("", vendor_information.wps_model_number);
458    EXPECT_EQ("", vendor_information.wps_device_name);
459    EXPECT_EQ(1, vendor_information.oui_set.size());
460    EXPECT_FALSE(vendor_information.oui_set.find(kVendorOUI) ==
461                 vendor_information.oui_set.end());
462
463    WiFiEndpointRefPtr endpoint =
464        MakeOpenEndpoint(nullptr, nullptr, string(1, 0), "00:00:00:00:00:01");
465    SetVendorInformation(endpoint, vendor_information);
466    map<string, string> vendor_stringmap(endpoint->GetVendorInformation());
467    EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSManufacturerProperty));
468    EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSModelNameProperty));
469    EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSModelNumberProperty));
470    EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorWPSDeviceNameProperty));
471    EXPECT_EQ("aa-bb-cc", vendor_stringmap[kVendorOUIListProperty]);
472  }
473  {
474    ScopedMockLog log;
475    EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
476                         HasSubstr("WPS element extends past containing PDU")))
477        .Times(1);
478    vector<uint8_t> ies;
479    vector<uint8_t> wps;
480    AddWPSElement(IEEE_80211::kWPSElementManufacturer, "foo", &wps);
481    wps.resize(wps.size() - 1);  // Cause an underrun in the data.
482    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft,
483                IEEE_80211::kOUIMicrosoftWPS, wps, &ies);
484    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
485    WiFiEndpoint::VendorInformation vendor_information;
486    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
487             nullptr, nullptr);
488    EXPECT_EQ("", vendor_information.wps_manufacturer);
489  }
490  {
491    vector<uint8_t> ies;
492    vector<uint8_t> wps;
493    const string kManufacturer("manufacturer");
494    const string kModelName("modelname");
495    const string kModelNumber("modelnumber");
496    const string kDeviceName("devicename");
497    AddWPSElement(IEEE_80211::kWPSElementManufacturer, kManufacturer, &wps);
498    AddWPSElement(IEEE_80211::kWPSElementModelName, kModelName, &wps);
499    AddWPSElement(IEEE_80211::kWPSElementModelNumber, kModelNumber, &wps);
500    AddWPSElement(IEEE_80211::kWPSElementDeviceName, kDeviceName, &wps);
501    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft,
502                IEEE_80211::kOUIMicrosoftWPS, wps, &ies);
503    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
504    WiFiEndpoint::VendorInformation vendor_information;
505    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
506             nullptr, nullptr);
507    EXPECT_EQ(kManufacturer, vendor_information.wps_manufacturer);
508    EXPECT_EQ(kModelName, vendor_information.wps_model_name);
509    EXPECT_EQ(kModelNumber, vendor_information.wps_model_number);
510    EXPECT_EQ(kDeviceName, vendor_information.wps_device_name);
511
512    WiFiEndpointRefPtr endpoint =
513        MakeOpenEndpoint(nullptr, nullptr, string(1, 0), "00:00:00:00:00:01");
514    SetVendorInformation(endpoint, vendor_information);
515    map<string, string> vendor_stringmap(endpoint->GetVendorInformation());
516    EXPECT_EQ(kManufacturer, vendor_stringmap[kVendorWPSManufacturerProperty]);
517    EXPECT_EQ(kModelName, vendor_stringmap[kVendorWPSModelNameProperty]);
518    EXPECT_EQ(kModelNumber, vendor_stringmap[kVendorWPSModelNumberProperty]);
519    EXPECT_EQ(kDeviceName, vendor_stringmap[kVendorWPSDeviceNameProperty]);
520    EXPECT_FALSE(ContainsKey(vendor_stringmap, kVendorOUIListProperty));
521  }
522  {
523    vector<uint8_t> ies;
524    vector<uint8_t> wps;
525    const string kManufacturer("manufacturer");
526    const string kModelName("modelname");
527    AddWPSElement(IEEE_80211::kWPSElementManufacturer, kManufacturer, &wps);
528    wps.resize(wps.size() - 1);  // Insert a non-ASCII character in the WPS.
529    wps.push_back(0x80);
530    AddWPSElement(IEEE_80211::kWPSElementModelName, kModelName, &wps);
531    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft,
532                IEEE_80211::kOUIMicrosoftWPS, wps, &ies);
533    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
534    WiFiEndpoint::VendorInformation vendor_information;
535    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
536             nullptr, nullptr);
537    EXPECT_EQ("", vendor_information.wps_manufacturer);
538    EXPECT_EQ(kModelName, vendor_information.wps_model_name);
539  }
540}
541
542TEST_F(WiFiEndpointTest, ParseWPACapabilities) {
543  {
544    vector<uint8_t> ies;
545    vector<uint8_t> rsn;
546    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft, IEEE_80211::kOUIMicrosoftWPA,
547                rsn, &ies);
548    AddIEWithData(IEEE_80211::kElemIdRSN, rsn, &ies);
549    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
550    WiFiEndpoint::VendorInformation vendor_information;
551    bool ieee80211w_required = false;
552    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
553             &ieee80211w_required, nullptr);
554    EXPECT_FALSE(ieee80211w_required);
555  }
556  {
557    vector<uint8_t> ies;
558    vector<uint8_t> rsn = MakeRSNProperties(
559        2, 3, ~IEEE_80211::kRSNCapabilityFrameProtectionRequired);
560    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft, IEEE_80211::kOUIMicrosoftWPA,
561                rsn, &ies);
562    AddIEWithData(IEEE_80211::kElemIdRSN, rsn, &ies);
563    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
564    WiFiEndpoint::VendorInformation vendor_information;
565    bool ieee80211w_required = false;
566    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
567             &ieee80211w_required, nullptr);
568    EXPECT_FALSE(ieee80211w_required);
569  }
570  {
571    vector<uint8_t> ies;
572    vector<uint8_t> rsn = MakeRSNProperties(
573        2, 3, IEEE_80211::kRSNCapabilityFrameProtectionRequired);
574    AddVendorIE(IEEE_80211::kOUIVendorMicrosoft, IEEE_80211::kOUIMicrosoftWPA,
575                rsn, &ies);
576    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
577    WiFiEndpoint::VendorInformation vendor_information;
578    bool ieee80211w_required = false;
579    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
580             &ieee80211w_required, nullptr);
581    EXPECT_TRUE(ieee80211w_required);
582  }
583  {
584    vector<uint8_t> ies;
585    vector<uint8_t> rsn = MakeRSNProperties(
586        8, 2, IEEE_80211::kRSNCapabilityFrameProtectionRequired);
587    AddIEWithData(IEEE_80211::kElemIdRSN, rsn, &ies);
588    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
589    WiFiEndpoint::VendorInformation vendor_information;
590    bool ieee80211w_required = false;
591    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
592             &ieee80211w_required, nullptr);
593    EXPECT_TRUE(ieee80211w_required);
594  }
595  {
596    vector<uint8_t> ies;
597    vector<uint8_t> rsn = MakeRSNProperties(
598        8, 2, IEEE_80211::kRSNCapabilityFrameProtectionRequired);
599    rsn.resize(rsn.size() + 1);
600    AddIEWithData(IEEE_80211::kElemIdRSN, rsn, &ies);
601    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
602    WiFiEndpoint::VendorInformation vendor_information;
603    bool ieee80211w_required = false;
604    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
605             &ieee80211w_required, nullptr);
606    EXPECT_TRUE(ieee80211w_required);
607  }
608  {
609    vector<uint8_t> ies;
610    vector<uint8_t> rsn = MakeRSNProperties(
611        8, 2, IEEE_80211::kRSNCapabilityFrameProtectionRequired);
612    rsn.resize(rsn.size() - 1);
613    AddIEWithData(IEEE_80211::kElemIdRSN, rsn, &ies);
614    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
615    WiFiEndpoint::VendorInformation vendor_information;
616    bool ieee80211w_required = false;
617    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
618             &ieee80211w_required, nullptr);
619    EXPECT_FALSE(ieee80211w_required);
620  }
621  {
622    vector<uint8_t> ies;
623    vector<uint8_t> rsn0 = MakeRSNProperties(
624        1, 1, IEEE_80211::kRSNCapabilityFrameProtectionRequired);
625    AddIEWithData(IEEE_80211::kElemIdRSN, rsn0, &ies);
626    vector<uint8_t> rsn1 = MakeRSNProperties(1, 1, 0);
627    AddIEWithData(IEEE_80211::kElemIdRSN, rsn1, &ies);
628    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
629    WiFiEndpoint::VendorInformation vendor_information;
630    bool ieee80211w_required = false;
631    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
632             &ieee80211w_required, nullptr);
633    EXPECT_TRUE(ieee80211w_required);
634  }
635}
636
637TEST_F(WiFiEndpointTest, ParseCountryCode) {
638  {
639    vector<uint8_t> ies;
640    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
641    WiFiEndpoint::VendorInformation vendor_information;
642    string country_code;
643    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
644             nullptr, &country_code);
645    EXPECT_TRUE(country_code.empty());
646  }
647  {
648    const string kCountryCode("G");
649    const vector<uint8_t> kCountryCodeAsVector(
650        kCountryCode.begin(), kCountryCode.end());
651    vector<uint8_t> ies;
652    AddIEWithData(IEEE_80211::kElemIdCountry, kCountryCodeAsVector, &ies);
653    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
654    WiFiEndpoint::VendorInformation vendor_information;
655    string country_code;
656    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
657             nullptr, &country_code);
658    EXPECT_TRUE(country_code.empty());
659  }
660  {
661    const string kCountryCode("GO");
662    const vector<uint8_t> kCountryCodeAsVector(
663        kCountryCode.begin(), kCountryCode.end());
664    vector<uint8_t> ies;
665    AddIEWithData(IEEE_80211::kElemIdCountry, kCountryCodeAsVector, &ies);
666    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
667    WiFiEndpoint::VendorInformation vendor_information;
668    string country_code;
669    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
670             nullptr, &country_code);
671    EXPECT_EQ(kCountryCode, country_code);
672  }
673  {
674    const string kCountryCode("GOO");
675    const vector<uint8_t> kCountryCodeAsVector(
676        kCountryCode.begin(), kCountryCode.end());
677    vector<uint8_t> ies;
678    AddIEWithData(IEEE_80211::kElemIdCountry, kCountryCodeAsVector, &ies);
679    Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
680    WiFiEndpoint::VendorInformation vendor_information;
681    string country_code;
682    ParseIEs(MakeBSSPropertiesWithIEs(ies), &phy_mode, &vendor_information,
683             nullptr, &country_code);
684    EXPECT_EQ(string(kCountryCode, 0, 2), country_code);
685  }
686}
687
688TEST_F(WiFiEndpointTest, PropertiesChangedNone) {
689  WiFiEndpointRefPtr endpoint =
690      MakeOpenEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01");
691  EXPECT_EQ(kModeManaged, endpoint->network_mode());
692  EXPECT_EQ(kSecurityNone, endpoint->security_mode());
693  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(0);
694  KeyValueStore no_changed_properties;
695  endpoint->PropertiesChanged(no_changed_properties);
696  EXPECT_EQ(kModeManaged, endpoint->network_mode());
697  EXPECT_EQ(kSecurityNone, endpoint->security_mode());
698}
699
700TEST_F(WiFiEndpointTest, PropertiesChangedStrength) {
701  WiFiEndpointRefPtr endpoint =
702      MakeOpenEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01");
703  KeyValueStore changed_properties;
704  int16_t signal_strength = 10;
705
706  EXPECT_NE(signal_strength, endpoint->signal_strength());
707  changed_properties.SetInt16(WPASupplicant::kBSSPropertySignal,
708                              signal_strength);
709
710  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_));
711  endpoint->PropertiesChanged(changed_properties);
712  EXPECT_EQ(signal_strength, endpoint->signal_strength());
713}
714
715TEST_F(WiFiEndpointTest, PropertiesChangedNetworkMode) {
716  WiFiEndpointRefPtr endpoint =
717      MakeOpenEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01");
718  EXPECT_EQ(kModeManaged, endpoint->network_mode());
719  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(1);
720  KeyValueStore changed_properties;
721  changed_properties.SetString(WPASupplicant::kBSSPropertyMode,
722                               WPASupplicant::kNetworkModeAdHoc);
723  endpoint->PropertiesChanged(changed_properties);
724  EXPECT_EQ(kModeAdhoc, endpoint->network_mode());
725}
726
727TEST_F(WiFiEndpointTest, PropertiesChangedSecurityMode) {
728  WiFiEndpointRefPtr endpoint =
729      MakeOpenEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01");
730  EXPECT_EQ(kSecurityNone, endpoint->security_mode());
731
732  // Upgrade to WEP if privacy flag is added.
733  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(1);
734  endpoint->PropertiesChanged(make_privacy_args(true));
735  Mock::VerifyAndClearExpectations(wifi().get());
736  EXPECT_EQ(kSecurityWep, endpoint->security_mode());
737
738  // Make sure we don't downgrade if no interesting arguments arrive.
739  KeyValueStore no_changed_properties;
740  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(0);
741  endpoint->PropertiesChanged(no_changed_properties);
742  Mock::VerifyAndClearExpectations(wifi().get());
743  EXPECT_EQ(kSecurityWep, endpoint->security_mode());
744
745  // Another upgrade to 802.1x.
746  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(1);
747  endpoint->PropertiesChanged(make_security_args("RSN", "something-eap"));
748  Mock::VerifyAndClearExpectations(wifi().get());
749  EXPECT_EQ(kSecurity8021x, endpoint->security_mode());
750
751  // Add WPA-PSK, however this is trumped by RSN 802.1x above, so we don't
752  // change our security nor do we notify anyone.
753  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(0);
754  endpoint->PropertiesChanged(make_security_args("WPA", "something-psk"));
755  Mock::VerifyAndClearExpectations(wifi().get());
756  EXPECT_EQ(kSecurity8021x, endpoint->security_mode());
757
758  // If nothing changes, we should stay the same.
759  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(0);
760  endpoint->PropertiesChanged(no_changed_properties);
761  Mock::VerifyAndClearExpectations(wifi().get());
762  EXPECT_EQ(kSecurity8021x, endpoint->security_mode());
763
764  // However, if the BSS updates to no longer support 802.1x, we degrade
765  // to WPA.
766  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(1);
767  endpoint->PropertiesChanged(make_security_args("RSN", ""));
768  Mock::VerifyAndClearExpectations(wifi().get());
769  EXPECT_EQ(kSecurityWpa, endpoint->security_mode());
770
771  // Losing WPA brings us back to WEP (since the privacy flag hasn't changed).
772  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(1);
773  endpoint->PropertiesChanged(make_security_args("WPA", ""));
774  Mock::VerifyAndClearExpectations(wifi().get());
775  EXPECT_EQ(kSecurityWep, endpoint->security_mode());
776
777  // From WEP to open security.
778  EXPECT_CALL(*wifi(), NotifyEndpointChanged(_)).Times(1);
779  endpoint->PropertiesChanged(make_privacy_args(false));
780  Mock::VerifyAndClearExpectations(wifi().get());
781  EXPECT_EQ(kSecurityNone, endpoint->security_mode());
782}
783
784TEST_F(WiFiEndpointTest, HasRsnWpaProperties) {
785  {
786    WiFiEndpointRefPtr endpoint = MakeEndpoint(
787        nullptr, wifi(), "ssid", "00:00:00:00:00:01", false, false);
788    EXPECT_FALSE(endpoint->has_wpa_property());
789    EXPECT_FALSE(endpoint->has_rsn_property());
790  }
791  {
792    WiFiEndpointRefPtr endpoint =
793        MakeEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01", true, false);
794    EXPECT_TRUE(endpoint->has_wpa_property());
795    EXPECT_FALSE(endpoint->has_rsn_property());
796  }
797  {
798    WiFiEndpointRefPtr endpoint =
799        MakeEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01", false, true);
800    EXPECT_FALSE(endpoint->has_wpa_property());
801    EXPECT_TRUE(endpoint->has_rsn_property());
802  }
803  {
804    // Both can be true.
805    WiFiEndpointRefPtr endpoint =
806        MakeEndpoint(nullptr, wifi(), "ssid", "00:00:00:00:00:01", true, true);
807    EXPECT_TRUE(endpoint->has_wpa_property());
808    EXPECT_TRUE(endpoint->has_rsn_property());
809  }
810}
811
812TEST_F(WiFiEndpointTest, HasTetheringSignature) {
813  {
814    WiFiEndpointRefPtr endpoint = MakeEndpoint(
815        nullptr, wifi(), "ssid", "02:1a:11:00:00:01", false, false);
816    EXPECT_TRUE(endpoint->has_tethering_signature());
817  }
818  {
819    WiFiEndpointRefPtr endpoint = MakeEndpoint(
820        nullptr, wifi(), "ssid", "02:1a:10:00:00:01", false, false);
821    EXPECT_FALSE(endpoint->has_tethering_signature());
822    endpoint->vendor_information_.oui_set.insert(Tethering::kIosOui);
823    endpoint->CheckForTetheringSignature();
824    EXPECT_TRUE(endpoint->has_tethering_signature());
825  }
826  {
827    WiFiEndpointRefPtr endpoint = MakeEndpoint(
828        nullptr, wifi(), "ssid", "04:1a:10:00:00:01", false, false);
829    EXPECT_FALSE(endpoint->has_tethering_signature());
830    endpoint->vendor_information_.oui_set.insert(Tethering::kIosOui);
831    endpoint->CheckForTetheringSignature();
832    EXPECT_FALSE(endpoint->has_tethering_signature());
833  }
834}
835
836}  // namespace shill
837