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 // Disabled technologies are only allowed for user policies.
153 OncParams("managed_toplevel_with_disabled_technologies.onc",
154 &kToplevelConfigurationSignature
,
156 ::onc::ONC_SOURCE_USER_POLICY
),
157 OncParams("managed_toplevel_l2tpipsec.onc",
158 &kToplevelConfigurationSignature
,
160 OncParams("toplevel_wifi_hexssid.onc",
161 &kToplevelConfigurationSignature
,
163 OncParams("toplevel_wifi_ssid_and_hexssid.onc",
164 &kToplevelConfigurationSignature
,
166 OncParams("toplevel_wifi_wpa_psk.onc",
167 &kToplevelConfigurationSignature
,
169 OncParams("toplevel_wifi_wep_proxy.onc",
170 &kToplevelConfigurationSignature
,
172 OncParams("toplevel_wifi_leap.onc",
173 &kToplevelConfigurationSignature
,
175 OncParams("toplevel_wifi_eap_clientcert_with_cert_pems.onc",
176 &kToplevelConfigurationSignature
,
178 OncParams("toplevel_wifi_remove.onc",
179 &kToplevelConfigurationSignature
,
181 OncParams("toplevel_wifi_open.onc",
182 &kToplevelConfigurationSignature
,
184 OncParams("toplevel_openvpn_clientcert_with_cert_pems.onc",
185 &kToplevelConfigurationSignature
,
187 OncParams("toplevel_empty.onc",
188 &kToplevelConfigurationSignature
,
190 OncParams("toplevel_only_global_config.onc",
191 &kToplevelConfigurationSignature
,
193 OncParams("encrypted.onc", &kToplevelConfigurationSignature
, true),
194 OncParams("managed_vpn.onc", &kNetworkConfigurationSignature
, true),
195 OncParams("ethernet.onc", &kNetworkConfigurationSignature
, true),
196 OncParams("ethernet_with_eap.onc",
197 &kNetworkConfigurationSignature
,
199 OncParams("translation_of_shill_ethernet_with_ipconfig.onc",
200 &kNetworkWithStateSignature
,
202 OncParams("translation_of_shill_wifi_with_state.onc",
203 &kNetworkWithStateSignature
,
205 OncParams("translation_of_shill_cellular_with_state.onc",
206 &kNetworkWithStateSignature
,
208 OncParams("translation_of_shill_wimax_with_state.onc",
209 &kNetworkWithStateSignature
,
211 OncParams("valid_openvpn_with_cert_pems.onc",
212 &kNetworkConfigurationSignature
,
214 OncParams("openvpn_with_password.onc",
215 &kNetworkConfigurationSignature
,
217 OncParams("third_party_vpn.onc",
218 &kNetworkConfigurationSignature
,
223 struct RepairParams
{
224 RepairParams(const std::string
& strict_repaired
,
225 const std::string
& liberal_repaired
,
227 : location_of_strict_repaired(strict_repaired
),
228 location_of_liberal_repaired(liberal_repaired
),
229 expect_liberal_valid(liberal_valid
) {}
231 std::string location_of_strict_repaired
;
232 std::string location_of_liberal_repaired
;
233 bool expect_liberal_valid
;
236 // Both |strict_repaired| and |liberal_repaired| are strings to identify the
237 // object that is expected as the validation result. They may either be used
238 // as filenames or as dictionary keys.
239 RepairParams
ExpectBothNotValid(const std::string
& strict_repaired
,
240 const std::string
& liberal_repaired
) {
241 return RepairParams(strict_repaired
, liberal_repaired
, false);
244 // |strict_repaired| is a string to identify the object that is expected as the
245 // validation result. They may either be used
246 // as filenames or as dictionary keys.
247 RepairParams
ExpectStrictNotValid(const std::string
& strict_repaired
) {
248 return RepairParams(strict_repaired
, std::string(), true);
251 ::std::ostream
& operator<<(::std::ostream
& os
, const RepairParams
& rp
) {
252 if (rp
.expect_liberal_valid
) {
253 os
<< "(" << rp
.location_of_strict_repaired
<< ", liberal is valid)";
255 os
<< "(" << rp
.location_of_strict_repaired
<< ", "
256 << rp
.location_of_liberal_repaired
<< ")";
263 // This test case is about validating ONC objects that contain errors which can
264 // be repaired (then the errors count as warnings). If a location of the
265 // expected repaired object is given, then it is checked that the validator
266 // (either strict or liberal) returns this repaired object and the result is
267 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected
268 // that the validator returns NULL and the result INVALID.
269 class ONCValidatorTestRepairable
270 : public ONCValidatorTest
,
271 public ::testing::WithParamInterface
<std::pair
<OncParams
,
274 // Load the common test data and return the dictionary at the field with
276 scoped_ptr
<base::DictionaryValue
> GetDictionaryFromTestFile(
277 const std::string
&name
) {
278 scoped_ptr
<const base::DictionaryValue
> dict(
279 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"));
280 const base::DictionaryValue
* onc_object
= NULL
;
281 CHECK(dict
->GetDictionary(name
, &onc_object
));
282 return make_scoped_ptr(onc_object
->DeepCopy());
286 TEST_P(ONCValidatorTestRepairable
, StrictValidation
) {
287 OncParams onc
= GetParam().first
;
288 Validate(true, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
289 onc
.is_managed
, onc
.onc_source
);
290 std::string location_of_repaired
=
291 GetParam().second
.location_of_strict_repaired
;
292 if (location_of_repaired
.empty())
295 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired
));
298 TEST_P(ONCValidatorTestRepairable
, LiberalValidation
) {
299 OncParams onc
= GetParam().first
;
300 Validate(false, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
301 onc
.is_managed
, onc
.onc_source
);
302 if (GetParam().second
.expect_liberal_valid
) {
305 std::string location_of_repaired
=
306 GetParam().second
.location_of_liberal_repaired
;
307 if (location_of_repaired
.empty())
310 ExpectRepairWithWarnings(
311 *GetDictionaryFromTestFile(location_of_repaired
));
315 // The parameters for all test case instantations below are:
316 // OncParams(string: A fieldname in the dictionary from the file
317 // "invalid_settings_with_repairs.json". That nested
318 // dictionary will be tested.
319 // OncValueSignature: signature of that ONC,
320 // bool: true if the ONC is managed).
322 // If both strict and liberal validation are expected to be not valid:
323 // ExpectBothNotValid(string: A fieldname in the dictionary from the file
324 // "invalid_settings_with_repairs.json". That nested
325 // dictionary is the expected result from strict
327 // string: A fieldname in the dictionary from the file
328 // "invalid_settings_with_repairs.json". That nested
329 // dictionary is the expected result from liberal
332 // If liberal valiation is expected to return VALID and strict validation is
333 // expected to be not valid:
334 // ExpectStrictNotValid(string: A fieldname in the dictionary from the file
335 // "invalid_settings_with_repairs.json". That nested
336 // dictionary is the expected result from strict
339 // Strict validator returns INVALID. Liberal validator returns VALID.
340 INSTANTIATE_TEST_CASE_P(
341 StrictInvalidLiberalValid
,
342 ONCValidatorTestRepairable
,
344 std::make_pair(OncParams("network-missing-required",
345 &kNetworkConfigurationSignature
,
347 ExpectStrictNotValid("")),
348 std::make_pair(OncParams("network-missing-required-type",
349 &kNetworkConfigurationSignature
,
351 ExpectStrictNotValid("")),
352 std::make_pair(OncParams("managed-network-missing-required",
353 &kNetworkConfigurationSignature
,
355 ExpectStrictNotValid("")),
356 std::make_pair(OncParams("openvpn-missing-verify-x509-name",
357 &kNetworkConfigurationSignature
,
359 ExpectStrictNotValid("")),
360 std::make_pair(OncParams("third-party-vpn-missing-extension-id",
361 &kNetworkConfigurationSignature
,
363 ExpectStrictNotValid(""))));
365 // Strict validator returns INVALID. Liberal validator repairs.
366 INSTANTIATE_TEST_CASE_P(
367 StrictInvalidLiberalRepair
,
368 ONCValidatorTestRepairable
,
370 std::make_pair(OncParams("network-unknown-fieldname",
371 &kNetworkConfigurationSignature
,
373 ExpectBothNotValid("", "network-repaired")),
374 std::make_pair(OncParams("managed-network-unknown-fieldname",
375 &kNetworkConfigurationSignature
,
377 ExpectBothNotValid("", "managed-network-repaired")),
378 std::make_pair(OncParams("managed-network-unknown-recommended",
379 &kNetworkConfigurationSignature
,
381 ExpectBothNotValid("", "managed-network-repaired")),
382 std::make_pair(OncParams("managed-network-dict-recommended",
383 &kNetworkConfigurationSignature
,
385 ExpectBothNotValid("", "managed-network-repaired")),
386 // Ensure that state values from Shill aren't accepted as
388 std::make_pair(OncParams("network-state-field",
389 &kNetworkConfigurationSignature
,
391 ExpectBothNotValid("", "network-repaired")),
393 OncParams("network-nested-state-field",
394 &kNetworkConfigurationSignature
,
396 ExpectBothNotValid("", "network-nested-state-field-repaired")),
397 std::make_pair(OncParams("network-with-ipconfigs",
398 &kNetworkConfigurationSignature
,
400 ExpectBothNotValid("", "network-repaired")),
402 OncParams("ipsec-with-client-cert-missing-cacert",
405 ExpectBothNotValid("", "ipsec-with-client-cert-missing-cacert")),
406 std::make_pair(OncParams("toplevel-with-repairable-networks",
407 &kToplevelConfigurationSignature
,
409 ::onc::ONC_SOURCE_DEVICE_POLICY
),
410 ExpectBothNotValid("",
411 "toplevel-with-repaired-networks"))));
413 // Strict and liberal validator repair identically.
414 INSTANTIATE_TEST_CASE_P(
415 StrictAndLiberalRepairIdentically
,
416 ONCValidatorTestRepairable
,
418 std::make_pair(OncParams("toplevel-invalid-network",
419 &kToplevelConfigurationSignature
,
421 ExpectBothNotValid("toplevel-repaired",
422 "toplevel-repaired")),
423 std::make_pair(OncParams("duplicate-network-guid",
424 &kToplevelConfigurationSignature
,
426 ExpectBothNotValid("repaired-duplicate-network-guid",
427 "repaired-duplicate-network-guid")),
428 std::make_pair(OncParams("duplicate-cert-guid",
429 &kToplevelConfigurationSignature
,
431 ExpectBothNotValid("repaired-duplicate-cert-guid",
432 "repaired-duplicate-cert-guid")),
433 std::make_pair(OncParams("toplevel-invalid-network",
434 &kToplevelConfigurationSignature
,
436 ExpectBothNotValid("toplevel-repaired",
437 "toplevel-repaired")),
438 // Ignore recommended arrays in unmanaged ONC.
439 std::make_pair(OncParams("network-with-illegal-recommended",
440 &kNetworkConfigurationSignature
,
442 ExpectBothNotValid("network-repaired",
443 "network-repaired")),
444 std::make_pair(OncParams("toplevel-with-vpn",
445 &kToplevelConfigurationSignature
,
447 ::onc::ONC_SOURCE_DEVICE_POLICY
),
448 ExpectBothNotValid("toplevel-empty", "toplevel-empty")),
449 std::make_pair(OncParams("wifi-ssid-and-hexssid-inconsistent",
450 &kNetworkConfigurationSignature
,
452 ExpectBothNotValid("wifi-ssid-and-hexssid-repaired",
453 "wifi-ssid-and-hexssid-repaired")),
454 std::make_pair(OncParams("wifi-ssid-and-hexssid-partially-invalid",
455 &kNetworkConfigurationSignature
,
457 ExpectBothNotValid("wifi-ssid-and-hexssid-repaired",
458 "wifi-ssid-and-hexssid-repaired")),
460 OncParams("toplevel-with-server-and-ca-cert",
461 &kToplevelConfigurationSignature
,
463 ::onc::ONC_SOURCE_DEVICE_POLICY
),
464 ExpectBothNotValid("toplevel-server-and-ca-cert-dropped",
465 "toplevel-server-and-ca-cert-dropped"))));
467 // Strict and liberal validator both repair, but with different results.
468 INSTANTIATE_TEST_CASE_P(
469 StrictAndLiberalRepairDifferently
,
470 ONCValidatorTestRepairable
,
471 ::testing::Values(std::make_pair(OncParams("toplevel-with-nested-warning",
472 &kToplevelConfigurationSignature
,
474 ExpectBothNotValid("toplevel-empty",
475 "toplevel-repaired"))));
477 // Strict and liberal validator return both INVALID.
478 INSTANTIATE_TEST_CASE_P(
479 StrictAndLiberalInvalid
,
480 ONCValidatorTestRepairable
,
482 std::make_pair(OncParams("global-disabled-technologies",
483 &kGlobalNetworkConfigurationSignature
,
485 ExpectBothNotValid("", "")),
486 std::make_pair(OncParams("network-unknown-value",
487 &kNetworkConfigurationSignature
,
489 ExpectBothNotValid("", "")),
490 std::make_pair(OncParams("wifi-hexssid-invalid-length",
491 &kNetworkConfigurationSignature
,
493 ExpectBothNotValid("", "")),
494 std::make_pair(OncParams("wifi-ssid-invalid-length",
495 &kNetworkConfigurationSignature
,
497 ExpectBothNotValid("", "")),
498 std::make_pair(OncParams("wifi-invalid-hexssid",
499 &kNetworkConfigurationSignature
,
501 ExpectBothNotValid("", "")),
502 std::make_pair(OncParams("managed-network-unknown-value",
503 &kNetworkConfigurationSignature
,
505 ExpectBothNotValid("", "")),
506 std::make_pair(OncParams("network-value-out-of-range",
507 &kNetworkConfigurationSignature
,
509 ExpectBothNotValid("", "")),
511 OncParams("ipsec-with-psk-and-cacert", &kIPsecSignature
, false),
512 ExpectBothNotValid("", "")),
514 OncParams("ipsec-with-empty-cacertrefs", &kIPsecSignature
, false),
515 ExpectBothNotValid("", "")),
516 std::make_pair(OncParams("ipsec-with-servercaref-and-servercarefs",
519 ExpectBothNotValid("", "")),
520 std::make_pair(OncParams("openvpn-with-servercaref-and-servercarefs",
523 ExpectBothNotValid("", "")),
524 std::make_pair(OncParams("eap-with-servercaref-and-servercarefs",
527 ExpectBothNotValid("", "")),
528 std::make_pair(OncParams("managed-network-value-out-of-range",
529 &kNetworkConfigurationSignature
,
531 ExpectBothNotValid("", "")),
532 std::make_pair(OncParams("network-wrong-type",
533 &kNetworkConfigurationSignature
,
535 ExpectBothNotValid("", "")),
536 std::make_pair(OncParams("managed-network-wrong-type",
537 &kNetworkConfigurationSignature
,
539 ExpectBothNotValid("", "")),
540 std::make_pair(OncParams("network-with-client-cert-pattern",
541 &kNetworkConfigurationSignature
,
543 ::onc::ONC_SOURCE_DEVICE_POLICY
),
544 ExpectBothNotValid("", "")),
545 std::make_pair(OncParams("openvpn-invalid-verify-x509-type",
546 &kNetworkConfigurationSignature
,
548 ExpectBothNotValid("", ""))));
551 } // namespace chromeos