diff options
author | quiche <quiche@chromium.org> | 2015-01-09 17:21:47 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-10 01:22:45 +0000 |
commit | 80674e39108f7c132716a5c8c9a9056ec4716d1e (patch) | |
tree | 355a8fc977cabb66d619376f31cf62fa59b30219 /components/wifi_sync | |
parent | 8c03af4290db10990cb4a0bb37cd2dbd4ea41605 (diff) | |
download | chromium_src-80674e39108f7c132716a5c8c9a9056ec4716d1e.zip chromium_src-80674e39108f7c132716a5c8c9a9056ec4716d1e.tar.gz chromium_src-80674e39108f7c132716a5c8c9a9056ec4716d1e.tar.bz2 |
wifi_sync: add ability to convert WifiCredential to onc properties
There will be a couple of places where we need to convert from
a WifiCredential, to a DictionaryValue of ONC properties. So let's
put the conversion code someplace where it can be re-used.
The two places we'll need to convert a WifiCredential to ONC
properties will be WifiConfigDelegate and sync integration tests.
Both will need ONC properties to create a network in the
platform-specific network configuration for ChromeOS.
BUG=chromium:431435
TEST=components_unittests --gtest_filter="Wifi*"
Review URL: https://codereview.chromium.org/809803005
Cr-Commit-Position: refs/heads/master@{#310930}
Diffstat (limited to 'components/wifi_sync')
-rw-r--r-- | components/wifi_sync/BUILD.gn | 1 | ||||
-rw-r--r-- | components/wifi_sync/network_state_helper_chromeos.cc | 10 | ||||
-rw-r--r-- | components/wifi_sync/wifi_credential.cc | 80 | ||||
-rw-r--r-- | components/wifi_sync/wifi_credential.h | 44 | ||||
-rw-r--r-- | components/wifi_sync/wifi_credential_unittest.cc | 140 |
5 files changed, 256 insertions, 19 deletions
diff --git a/components/wifi_sync/BUILD.gn b/components/wifi_sync/BUILD.gn index 38626ba..9ca41db 100644 --- a/components/wifi_sync/BUILD.gn +++ b/components/wifi_sync/BUILD.gn @@ -34,6 +34,7 @@ source_set("unit_tests") { ] sources = [ + "wifi_credential_unittest.cc", "wifi_security_class_chromeos_unittest.cc", "wifi_security_class_unittest.cc", ] diff --git a/components/wifi_sync/network_state_helper_chromeos.cc b/components/wifi_sync/network_state_helper_chromeos.cc index 5cf6f18..f7afa73 100644 --- a/components/wifi_sync/network_state_helper_chromeos.cc +++ b/components/wifi_sync/network_state_helper_chromeos.cc @@ -33,11 +33,15 @@ WifiCredential::CredentialSet GetWifiCredentialsForShillProfile( // TODO(quiche): Fill in the actual passphrase via an asynchronous // call to a chromeos::NetworkConfigurationHandler instance's // GetProperties method. - credentials.insert( - WifiCredential( + scoped_ptr<WifiCredential> credential = + WifiCredential::Create( network->raw_ssid(), WifiSecurityClassFromShillSecurity(network->security_class()), - "" /* empty passphrase */)); + "" /* empty passphrase */); + if (!credential) + LOG(ERROR) << "Failed to create credential"; + else + credentials.insert(*credential); } return credentials; } diff --git a/components/wifi_sync/wifi_credential.cc b/components/wifi_sync/wifi_credential.cc index 73fbaf2..490cd7b 100644 --- a/components/wifi_sync/wifi_credential.cc +++ b/components/wifi_sync/wifi_credential.cc @@ -4,25 +4,68 @@ #include "components/wifi_sync/wifi_credential.h" -#include <limits> -#include <string> - +#include "base/i18n/streaming_utf8_validator.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" +#include "base/values.h" +#include "components/onc/onc_constants.h" namespace wifi_sync { -WifiCredential::WifiCredential( - const std::vector<unsigned char>& ssid, +WifiCredential::~WifiCredential() { +} + +// static +scoped_ptr<WifiCredential> WifiCredential::Create( + const SsidBytes& ssid, WifiSecurityClass security_class, - const std::string& passphrase) - : ssid_(ssid), - security_class_(security_class), - passphrase_(passphrase) { + const std::string& passphrase) { + if (security_class == SECURITY_CLASS_INVALID) { + LOG(ERROR) << "SecurityClass is invalid."; + return nullptr; + } + + if (!base::StreamingUtf8Validator::Validate(passphrase)) { + LOG(ERROR) << "Passphrase is not valid UTF-8"; + return nullptr; + } + + return make_scoped_ptr(new WifiCredential(ssid, security_class, passphrase)); } -WifiCredential::~WifiCredential() { +scoped_ptr<base::DictionaryValue> WifiCredential::ToOncProperties() const { + const std::string ssid_utf8(ssid().begin(), ssid().end()); + // TODO(quiche): Remove this test, once ONC suports non-UTF-8 SSIDs. + // crbug.com/432546. + if (!base::StreamingUtf8Validator::Validate(ssid_utf8)) { + LOG(ERROR) << "SSID is not valid UTF-8"; + return nullptr; + } + + std::string onc_security; + if (!WifiSecurityClassToOncSecurityString(security_class(), &onc_security)) { + NOTREACHED() << "Failed to convert SecurityClass with value " + << security_class(); + return make_scoped_ptr(new base::DictionaryValue()); + } + + scoped_ptr<base::DictionaryValue> onc_properties( + new base::DictionaryValue()); + onc_properties->Set(onc::toplevel_config::kType, + new base::StringValue(onc::network_type::kWiFi)); + // TODO(quiche): Switch to the HexSSID property, once ONC fully supports it. + // crbug.com/432546. + onc_properties->Set(onc::network_config::WifiProperty(onc::wifi::kSSID), + new base::StringValue(ssid_utf8)); + onc_properties->Set(onc::network_config::WifiProperty(onc::wifi::kSecurity), + new base::StringValue(onc_security)); + if (WifiSecurityClassSupportsPassphrases(security_class())) { + onc_properties->Set( + onc::network_config::WifiProperty(onc::wifi::kPassphrase), + new base::StringValue(passphrase())); + } + return onc_properties; } std::string WifiCredential::ToString() const { @@ -45,4 +88,21 @@ WifiCredential::CredentialSet WifiCredential::MakeSet() { return CredentialSet(WifiCredential::IsLessThan); } +// static +WifiCredential::SsidBytes WifiCredential::MakeSsidBytesForTest( + const std::string& ssid) { + return SsidBytes(ssid.begin(), ssid.end()); +} + +// Private methods. + +WifiCredential::WifiCredential( + const std::vector<unsigned char>& ssid, + WifiSecurityClass security_class, + const std::string& passphrase) + : ssid_(ssid), + security_class_(security_class), + passphrase_(passphrase) { +} + } // namespace wifi_sync diff --git a/components/wifi_sync/wifi_credential.h b/components/wifi_sync/wifi_credential.h index 7c0342a..da36426 100644 --- a/components/wifi_sync/wifi_credential.h +++ b/components/wifi_sync/wifi_credential.h @@ -11,31 +11,52 @@ #include <string> #include <vector> +#include "base/memory/scoped_ptr.h" #include "components/wifi_sync/wifi_security_class.h" +namespace base { +class DictionaryValue; +} + namespace wifi_sync { // A container to hold the information required to locate and connect // to a WiFi network. class WifiCredential final { // final because the class is copyable public: + // Per IEEE 802.11-2012 (Sec 8.4.2.2), the only requirement on SSIDs + // is that they are between 0 and 32 bytes in length + // (inclusive). There are no restrictions on the values of those + // bytes. The SSID is not, e.g., required to be encoded as UTF-8. using SsidBytes = std::vector<uint8_t>; using CredentialSet = std::set< WifiCredential, bool(*)(const WifiCredential&a, const WifiCredential& b)>; - // Constructs a credential with the given |ssid|, |security_class|, - // and |passphrase|. No assumptions are made about the input - // encoding of |ssid|. The passphrase must be valid UTF-8. - WifiCredential(const SsidBytes& ssid, - WifiSecurityClass security_class, - const std::string& passphrase); ~WifiCredential(); + // Creates a WifiCredential with the given |ssid|, |security_class|, + // and |passphrase|. No assumptions are made about the input + // encoding of |ssid|. |passphrase|, however, must be valid + // UTF-8. Returns NULL if the parameters are invalid. + static scoped_ptr<WifiCredential> Create( + const SsidBytes& ssid, + WifiSecurityClass security_class, + const std::string& passphrase); + const SsidBytes& ssid() const { return ssid_; } WifiSecurityClass security_class() const { return security_class_; } const std::string& passphrase() const { return passphrase_; } + // Returns a dictionary which represents this WifiCredential as ONC + // properties. The resulting dictionary can be used, e.g, to + // configure a new network using + // chromeos::NetworkConfigurationHandler::CreateConfiguration. Due + // to limitations in ONC, this operation fails if ssid() is not + // valid UTF-8. In case of failure, returns a scoped_ptr with value + // nullptr. + scoped_ptr<base::DictionaryValue> ToOncProperties() const; + // Returns a string representation of the credential, for debugging // purposes. The string will not include the credential's passphrase. std::string ToString() const; @@ -47,7 +68,18 @@ class WifiCredential final { // final because the class is copyable // ordering function plumbed in. static CredentialSet MakeSet(); + // Returns |ssid| as an SsidBytes instance. This convenience + // function simplifies some tests, which need to instantiate + // SsidBytes from string literals. + static SsidBytes MakeSsidBytesForTest(const std::string& ssid); + private: + // Constructs a credential with the given |ssid|, |security_class|, + // and |passphrase|. + WifiCredential(const SsidBytes& ssid, + WifiSecurityClass security_class, + const std::string& passphrase); + // The WiFi network's SSID. const SsidBytes ssid_; // The WiFi network's security class (e.g. WEP, PSK). diff --git a/components/wifi_sync/wifi_credential_unittest.cc b/components/wifi_sync/wifi_credential_unittest.cc new file mode 100644 index 0000000..b737217 --- /dev/null +++ b/components/wifi_sync/wifi_credential_unittest.cc @@ -0,0 +1,140 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/wifi_sync/wifi_credential.h" + +#include "base/logging.h" +#include "base/values.h" +#include "components/onc/onc_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace wifi_sync { + +namespace { + +const char kSsid[] = "fake-ssid"; +const char kSsidNonUtf8[] = "\xc0"; +const char kPassphraseWep[] = "abcde"; +const char kPassphraseWepNonUtf8[] = "\xc0\xc0\xc0\xc0\xc0"; +const char kPassphrasePsk[] = "fake-psk-passphrase"; +const char kPassphrase8021X[] = "fake-8021X-passphrase"; + +WifiCredential MakeCredential(const std::string& ssid, + WifiSecurityClass security_class, + const std::string& passphrase) { + scoped_ptr<WifiCredential> credential = + WifiCredential::Create( + WifiCredential::MakeSsidBytesForTest(ssid), + security_class, + passphrase); + CHECK(credential); + return *credential; +} + +bool TypeIsWifi(const base::DictionaryValue& onc_properties) { + std::string network_type; + EXPECT_TRUE(onc_properties.GetString( + onc::toplevel_config::kType, &network_type)); + return network_type == onc::network_type::kWiFi; +} + +std::string GetSsid(const base::DictionaryValue& onc_properties) { + std::string ssid; + EXPECT_TRUE(onc_properties.GetString( + onc::network_config::WifiProperty(onc::wifi::kSSID), &ssid)); + return ssid; +} + +std::string GetOncSecurity(const base::DictionaryValue& onc_properties) { + std::string onc_security; + EXPECT_TRUE(onc_properties.GetString( + onc::network_config::WifiProperty(onc::wifi::kSecurity), &onc_security)); + return onc_security; +} + +std::string GetPassphrase(const base::DictionaryValue& onc_properties) { + std::string passphrase; + EXPECT_TRUE(onc_properties.GetString( + onc::network_config::WifiProperty(onc::wifi::kPassphrase), &passphrase)); + return passphrase; +} + +} // namespace + +TEST(WifiCredentialTest, CreateWithSecurityClassInvalid) { + scoped_ptr<WifiCredential> credential = + WifiCredential::Create( + WifiCredential::MakeSsidBytesForTest(kSsid), + SECURITY_CLASS_INVALID, + ""); + EXPECT_FALSE(credential); +} + +TEST(WifiCredentialTest, CreateWithPassphraseNonUtf8) { + scoped_ptr<WifiCredential> credential = + WifiCredential::Create( + WifiCredential::MakeSsidBytesForTest(kSsid), + SECURITY_CLASS_WEP, + kPassphraseWepNonUtf8); + EXPECT_FALSE(credential); +} + +TEST(WifiCredentialTest, ToOncPropertiesSecurityNone) { + const WifiCredential credential( + MakeCredential(kSsid, SECURITY_CLASS_NONE, "")); + scoped_ptr<base::DictionaryValue> onc_properties = + credential.ToOncProperties(); + ASSERT_TRUE(onc_properties); + EXPECT_TRUE(TypeIsWifi(*onc_properties)); + EXPECT_EQ(kSsid, GetSsid(*onc_properties)); + EXPECT_EQ(onc::wifi::kSecurityNone, GetOncSecurity(*onc_properties)); +} + +TEST(WifiCredentialTest, ToOncPropertiesSecurityWep) { + const WifiCredential credential( + MakeCredential(kSsid, SECURITY_CLASS_WEP, kPassphraseWep)); + scoped_ptr<base::DictionaryValue> onc_properties = + credential.ToOncProperties(); + ASSERT_TRUE(onc_properties); + EXPECT_TRUE(TypeIsWifi(*onc_properties)); + EXPECT_EQ(kSsid, GetSsid(*onc_properties)); + EXPECT_EQ(onc::wifi::kWEP_PSK, GetOncSecurity(*onc_properties)); + EXPECT_EQ(kPassphraseWep, GetPassphrase(*onc_properties)); +} + +TEST(WifiCredentialTest, ToOncPropertiesSecurityPsk) { + const WifiCredential credential( + MakeCredential(kSsid, SECURITY_CLASS_PSK, kPassphrasePsk)); + scoped_ptr<base::DictionaryValue> onc_properties = + credential.ToOncProperties(); + ASSERT_TRUE(onc_properties); + EXPECT_TRUE(TypeIsWifi(*onc_properties)); + EXPECT_EQ(kSsid, GetSsid(*onc_properties)); + EXPECT_EQ(onc::wifi::kWPA_PSK, GetOncSecurity(*onc_properties)); + EXPECT_EQ(kPassphrasePsk, GetPassphrase(*onc_properties)); +} + +TEST(WifiCredentialTest, ToOncPropertiesSecurity8021X) { + const WifiCredential credential( + MakeCredential(kSsid, SECURITY_CLASS_802_1X, kPassphrase8021X)); + scoped_ptr<base::DictionaryValue> onc_properties = + credential.ToOncProperties(); + ASSERT_TRUE(onc_properties); + EXPECT_TRUE(TypeIsWifi(*onc_properties)); + EXPECT_EQ(kSsid, GetSsid(*onc_properties)); + EXPECT_EQ(onc::wifi::kWPA_EAP, GetOncSecurity(*onc_properties)); + EXPECT_EQ(kPassphrase8021X, GetPassphrase(*onc_properties)); +} + +// TODO(quiche): Update this test, once ONC suports non-UTF-8 SSIDs. +// crbug.com/432546. +TEST(WifiCredentialTest, ToOncPropertiesSsidNonUtf8) { + const WifiCredential credential( + MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, "")); + scoped_ptr<base::DictionaryValue> onc_properties = + credential.ToOncProperties(); + EXPECT_FALSE(onc_properties); +} + +} // namespace wifi_sync |