Index: chromeos/network/onc/onc_utils.cc |
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc |
index c14a2a08990a080e540c79aecce03616303f39fa..1b31c9d96713997201289d4797273c2b7c0e0b3c 100644 |
--- a/chromeos/network/onc/onc_utils.cc |
+++ b/chromeos/network/onc/onc_utils.cc |
@@ -7,11 +7,14 @@ |
#include "base/base64.h" |
#include "base/json/json_reader.h" |
#include "base/logging.h" |
+#include "base/metrics/histogram.h" |
#include "base/string_util.h" |
#include "base/values.h" |
#include "chromeos/network/network_event_log.h" |
#include "chromeos/network/onc/onc_mapper.h" |
#include "chromeos/network/onc/onc_signature.h" |
+#include "chromeos/network/onc/onc_utils.h" |
+#include "chromeos/network/onc/onc_validator.h" |
#include "crypto/encryptor.h" |
#include "crypto/hmac.h" |
#include "crypto/symmetric_key.h" |
@@ -211,6 +214,8 @@ void ExpandStringsInOncObject( |
const OncFieldSignature* field_signature = |
GetFieldSignature(signature, it.key()); |
+ if (!field_signature) |
+ continue; |
ExpandStringsInOncObject(*field_signature->value_signature, |
substitution, inner_object); |
@@ -255,12 +260,93 @@ class OncMaskValues : public onc::Mapper { |
} // namespace |
-CHROMEOS_EXPORT scoped_ptr<base::DictionaryValue> MaskCredentialsInOncObject( |
+scoped_ptr<base::DictionaryValue> MaskCredentialsInOncObject( |
const onc::OncValueSignature& signature, |
const base::DictionaryValue& onc_object, |
const std::string& mask) { |
return OncMaskValues::Mask(signature, onc_object, mask); |
} |
+bool ParseAndValidateOncForImport( |
+ const std::string& onc_blob, |
+ chromeos::onc::ONCSource onc_source, |
+ const std::string& passphrase, |
+ base::ListValue* network_configs, |
+ base::ListValue* certificates) { |
+ certificates->Clear(); |
+ network_configs->Clear(); |
+ if (onc_blob.empty()) |
+ return true; |
+ |
+ scoped_ptr<base::DictionaryValue> toplevel_onc = |
+ onc::ReadDictionaryFromJson(onc_blob); |
+ if (toplevel_onc.get() == NULL) { |
+ LOG(ERROR) << "ONC loaded from " << onc::GetSourceAsString(onc_source) |
+ << " is not a valid JSON dictionary."; |
+ return false; |
+ } |
+ |
+ // Check and see if this is an encrypted ONC file. If so, decrypt it. |
+ std::string onc_type; |
+ toplevel_onc->GetStringWithoutPathExpansion(onc::toplevel_config::kType, |
+ &onc_type); |
+ if (onc_type == onc::toplevel_config::kEncryptedConfiguration) { |
+ toplevel_onc = onc::Decrypt(passphrase, *toplevel_onc); |
+ if (toplevel_onc.get() == NULL) { |
+ LOG(ERROR) << "Couldn't decrypt the ONC from " |
+ << onc::GetSourceAsString(onc_source); |
+ return false; |
+ } |
+ } |
+ |
+ bool from_policy = (onc_source == onc::ONC_SOURCE_USER_POLICY || |
+ onc_source == onc::ONC_SOURCE_DEVICE_POLICY); |
+ |
+ // Validate the ONC dictionary. We are liberal and ignore unknown field |
+ // names and ignore invalid field names in kRecommended arrays. |
+ onc::Validator validator(false, // Ignore unknown fields. |
+ false, // Ignore invalid recommended field names. |
+ true, // Fail on missing fields. |
+ from_policy); |
+ validator.SetOncSource(onc_source); |
+ |
+ onc::Validator::Result validation_result; |
+ toplevel_onc = validator.ValidateAndRepairObject( |
+ &onc::kToplevelConfigurationSignature, |
+ *toplevel_onc, |
+ &validation_result); |
+ |
+ if (from_policy) { |
+ UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", |
+ validation_result == onc::Validator::VALID); |
+ } |
+ |
+ bool success = true; |
+ if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { |
+ LOG(WARNING) << "ONC from " << onc::GetSourceAsString(onc_source) |
+ << " produced warnings."; |
+ success = false; |
+ } else if (validation_result == onc::Validator::INVALID || |
+ toplevel_onc == NULL) { |
+ LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) |
+ << " is invalid and couldn't be repaired."; |
+ return false; |
+ } |
+ |
+ base::ListValue* validated_certs = NULL; |
+ if (toplevel_onc->GetListWithoutPathExpansion( |
+ onc::toplevel_config::kCertificates, &validated_certs)) { |
+ certificates->Swap(validated_certs); |
+ } |
+ |
+ base::ListValue* validated_networks = NULL; |
+ if (toplevel_onc->GetListWithoutPathExpansion( |
+ onc::toplevel_config::kNetworkConfigurations, &validated_networks)) { |
+ network_configs->Swap(validated_networks); |
+ } |
+ |
+ return success; |
+} |
+ |
} // namespace onc |
} // namespace chromeos |