1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/network/onc/onc_validator.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/values.h"
13 #include "chromeos/network/onc/onc_signature.h"
14 #include "chromeos/network/onc/onc_test_utils.h"
15 #include "chromeos/network/onc/onc_utils.h"
16 #include "components/onc/onc_constants.h"
17 #include "testing/gtest/include/gtest/gtest.h"
22 class ONCValidatorTest : public ::testing::Test {
24 // Validate |onc_object| with the given |signature|. The object is considered
25 // to be managed if |managed_onc| is true. A strict validator is used if
26 // |strict| is true. |onc_object| and the resulting repaired object of the
27 // validation is stored, so that expectations can be checked afterwards using
28 // one of the Expect* functions below.
29 void Validate(bool strict,
30 scoped_ptr<base::DictionaryValue> onc_object,
31 const OncValueSignature* signature,
33 ::onc::ONCSource onc_source) {
34 scoped_ptr<Validator> validator;
36 // Create a strict validator that complains about every error.
37 validator.reset(new Validator(true, true, true, managed_onc));
39 // Create a liberal validator that ignores or repairs non-critical errors.
40 validator.reset(new Validator(false, false, false, managed_onc));
42 validator->SetOncSource(onc_source);
43 original_object_ = onc_object.Pass();
44 repaired_object_ = validator->ValidateAndRepairObject(signature,
50 EXPECT_EQ(Validator::VALID, validation_result_);
51 EXPECT_TRUE(test_utils::Equals(original_object_.get(),
52 repaired_object_.get()));
55 void ExpectRepairWithWarnings(
56 const base::DictionaryValue& expected_repaired) {
57 EXPECT_EQ(Validator::VALID_WITH_WARNINGS, validation_result_);
58 EXPECT_TRUE(test_utils::Equals(&expected_repaired, repaired_object_.get()));
61 void ExpectInvalid() {
62 EXPECT_EQ(Validator::INVALID, validation_result_);
63 EXPECT_EQ(NULL, repaired_object_.get());
67 Validator::Result validation_result_;
68 scoped_ptr<const base::DictionaryValue> original_object_;
69 scoped_ptr<const base::DictionaryValue> repaired_object_;
75 // |location_of_object| is a string to identify the object to be tested. It
76 // may be used as a filename or as a dictionary key.
77 OncParams(const std::string& location_of_object,
78 const OncValueSignature* onc_signature,
80 ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE)
81 : location(location_of_object),
82 signature(onc_signature),
83 is_managed(is_managed_onc),
84 onc_source(onc_source) {
88 const OncValueSignature* signature;
90 ::onc::ONCSource onc_source;
93 ::std::ostream& operator<<(::std::ostream& os, const OncParams& onc) {
94 return os << "(" << onc.location << ", " << onc.signature << ", "
95 << (onc.is_managed ? "managed" : "unmanaged") << ", "
96 << GetSourceAsString(onc.onc_source) << ")";
101 // Ensure that the constant |kEmptyUnencryptedConfiguration| describes a valid
102 // ONC toplevel object.
103 TEST_F(ONCValidatorTest, EmptyUnencryptedConfiguration) {
104 Validate(true, ReadDictionaryFromJson(kEmptyUnencryptedConfiguration),
105 &kToplevelConfigurationSignature, false, ::onc::ONC_SOURCE_NONE);
109 // This test case is about validating valid ONC objects without any errors. Both
110 // the strict and the liberal validator accept the object.
111 class ONCValidatorValidTest : public ONCValidatorTest,
112 public ::testing::WithParamInterface<OncParams> {
115 TEST_P(ONCValidatorValidTest, StrictValidationValid) {
116 OncParams onc = GetParam();
117 Validate(true, test_utils::ReadTestDictionary(onc.location), onc.signature,
118 onc.is_managed, onc.onc_source);
122 TEST_P(ONCValidatorValidTest, LiberalValidationValid) {
123 OncParams onc = GetParam();
124 Validate(false, test_utils::ReadTestDictionary(onc.location), onc.signature,
125 onc.is_managed, onc.onc_source);
129 // The parameters are:
130 // OncParams(string: Filename of a ONC file that is to be validated,
131 // OncValueSignature: signature of that ONC,
132 // bool: true if the ONC is managed).
133 INSTANTIATE_TEST_CASE_P(
134 ONCValidatorValidTest,
135 ONCValidatorValidTest,
137 OncParams("managed_toplevel1.onc",
138 &kToplevelConfigurationSignature,
140 OncParams("managed_toplevel2.onc",
141 &kToplevelConfigurationSignature,
143 OncParams("managed_toplevel_with_global_config.onc",
144 &kToplevelConfigurationSignature,
146 // Check that at least one configuration is accepted for
148 OncParams("managed_toplevel_wifi_peap.onc",
149 &kToplevelConfigurationSignature,
151 ::onc::ONC_SOURCE_DEVICE_POLICY),
152 OncParams("managed_toplevel_l2tpipsec.onc",
153 &kToplevelConfigurationSignature,
155 OncParams("toplevel_wifi_wpa_psk.onc",
156 &kToplevelConfigurationSignature,
158 OncParams("toplevel_wifi_wep_proxy.onc",
159 &kToplevelConfigurationSignature,
161 OncParams("toplevel_wifi_leap.onc",
162 &kToplevelConfigurationSignature,
164 OncParams("toplevel_wifi_eap_clientcert_with_cert_pems.onc",
165 &kToplevelConfigurationSignature,
167 OncParams("toplevel_wifi_remove.onc",
168 &kToplevelConfigurationSignature,
170 OncParams("toplevel_wifi_open.onc",
171 &kToplevelConfigurationSignature,
173 OncParams("toplevel_openvpn_clientcert_with_cert_pems.onc",
174 &kToplevelConfigurationSignature,
176 OncParams("toplevel_empty.onc",
177 &kToplevelConfigurationSignature,
179 OncParams("toplevel_only_global_config.onc",
180 &kToplevelConfigurationSignature,
182 OncParams("encrypted.onc", &kToplevelConfigurationSignature, true),
183 OncParams("managed_vpn.onc", &kNetworkConfigurationSignature, true),
184 OncParams("ethernet.onc", &kNetworkConfigurationSignature, true),
185 OncParams("ethernet_with_eap.onc",
186 &kNetworkConfigurationSignature,
188 OncParams("translation_of_shill_ethernet_with_ipconfig.onc",
189 &kNetworkWithStateSignature,
191 OncParams("translation_of_shill_wifi_with_state.onc",
192 &kNetworkWithStateSignature,
194 OncParams("valid_openvpn_with_cert_pems.onc",
195 &kNetworkConfigurationSignature,
197 OncParams("openvpn_with_password.onc",
198 &kNetworkConfigurationSignature,
203 struct RepairParams {
204 // Both arguments are strings to identify the object that is expected as the
205 // validation result. They may either be used as filenames or as dictionary
207 RepairParams(std::string strict_repaired,
208 std::string liberal_repaired)
209 : location_of_strict_repaired(strict_repaired),
210 location_of_liberal_repaired(liberal_repaired) {
213 std::string location_of_strict_repaired;
214 std::string location_of_liberal_repaired;
217 ::std::ostream& operator<<(::std::ostream& os, const RepairParams& rp) {
218 return os << "(" << rp.location_of_strict_repaired << ", "
219 << rp.location_of_liberal_repaired << ")";
224 // This test case is about validating ONC objects that contain errors which can
225 // be repaired (then the errors count as warnings). If a location of the
226 // expected repaired object is given, then it is checked that the validator
227 // (either strict or liberal) returns this repaired object and the result is
228 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected
229 // that the validator returns NULL and the result INVALID.
230 class ONCValidatorTestRepairable
231 : public ONCValidatorTest,
232 public ::testing::WithParamInterface<std::pair<OncParams,
235 // Load the common test data and return the dictionary at the field with
237 scoped_ptr<base::DictionaryValue> GetDictionaryFromTestFile(
238 const std::string &name) {
239 scoped_ptr<const base::DictionaryValue> dict(
240 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"));
241 const base::DictionaryValue* onc_object = NULL;
242 CHECK(dict->GetDictionary(name, &onc_object));
243 return make_scoped_ptr(onc_object->DeepCopy());
247 TEST_P(ONCValidatorTestRepairable, StrictValidation) {
248 OncParams onc = GetParam().first;
249 Validate(true, GetDictionaryFromTestFile(onc.location), onc.signature,
250 onc.is_managed, onc.onc_source);
251 std::string location_of_repaired =
252 GetParam().second.location_of_strict_repaired;
253 if (location_of_repaired.empty())
256 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired));
259 TEST_P(ONCValidatorTestRepairable, LiberalValidation) {
260 OncParams onc = GetParam().first;
261 Validate(false, GetDictionaryFromTestFile(onc.location), onc.signature,
262 onc.is_managed, onc.onc_source);
263 std::string location_of_repaired =
264 GetParam().second.location_of_liberal_repaired;
265 if (location_of_repaired.empty())
268 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired));
271 // The parameters for all test case instantations below are:
272 // OncParams(string: A fieldname in the dictionary from the file
273 // "invalid_settings_with_repairs.json". That nested
274 // dictionary will be tested.
275 // OncValueSignature: signature of that ONC,
276 // bool: true if the ONC is managed).
277 // RepairParams(string: A fieldname in the dictionary from the file
278 // "invalid_settings_with_repairs.json". That nested
279 // dictionary is the expected result from strict
281 // string: A fieldname in the dictionary from the file
282 // "invalid_settings_with_repairs.json". That nested
283 // dictionary is the expected result from liberal
286 // Strict validator returns INVALID. Liberal validator repairs.
287 INSTANTIATE_TEST_CASE_P(
288 StrictInvalidLiberalRepair,
289 ONCValidatorTestRepairable,
291 std::make_pair(OncParams("network-unknown-fieldname",
292 &kNetworkConfigurationSignature,
294 RepairParams("", "network-repaired")),
295 std::make_pair(OncParams("managed-network-unknown-fieldname",
296 &kNetworkConfigurationSignature,
298 RepairParams("", "managed-network-repaired")),
299 std::make_pair(OncParams("managed-network-unknown-recommended",
300 &kNetworkConfigurationSignature,
302 RepairParams("", "managed-network-repaired")),
303 std::make_pair(OncParams("managed-network-dict-recommended",
304 &kNetworkConfigurationSignature,
306 RepairParams("", "managed-network-repaired")),
307 std::make_pair(OncParams("network-missing-required",
308 &kNetworkConfigurationSignature,
310 RepairParams("", "network-missing-required")),
311 std::make_pair(OncParams("managed-network-missing-required",
312 &kNetworkConfigurationSignature,
314 RepairParams("", "managed-network-missing-required")),
315 // Ensure that state values from Shill aren't accepted as
317 std::make_pair(OncParams("network-state-field",
318 &kNetworkConfigurationSignature,
320 RepairParams("", "network-repaired")),
321 std::make_pair(OncParams("network-nested-state-field",
322 &kNetworkConfigurationSignature,
324 RepairParams("", "network-nested-state-field-repaired")),
325 std::make_pair(OncParams("network-with-ipconfigs",
326 &kNetworkConfigurationSignature,
328 RepairParams("", "network-repaired")),
329 std::make_pair(OncParams("openvpn-missing-verify-x509-name",
330 &kNetworkConfigurationSignature, false),
331 RepairParams("", "openvpn-missing-verify-x509-name")),
332 std::make_pair(OncParams("ipsec-with-client-cert-missing-cacert",
336 "ipsec-with-client-cert-missing-cacert")),
337 std::make_pair(OncParams("toplevel-with-repairable-networks",
338 &kToplevelConfigurationSignature,
340 ::onc::ONC_SOURCE_DEVICE_POLICY),
341 RepairParams("", "toplevel-with-repaired-networks"))));
343 // Strict and liberal validator repair identically.
344 INSTANTIATE_TEST_CASE_P(
345 StrictAndLiberalRepairIdentically,
346 ONCValidatorTestRepairable,
348 std::make_pair(OncParams("toplevel-invalid-network",
349 &kToplevelConfigurationSignature,
351 RepairParams("toplevel-repaired",
352 "toplevel-repaired")),
353 std::make_pair(OncParams("duplicate-network-guid",
354 &kToplevelConfigurationSignature,
356 RepairParams("repaired-duplicate-network-guid",
357 "repaired-duplicate-network-guid")),
358 std::make_pair(OncParams("duplicate-cert-guid",
359 &kToplevelConfigurationSignature,
361 RepairParams("repaired-duplicate-cert-guid",
362 "repaired-duplicate-cert-guid")),
363 std::make_pair(OncParams("toplevel-invalid-network",
364 &kToplevelConfigurationSignature,
366 RepairParams("toplevel-repaired",
367 "toplevel-repaired")),
368 // Ignore recommended arrays in unmanaged ONC.
369 std::make_pair(OncParams("network-with-illegal-recommended",
370 &kNetworkConfigurationSignature,
372 RepairParams("network-repaired", "network-repaired")),
373 std::make_pair(OncParams("toplevel-with-vpn",
374 &kToplevelConfigurationSignature,
376 ::onc::ONC_SOURCE_DEVICE_POLICY),
377 RepairParams("toplevel-empty", "toplevel-empty")),
378 std::make_pair(OncParams("toplevel-with-server-and-ca-cert",
379 &kToplevelConfigurationSignature,
381 ::onc::ONC_SOURCE_DEVICE_POLICY),
382 RepairParams("toplevel-server-and-ca-cert-dropped",
383 "toplevel-server-and-ca-cert-dropped"))));
385 // Strict and liberal validator both repair, but with different results.
386 INSTANTIATE_TEST_CASE_P(
387 StrictAndLiberalRepairDifferently,
388 ONCValidatorTestRepairable,
390 std::make_pair(OncParams("toplevel-with-nested-warning",
391 &kToplevelConfigurationSignature,
393 RepairParams("toplevel-empty", "toplevel-repaired"))));
395 // Strict and liberal validator return both INVALID.
396 INSTANTIATE_TEST_CASE_P(
397 StrictAndLiberalInvalid,
398 ONCValidatorTestRepairable,
400 std::make_pair(OncParams("network-unknown-value",
401 &kNetworkConfigurationSignature, false),
402 RepairParams("", "")),
403 std::make_pair(OncParams("managed-network-unknown-value",
404 &kNetworkConfigurationSignature, true),
405 RepairParams("", "")),
406 std::make_pair(OncParams("network-value-out-of-range",
407 &kNetworkConfigurationSignature, false),
408 RepairParams("", "")),
409 std::make_pair(OncParams("ipsec-with-psk-and-cacert",
410 &kIPsecSignature, false),
411 RepairParams("", "")),
412 std::make_pair(OncParams("ipsec-with-empty-cacertrefs",
413 &kIPsecSignature, false),
414 RepairParams("", "")),
415 std::make_pair(OncParams("ipsec-with-servercaref-and-servercarefs",
416 &kIPsecSignature, false),
417 RepairParams("", "")),
418 std::make_pair(OncParams("openvpn-with-servercaref-and-servercarefs",
419 &kOpenVPNSignature, false),
420 RepairParams("", "")),
421 std::make_pair(OncParams("eap-with-servercaref-and-servercarefs",
422 &kEAPSignature, false),
423 RepairParams("", "")),
424 std::make_pair(OncParams("managed-network-value-out-of-range",
425 &kNetworkConfigurationSignature, true),
426 RepairParams("", "")),
427 std::make_pair(OncParams("network-wrong-type",
428 &kNetworkConfigurationSignature, false),
429 RepairParams("", "")),
430 std::make_pair(OncParams("managed-network-wrong-type",
431 &kNetworkConfigurationSignature, true),
432 RepairParams("", "")),
433 std::make_pair(OncParams("network-with-client-cert-pattern",
434 &kNetworkConfigurationSignature, true,
435 ::onc::ONC_SOURCE_DEVICE_POLICY),
436 RepairParams("", "")),
437 std::make_pair(OncParams("openvpn-invalid-verify-x509-type",
438 &kNetworkConfigurationSignature, false),
439 RepairParams("", ""))
443 } // namespace chromeos