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
,
212 OncParams("third_party_vpn.onc",
213 &kNetworkConfigurationSignature
,
218 struct RepairParams
{
219 RepairParams(const std::string
& strict_repaired
,
220 const std::string
& liberal_repaired
,
222 : location_of_strict_repaired(strict_repaired
),
223 location_of_liberal_repaired(liberal_repaired
),
224 expect_liberal_valid(liberal_valid
) {}
226 std::string location_of_strict_repaired
;
227 std::string location_of_liberal_repaired
;
228 bool expect_liberal_valid
;
231 // Both |strict_repaired| and |liberal_repaired| are strings to identify the
232 // object that is expected as the validation result. They may either be used
233 // as filenames or as dictionary keys.
234 RepairParams
ExpectBothNotValid(const std::string
& strict_repaired
,
235 const std::string
& liberal_repaired
) {
236 return RepairParams(strict_repaired
, liberal_repaired
, false);
239 // |strict_repaired| is a string to identify the object that is expected as the
240 // validation result. They may either be used
241 // as filenames or as dictionary keys.
242 RepairParams
ExpectStrictNotValid(const std::string
& strict_repaired
) {
243 return RepairParams(strict_repaired
, std::string(), true);
246 ::std::ostream
& operator<<(::std::ostream
& os
, const RepairParams
& rp
) {
247 if (rp
.expect_liberal_valid
) {
248 os
<< "(" << rp
.location_of_strict_repaired
<< ", liberal is valid)";
250 os
<< "(" << rp
.location_of_strict_repaired
<< ", "
251 << rp
.location_of_liberal_repaired
<< ")";
258 // This test case is about validating ONC objects that contain errors which can
259 // be repaired (then the errors count as warnings). If a location of the
260 // expected repaired object is given, then it is checked that the validator
261 // (either strict or liberal) returns this repaired object and the result is
262 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected
263 // that the validator returns NULL and the result INVALID.
264 class ONCValidatorTestRepairable
265 : public ONCValidatorTest
,
266 public ::testing::WithParamInterface
<std::pair
<OncParams
,
269 // Load the common test data and return the dictionary at the field with
271 scoped_ptr
<base::DictionaryValue
> GetDictionaryFromTestFile(
272 const std::string
&name
) {
273 scoped_ptr
<const base::DictionaryValue
> dict(
274 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"));
275 const base::DictionaryValue
* onc_object
= NULL
;
276 CHECK(dict
->GetDictionary(name
, &onc_object
));
277 return make_scoped_ptr(onc_object
->DeepCopy());
281 TEST_P(ONCValidatorTestRepairable
, StrictValidation
) {
282 OncParams onc
= GetParam().first
;
283 Validate(true, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
284 onc
.is_managed
, onc
.onc_source
);
285 std::string location_of_repaired
=
286 GetParam().second
.location_of_strict_repaired
;
287 if (location_of_repaired
.empty())
290 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired
));
293 TEST_P(ONCValidatorTestRepairable
, LiberalValidation
) {
294 OncParams onc
= GetParam().first
;
295 Validate(false, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
296 onc
.is_managed
, onc
.onc_source
);
297 if (GetParam().second
.expect_liberal_valid
) {
300 std::string location_of_repaired
=
301 GetParam().second
.location_of_liberal_repaired
;
302 if (location_of_repaired
.empty())
305 ExpectRepairWithWarnings(
306 *GetDictionaryFromTestFile(location_of_repaired
));
310 // The parameters for all test case instantations below are:
311 // OncParams(string: A fieldname in the dictionary from the file
312 // "invalid_settings_with_repairs.json". That nested
313 // dictionary will be tested.
314 // OncValueSignature: signature of that ONC,
315 // bool: true if the ONC is managed).
317 // If both strict and liberal validation are expected to be not valid:
318 // ExpectBothNotValid(string: A fieldname in the dictionary from the file
319 // "invalid_settings_with_repairs.json". That nested
320 // dictionary is the expected result from strict
322 // string: A fieldname in the dictionary from the file
323 // "invalid_settings_with_repairs.json". That nested
324 // dictionary is the expected result from liberal
327 // If liberal valiation is expected to return VALID and strict validation is
328 // expected to be not valid:
329 // ExpectStrictNotValid(string: A fieldname in the dictionary from the file
330 // "invalid_settings_with_repairs.json". That nested
331 // dictionary is the expected result from strict
334 // Strict validator returns INVALID. Liberal validator returns VALID.
335 INSTANTIATE_TEST_CASE_P(
336 StrictInvalidLiberalValid
,
337 ONCValidatorTestRepairable
,
339 std::make_pair(OncParams("network-missing-required",
340 &kNetworkConfigurationSignature
,
342 ExpectStrictNotValid("")),
343 std::make_pair(OncParams("network-missing-required-type",
344 &kNetworkConfigurationSignature
,
346 ExpectStrictNotValid("")),
347 std::make_pair(OncParams("managed-network-missing-required",
348 &kNetworkConfigurationSignature
,
350 ExpectStrictNotValid("")),
351 std::make_pair(OncParams("openvpn-missing-verify-x509-name",
352 &kNetworkConfigurationSignature
,
354 ExpectStrictNotValid("")),
355 std::make_pair(OncParams("third-party-vpn-missing-extension-id",
356 &kNetworkConfigurationSignature
,
358 ExpectStrictNotValid(""))));
360 // Strict validator returns INVALID. Liberal validator repairs.
361 INSTANTIATE_TEST_CASE_P(
362 StrictInvalidLiberalRepair
,
363 ONCValidatorTestRepairable
,
365 std::make_pair(OncParams("network-unknown-fieldname",
366 &kNetworkConfigurationSignature
,
368 ExpectBothNotValid("", "network-repaired")),
369 std::make_pair(OncParams("managed-network-unknown-fieldname",
370 &kNetworkConfigurationSignature
,
372 ExpectBothNotValid("", "managed-network-repaired")),
373 std::make_pair(OncParams("managed-network-unknown-recommended",
374 &kNetworkConfigurationSignature
,
376 ExpectBothNotValid("", "managed-network-repaired")),
377 std::make_pair(OncParams("managed-network-dict-recommended",
378 &kNetworkConfigurationSignature
,
380 ExpectBothNotValid("", "managed-network-repaired")),
381 // Ensure that state values from Shill aren't accepted as
383 std::make_pair(OncParams("network-state-field",
384 &kNetworkConfigurationSignature
,
386 ExpectBothNotValid("", "network-repaired")),
388 OncParams("network-nested-state-field",
389 &kNetworkConfigurationSignature
,
391 ExpectBothNotValid("", "network-nested-state-field-repaired")),
392 std::make_pair(OncParams("network-with-ipconfigs",
393 &kNetworkConfigurationSignature
,
395 ExpectBothNotValid("", "network-repaired")),
397 OncParams("ipsec-with-client-cert-missing-cacert",
400 ExpectBothNotValid("", "ipsec-with-client-cert-missing-cacert")),
401 std::make_pair(OncParams("toplevel-with-repairable-networks",
402 &kToplevelConfigurationSignature
,
404 ::onc::ONC_SOURCE_DEVICE_POLICY
),
405 ExpectBothNotValid("",
406 "toplevel-with-repaired-networks"))));
408 // Strict and liberal validator repair identically.
409 INSTANTIATE_TEST_CASE_P(
410 StrictAndLiberalRepairIdentically
,
411 ONCValidatorTestRepairable
,
413 std::make_pair(OncParams("toplevel-invalid-network",
414 &kToplevelConfigurationSignature
,
416 ExpectBothNotValid("toplevel-repaired",
417 "toplevel-repaired")),
418 std::make_pair(OncParams("duplicate-network-guid",
419 &kToplevelConfigurationSignature
,
421 ExpectBothNotValid("repaired-duplicate-network-guid",
422 "repaired-duplicate-network-guid")),
423 std::make_pair(OncParams("duplicate-cert-guid",
424 &kToplevelConfigurationSignature
,
426 ExpectBothNotValid("repaired-duplicate-cert-guid",
427 "repaired-duplicate-cert-guid")),
428 std::make_pair(OncParams("toplevel-invalid-network",
429 &kToplevelConfigurationSignature
,
431 ExpectBothNotValid("toplevel-repaired",
432 "toplevel-repaired")),
433 // Ignore recommended arrays in unmanaged ONC.
434 std::make_pair(OncParams("network-with-illegal-recommended",
435 &kNetworkConfigurationSignature
,
437 ExpectBothNotValid("network-repaired",
438 "network-repaired")),
439 std::make_pair(OncParams("toplevel-with-vpn",
440 &kToplevelConfigurationSignature
,
442 ::onc::ONC_SOURCE_DEVICE_POLICY
),
443 ExpectBothNotValid("toplevel-empty", "toplevel-empty")),
444 std::make_pair(OncParams("wifi-ssid-and-hexssid-inconsistent",
445 &kNetworkConfigurationSignature
,
447 ExpectBothNotValid("wifi-ssid-and-hexssid-repaired",
448 "wifi-ssid-and-hexssid-repaired")),
449 std::make_pair(OncParams("wifi-ssid-and-hexssid-partially-invalid",
450 &kNetworkConfigurationSignature
,
452 ExpectBothNotValid("wifi-ssid-and-hexssid-repaired",
453 "wifi-ssid-and-hexssid-repaired")),
455 OncParams("toplevel-with-server-and-ca-cert",
456 &kToplevelConfigurationSignature
,
458 ::onc::ONC_SOURCE_DEVICE_POLICY
),
459 ExpectBothNotValid("toplevel-server-and-ca-cert-dropped",
460 "toplevel-server-and-ca-cert-dropped"))));
462 // Strict and liberal validator both repair, but with different results.
463 INSTANTIATE_TEST_CASE_P(
464 StrictAndLiberalRepairDifferently
,
465 ONCValidatorTestRepairable
,
466 ::testing::Values(std::make_pair(OncParams("toplevel-with-nested-warning",
467 &kToplevelConfigurationSignature
,
469 ExpectBothNotValid("toplevel-empty",
470 "toplevel-repaired"))));
472 // Strict and liberal validator return both INVALID.
473 INSTANTIATE_TEST_CASE_P(
474 StrictAndLiberalInvalid
,
475 ONCValidatorTestRepairable
,
477 std::make_pair(OncParams("network-unknown-value",
478 &kNetworkConfigurationSignature
,
480 ExpectBothNotValid("", "")),
481 std::make_pair(OncParams("wifi-hexssid-invalid-length",
482 &kNetworkConfigurationSignature
,
484 ExpectBothNotValid("", "")),
485 std::make_pair(OncParams("wifi-ssid-invalid-length",
486 &kNetworkConfigurationSignature
,
488 ExpectBothNotValid("", "")),
489 std::make_pair(OncParams("wifi-invalid-hexssid",
490 &kNetworkConfigurationSignature
,
492 ExpectBothNotValid("", "")),
493 std::make_pair(OncParams("managed-network-unknown-value",
494 &kNetworkConfigurationSignature
,
496 ExpectBothNotValid("", "")),
497 std::make_pair(OncParams("network-value-out-of-range",
498 &kNetworkConfigurationSignature
,
500 ExpectBothNotValid("", "")),
502 OncParams("ipsec-with-psk-and-cacert", &kIPsecSignature
, false),
503 ExpectBothNotValid("", "")),
505 OncParams("ipsec-with-empty-cacertrefs", &kIPsecSignature
, false),
506 ExpectBothNotValid("", "")),
507 std::make_pair(OncParams("ipsec-with-servercaref-and-servercarefs",
510 ExpectBothNotValid("", "")),
511 std::make_pair(OncParams("openvpn-with-servercaref-and-servercarefs",
514 ExpectBothNotValid("", "")),
515 std::make_pair(OncParams("eap-with-servercaref-and-servercarefs",
518 ExpectBothNotValid("", "")),
519 std::make_pair(OncParams("managed-network-value-out-of-range",
520 &kNetworkConfigurationSignature
,
522 ExpectBothNotValid("", "")),
523 std::make_pair(OncParams("network-wrong-type",
524 &kNetworkConfigurationSignature
,
526 ExpectBothNotValid("", "")),
527 std::make_pair(OncParams("managed-network-wrong-type",
528 &kNetworkConfigurationSignature
,
530 ExpectBothNotValid("", "")),
531 std::make_pair(OncParams("network-with-client-cert-pattern",
532 &kNetworkConfigurationSignature
,
534 ::onc::ONC_SOURCE_DEVICE_POLICY
),
535 ExpectBothNotValid("", "")),
536 std::make_pair(OncParams("openvpn-invalid-verify-x509-type",
537 &kNetworkConfigurationSignature
,
539 ExpectBothNotValid("", ""))));
542 } // namespace chromeos