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#ifndef CHROMEOS_NETWORK_ONC_ONC_VALIDATOR_H_
6#define CHROMEOS_NETWORK_ONC_ONC_VALIDATOR_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/memory/scoped_ptr.h"
13#include "chromeos/chromeos_export.h"
14#include "chromeos/network/onc/onc_mapper.h"
15#include "components/onc/onc_constants.h"
16
17namespace base {
18class DictionaryValue;
19class Value;
20}
21
22namespace chromeos {
23namespace onc {
24
25struct OncValueSignature;
26
27// The ONC Validator searches for the following invalid cases:
28// - a value is found that has the wrong type or is not expected according to
29//   the ONC spec (always an error)
30//
31// - a field name is found that is not part of the signature
32//   (controlled by flag |error_on_unknown_field|)
33//
34// - a kRecommended array contains a field name that is not part of the
35//   enclosing object's signature or if that field is dictionary typed
36//   (controlled by flag |error_on_wrong_recommended|)
37//
38// - |managed_onc| is false and a field with name kRecommended is found
39//   (always ignored)
40//
41// - a required field is missing (controlled by flag |error_on_missing_field|)
42//
43// If one of these invalid cases occurs and, in case of a controlling flag, that
44// flag is true, then it is an error. The function ValidateAndRepairObject sets
45// |result| to INVALID and returns NULL.
46//
47// Otherwise, a DeepCopy of the validated object is created, which contains
48// all but the invalid fields and values.
49//
50// If one of the invalid cases occurs and the controlling flag is false, then
51// it is a warning. The function ValidateAndRepairObject sets |result| to
52// VALID_WITH_WARNINGS and returns the repaired copy.
53//
54// If no error occurred, |result| is set to VALID and an exact DeepCopy is
55// returned.
56class CHROMEOS_EXPORT Validator : public Mapper {
57 public:
58  enum Result {
59    VALID,
60    VALID_WITH_WARNINGS,
61    INVALID
62  };
63
64  // See the class comment.
65  Validator(bool error_on_unknown_field,
66            bool error_on_wrong_recommended,
67            bool error_on_missing_field,
68            bool managed_onc);
69
70  virtual ~Validator();
71
72  // Sets the ONC source to |source|. If not set, defaults to ONC_SOURCE_NONE.
73  // If the source is set to ONC_SOURCE_DEVICE_POLICY, validation additionally
74  // checks:
75  // - only the network types Wifi and Ethernet are allowed
76  // - client certificate patterns are disallowed
77  void SetOncSource(::onc::ONCSource source) {
78    onc_source_ = source;
79  }
80
81  // Validate the given |onc_object| according to |object_signature|. The
82  // |object_signature| has to be a pointer to one of the signatures in
83  // |onc_signature.h|. If an error is found, the function returns NULL and sets
84  // |result| to INVALID. If possible (no error encountered) a DeepCopy is
85  // created that contains all but the invalid fields and values and returns
86  // this "repaired" object. That means, if not handled as an error, then the
87  // following are dropped from the copy:
88  // - unknown fields
89  // - invalid field names in kRecommended arrays
90  // - kRecommended fields in an unmanaged ONC
91  // If any of these cases occurred, sets |result| to VALID_WITH_WARNINGS and
92  // otherwise to VALID.
93  // For details, see the class comment.
94  scoped_ptr<base::DictionaryValue> ValidateAndRepairObject(
95      const OncValueSignature* object_signature,
96      const base::DictionaryValue& onc_object,
97      Result* result);
98
99 private:
100  // Overridden from Mapper:
101  // Compare |onc_value|s type with |onc_type| and validate/repair according to
102  // |signature|. On error returns NULL.
103  virtual scoped_ptr<base::Value> MapValue(const OncValueSignature& signature,
104                                           const base::Value& onc_value,
105                                           bool* error) OVERRIDE;
106
107  // Dispatch to the right validation function according to
108  // |signature|. Iterates over all fields and recursively validates/repairs
109  // these. All valid fields are added to the result dictionary. Returns the
110  // repaired dictionary. Only on error returns NULL.
111  virtual scoped_ptr<base::DictionaryValue> MapObject(
112      const OncValueSignature& signature,
113      const base::DictionaryValue& onc_object,
114      bool* error) OVERRIDE;
115
116  // Pushes/pops the |field_name| to |path_|, otherwise like |Mapper::MapField|.
117  virtual scoped_ptr<base::Value> MapField(
118      const std::string& field_name,
119      const OncValueSignature& object_signature,
120      const base::Value& onc_value,
121      bool* found_unknown_field,
122      bool* error) OVERRIDE;
123
124  // Ignores nested errors in NetworkConfigurations and Certificates, otherwise
125  // like |Mapper::MapArray|.
126  virtual scoped_ptr<base::ListValue> MapArray(
127      const OncValueSignature& array_signature,
128      const base::ListValue& onc_array,
129      bool* nested_error) OVERRIDE;
130
131  // Pushes/pops the index to |path_|, otherwise like |Mapper::MapEntry|.
132  virtual scoped_ptr<base::Value> MapEntry(int index,
133                                           const OncValueSignature& signature,
134                                           const base::Value& onc_value,
135                                           bool* error) OVERRIDE;
136
137  // This is the default validation of objects/dictionaries. Validates
138  // |onc_object| according to |object_signature|. |result| must point to a
139  // dictionary into which the repaired fields are written.
140  bool ValidateObjectDefault(const OncValueSignature& object_signature,
141                             const base::DictionaryValue& onc_object,
142                             base::DictionaryValue* result);
143
144  // Validates/repairs the kRecommended array in |result| according to
145  // |object_signature| of the enclosing object.
146  bool ValidateRecommendedField(const OncValueSignature& object_signature,
147                                base::DictionaryValue* result);
148
149  // Validates the ClientCert* fields in a VPN or EAP object. Only if
150  // |allow_cert_type_none| is true, the value "None" is allowed as
151  // ClientCertType.
152  bool ValidateClientCertFields(bool allow_cert_type_none,
153                                base::DictionaryValue* result);
154
155  bool ValidateToplevelConfiguration(base::DictionaryValue* result);
156  bool ValidateNetworkConfiguration(base::DictionaryValue* result);
157  bool ValidateEthernet(base::DictionaryValue* result);
158  bool ValidateIPConfig(base::DictionaryValue* result);
159  bool ValidateWiFi(base::DictionaryValue* result);
160  bool ValidateVPN(base::DictionaryValue* result);
161  bool ValidateIPsec(base::DictionaryValue* result);
162  bool ValidateOpenVPN(base::DictionaryValue* result);
163  bool ValidateVerifyX509(base::DictionaryValue* result);
164  bool ValidateCertificatePattern(base::DictionaryValue* result);
165  bool ValidateProxySettings(base::DictionaryValue* result);
166  bool ValidateProxyLocation(base::DictionaryValue* result);
167  bool ValidateEAP(base::DictionaryValue* result);
168  bool ValidateCertificate(base::DictionaryValue* result);
169
170  bool FieldExistsAndHasNoValidValue(
171      const base::DictionaryValue& object,
172      const std::string& field_name,
173      const std::vector<const char*>& valid_values);
174
175  bool FieldExistsAndIsNotInRange(const base::DictionaryValue& object,
176                                  const std::string &field_name,
177                                  int lower_bound,
178                                  int upper_bound);
179
180  bool FieldExistsAndIsEmpty(const base::DictionaryValue& object,
181                             const std::string& field_name);
182
183  bool RequireField(const base::DictionaryValue& dict, const std::string& key);
184
185  // Returns true if the GUID is unique or if the GUID is not a string
186  // and false otherwise. The function also adds the GUID to a set in
187  // order to identify duplicates.
188  bool CheckGuidIsUniqueAndAddToSet(const base::DictionaryValue& dict,
189                                    const std::string& kGUID,
190                                    std::set<std::string> *guids);
191
192  // Prohibit certificate patterns for device policy ONC so that an unmanaged
193  // user won't have a certificate presented for them involuntarily.
194  bool IsCertPatternInDevicePolicy(const std::string& cert_type);
195
196  // Prohibit global network configuration in user ONC imports.
197  bool IsGlobalNetworkConfigInUserImport(
198      const base::DictionaryValue& onc_object);
199
200  std::string MessageHeader();
201
202  const bool error_on_unknown_field_;
203  const bool error_on_wrong_recommended_;
204  const bool error_on_missing_field_;
205  const bool managed_onc_;
206
207  ::onc::ONCSource onc_source_;
208
209  // The path of field names and indices to the current value. Indices
210  // are stored as strings in decimal notation.
211  std::vector<std::string> path_;
212
213  // Accumulates all network GUIDs during validation. Used to identify
214  // duplicate GUIDs.
215  std::set<std::string> network_guids_;
216
217  // Accumulates all certificate GUIDs during validation. Used to identify
218  // duplicate GUIDs.
219  std::set<std::string> certificate_guids_;
220
221  // Tracks if an error or warning occurred within validation initiated by
222  // function ValidateAndRepairObject.
223  bool error_or_warning_found_;
224
225  DISALLOW_COPY_AND_ASSIGN(Validator);
226};
227
228}  // namespace onc
229}  // namespace chromeos
230
231#endif  // CHROMEOS_NETWORK_ONC_ONC_VALIDATOR_H_
232