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 
41 using std::map;
42 using std::set;
43 using std::string;
44 using std::vector;
45 using ::testing::_;
46 using ::testing::HasSubstr;
47 using ::testing::Mock;
48 using ::testing::NiceMock;
49 
50 namespace shill {
51 
52 class WiFiEndpointTest : public PropertyStoreTest {
53  public:
WiFiEndpointTest()54   WiFiEndpointTest() : wifi_(
55       new NiceMock<MockWiFi>(
56           control_interface(),
57           dispatcher(),
58           metrics(),
59           manager(),
60           "wifi",
61           "aabbccddeeff",  // fake mac
62           0)) {}
~WiFiEndpointTest()63   virtual ~WiFiEndpointTest() {}
64 
65  protected:
make_string_vector1(const string & str1)66   vector<string> make_string_vector1(const string& str1) {
67     vector<string> strvec;
68     strvec.push_back(str1);
69     return strvec;
70   }
71 
make_string_vector2(const string & str1,const string & str2)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 
make_key_management_args(vector<string> key_management_method_strings)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 
make_privacy_args(bool is_private)87   KeyValueStore make_privacy_args(bool is_private) {
88     KeyValueStore props;
89     props.SetBool(WPASupplicant::kPropertyPrivacy, is_private);
90     return props;
91   }
92 
make_security_args(const string & security_protocol,const string & key_management_method)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 
ParseSecurity(const KeyValueStore & properties)107   const char* ParseSecurity(
108     const KeyValueStore& properties) {
109     WiFiEndpoint::SecurityFlags security_flags;
110     return WiFiEndpoint::ParseSecurity(properties, &security_flags);
111   }
112 
AddIEWithData(uint8_t type,vector<uint8_t> data,vector<uint8_t> * ies)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 
AddIE(uint8_t type,vector<uint8_t> * ies)119   void AddIE(uint8_t type, vector<uint8_t>* ies) {
120     AddIEWithData(type, vector<uint8_t>(1), ies);
121   }
122 
AddVendorIE(uint32_t oui,uint8_t vendor_type,const vector<uint8_t> & data,vector<uint8_t> * ies)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 
AddWPSElement(uint16_t type,const string & value,vector<uint8_t> * wps)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 
MakeBSSPropertiesWithIEs(const vector<uint8_t> & ies)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).
MakeRSNProperties(uint16_t pairwise_count,uint16_t authkey_count,uint16_t capabilities)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 
ParseIEs(const KeyValueStore & properties,Metrics::WiFiNetworkPhyMode * phy_mode,WiFiEndpoint::VendorInformation * vendor_information,bool * ieee80211w_required,std::string * country_code)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 
SetVendorInformation(const WiFiEndpointRefPtr & endpoint,const WiFiEndpoint::VendorInformation & vendor_information)187   void SetVendorInformation(
188       const WiFiEndpointRefPtr& endpoint,
189       const WiFiEndpoint::VendorInformation& vendor_information) {
190     endpoint->vendor_information_ = vendor_information;
191   }
192 
MakeEndpoint(ControlInterface * control_interface,const WiFiRefPtr & wifi,const std::string & ssid,const std::string & bssid,bool has_wpa_property,bool has_rsn_property)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 
MakeOpenEndpoint(ControlInterface * control_interface,const WiFiRefPtr & wifi,const std::string & ssid,const std::string & bssid)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 
wifi()214   scoped_refptr<MockWiFi> wifi() { return wifi_; }
215 
216  private:
217   scoped_refptr<MockWiFi> wifi_;
218 };
219 
TEST_F(WiFiEndpointTest,ParseKeyManagementMethodsEAP)220 TEST_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 
TEST_F(WiFiEndpointTest,ParseKeyManagementMethodsPSK)231 TEST_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 
TEST_F(WiFiEndpointTest,ParseKeyManagementMethodsEAPAndPSK)242 TEST_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 
TEST_F(WiFiEndpointTest,ParseSecurityRSN802_1x)254 TEST_F(WiFiEndpointTest, ParseSecurityRSN802_1x) {
255   EXPECT_STREQ(kSecurity8021x,
256                ParseSecurity(make_security_args("RSN", "something-eap")));
257 }
258 
TEST_F(WiFiEndpointTest,ParseSecurityWPA802_1x)259 TEST_F(WiFiEndpointTest, ParseSecurityWPA802_1x) {
260   EXPECT_STREQ(kSecurity8021x,
261                ParseSecurity(make_security_args("WPA", "something-eap")));
262 }
263 
TEST_F(WiFiEndpointTest,ParseSecurityRSNPSK)264 TEST_F(WiFiEndpointTest, ParseSecurityRSNPSK) {
265   EXPECT_STREQ(kSecurityRsn,
266                ParseSecurity(make_security_args("RSN", "something-psk")));
267 }
268 
TEST_F(WiFiEndpointTest,ParseSecurityWPAPSK)269 TEST_F(WiFiEndpointTest, ParseSecurityWPAPSK) {
270   EXPECT_STREQ(kSecurityWpa,
271                ParseSecurity(make_security_args("WPA", "something-psk")));
272 }
273 
TEST_F(WiFiEndpointTest,ParseSecurityWEP)274 TEST_F(WiFiEndpointTest, ParseSecurityWEP) {
275   EXPECT_STREQ(kSecurityWep, ParseSecurity(make_privacy_args(true)));
276 }
277 
TEST_F(WiFiEndpointTest,ParseSecurityNone)278 TEST_F(WiFiEndpointTest, ParseSecurityNone) {
279   KeyValueStore top_params;
280   EXPECT_STREQ(kSecurityNone, ParseSecurity(top_params));
281 }
282 
TEST_F(WiFiEndpointTest,SSIDAndBSSIDString)283 TEST_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 
TEST_F(WiFiEndpointTest,SSIDWithNull)296 TEST_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 
TEST_F(WiFiEndpointTest,DeterminePhyModeFromFrequency)302 TEST_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 
TEST_F(WiFiEndpointTest,ParseIEs)331 TEST_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 
TEST_F(WiFiEndpointTest,ParseVendorIEs)408 TEST_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 
TEST_F(WiFiEndpointTest,ParseWPACapabilities)542 TEST_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 
TEST_F(WiFiEndpointTest,ParseCountryCode)637 TEST_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 
TEST_F(WiFiEndpointTest,PropertiesChangedNone)688 TEST_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 
TEST_F(WiFiEndpointTest,PropertiesChangedStrength)700 TEST_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 
TEST_F(WiFiEndpointTest,PropertiesChangedNetworkMode)715 TEST_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 
TEST_F(WiFiEndpointTest,PropertiesChangedSecurityMode)727 TEST_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 
TEST_F(WiFiEndpointTest,HasRsnWpaProperties)784 TEST_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 
TEST_F(WiFiEndpointTest,HasTetheringSignature)812 TEST_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