diff options
author | pneubeck@google.com <pneubeck@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-26 15:02:51 +0000 |
---|---|---|
committer | pneubeck@google.com <pneubeck@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-26 15:02:51 +0000 |
commit | 7d7f2bb88febe255663805c93e16adba63e468d8 (patch) | |
tree | 052d719ae0d5eb34a95e844c63a0ec49e0806616 /chromeos | |
parent | 3103670a5994d88e64b84f56808f904b034b0546 (diff) | |
download | chromium_src-7d7f2bb88febe255663805c93e16adba63e468d8.zip chromium_src-7d7f2bb88febe255663805c93e16adba63e468d8.tar.gz chromium_src-7d7f2bb88febe255663805c93e16adba63e468d8.tar.bz2 |
Extract certificate policy application from NetworkLibrary.
This is mostly a refactoring:
- Import of certificates is handled by a new CertifcateHandler, which will get more functionality like resolving CertificatePatterns in upcoming commits.
- Policy validation moved into NetworkConfigurationUpdater and net_internals, because it covers both certificates and networks.
The only functional change is that certificate policies should now also work if ManagedNetworkConfigurationHandler is used instead of NetworkLibrary.
BUG=223869
Review URL: https://codereview.chromium.org/14192017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196735 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r-- | chromeos/chromeos.gyp | 20 | ||||
-rw-r--r-- | chromeos/network/certificate_handler.cc | 38 | ||||
-rw-r--r-- | chromeos/network/certificate_handler.h | 38 | ||||
-rw-r--r-- | chromeos/network/managed_network_configuration_handler.cc | 78 | ||||
-rw-r--r-- | chromeos/network/managed_network_configuration_handler.h | 8 | ||||
-rw-r--r-- | chromeos/network/managed_network_configuration_handler_unittest.cc | 6 | ||||
-rw-r--r-- | chromeos/network/mock_certificate_handler.cc | 15 | ||||
-rw-r--r-- | chromeos/network/mock_certificate_handler.h | 28 | ||||
-rw-r--r-- | chromeos/network/onc/onc_certificate_importer_unittest.cc | 60 | ||||
-rw-r--r-- | chromeos/network/onc/onc_utils.cc | 88 | ||||
-rw-r--r-- | chromeos/network/onc/onc_utils.h | 13 | ||||
-rw-r--r-- | chromeos/network/onc/onc_validator_unittest.cc | 7 | ||||
-rw-r--r-- | chromeos/test/data/network/invalid_settings_with_repairs.json | 47 | ||||
-rw-r--r-- | chromeos/test/data/network/repaired_toplevel_partially_invalid.onc | 45 |
14 files changed, 404 insertions, 87 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 3b5eb3d..4b6a7bb 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -211,6 +211,8 @@ 'ime/xkeyboard.h', 'login/login_state.cc', 'login/login_state.h', + 'network/certificate_handler.cc', + 'network/certificate_handler.h', 'network/certificate_pattern.cc', 'network/certificate_pattern.h', 'network/cros_network_functions.cc', @@ -342,6 +344,14 @@ 'dbus/mock_cryptohome_client.h', 'dbus/mock_dbus_thread_manager.cc', 'dbus/mock_dbus_thread_manager.h', + 'dbus/mock_gsm_sms_client.cc', + 'dbus/mock_gsm_sms_client.h', + 'dbus/mock_image_burner_client.cc', + 'dbus/mock_image_burner_client.h', + 'dbus/mock_power_manager_client.cc', + 'dbus/mock_power_manager_client.h', + 'dbus/mock_session_manager_client.cc', + 'dbus/mock_session_manager_client.h', 'dbus/mock_shill_device_client.cc', 'dbus/mock_shill_device_client.h', 'dbus/mock_shill_ipconfig_client.cc', @@ -352,14 +362,6 @@ 'dbus/mock_shill_profile_client.h', 'dbus/mock_shill_service_client.cc', 'dbus/mock_shill_service_client.h', - 'dbus/mock_gsm_sms_client.cc', - 'dbus/mock_gsm_sms_client.h', - 'dbus/mock_image_burner_client.cc', - 'dbus/mock_image_burner_client.h', - 'dbus/mock_power_manager_client.cc', - 'dbus/mock_power_manager_client.h', - 'dbus/mock_session_manager_client.cc', - 'dbus/mock_session_manager_client.h', 'dbus/mock_system_clock_client.cc', 'dbus/mock_system_clock_client.h', 'dbus/mock_update_engine_client.cc', @@ -370,6 +372,8 @@ 'disks/mock_disk_mount_manager.h', 'ime/mock_component_extension_ime_manager_delegate.cc', 'ime/mock_component_extension_ime_manager_delegate.h', + 'network/mock_certificate_handler.cc', + 'network/mock_certificate_handler.h', 'network/onc/onc_test_utils.cc', 'network/onc/onc_test_utils.h', ], diff --git a/chromeos/network/certificate_handler.cc b/chromeos/network/certificate_handler.cc new file mode 100644 index 0000000..d471813 --- /dev/null +++ b/chromeos/network/certificate_handler.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2013 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 "chromeos/network/certificate_handler.h" + +#include "base/values.h" +#include "chromeos/network/onc/onc_certificate_importer.h" +#include "chromeos/network/onc/onc_utils.h" + +namespace chromeos { + +CertificateHandler::CertificateHandler() { +} + +CertificateHandler::~CertificateHandler() { +} + +bool CertificateHandler::ImportCertificates( + const base::ListValue& certificates, + onc::ONCSource source, + net::CertificateList* onc_trusted_certificates) { + VLOG(2) << "ONC file has " << certificates.GetSize() << " certificates"; + + // Web trust is only granted to certificates imported by the user. + bool allow_trust_imports = source == onc::ONC_SOURCE_USER_IMPORT; + onc::CertificateImporter cert_importer(allow_trust_imports); + if (cert_importer.ParseAndStoreCertificates( + certificates, onc_trusted_certificates) != + onc::CertificateImporter::IMPORT_OK) { + LOG(ERROR) << "Cannot parse some of the certificates in the ONC from " + << onc::GetSourceAsString(source); + return false; + } + return true; +} + +} // namespace chromeos diff --git a/chromeos/network/certificate_handler.h b/chromeos/network/certificate_handler.h new file mode 100644 index 0000000..7b899d2 --- /dev/null +++ b/chromeos/network/certificate_handler.h @@ -0,0 +1,38 @@ +// Copyright (c) 2013 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. + +#ifndef CHROMEOS_NETWORK_CERTIFICATE_HANDLER_H_ +#define CHROMEOS_NETWORK_CERTIFICATE_HANDLER_H_ + +#include "chromeos/chromeos_export.h" +#include "chromeos/network/onc/onc_constants.h" +#include "net/cert/x509_certificate.h" + +namespace base { +class ListValue; +} + +namespace chromeos { + +class CHROMEOS_EXPORT CertificateHandler { + public: + CertificateHandler(); + virtual ~CertificateHandler(); + + // Import the |certificates|, which must be a list of ONC Certificate objects. + // If |onc_trusted_certificates| is not NULL, it will be filled with the list + // of certificates that requested the TrustBit "Web". Returns true if all + // certificates were imported successfully. + virtual bool ImportCertificates( + const base::ListValue& certificates, + onc::ONCSource source, + net::CertificateList* onc_trusted_certificates); + + private: + DISALLOW_COPY_AND_ASSIGN(CertificateHandler); +}; + +} // namespace chromeos + +#endif // CHROMEOS_NETWORK_CERTIFICATE_HANDLER_H_ diff --git a/chromeos/network/managed_network_configuration_handler.cc b/chromeos/network/managed_network_configuration_handler.cc index 58ab03f..a7e7d62 100644 --- a/chromeos/network/managed_network_configuration_handler.cc +++ b/chromeos/network/managed_network_configuration_handler.cc @@ -799,35 +799,10 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator void ManagedNetworkConfigurationHandler::SetPolicy( onc::ONCSource onc_source, - const base::DictionaryValue& toplevel_onc) { + const base::ListValue& network_configs_onc) { VLOG(1) << "Setting policies for ONC source " << onc::GetSourceAsString(onc_source) << "."; - // 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. - true); // This ONC comes from policy. - validator.SetOncSource(onc_source); - - onc::Validator::Result validation_result; - scoped_ptr<base::DictionaryValue> onc_validated = - validator.ValidateAndRepairObject( - &onc::kToplevelConfigurationSignature, - toplevel_onc, - &validation_result); - - if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { - LOG(WARNING) << "ONC from " << onc::GetSourceAsString(onc_source) - << " produced warnings."; - } else if (validation_result == onc::Validator::INVALID || - onc_validated == NULL) { - LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) - << " is invalid and couldn't be repaired."; - return; - } - PolicyMap* policies; std::string profile; if (onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY) { @@ -846,37 +821,28 @@ void ManagedNetworkConfigurationHandler::SetPolicy( // This stores all GUIDs of policies that have changed or are new. std::set<std::string> modified_policies; - base::ListValue* network_configurations = NULL; - onc_validated->GetListWithoutPathExpansion( - onc::toplevel_config::kNetworkConfigurations, - &network_configurations); - - if (network_configurations) { - while (!network_configurations->empty()) { - base::Value* network_value = NULL; - // Passes ownership of network_value. - network_configurations->Remove(network_configurations->GetSize() - 1, - &network_value); - const base::DictionaryValue* network = NULL; - network_value->GetAsDictionary(&network); - std::string guid; - network->GetStringWithoutPathExpansion(onc::network_config::kGUID, - &guid); - - const base::DictionaryValue* old_entry = old_policies[guid]; - const base::DictionaryValue*& new_entry = (*policies)[guid]; - if (new_entry) { - LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) - << " contains several entries for the same GUID " - << guid << "."; - delete new_entry; - } - new_entry = network; - - if (!old_entry || !old_entry->Equals(new_entry)) { - modified_policies.insert(guid); - } + for (base::ListValue::const_iterator it = network_configs_onc.begin(); + it != network_configs_onc.end(); ++it) { + const base::DictionaryValue* network = NULL; + (*it)->GetAsDictionary(&network); + DCHECK(network); + + std::string guid; + network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid); + DCHECK(!guid.empty()); + + if (policies->count(guid) > 0) { + LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) + << " contains several entries for the same GUID " + << guid << "."; + delete (*policies)[guid]; } + const base::DictionaryValue* new_entry = network->DeepCopy(); + (*policies)[guid] = new_entry; + + const base::DictionaryValue* old_entry = old_policies[guid]; + if (!old_entry || !old_entry->Equals(new_entry)) + modified_policies.insert(guid); } STLDeleteValues(&old_policies); diff --git a/chromeos/network/managed_network_configuration_handler.h b/chromeos/network/managed_network_configuration_handler.h index 5b53fff..e563fe4 100644 --- a/chromeos/network/managed_network_configuration_handler.h +++ b/chromeos/network/managed_network_configuration_handler.h @@ -18,6 +18,7 @@ namespace base { class DictionaryValue; +class ListValue; } namespace chromeos { @@ -118,13 +119,14 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler { const base::Closure& callback, const network_handler::ErrorCallback& error_callback) const; - // Only to be called by NetworkConfigurationUpdater or from tests. - // Sets |toplevel_onc| as the current policy of |onc_source|. The network + // Only to be called by NetworkConfigurationUpdater or from tests. Sets + // |network_configs_onc| as the current policy of |onc_source|. The network // configurations of the policy will be applied (not necessarily immediately) // to Shill's profiles and enforced in future configurations until the policy // associated with |onc_source| is changed again with this function. + // This function doesn't validate the policy. The caller must ensure validity. void SetPolicy(onc::ONCSource onc_source, - const base::DictionaryValue& toplevel_onc); + const base::ListValue& network_configs_onc); private: class PolicyApplicator; diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc index 49c150a..def9204 100644 --- a/chromeos/network/managed_network_configuration_handler_unittest.cc +++ b/chromeos/network/managed_network_configuration_handler_unittest.cc @@ -111,7 +111,11 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { else policy = test_utils::ReadTestDictionary(path_to_onc); - managed_handler()->SetPolicy(onc::ONC_SOURCE_USER_POLICY, *policy); + base::ListValue* network_configs = NULL; + policy->GetListWithoutPathExpansion( + onc::toplevel_config::kNetworkConfigurations, &network_configs); + + managed_handler()->SetPolicy(onc::ONC_SOURCE_USER_POLICY, *network_configs); } ManagedNetworkConfigurationHandler* managed_handler() { diff --git a/chromeos/network/mock_certificate_handler.cc b/chromeos/network/mock_certificate_handler.cc new file mode 100644 index 0000000..8ff080f --- /dev/null +++ b/chromeos/network/mock_certificate_handler.cc @@ -0,0 +1,15 @@ +// Copyright (c) 2013 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 "chromeos/network/mock_certificate_handler.h" + +namespace chromeos { + +MockCertificateHandler::MockCertificateHandler() { +} + +MockCertificateHandler::~MockCertificateHandler() { +} + +} // namespace chromeos diff --git a/chromeos/network/mock_certificate_handler.h b/chromeos/network/mock_certificate_handler.h new file mode 100644 index 0000000..a73b7a2 --- /dev/null +++ b/chromeos/network/mock_certificate_handler.h @@ -0,0 +1,28 @@ +// Copyright (c) 2013 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. + +#ifndef CHROMEOS_NETWORK_MOCK_CERTIFICATE_HANDLER_H_ +#define CHROMEOS_NETWORK_MOCK_CERTIFICATE_HANDLER_H_ + +#include "base/values.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/network/certificate_handler.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class CHROMEOS_EXPORT MockCertificateHandler : public CertificateHandler { + public: + MockCertificateHandler(); + virtual ~MockCertificateHandler(); + MOCK_METHOD3(ImportCertificates, bool(const base::ListValue&, + onc::ONCSource, + net::CertificateList*)); + private: + DISALLOW_COPY_AND_ASSIGN(MockCertificateHandler); +}; + +} // chromeos + +#endif // CHROMEOS_NETWORK_MOCK_CERTIFICATE_HANDLER_H_ diff --git a/chromeos/network/onc/onc_certificate_importer_unittest.cc b/chromeos/network/onc/onc_certificate_importer_unittest.cc index 14106d1..1fbb633 100644 --- a/chromeos/network/onc/onc_certificate_importer_unittest.cc +++ b/chromeos/network/onc/onc_certificate_importer_unittest.cc @@ -66,50 +66,63 @@ class ONCCertificateImporterTest : public testing::Test { ASSERT_TRUE(slot_->os_module_handle()); // Test db should be empty at start of test. - EXPECT_EQ(0ul, ListCertsInSlot(slot_->os_module_handle()).size()); + EXPECT_EQ(0ul, ListCertsInSlot().size()); } virtual void TearDown() { - EXPECT_TRUE(CleanupSlotContents(slot_->os_module_handle())); - EXPECT_EQ(0ul, ListCertsInSlot(slot_->os_module_handle()).size()); + EXPECT_TRUE(CleanupSlotContents()); + EXPECT_EQ(0ul, ListCertsInSlot().size()); } virtual ~ONCCertificateImporterTest() {} protected: - void AddCertificateFromFile(std::string filename, - net::CertType expected_type, - std::string* guid) { + void AddCertificatesFromFile( + std::string filename, + CertificateImporter::ParseResult expected_parse_result) { scoped_ptr<base::DictionaryValue> onc = test_utils::ReadTestDictionary(filename); + base::Value* certificates_value = NULL; base::ListValue* certificates = NULL; - onc->GetListWithoutPathExpansion(toplevel_config::kCertificates, - &certificates); - - base::DictionaryValue* certificate = NULL; - certificates->GetDictionary(0, &certificate); - certificate->GetStringWithoutPathExpansion(certificate::kGUID, guid); + onc->RemoveWithoutPathExpansion(toplevel_config::kCertificates, + &certificates_value); + certificates_value->GetAsList(&certificates); + onc_certificates_.reset(certificates); web_trust_certificates_.clear(); CertificateImporter importer(true /* allow web trust */); - EXPECT_EQ(CertificateImporter::IMPORT_OK, + EXPECT_EQ(expected_parse_result, importer.ParseAndStoreCertificates(*certificates, &web_trust_certificates_)); result_list_.clear(); + result_list_ = ListCertsInSlot(); + } + + void AddCertificateFromFile(std::string filename, + net::CertType expected_type, + std::string* guid) { + AddCertificatesFromFile(filename, CertificateImporter::IMPORT_OK); + EXPECT_EQ(1ul, result_list_.size()); + + base::DictionaryValue* certificate = NULL; + onc_certificates_->GetDictionary(0, &certificate); + certificate->GetStringWithoutPathExpansion(certificate::kGUID, guid); + CertificateImporter::ListCertsWithNickname(*guid, &result_list_); ASSERT_EQ(1ul, result_list_.size()); EXPECT_EQ(expected_type, GetCertType(result_list_[0]->os_cert_handle())); } + scoped_ptr<base::ListValue> onc_certificates_; scoped_refptr<net::CryptoModule> slot_; net::CertificateList result_list_; net::CertificateList web_trust_certificates_; private: - net::CertificateList ListCertsInSlot(PK11SlotInfo* slot) { + net::CertificateList ListCertsInSlot() { net::CertificateList result; - CERTCertList* cert_list = PK11_ListCertsInSlot(slot); + CERTCertList* cert_list = PK11_ListCertsInSlot(slot_->os_module_handle()); for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { @@ -123,9 +136,9 @@ class ONCCertificateImporterTest : public testing::Test { return result; } - bool CleanupSlotContents(PK11SlotInfo* slot) { + bool CleanupSlotContents() { bool ok = true; - net::CertificateList certs = ListCertsInSlot(slot); + net::CertificateList certs = ListCertsInSlot(); for (size_t i = 0; i < certs.size(); ++i) { if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(certs[i])) ok = false; @@ -136,6 +149,19 @@ class ONCCertificateImporterTest : public testing::Test { crypto::ScopedTestNSSDB test_nssdb_; }; +TEST_F(ONCCertificateImporterTest, MultipleCertificates) { + AddCertificatesFromFile("managed_toplevel2.onc", + CertificateImporter::IMPORT_OK); + EXPECT_EQ(onc_certificates_->GetSize(), result_list_.size()); +} + +TEST_F(ONCCertificateImporterTest, MultipleCertificatesWithFailures) { + AddCertificatesFromFile("toplevel_partially_invalid.onc", + CertificateImporter::IMPORT_INCOMPLETE); + EXPECT_EQ(2ul, onc_certificates_->GetSize()); + EXPECT_EQ(1ul, result_list_.size()); +} + TEST_F(ONCCertificateImporterTest, AddClientCertificate) { std::string guid; AddCertificateFromFile("certificate-client.onc", net::USER_CERT, &guid); diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc index c14a2a0..1b31c9d 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 diff --git a/chromeos/network/onc/onc_utils.h b/chromeos/network/onc/onc_utils.h index 1d4e28f..6a6d273 100644 --- a/chromeos/network/onc/onc_utils.h +++ b/chromeos/network/onc/onc_utils.h @@ -14,6 +14,7 @@ namespace base { class DictionaryValue; +class ListValue; } namespace chromeos { @@ -73,6 +74,18 @@ CHROMEOS_EXPORT scoped_ptr<base::DictionaryValue> MaskCredentialsInOncObject( const base::DictionaryValue& onc_object, const std::string& mask); +// Decrypts |onc_blob| with |passphrase| if necessary. Clears |network_configs| +// and |certificates| and fills them with the validated NetworkConfigurations +// and Certificates of |onc_blob|. Returns false if any validation errors or +// warnings occurred. Still, some networks or certificates might be added to the +// output lists and should be further processed by the caller. +CHROMEOS_EXPORT bool ParseAndValidateOncForImport( + const std::string& onc_blob, + chromeos::onc::ONCSource onc_source, + const std::string& passphrase, + base::ListValue* network_configs, + base::ListValue* certificates); + } // namespace onc } // namespace chromeos diff --git a/chromeos/network/onc/onc_validator_unittest.cc b/chromeos/network/onc/onc_validator_unittest.cc index cf7bfdc..d839466 100644 --- a/chromeos/network/onc/onc_validator_unittest.cc +++ b/chromeos/network/onc/onc_validator_unittest.cc @@ -285,7 +285,12 @@ INSTANTIATE_TEST_CASE_P( &kNetworkConfigurationSignature, false), RepairParams("", - "network-nested-state-field-repaired")))); + "network-nested-state-field-repaired")), + std::make_pair(OncParams("toplevel-with-repairable-networks", + &kToplevelConfigurationSignature, + false, + ONC_SOURCE_DEVICE_POLICY), + RepairParams("", "toplevel-with-repaired-networks")))); // Strict and liberal validator repair identically. INSTANTIATE_TEST_CASE_P( diff --git a/chromeos/test/data/network/invalid_settings_with_repairs.json b/chromeos/test/data/network/invalid_settings_with_repairs.json index 1e03c6f..34c9ce1 100644 --- a/chromeos/test/data/network/invalid_settings_with_repairs.json +++ b/chromeos/test/data/network/invalid_settings_with_repairs.json @@ -271,5 +271,52 @@ { "GUID": "3", "PKCS12": "abc" , "Type": "Client" } ] + }, + "toplevel-with-repaired-networks": { + "NetworkConfigurations": + [ { "GUID": "{485d6076-dd44-6b6d-69787465725f5045}", + "Type": "WiFi", + "Name": "My WiFi Network", + "WiFi": { + "SSID": "ssid-none", + "Security": "None" } + }, + { "GUID": "{485d6076-dd44-6b6d-69787465725f5046}", + "Type": "WiFi", + "Name": "My WiFi Network2", + "WiFi": { + "Passphrase": "12345678", + "SSID": "ssid-wpa", + "Security": "WPA-PSK" } + } + ], + "Certificates": [], + "Type": "UnencryptedConfiguration", + }, + "toplevel-with-repairable-networks": { + "NetworkConfigurations": + [ { "GUID": "{485d6076-dd44-6b6d-69787465725f5045}", + "Type": "WiFi", + "Name": "My WiFi Network", + "UnknownField1": "Value1", + "UnknownField2": { + "UnknownSubField": "Value2" }, + "WiFi": { + "SSID": "ssid-none", + "Security": "None" } + }, + { "GUID": "{485d6076-dd44-6b6d-69787465725f5046}", + "Type": "WiFi", + "Name": "My WiFi Network2", + "WiFi": { + "Passphrase": "12345678", + "SSID": "ssid-wpa", + "UnknownField1": "Value1", + "Security": "WPA-PSK" } + } + ], + "Certificates": [], + "Type": "UnencryptedConfiguration", + "UnknownField3": [], } } diff --git a/chromeos/test/data/network/repaired_toplevel_partially_invalid.onc b/chromeos/test/data/network/repaired_toplevel_partially_invalid.onc new file mode 100644 index 0000000..7758838 --- /dev/null +++ b/chromeos/test/data/network/repaired_toplevel_partially_invalid.onc @@ -0,0 +1,45 @@ +{ "Type": "UnencryptedConfiguration", + "NetworkConfigurations": + [ { "GUID": "123", + "Type": "VPN", + "Name": "testopenvpn", + "IPConfigs": [ + { "Type": "IPv4", + "IPAddress": "127.0.0.1", + "RoutingPrefix": 32 } + ], + "VPN": { + "Host": "policys host", + "Recommended": ["Host"], + "Type": "OpenVPN", + "OpenVPN": { + "Port": 1194, + "Username": "abc ${LOGIN_ID} def", + "Recommended": [ "Username", "Password" ], + "ClientCertType": "Pattern", + "ClientCertPattern": { + "IssuerCARef": [ "openvpn-test-ca" ], + "Recommended": [ "EnrollmentURI", "IssuerCARef" ] + } + }, + "IPsec": { + "AuthenticationType": "PSK", + "PSK": "sharedkey", + "IKEVersion": 1 + } + } + } + ], + "Certificates": [ + { + "GUID": "{f998f760-272b-6939-4c2beffe428697ac}", + "PKCS12": "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", + "Type": "Client" + }, + { + "GUID": "{456}", + "PKCS12": "ERROR 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", + "Type": "Client" + } + ] +} |