Home | History | Annotate | Download | only in onc
      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.
      4 
      5 #include "chromeos/network/onc/onc_validator.h"
      6 
      7 #include <string>
      8 #include <utility>
      9 
     10 #include "base/logging.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/values.h"
     13 #include "chromeos/network/onc/onc_constants.h"
     14 #include "chromeos/network/onc/onc_signature.h"
     15 #include "chromeos/network/onc/onc_test_utils.h"
     16 #include "chromeos/network/onc/onc_utils.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace chromeos {
     20 namespace onc {
     21 
     22 class ONCValidatorTest : public ::testing::Test {
     23  public:
     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,
     32                 bool managed_onc,
     33                 ONCSource onc_source) {
     34     scoped_ptr<Validator> validator;
     35     if (strict) {
     36       // Create a strict validator that complains about every error.
     37       validator.reset(new Validator(true, true, true, managed_onc));
     38     } else {
     39       // Create a liberal validator that ignores or repairs non-critical errors.
     40       validator.reset(new Validator(false, false, false, managed_onc));
     41     }
     42     validator->SetOncSource(onc_source);
     43     original_object_ = onc_object.Pass();
     44     repaired_object_ = validator->ValidateAndRepairObject(signature,
     45                                                           *original_object_,
     46                                                           &validation_result_);
     47   }
     48 
     49   void ExpectValid() {
     50     EXPECT_EQ(Validator::VALID, validation_result_);
     51     EXPECT_TRUE(test_utils::Equals(original_object_.get(),
     52                                    repaired_object_.get()));
     53   }
     54 
     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()));
     59   }
     60 
     61   void ExpectInvalid() {
     62     EXPECT_EQ(Validator::INVALID, validation_result_);
     63     EXPECT_EQ(NULL, repaired_object_.get());
     64   }
     65 
     66  private:
     67   Validator::Result validation_result_;
     68   scoped_ptr<const base::DictionaryValue> original_object_;
     69   scoped_ptr<const base::DictionaryValue> repaired_object_;
     70 };
     71 
     72 namespace {
     73 
     74 struct OncParams {
     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,
     79             bool is_managed_onc,
     80             ONCSource onc_source = ONC_SOURCE_NONE)
     81       : location(location_of_object),
     82         signature(onc_signature),
     83         is_managed(is_managed_onc),
     84         onc_source(onc_source) {
     85   }
     86 
     87   std::string location;
     88   const OncValueSignature* signature;
     89   bool is_managed;
     90   ONCSource onc_source;
     91 };
     92 
     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) << ")";
     97 }
     98 
     99 }  // namespace
    100 
    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_SOURCE_NONE);
    106   ExpectValid();
    107 }
    108 
    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> {
    113 };
    114 
    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);
    119   ExpectValid();
    120 }
    121 
    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);
    126   ExpectValid();
    127 }
    128 
    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,
    136     ::testing::Values(OncParams("managed_toplevel1.onc",
    137                                 &kToplevelConfigurationSignature,
    138                                 true),
    139                       OncParams("managed_toplevel2.onc",
    140                                 &kToplevelConfigurationSignature,
    141                                 true),
    142                       // Check that at least one configuration is accepted for
    143                       // device policies.
    144                       OncParams("managed_toplevel_wifi_peap.onc",
    145                                 &kToplevelConfigurationSignature,
    146                                 true,
    147                                 ONC_SOURCE_DEVICE_POLICY),
    148                       OncParams("toplevel_wifi_wpa_psk.onc",
    149                                 &kToplevelConfigurationSignature,
    150                                 false),
    151                       OncParams("encrypted.onc",
    152                                 &kToplevelConfigurationSignature,
    153                                 true),
    154                       OncParams("managed_vpn.onc",
    155                                 &kNetworkConfigurationSignature,
    156                                 true),
    157                       OncParams("managed_ethernet.onc",
    158                                 &kNetworkConfigurationSignature,
    159                                 true),
    160                       OncParams("translation_of_shill_wifi_with_state.onc",
    161                                 &kNetworkWithStateSignature,
    162                                 false)));
    163 
    164 namespace {
    165 
    166 struct RepairParams {
    167   // Both arguments are strings to identify the object that is expected as the
    168   // validation result. They may either be used as filenames or as dictionary
    169   // keys.
    170   RepairParams(std::string strict_repaired,
    171                std::string liberal_repaired)
    172       : location_of_strict_repaired(strict_repaired),
    173         location_of_liberal_repaired(liberal_repaired) {
    174   }
    175 
    176   std::string location_of_strict_repaired;
    177   std::string location_of_liberal_repaired;
    178 };
    179 
    180 ::std::ostream& operator<<(::std::ostream& os, const RepairParams& rp) {
    181   return os << "(" << rp.location_of_strict_repaired << ", "
    182             << rp.location_of_liberal_repaired << ")";
    183 }
    184 
    185 }  // namespace
    186 
    187 // This test case is about validating ONC objects that contain errors which can
    188 // be repaired (then the errors count as warnings). If a location of the
    189 // expected repaired object is given, then it is checked that the validator
    190 // (either strict or liberal) returns this repaired object and the result is
    191 // VALID_WITH_WARNINGS. If the location is the empty string, then it is expected
    192 // that the validator returns NULL and the result INVALID.
    193 class ONCValidatorTestRepairable
    194     : public ONCValidatorTest,
    195       public ::testing::WithParamInterface<std::pair<OncParams,
    196                                                      RepairParams> > {
    197  public:
    198   // Load the common test data and return the dictionary at the field with
    199   // name |name|.
    200   scoped_ptr<base::DictionaryValue> GetDictionaryFromTestFile(
    201       const std::string &name) {
    202     scoped_ptr<const base::DictionaryValue> dict(
    203         test_utils::ReadTestDictionary("invalid_settings_with_repairs.json"));
    204     const base::DictionaryValue* onc_object = NULL;
    205     CHECK(dict->GetDictionary(name, &onc_object));
    206     return make_scoped_ptr(onc_object->DeepCopy());
    207   }
    208 };
    209 
    210 TEST_P(ONCValidatorTestRepairable, StrictValidation) {
    211   OncParams onc = GetParam().first;
    212   Validate(true, GetDictionaryFromTestFile(onc.location), onc.signature,
    213            onc.is_managed, onc.onc_source);
    214   std::string location_of_repaired =
    215       GetParam().second.location_of_strict_repaired;
    216   if (location_of_repaired.empty())
    217     ExpectInvalid();
    218   else
    219     ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired));
    220 }
    221 
    222 TEST_P(ONCValidatorTestRepairable, LiberalValidation) {
    223   OncParams onc = GetParam().first;
    224   Validate(false, GetDictionaryFromTestFile(onc.location), onc.signature,
    225            onc.is_managed, onc.onc_source);
    226   std::string location_of_repaired =
    227       GetParam().second.location_of_liberal_repaired;
    228   if (location_of_repaired.empty())
    229     ExpectInvalid();
    230   else
    231     ExpectRepairWithWarnings(*GetDictionaryFromTestFile(location_of_repaired));
    232 }
    233 
    234 // The parameters for all test case instantations below are:
    235 // OncParams(string: A fieldname in the dictionary from the file
    236 //                   "invalid_settings_with_repairs.json". That nested
    237 //                   dictionary will be tested.
    238 //           OncValueSignature: signature of that ONC,
    239 //           bool: true if the ONC is managed).
    240 // RepairParams(string: A fieldname in the dictionary from the file
    241 //                      "invalid_settings_with_repairs.json". That nested
    242 //                      dictionary is the expected result from strict
    243 //                      validation,
    244 //              string: A fieldname in the dictionary from the file
    245 //                      "invalid_settings_with_repairs.json". That nested
    246 //                      dictionary is the expected result from liberal
    247 //                      validation).
    248 
    249 // Strict validator returns INVALID. Liberal validator repairs.
    250 INSTANTIATE_TEST_CASE_P(
    251     StrictInvalidLiberalRepair,
    252     ONCValidatorTestRepairable,
    253     ::testing::Values(
    254          std::make_pair(OncParams("network-unknown-fieldname",
    255                                   &kNetworkConfigurationSignature,
    256                                   false),
    257                         RepairParams("", "network-repaired")),
    258          std::make_pair(OncParams("managed-network-unknown-fieldname",
    259                                   &kNetworkConfigurationSignature,
    260                                   true),
    261                         RepairParams("", "managed-network-repaired")),
    262          std::make_pair(OncParams("managed-network-unknown-recommended",
    263                                   &kNetworkConfigurationSignature,
    264                                   true),
    265                         RepairParams("", "managed-network-repaired")),
    266          std::make_pair(OncParams("managed-network-dict-recommended",
    267                                   &kNetworkConfigurationSignature,
    268                                   true),
    269                         RepairParams("", "managed-network-repaired")),
    270          std::make_pair(OncParams("network-missing-required",
    271                                   &kNetworkConfigurationSignature,
    272                                   false),
    273                         RepairParams("", "network-missing-required")),
    274          std::make_pair(OncParams("managed-network-missing-required",
    275                                   &kNetworkConfigurationSignature,
    276                                   true),
    277                         RepairParams("", "managed-network-missing-required")),
    278          // Ensure that state values from Shill aren't accepted as
    279          // configuration.
    280          std::make_pair(OncParams("network-state-field",
    281                                   &kNetworkConfigurationSignature,
    282                                   false),
    283                         RepairParams("", "network-repaired")),
    284          std::make_pair(OncParams("network-nested-state-field",
    285                                   &kNetworkConfigurationSignature,
    286                                   false),
    287                         RepairParams("",
    288                                      "network-nested-state-field-repaired")),
    289          std::make_pair(OncParams("toplevel-with-repairable-networks",
    290                                   &kToplevelConfigurationSignature,
    291                                   false,
    292                                   ONC_SOURCE_DEVICE_POLICY),
    293                         RepairParams("", "toplevel-with-repaired-networks"))));
    294 
    295 // Strict and liberal validator repair identically.
    296 INSTANTIATE_TEST_CASE_P(
    297     StrictAndLiberalRepairIdentically,
    298     ONCValidatorTestRepairable,
    299     ::testing::Values(
    300          std::make_pair(OncParams("toplevel-invalid-network",
    301                                   &kToplevelConfigurationSignature,
    302                                   false),
    303                         RepairParams("toplevel-repaired",
    304                                      "toplevel-repaired")),
    305          std::make_pair(OncParams("toplevel-invalid-network",
    306                                   &kToplevelConfigurationSignature,
    307                                   true),
    308                         RepairParams("toplevel-repaired",
    309                                      "toplevel-repaired")),
    310          // Ignore recommended arrays in unmanaged ONC.
    311          std::make_pair(OncParams("network-with-illegal-recommended",
    312                                   &kNetworkConfigurationSignature,
    313                                   false),
    314                         RepairParams("network-repaired", "network-repaired")),
    315          std::make_pair(OncParams("toplevel-with-vpn",
    316                                   &kToplevelConfigurationSignature,
    317                                   false,
    318                                   ONC_SOURCE_DEVICE_POLICY),
    319                         RepairParams("toplevel-empty", "toplevel-empty")),
    320          std::make_pair(OncParams("toplevel-with-server-and-ca-cert",
    321                                   &kToplevelConfigurationSignature,
    322                                   true,
    323                                   ONC_SOURCE_DEVICE_POLICY),
    324                         RepairParams("toplevel-server-and-ca-cert-dropped",
    325                                      "toplevel-server-and-ca-cert-dropped"))));
    326 
    327 // Strict and liberal validator both repair, but with different results.
    328 INSTANTIATE_TEST_CASE_P(
    329     StrictAndLiberalRepairDifferently,
    330     ONCValidatorTestRepairable,
    331     ::testing::Values(
    332          std::make_pair(OncParams("toplevel-with-nested-warning",
    333                                   &kToplevelConfigurationSignature,
    334                                   false),
    335                         RepairParams("toplevel-empty", "toplevel-repaired"))));
    336 
    337 // Strict and liberal validator return both INVALID.
    338 INSTANTIATE_TEST_CASE_P(
    339     StrictAndLiberalInvalid,
    340     ONCValidatorTestRepairable,
    341     ::testing::Values(
    342          std::make_pair(OncParams("network-unknown-value",
    343                                   &kNetworkConfigurationSignature, false),
    344                         RepairParams("", "")),
    345          std::make_pair(OncParams("managed-network-unknown-value",
    346                                   &kNetworkConfigurationSignature, true),
    347                         RepairParams("", "")),
    348          std::make_pair(OncParams("network-value-out-of-range",
    349                                   &kNetworkConfigurationSignature, false),
    350                         RepairParams("", "")),
    351          std::make_pair(OncParams("managed-network-value-out-of-range",
    352                                   &kNetworkConfigurationSignature, true),
    353                         RepairParams("", "")),
    354          std::make_pair(OncParams("network-wrong-type",
    355                                   &kNetworkConfigurationSignature, false),
    356                         RepairParams("", "")),
    357          std::make_pair(OncParams("managed-network-wrong-type",
    358                                   &kNetworkConfigurationSignature, true),
    359                         RepairParams("", "")),
    360          std::make_pair(OncParams("network-with-client-cert-pattern",
    361                                   &kNetworkConfigurationSignature, true,
    362                                   ONC_SOURCE_DEVICE_POLICY),
    363                         RepairParams("", ""))));
    364 
    365 }  // namespace onc
    366 }  // namespace chromeos
    367