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
,
200 struct RepairParams
{
201 // Both arguments are strings to identify the object that is expected as the
202 // validation result. They may either be used as filenames or as dictionary
204 RepairParams(std::string strict_repaired
,
205 std::string liberal_repaired
)
206 : location_of_strict_repaired(strict_repaired
),
207 location_of_liberal_repaired(liberal_repaired
) {
210 std::string location_of_strict_repaired
;
211 std::string location_of_liberal_repaired
;
214 ::std::ostream
& operator<<(::std::ostream
& os
, const RepairParams
& rp
) {
215 return os
<< "(" << rp
.location_of_strict_repaired
<< ", "
216 << rp
.location_of_liberal_repaired
<< ")";
221 // This test case is about validating ONC objects that contain errors which can
222 // be repaired (then the errors count as warnings). If a location of the
223 // expected repaired object is given, then it is checked that the validator
224 // (either strict or liberal) returns this repaired object and the result is
225 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected
226 // that the validator returns NULL and the result INVALID.
227 class ONCValidatorTestRepairable
228 : public ONCValidatorTest
,
229 public ::testing::WithParamInterface
<std::pair
<OncParams
,
232 // Load the common test data and return the dictionary at the field with
234 scoped_ptr
<base::DictionaryValue
> GetDictionaryFromTestFile(
235 const std::string
&name
) {
236 scoped_ptr
<const base::DictionaryValue
> dict(
237 test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"));
238 const base::DictionaryValue
* onc_object
= NULL
;
239 CHECK(dict
->GetDictionary(name
, &onc_object
));
240 return make_scoped_ptr(onc_object
->DeepCopy());
244 TEST_P(ONCValidatorTestRepairable
, StrictValidation
) {
245 OncParams onc
= GetParam().first
;
246 Validate(true, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
247 onc
.is_managed
, onc
.onc_source
);
248 std::string location_of_repaired
=
249 GetParam().second
.location_of_strict_repaired
;
250 if (location_of_repaired
.empty())
253 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired
));
256 TEST_P(ONCValidatorTestRepairable
, LiberalValidation
) {
257 OncParams onc
= GetParam().first
;
258 Validate(false, GetDictionaryFromTestFile(onc
.location
), onc
.signature
,
259 onc
.is_managed
, onc
.onc_source
);
260 std::string location_of_repaired
=
261 GetParam().second
.location_of_liberal_repaired
;
262 if (location_of_repaired
.empty())
265 ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired
));
268 // The parameters for all test case instantations below are:
269 // OncParams(string: A fieldname in the dictionary from the file
270 // "invalid_settings_with_repairs.json". That nested
271 // dictionary will be tested.
272 // OncValueSignature: signature of that ONC,
273 // bool: true if the ONC is managed).
274 // RepairParams(string: A fieldname in the dictionary from the file
275 // "invalid_settings_with_repairs.json". That nested
276 // dictionary is the expected result from strict
278 // string: A fieldname in the dictionary from the file
279 // "invalid_settings_with_repairs.json". That nested
280 // dictionary is the expected result from liberal
283 // Strict validator returns INVALID. Liberal validator repairs.
284 INSTANTIATE_TEST_CASE_P(
285 StrictInvalidLiberalRepair
,
286 ONCValidatorTestRepairable
,
288 std::make_pair(OncParams("network-unknown-fieldname",
289 &kNetworkConfigurationSignature
,
291 RepairParams("", "network-repaired")),
292 std::make_pair(OncParams("managed-network-unknown-fieldname",
293 &kNetworkConfigurationSignature
,
295 RepairParams("", "managed-network-repaired")),
296 std::make_pair(OncParams("managed-network-unknown-recommended",
297 &kNetworkConfigurationSignature
,
299 RepairParams("", "managed-network-repaired")),
300 std::make_pair(OncParams("managed-network-dict-recommended",
301 &kNetworkConfigurationSignature
,
303 RepairParams("", "managed-network-repaired")),
304 std::make_pair(OncParams("network-missing-required",
305 &kNetworkConfigurationSignature
,
307 RepairParams("", "network-missing-required")),
308 std::make_pair(OncParams("managed-network-missing-required",
309 &kNetworkConfigurationSignature
,
311 RepairParams("", "managed-network-missing-required")),
312 // Ensure that state values from Shill aren't accepted as
314 std::make_pair(OncParams("network-state-field",
315 &kNetworkConfigurationSignature
,
317 RepairParams("", "network-repaired")),
318 std::make_pair(OncParams("network-nested-state-field",
319 &kNetworkConfigurationSignature
,
321 RepairParams("", "network-nested-state-field-repaired")),
322 std::make_pair(OncParams("network-with-ipconfigs",
323 &kNetworkConfigurationSignature
,
325 RepairParams("", "network-repaired")),
326 std::make_pair(OncParams("openvpn-missing-verify-x509-name",
327 &kNetworkConfigurationSignature
, false),
328 RepairParams("", "openvpn-missing-verify-x509-name")),
329 std::make_pair(OncParams("ipsec-with-client-cert-missing-cacert",
333 "ipsec-with-client-cert-missing-cacert")),
334 std::make_pair(OncParams("toplevel-with-repairable-networks",
335 &kToplevelConfigurationSignature
,
337 ::onc::ONC_SOURCE_DEVICE_POLICY
),
338 RepairParams("", "toplevel-with-repaired-networks"))));
340 // Strict and liberal validator repair identically.
341 INSTANTIATE_TEST_CASE_P(
342 StrictAndLiberalRepairIdentically
,
343 ONCValidatorTestRepairable
,
345 std::make_pair(OncParams("toplevel-invalid-network",
346 &kToplevelConfigurationSignature
,
348 RepairParams("toplevel-repaired",
349 "toplevel-repaired")),
350 std::make_pair(OncParams("duplicate-network-guid",
351 &kToplevelConfigurationSignature
,
353 RepairParams("repaired-duplicate-network-guid",
354 "repaired-duplicate-network-guid")),
355 std::make_pair(OncParams("duplicate-cert-guid",
356 &kToplevelConfigurationSignature
,
358 RepairParams("repaired-duplicate-cert-guid",
359 "repaired-duplicate-cert-guid")),
360 std::make_pair(OncParams("toplevel-invalid-network",
361 &kToplevelConfigurationSignature
,
363 RepairParams("toplevel-repaired",
364 "toplevel-repaired")),
365 // Ignore recommended arrays in unmanaged ONC.
366 std::make_pair(OncParams("network-with-illegal-recommended",
367 &kNetworkConfigurationSignature
,
369 RepairParams("network-repaired", "network-repaired")),
370 std::make_pair(OncParams("toplevel-with-vpn",
371 &kToplevelConfigurationSignature
,
373 ::onc::ONC_SOURCE_DEVICE_POLICY
),
374 RepairParams("toplevel-empty", "toplevel-empty")),
375 std::make_pair(OncParams("toplevel-with-server-and-ca-cert",
376 &kToplevelConfigurationSignature
,
378 ::onc::ONC_SOURCE_DEVICE_POLICY
),
379 RepairParams("toplevel-server-and-ca-cert-dropped",
380 "toplevel-server-and-ca-cert-dropped"))));
382 // Strict and liberal validator both repair, but with different results.
383 INSTANTIATE_TEST_CASE_P(
384 StrictAndLiberalRepairDifferently
,
385 ONCValidatorTestRepairable
,
387 std::make_pair(OncParams("toplevel-with-nested-warning",
388 &kToplevelConfigurationSignature
,
390 RepairParams("toplevel-empty", "toplevel-repaired"))));
392 // Strict and liberal validator return both INVALID.
393 INSTANTIATE_TEST_CASE_P(
394 StrictAndLiberalInvalid
,
395 ONCValidatorTestRepairable
,
397 std::make_pair(OncParams("network-unknown-value",
398 &kNetworkConfigurationSignature
, false),
399 RepairParams("", "")),
400 std::make_pair(OncParams("managed-network-unknown-value",
401 &kNetworkConfigurationSignature
, true),
402 RepairParams("", "")),
403 std::make_pair(OncParams("network-value-out-of-range",
404 &kNetworkConfigurationSignature
, false),
405 RepairParams("", "")),
406 std::make_pair(OncParams("ipsec-with-psk-and-cacert",
407 &kIPsecSignature
, false),
408 RepairParams("", "")),
409 std::make_pair(OncParams("ipsec-with-empty-cacertrefs",
410 &kIPsecSignature
, false),
411 RepairParams("", "")),
412 std::make_pair(OncParams("ipsec-with-servercaref-and-servercarefs",
413 &kIPsecSignature
, false),
414 RepairParams("", "")),
415 std::make_pair(OncParams("openvpn-with-servercaref-and-servercarefs",
416 &kOpenVPNSignature
, false),
417 RepairParams("", "")),
418 std::make_pair(OncParams("eap-with-servercaref-and-servercarefs",
419 &kEAPSignature
, false),
420 RepairParams("", "")),
421 std::make_pair(OncParams("managed-network-value-out-of-range",
422 &kNetworkConfigurationSignature
, true),
423 RepairParams("", "")),
424 std::make_pair(OncParams("network-wrong-type",
425 &kNetworkConfigurationSignature
, false),
426 RepairParams("", "")),
427 std::make_pair(OncParams("managed-network-wrong-type",
428 &kNetworkConfigurationSignature
, true),
429 RepairParams("", "")),
430 std::make_pair(OncParams("network-with-client-cert-pattern",
431 &kNetworkConfigurationSignature
, true,
432 ::onc::ONC_SOURCE_DEVICE_POLICY
),
433 RepairParams("", "")),
434 std::make_pair(OncParams("openvpn-invalid-verify-x509-type",
435 &kNetworkConfigurationSignature
, false),
436 RepairParams("", ""))
440 } // namespace chromeos