Home | History | Annotate | Download | only in wifi
      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:
     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 
    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 
    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 
    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 
    254 TEST_F(WiFiEndpointTest, ParseSecurityRSN802_1x) {
    255   EXPECT_STREQ(kSecurity8021x,
    256                ParseSecurity(make_security_args("RSN", "something-eap")));
    257 }
    258 
    259 TEST_F(WiFiEndpointTest, ParseSecurityWPA802_1x) {
    260   EXPECT_STREQ(kSecurity8021x,
    261                ParseSecurity(make_security_args("WPA", "something-eap")));
    262 }
    263 
    264 TEST_F(WiFiEndpointTest, ParseSecurityRSNPSK) {
    265   EXPECT_STREQ(kSecurityRsn,
    266                ParseSecurity(make_security_args("RSN", "something-psk")));
    267 }
    268 
    269 TEST_F(WiFiEndpointTest, ParseSecurityWPAPSK) {
    270   EXPECT_STREQ(kSecurityWpa,
    271                ParseSecurity(make_security_args("WPA", "something-psk")));
    272 }
    273 
    274 TEST_F(WiFiEndpointTest, ParseSecurityWEP) {
    275   EXPECT_STREQ(kSecurityWep, ParseSecurity(make_privacy_args(true)));
    276 }
    277 
    278 TEST_F(WiFiEndpointTest, ParseSecurityNone) {
    279   KeyValueStore top_params;
    280   EXPECT_STREQ(kSecurityNone, ParseSecurity(top_params));
    281 }
    282 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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