diff options
Diffstat (limited to 'chromeos/network/onc')
-rw-r--r-- | chromeos/network/onc/onc_normalizer.cc | 2 | ||||
-rw-r--r-- | chromeos/network/onc/onc_normalizer.h | 5 | ||||
-rw-r--r-- | chromeos/network/onc/onc_normalizer_unittest.cc | 18 | ||||
-rw-r--r-- | chromeos/network/onc/onc_signature.cc | 1 | ||||
-rw-r--r-- | chromeos/network/onc/onc_utils.cc | 37 | ||||
-rw-r--r-- | chromeos/network/onc/onc_utils.h | 11 | ||||
-rw-r--r-- | chromeos/network/onc/onc_validator.cc | 64 | ||||
-rw-r--r-- | chromeos/network/onc/onc_validator.h | 2 | ||||
-rw-r--r-- | chromeos/network/onc/onc_validator_unittest.cc | 18 |
9 files changed, 154 insertions, 4 deletions
diff --git a/chromeos/network/onc/onc_normalizer.cc b/chromeos/network/onc/onc_normalizer.cc index f93882f..abe93e0 100644 --- a/chromeos/network/onc/onc_normalizer.cc +++ b/chromeos/network/onc/onc_normalizer.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/values.h" #include "chromeos/network/onc/onc_signature.h" +#include "chromeos/network/onc/onc_utils.h" #include "components/onc/onc_constants.h" namespace chromeos { @@ -232,6 +233,7 @@ void Normalizer::NormalizeWiFi(base::DictionaryValue* wifi) { RemoveEntryUnless(wifi, kEAP, security == kWEP_8021X || security == kWPA_EAP); RemoveEntryUnless(wifi, kPassphrase, security == kWEP_PSK || security == kWPA_PSK); + FillInHexSSIDField(wifi); } } // namespace onc diff --git a/chromeos/network/onc/onc_normalizer.h b/chromeos/network/onc/onc_normalizer.h index 7268879..9c97d32 100644 --- a/chromeos/network/onc/onc_normalizer.h +++ b/chromeos/network/onc/onc_normalizer.h @@ -24,7 +24,10 @@ class CHROMEOS_EXPORT Normalizer : public Mapper { // type is "Ethernet". If |remove_recommended_fields| is true, kRecommended // arrays are removed (the array itself and not the field names listed // there). |object_signature| must point to one of the signatures in - // |onc_signature.h|. + // |onc_signature.h|. For configurations of type "WiFi", if the "SSID" field + // is set, but the field "HexSSID" is not, the contents of the "SSID" field is + // converted to UTF-8 encoding, a hex representation of the byte sequence is + // created and stored in the field "HexSSID". scoped_ptr<base::DictionaryValue> NormalizeObject( const OncValueSignature* object_signature, const base::DictionaryValue& onc_object); diff --git a/chromeos/network/onc/onc_normalizer_unittest.cc b/chromeos/network/onc/onc_normalizer_unittest.cc index 022f33f..bf80d42 100644 --- a/chromeos/network/onc/onc_normalizer_unittest.cc +++ b/chromeos/network/onc/onc_normalizer_unittest.cc @@ -14,7 +14,7 @@ namespace chromeos { namespace onc { // This test case is about validating valid ONC objects. -TEST(ONCNormalizerTest, NormalizeNetworkConfiguration) { +TEST(ONCNormalizerTest, NormalizeNetworkConfigurationEthernetAndVPN) { Normalizer normalizer(true); scoped_ptr<const base::DictionaryValue> data( test_utils::ReadTestDictionary("settings_with_normalization.json")); @@ -29,5 +29,21 @@ TEST(ONCNormalizerTest, NormalizeNetworkConfiguration) { EXPECT_TRUE(test_utils::Equals(expected_normalized, actual_normalized.get())); } +// This test case is about validating valid ONC objects. +TEST(ONCNormalizerTest, NormalizeNetworkConfigurationWifi) { + Normalizer normalizer(true); + scoped_ptr<const base::DictionaryValue> data( + test_utils::ReadTestDictionary("settings_with_normalization.json")); + + const base::DictionaryValue* original = NULL; + const base::DictionaryValue* expected_normalized = NULL; + data->GetDictionary("wifi", &original); + data->GetDictionary("wifi-normalized", &expected_normalized); + + scoped_ptr<base::DictionaryValue> actual_normalized = + normalizer.NormalizeObject(&kNetworkConfigurationSignature, *original); + EXPECT_TRUE(test_utils::Equals(expected_normalized, actual_normalized.get())); +} + } // namespace onc } // namespace chromeos diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc index b6b7a2e..2bd48ea 100644 --- a/chromeos/network/onc/onc_signature.cc +++ b/chromeos/network/onc/onc_signature.cc @@ -206,6 +206,7 @@ const OncFieldSignature wifi_fields[] = { { ::onc::wifi::kAllowGatewayARPPolling, &kBoolSignature}, { ::onc::wifi::kAutoConnect, &kBoolSignature}, { ::onc::wifi::kEAP, &kEAPSignature}, + { ::onc::wifi::kHexSSID, &kStringSignature}, { ::onc::wifi::kHiddenSSID, &kBoolSignature}, { ::onc::wifi::kPassphrase, &kStringSignature}, { ::onc::wifi::kSSID, &kStringSignature}, diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc index fdff42d..7b544cf 100644 --- a/chromeos/network/onc/onc_utils.cc +++ b/chromeos/network/onc/onc_utils.cc @@ -8,6 +8,7 @@ #include "base/json/json_reader.h" #include "base/logging.h" #include "base/metrics/histogram.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/values.h" #include "chromeos/network/network_event_log.h" @@ -240,6 +241,39 @@ void ExpandStringsInNetworks(const StringSubstitution& substitution, } } +void FillInHexSSIDFieldsInOncObject(const OncValueSignature& signature, + base::DictionaryValue* onc_object) { + if (&signature == &kWiFiSignature) + FillInHexSSIDField(onc_object); + + // Recurse into nested objects. + for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd(); + it.Advance()) { + base::DictionaryValue* inner_object = nullptr; + if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object)) + continue; + + const OncFieldSignature* field_signature = + GetFieldSignature(signature, it.key()); + if (!field_signature) + continue; + + FillInHexSSIDFieldsInOncObject(*field_signature->value_signature, + inner_object); + } +} + +void FillInHexSSIDField(base::DictionaryValue* wifi_fields) { + if (!wifi_fields->HasKey(::onc::wifi::kHexSSID)) { + std::string ssid_string; + wifi_fields->GetStringWithoutPathExpansion(::onc::wifi::kSSID, + &ssid_string); + wifi_fields->SetStringWithoutPathExpansion( + ::onc::wifi::kHexSSID, + base::HexEncode(ssid_string.c_str(), ssid_string.size())); + } +} + namespace { class OncMaskValues : public Mapper { @@ -398,6 +432,9 @@ bool ParseAndValidateOncForImport(const std::string& onc_blob, *toplevel_onc, &validation_result); + FillInHexSSIDFieldsInOncObject(kToplevelConfigurationSignature, + toplevel_onc.get()); + if (from_policy) { UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", validation_result == Validator::VALID); diff --git a/chromeos/network/onc/onc_utils.h b/chromeos/network/onc/onc_utils.h index c31cd2e..0e2122e 100644 --- a/chromeos/network/onc/onc_utils.h +++ b/chromeos/network/onc/onc_utils.h @@ -83,6 +83,17 @@ CHROMEOS_EXPORT void ExpandStringsInNetworks( const StringSubstitution& substitution, base::ListValue* network_configs); +// Fills in all missing HexSSID fields that are mentioned in the ONC +// specification. The object of |onc_object| is modified in place. +CHROMEOS_EXPORT void FillInHexSSIDFieldsInOncObject( + const OncValueSignature& signature, + base::DictionaryValue* onc_object); + +// If the SSID field is set, but HexSSID is not, converts the contents of the +// SSID field to UTF-8 encoding, creates the hex representation and assigns the +// result to HexSSID. +CHROMEOS_EXPORT void FillInHexSSIDField(base::DictionaryValue* wifi_fields); + // Creates a copy of |onc_object| with all values of sensitive fields replaced // by |mask|. To find sensitive fields, signature and field name are checked // with the function FieldIsCredential(). diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc index d84d255..fd55b29 100644 --- a/chromeos/network/onc/onc_validator.cc +++ b/chromeos/network/onc/onc_validator.cc @@ -20,6 +20,9 @@ namespace onc { namespace { +// According to the IEEE 802.11 standard the SSID is a series of 0 to 32 octets. +const int kMaximumSSIDLengthInBytes = 32; + template <typename T, size_t N> std::vector<T> toVector(T const (&array)[N]) { return std::vector<T>(array, array + N); @@ -396,6 +399,54 @@ bool Validator::FieldExistsAndIsEmpty(const base::DictionaryValue& object, return true; } +bool Validator::IsSSIDOrHexSSIDValid(const base::DictionaryValue& object) { + // Check SSID validity. + std::string ssid_string; + if (object.GetStringWithoutPathExpansion(::onc::wifi::kSSID, &ssid_string)) { + if (ssid_string.size() <= 0 || + ssid_string.size() > kMaximumSSIDLengthInBytes) { + LOG(ERROR) << MessageHeader() << ::onc::wifi::kSSID + << " has an invalid length."; + error_or_warning_found_ = true; + return false; + } + } + + // Check HexSSID validity. + std::string hex_ssid_string; + if (object.GetStringWithoutPathExpansion(::onc::wifi::kHexSSID, + &hex_ssid_string)) { + std::vector<uint8> bytes; + if (!base::HexStringToBytes(hex_ssid_string, &bytes)) { + LOG(ERROR) << MessageHeader() << "Field " << ::onc::wifi::kHexSSID + << " is not a valid hex representation: \"" << hex_ssid_string + << "\""; + error_or_warning_found_ = true; + return false; + } + if (bytes.size() <= 0 || bytes.size() > kMaximumSSIDLengthInBytes) { + LOG(ERROR) << MessageHeader() << ::onc::wifi::kHexSSID + << " has an invalid length."; + error_or_warning_found_ = true; + return false; + } + } + // If both SSID and HexSSID are set, ensure that they are consistent. + if (ssid_string.length() > 0 && hex_ssid_string.length() > 0) { + std::string hexified = + base::HexEncode(ssid_string.c_str(), ssid_string.size()); + if (hexified != hex_ssid_string) { + LOG(ERROR) << MessageHeader() << "Fields " << ::onc::wifi::kSSID + << " and " << ::onc::wifi::kHexSSID + << " contain inconsistent values."; + error_or_warning_found_ = true; + return false; + } + } + + return true; +} + bool Validator::RequireField(const base::DictionaryValue& dict, const std::string& field_name) { if (dict.HasKey(field_name)) @@ -572,8 +623,17 @@ bool Validator::ValidateWiFi(base::DictionaryValue* result) { if (FieldExistsAndHasNoValidValue(*result, kSecurity, valid_securities)) return false; - bool all_required_exist = - RequireField(*result, kSecurity) && RequireField(*result, kSSID); + // Validate SSID and HexSSID fields, if present. + if (!IsSSIDOrHexSSIDValid(*result)) + return false; + + bool all_required_exist = RequireField(*result, kSecurity); + + // One of {kSSID, kHexSSID} must be present. + if (!result->HasKey(kSSID)) + all_required_exist &= RequireField(*result, kHexSSID); + if (!result->HasKey(kHexSSID)) + all_required_exist &= RequireField(*result, kSSID); std::string security; result->GetStringWithoutPathExpansion(kSecurity, &security); diff --git a/chromeos/network/onc/onc_validator.h b/chromeos/network/onc/onc_validator.h index 0fb60eb..857f31e 100644 --- a/chromeos/network/onc/onc_validator.h +++ b/chromeos/network/onc/onc_validator.h @@ -182,6 +182,8 @@ class CHROMEOS_EXPORT Validator : public Mapper { bool FieldExistsAndIsEmpty(const base::DictionaryValue& object, const std::string& field_name); + bool IsSSIDOrHexSSIDValid(const base::DictionaryValue& object); + // Returns true if |key| is a key of |dict|. Otherwise, returns false and, // depending on |error_on_missing_field_|, logs a message and sets // |error_or_warning_found_|. diff --git a/chromeos/network/onc/onc_validator_unittest.cc b/chromeos/network/onc/onc_validator_unittest.cc index c109ddc..4daa6a6 100644 --- a/chromeos/network/onc/onc_validator_unittest.cc +++ b/chromeos/network/onc/onc_validator_unittest.cc @@ -152,6 +152,12 @@ INSTANTIATE_TEST_CASE_P( OncParams("managed_toplevel_l2tpipsec.onc", &kToplevelConfigurationSignature, true), + OncParams("toplevel_wifi_hexssid.onc", + &kToplevelConfigurationSignature, + false), + OncParams("toplevel_wifi_ssid_and_hexssid.onc", + &kToplevelConfigurationSignature, + false), OncParams("toplevel_wifi_wpa_psk.onc", &kToplevelConfigurationSignature, false), @@ -449,6 +455,18 @@ INSTANTIATE_TEST_CASE_P( &kNetworkConfigurationSignature, false), ExpectBothNotValid("", "")), + std::make_pair(OncParams("network-wifi-hexssid-invalid-length", + &kNetworkConfigurationSignature, + false), + ExpectBothNotValid("", "")), + std::make_pair(OncParams("network-wifi-invalid-hexssid", + &kNetworkConfigurationSignature, + false), + ExpectBothNotValid("", "")), + std::make_pair(OncParams("network-wifi-ssid-and-hexssid-inconsistent", + &kNetworkConfigurationSignature, + false), + ExpectBothNotValid("", "")), std::make_pair(OncParams("managed-network-unknown-value", &kNetworkConfigurationSignature, true), |