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_hexssid.onc",
156 &kToplevelConfigurationSignature
,
158 OncParams("toplevel_wifi_ssid_and_hexssid.onc",
159 &kToplevelConfigurationSignature
,
161 OncParams("toplevel_wifi_wpa_psk.onc",
162 &kToplevelConfigurationSignature
,
164 OncParams("toplevel_wifi_wep_proxy.onc",
165 &kToplevelConfigurationSignature
,
167 OncParams("toplevel_wifi_leap.onc",
168 &kToplevelConfigurationSignature
,
170 OncParams("toplevel_wifi_eap_clientcert_with_cert_pems.onc",
171 &kToplevelConfigurationSignature
,
173 OncParams("toplevel_wifi_remove.onc",
174 &kToplevelConfigurationSignature
,
176 OncParams("toplevel_wifi_open.onc",
177 &kToplevelConfigurationSignature
,
179 OncParams("toplevel_openvpn_clientcert_with_cert_pems.onc",
180 &kToplevelConfigurationSignature
,
182 OncParams("toplevel_empty.onc",
183 &kToplevelConfigurationSignature
,
185 OncParams("toplevel_only_global_config.onc",
186 &kToplevelConfigurationSignature
,
188 OncParams("encrypted.onc", &kToplevelConfigurationSignature
, true),
189 OncParams("managed_vpn.onc", &kNetworkConfigurationSignature
, true),
190 OncParams("ethernet.onc", &kNetworkConfigurationSignature
, true),
191 OncParams("ethernet_with_eap.onc",
192 &kNetworkConfigurationSignature
,
194 OncParams("translation_of_shill_ethernet_with_ipconfig.onc",
195 &kNetworkWithStateSignature
,
197 OncParams("translation_of_shill_wifi_with_state.onc",
198 &kNetworkWithStateSignature
,
200 OncParams("translation_of_shill_cellular_with_state.onc",
201 &kNetworkWithStateSignature
,
203 OncParams("translation_of_shill_wimax_with_state.onc",
204 &kNetworkWithStateSignature
,
206 OncParams("valid_openvpn_with_cert_pems.onc",
207 &kNetworkConfigurationSignature
,
209 OncParams("openvpn_with_password.onc",
210 &kNetworkConfigurationSignature
,
215 struct RepairParams
{
216 RepairParams(const std::string
& strict_repaired
,
217 const std::string
& liberal_repaired
,
219 : location_of_strict_repaired(strict_repaired
),
220 location_of_liberal_repaired(liberal_repaired
),
221 expect_liberal_valid(liberal_valid
) {}
223 std::string location_of_strict_repaired
;
224 std::string location_of_liberal_repaired
;
225 bool expect_liberal_valid
;
228 // Both |strict_repaired| and |liberal_repaired| are strings to identify the
229 // object that is expected as the validation result. They may either be used
230 // as filenames or as dictionary keys.
231 RepairParams
ExpectBothNotValid(const std::string
& strict_repaired
,
232 const std::string
& liberal_repaired
) {
233 return RepairParams(strict_repaired
, liberal_repaired
, false);
236 // |strict_repaired| is a string to identify the object that is expected as the
237 // validation result. They may either be used
238 // as filenames or as dictionary keys.
239 RepairParams
ExpectStrictNotValid(const std::string
& strict_repaired
) {
240 return RepairParams(strict_repaired
, std::string(), true);
243 ::std::ostream
& operator<<(::std::ostream
& os
, const RepairParams
& rp
) {
244 if (rp
.expect_liberal_valid
) {
245 os
<< "(" << rp
.location_of_strict_repaired
<< ", liberal is valid)";
247 os
<< "(" << rp
.location_of_strict_repaired
<< ", "
248 << rp
.location_of_liberal_repaired
<< ")";
255 // This test case is about validating ONC objects that contain errors which can
256 // be repaired (then the errors count as warnings). If a location of the
257 // expected repaired object is given, then it is checked that the validator
258 // (either strict or liberal) returns this repaired object and the result is
259 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected
260 // that the validator returns NULL and the result INVALID.
261 class ONCValidatorTestRepairable
262 : public ONCValidatorTest
,
263 public ::testing::WithParamInterface
<std::pair
<OncParams
,
266 // Load the common test data and return the dictionary at the field with
268 scoped_ptr
<base::DictionaryValue
> GetDictionaryFromTestFile(
269 const std::string
&name
) {
270 scoped_ptr
<const base::DictionaryValue
> dict(
271 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"));
272 const base::DictionaryValue
* onc_object
= NULL
;
273 CHECK(dict
->GetDictionary(name
, &onc_object
));
274 return make_scoped_ptr(onc_object
->DeepCopy());
278 TEST_P(ONCValidatorTestRepairable
, StrictValidation
) {
279 OncParams onc
= GetParam().first
;
280 Validate(true, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
281 onc
.is_managed
, onc
.onc_source
);
282 std::string location_of_repaired
=
283 GetParam().second
.location_of_strict_repaired
;
284 if (location_of_repaired
.empty())
287 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired
));
290 TEST_P(ONCValidatorTestRepairable
, LiberalValidation
) {
291 OncParams onc
= GetParam().first
;
292 Validate(false, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
293 onc
.is_managed
, onc
.onc_source
);
294 if (GetParam().second
.expect_liberal_valid
) {
297 std::string location_of_repaired
=
298 GetParam().second
.location_of_liberal_repaired
;
299 if (location_of_repaired
.empty())
302 ExpectRepairWithWarnings(
303 *GetDictionaryFromTestFile(location_of_repaired
));
307 // The parameters for all test case instantations below are:
308 // OncParams(string: A fieldname in the dictionary from the file
309 // "invalid_settings_with_repairs.json". That nested
310 // dictionary will be tested.
311 // OncValueSignature: signature of that ONC,
312 // bool: true if the ONC is managed).
314 // If both strict and liberal validation are expected to be not valid:
315 // ExpectBothNotValid(string: A fieldname in the dictionary from the file
316 // "invalid_settings_with_repairs.json". That nested
317 // dictionary is the expected result from strict
319 // string: A fieldname in the dictionary from the file
320 // "invalid_settings_with_repairs.json". That nested
321 // dictionary is the expected result from liberal
324 // If liberal valiation is expected to return VALID and strict validation is
325 // expected to be not valid:
326 // ExpectStrictNotValid(string: A fieldname in the dictionary from the file
327 // "invalid_settings_with_repairs.json". That nested
328 // dictionary is the expected result from strict
331 // Strict validator returns INVALID. Liberal validator returns VALID.
332 INSTANTIATE_TEST_CASE_P(
333 StrictInvalidLiberalValid
,
334 ONCValidatorTestRepairable
,
336 std::make_pair(OncParams("network-missing-required",
337 &kNetworkConfigurationSignature
,
339 ExpectStrictNotValid("")),
340 std::make_pair(OncParams("network-missing-required-type",
341 &kNetworkConfigurationSignature
,
343 ExpectStrictNotValid("")),
344 std::make_pair(OncParams("managed-network-missing-required",
345 &kNetworkConfigurationSignature
,
347 ExpectStrictNotValid("")),
348 std::make_pair(OncParams("openvpn-missing-verify-x509-name",
349 &kNetworkConfigurationSignature
,
351 ExpectStrictNotValid(""))));
353 // Strict validator returns INVALID. Liberal validator repairs.
354 INSTANTIATE_TEST_CASE_P(
355 StrictInvalidLiberalRepair
,
356 ONCValidatorTestRepairable
,
358 std::make_pair(OncParams("network-unknown-fieldname",
359 &kNetworkConfigurationSignature
,
361 ExpectBothNotValid("", "network-repaired")),
362 std::make_pair(OncParams("managed-network-unknown-fieldname",
363 &kNetworkConfigurationSignature
,
365 ExpectBothNotValid("", "managed-network-repaired")),
366 std::make_pair(OncParams("managed-network-unknown-recommended",
367 &kNetworkConfigurationSignature
,
369 ExpectBothNotValid("", "managed-network-repaired")),
370 std::make_pair(OncParams("managed-network-dict-recommended",
371 &kNetworkConfigurationSignature
,
373 ExpectBothNotValid("", "managed-network-repaired")),
374 // Ensure that state values from Shill aren't accepted as
376 std::make_pair(OncParams("network-state-field",
377 &kNetworkConfigurationSignature
,
379 ExpectBothNotValid("", "network-repaired")),
381 OncParams("network-nested-state-field",
382 &kNetworkConfigurationSignature
,
384 ExpectBothNotValid("", "network-nested-state-field-repaired")),
385 std::make_pair(OncParams("network-with-ipconfigs",
386 &kNetworkConfigurationSignature
,
388 ExpectBothNotValid("", "network-repaired")),
390 OncParams("ipsec-with-client-cert-missing-cacert",
393 ExpectBothNotValid("", "ipsec-with-client-cert-missing-cacert")),
394 std::make_pair(OncParams("toplevel-with-repairable-networks",
395 &kToplevelConfigurationSignature
,
397 ::onc::ONC_SOURCE_DEVICE_POLICY
),
398 ExpectBothNotValid("",
399 "toplevel-with-repaired-networks"))));
401 // Strict and liberal validator repair identically.
402 INSTANTIATE_TEST_CASE_P(
403 StrictAndLiberalRepairIdentically
,
404 ONCValidatorTestRepairable
,
406 std::make_pair(OncParams("toplevel-invalid-network",
407 &kToplevelConfigurationSignature
,
409 ExpectBothNotValid("toplevel-repaired",
410 "toplevel-repaired")),
411 std::make_pair(OncParams("duplicate-network-guid",
412 &kToplevelConfigurationSignature
,
414 ExpectBothNotValid("repaired-duplicate-network-guid",
415 "repaired-duplicate-network-guid")),
416 std::make_pair(OncParams("duplicate-cert-guid",
417 &kToplevelConfigurationSignature
,
419 ExpectBothNotValid("repaired-duplicate-cert-guid",
420 "repaired-duplicate-cert-guid")),
421 std::make_pair(OncParams("toplevel-invalid-network",
422 &kToplevelConfigurationSignature
,
424 ExpectBothNotValid("toplevel-repaired",
425 "toplevel-repaired")),
426 // Ignore recommended arrays in unmanaged ONC.
427 std::make_pair(OncParams("network-with-illegal-recommended",
428 &kNetworkConfigurationSignature
,
430 ExpectBothNotValid("network-repaired",
431 "network-repaired")),
432 std::make_pair(OncParams("toplevel-with-vpn",
433 &kToplevelConfigurationSignature
,
435 ::onc::ONC_SOURCE_DEVICE_POLICY
),
436 ExpectBothNotValid("toplevel-empty", "toplevel-empty")),
437 std::make_pair(OncParams("wifi-ssid-and-hexssid-inconsistent",
438 &kNetworkConfigurationSignature
,
440 ExpectBothNotValid("wifi-ssid-and-hexssid-repaired",
441 "wifi-ssid-and-hexssid-repaired")),
442 std::make_pair(OncParams("wifi-ssid-and-hexssid-partially-invalid",
443 &kNetworkConfigurationSignature
,
445 ExpectBothNotValid("wifi-ssid-and-hexssid-repaired",
446 "wifi-ssid-and-hexssid-repaired")),
448 OncParams("toplevel-with-server-and-ca-cert",
449 &kToplevelConfigurationSignature
,
451 ::onc::ONC_SOURCE_DEVICE_POLICY
),
452 ExpectBothNotValid("toplevel-server-and-ca-cert-dropped",
453 "toplevel-server-and-ca-cert-dropped"))));
455 // Strict and liberal validator both repair, but with different results.
456 INSTANTIATE_TEST_CASE_P(
457 StrictAndLiberalRepairDifferently
,
458 ONCValidatorTestRepairable
,
459 ::testing::Values(std::make_pair(OncParams("toplevel-with-nested-warning",
460 &kToplevelConfigurationSignature
,
462 ExpectBothNotValid("toplevel-empty",
463 "toplevel-repaired"))));
465 // Strict and liberal validator return both INVALID.
466 INSTANTIATE_TEST_CASE_P(
467 StrictAndLiberalInvalid
,
468 ONCValidatorTestRepairable
,
470 std::make_pair(OncParams("network-unknown-value",
471 &kNetworkConfigurationSignature
,
473 ExpectBothNotValid("", "")),
474 std::make_pair(OncParams("wifi-hexssid-invalid-length",
475 &kNetworkConfigurationSignature
,
477 ExpectBothNotValid("", "")),
478 std::make_pair(OncParams("wifi-ssid-invalid-length",
479 &kNetworkConfigurationSignature
,
481 ExpectBothNotValid("", "")),
482 std::make_pair(OncParams("wifi-invalid-hexssid",
483 &kNetworkConfigurationSignature
,
485 ExpectBothNotValid("", "")),
486 std::make_pair(OncParams("managed-network-unknown-value",
487 &kNetworkConfigurationSignature
,
489 ExpectBothNotValid("", "")),
490 std::make_pair(OncParams("network-value-out-of-range",
491 &kNetworkConfigurationSignature
,
493 ExpectBothNotValid("", "")),
495 OncParams("ipsec-with-psk-and-cacert", &kIPsecSignature
, false),
496 ExpectBothNotValid("", "")),
498 OncParams("ipsec-with-empty-cacertrefs", &kIPsecSignature
, false),
499 ExpectBothNotValid("", "")),
500 std::make_pair(OncParams("ipsec-with-servercaref-and-servercarefs",
503 ExpectBothNotValid("", "")),
504 std::make_pair(OncParams("openvpn-with-servercaref-and-servercarefs",
507 ExpectBothNotValid("", "")),
508 std::make_pair(OncParams("eap-with-servercaref-and-servercarefs",
511 ExpectBothNotValid("", "")),
512 std::make_pair(OncParams("managed-network-value-out-of-range",
513 &kNetworkConfigurationSignature
,
515 ExpectBothNotValid("", "")),
516 std::make_pair(OncParams("network-wrong-type",
517 &kNetworkConfigurationSignature
,
519 ExpectBothNotValid("", "")),
520 std::make_pair(OncParams("managed-network-wrong-type",
521 &kNetworkConfigurationSignature
,
523 ExpectBothNotValid("", "")),
524 std::make_pair(OncParams("network-with-client-cert-pattern",
525 &kNetworkConfigurationSignature
,
527 ::onc::ONC_SOURCE_DEVICE_POLICY
),
528 ExpectBothNotValid("", "")),
529 std::make_pair(OncParams("openvpn-invalid-verify-x509-type",
530 &kNetworkConfigurationSignature
,
532 ExpectBothNotValid("", ""))));
535 } // namespace chromeos