summaryrefslogtreecommitdiffstats
path: root/chromeos/network/onc
diff options
context:
space:
mode:
Diffstat (limited to 'chromeos/network/onc')
-rw-r--r--chromeos/network/onc/onc_normalizer.cc2
-rw-r--r--chromeos/network/onc/onc_normalizer.h5
-rw-r--r--chromeos/network/onc/onc_normalizer_unittest.cc18
-rw-r--r--chromeos/network/onc/onc_signature.cc1
-rw-r--r--chromeos/network/onc/onc_utils.cc37
-rw-r--r--chromeos/network/onc/onc_utils.h11
-rw-r--r--chromeos/network/onc/onc_validator.cc64
-rw-r--r--chromeos/network/onc/onc_validator.h2
-rw-r--r--chromeos/network/onc/onc_validator_unittest.cc18
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),