| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMEOS_COMPONENTS_ONC_ONC_VALIDATOR_H_ |
| #define CHROMEOS_COMPONENTS_ONC_ONC_VALIDATOR_H_ |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/component_export.h" |
| #include "base/values.h" |
| #include "chromeos/components/onc/onc_mapper.h" |
| #include "components/onc/onc_constants.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace chromeos::onc { |
| |
| struct OncValueSignature; |
| |
| // *** ONC Validator Modes of Operation *** |
| // The ONC validator supports different modes of operation depending on the |
| // combination of flags passed to the constructor. |
| // |
| // ** |log_warnings| ** |
| // If this flag is set to true, warnings will be logged. |
| // |
| // ** |error_on_unknown_field| ** |
| // If this flag is set to true, and error will be logged in case of unknown |
| // fields are encountered in the ONC to be validated and the validation will |
| // fail. If it is set to false, a warning will be logged instead and the |
| // validation will not fail for that cause. |
| // |
| // ** |error_on_wrong_recommended| ** |
| // If this flag is set to true, an error will be logged and the validation will |
| // fail in case of encountering recommended fields that are not expected to be |
| // recommended. If it is set to false, a warning will be logged instead and the |
| // validation will not fail for that cause. |
| // |
| // ** |managed_onc| ** |
| // ONC set by policy are validated differently from ONC set through UI. |
| // Set this flag to true if policy is the source of the ONC to be validated. |
| // |
| // The ONC Validator searches for the following invalid cases: |
| // - a value is found that has the wrong type or is not expected according to |
| // the ONC spec (always an error) |
| // |
| // - a field name is found that is not part of the signature |
| // (controlled by flag |error_on_unknown_field|) |
| // |
| // - a kRecommended array contains a field name that is not part of the |
| // enclosing object's signature or if that field is dictionary typed |
| // (controlled by flag |error_on_wrong_recommended|) |
| // |
| // - |managed_onc| is false and a field with name kRecommended is found |
| // (always ignored) |
| // |
| // - a required field is missing. Controlled by flag |error_on_missing_field|. |
| // If true this is an error. If false, a message is logged but no error or |
| // warning is flagged. |
| // |
| // If one of these invalid cases occurs and, in case of a controlling flag, that |
| // flag is true, then it is an error. The function ValidateAndRepairObject sets |
| // |result| to INVALID and returns NULL. |
| // |
| // Otherwise, a DeepCopy of the validated object is created, which contains |
| // all but the invalid fields and values. |
| // |
| // If one of the invalid cases occurs and the controlling flag is false, then |
| // it is a warning. The function ValidateAndRepairObject sets |result| to |
| // VALID_WITH_WARNINGS and returns the repaired copy. |
| // |
| // If no error occurred, |result| is set to VALID and an exact DeepCopy is |
| // returned. |
| class COMPONENT_EXPORT(CHROMEOS_ONC) Validator : public Mapper { |
| public: |
| enum Result { VALID, VALID_WITH_WARNINGS, INVALID }; |
| |
| struct ValidationIssue { |
| // If true, the ONC value does not adhere to the specification and may be |
| // rejected. |
| bool is_error; |
| |
| // Detailed description containing the error/warning type and specific |
| // location (path). |
| std::string message; |
| }; |
| |
| // See the class comment. |
| Validator(bool error_on_unknown_field, |
| bool error_on_wrong_recommended, |
| bool error_on_missing_field, |
| bool managed_onc, |
| bool log_warnings); |
| |
| Validator(const Validator&) = delete; |
| Validator& operator=(const Validator&) = delete; |
| |
| ~Validator() override; |
| |
| // Sets the ONC source to |source|. If not set, defaults to ONC_SOURCE_NONE. |
| // If the source is set to ONC_SOURCE_DEVICE_POLICY, validation additionally |
| // checks: |
| // - only the network types Wifi and Ethernet are allowed |
| // - client certificate patterns are disallowed |
| void SetOncSource(::onc::ONCSource source) { onc_source_ = source; } |
| |
| // Validate the given |onc_object| dictionary according to |object_signature|. |
| // The |object_signature| has to be a pointer to one of the signatures in |
| // |onc_signature.h|. If an error is found, the function returns nullopt and |
| // sets |result| to INVALID. If possible (no error encountered) a Clone is |
| // created that contains all but the invalid fields and values and returns |
| // this "repaired" object. That means, if not handled as an error, then the |
| // following are dropped from the copy: |
| // - unknown fields |
| // - invalid field names in kRecommended arrays |
| // - kRecommended fields in an unmanaged ONC |
| // If any of these cases occurred, sets |result| to VALID_WITH_WARNINGS and |
| // otherwise to VALID. |
| // For details, see the class comment. |
| absl::optional<base::Value::Dict> ValidateAndRepairObject( |
| const OncValueSignature* object_signature, |
| const base::Value::Dict& onc_object, |
| Result* result); |
| |
| // Returns the list of validation results that occurred within validation |
| // initiated by the last call to |ValidateAndRepairObject|. |
| const std::vector<ValidationIssue>& validation_issues() const { |
| return validation_issues_; |
| } |
| |
| private: |
| // Overridden from Mapper: |
| // Compare |onc_value|s type with |onc_type| and validate/repair according to |
| // |signature|. On error returns a Value of type base::Value::Type::NONE. |
| base::Value MapValue(const OncValueSignature& signature, |
| const base::Value& onc_value, |
| bool* error) override; |
| |
| // Dispatch to the right validation function according to |
| // |signature|. Iterates over all fields and recursively validates/repairs |
| // these. All valid fields are added to the result dictionary. Returns the |
| // repaired dictionary. |
| base::Value::Dict MapObject(const OncValueSignature& signature, |
| const base::Value::Dict& onc_object, |
| bool* error) override; |
| |
| // Pushes/pops the |field_name| to |path_|, otherwise like |Mapper::MapField|. |
| base::Value MapField(const std::string& field_name, |
| const OncValueSignature& object_signature, |
| const base::Value& onc_value, |
| bool* found_unknown_field, |
| bool* error) override; |
| |
| // Ignores nested errors in NetworkConfigurations and Certificates, otherwise |
| // like |Mapper::MapArray|. |
| base::Value::List MapArray(const OncValueSignature& array_signature, |
| const base::Value::List& onc_array, |
| bool* nested_error) override; |
| |
| // Pushes/pops the index to |path_|, otherwise like |Mapper::MapEntry|. |
| base::Value MapEntry(int index, |
| const OncValueSignature& signature, |
| const base::Value& onc_value, |
| bool* error) override; |
| |
| // This is the default validation of objects/dictionaries. Validates |
| // |onc_object| according to |object_signature|. |result| must point to a |
| // dictionary into which the repaired fields are written. |
| bool ValidateObjectDefault(const OncValueSignature& object_signature, |
| const base::Value::Dict& onc_object, |
| base::Value::Dict* result); |
| |
| // Validates/repairs the kRecommended array in |result| according to |
| // |object_signature| of the enclosing object. |
| bool ValidateRecommendedField(const OncValueSignature& object_signature, |
| base::Value::Dict* result); |
| |
| // Validates the ClientCert* fields in a VPN or EAP object. Only if |
| // |allow_cert_type_none| is true, the value "None" is allowed as |
| // ClientCertType. |
| bool ValidateClientCertFields(bool allow_cert_type_none, |
| base::Value::Dict* result); |
| |
| bool ValidateToplevelConfiguration(base::Value::Dict* result); |
| bool ValidateNetworkConfiguration(base::Value::Dict* result); |
| bool ValidateCellular(base::Value::Dict* result); |
| bool ValidateEthernet(base::Value::Dict* result); |
| bool ValidateIPConfig(base::Value::Dict* result, bool require_fields = true); |
| bool ValidateNameServersConfig(base::Value::Dict* result); |
| bool ValidateWiFi(base::Value::Dict* result); |
| bool ValidateVPN(base::Value::Dict* result); |
| bool ValidateIPsec(base::Value::Dict* result); |
| bool ValidateOpenVPN(base::Value::Dict* result); |
| bool ValidateWireGuard(base::Value::Dict* result); |
| bool ValidateThirdPartyVPN(base::Value::Dict* result); |
| bool ValidateARCVPN(base::Value::Dict* result); |
| bool ValidateVerifyX509(base::Value::Dict* result); |
| bool ValidateCertificatePattern(base::Value::Dict* result); |
| bool ValidateGlobalNetworkConfiguration(base::Value::Dict* result); |
| bool ValidateProxySettings(base::Value::Dict* result); |
| bool ValidateProxyLocation(base::Value::Dict* result); |
| bool ValidateEAP(base::Value::Dict* result); |
| bool ValidateSubjectAlternativeNameMatch(base::Value::Dict* result); |
| bool ValidateCertificate(base::Value::Dict* result); |
| bool ValidateScope(base::Value::Dict* result); |
| bool ValidateTether(base::Value::Dict* result); |
| void ValidateEthernetConfigs(base::Value::List* result); |
| void OnlyKeepLast(base::Value::List* network_configurations_list, |
| const std::vector<std::string>& guids, |
| const char* type_for_messages); |
| void RemoveNetworkConfigurationWithGuid( |
| base::Value::List* network_configurations_list, |
| const std::string& guid_to_remove); |
| |
| bool IsValidValue(const std::string& field_value, |
| const std::vector<const char*>& valid_values); |
| |
| bool IsInDevicePolicy(base::Value::Dict* result, |
| const std::string& field_name); |
| |
| bool FieldExistsAndHasNoValidValue( |
| const base::Value::Dict& object, |
| const std::string& field_name, |
| const std::vector<const char*>& valid_values); |
| |
| bool FieldExistsAndIsNotInRange(const base::Value::Dict& object, |
| const std::string& field_name, |
| int lower_bound, |
| int upper_bound); |
| |
| bool FieldExistsAndIsEmpty(const base::Value::Dict& object, |
| const std::string& field_name); |
| |
| // Validates 'StaticIPConfig' field of the given network configuration. This |
| // method takes 'NetworkConfiguration' dict instead of 'StaticIPConfig' dict |
| // because it needs other 'NetworkConfiguration' fields (e.g. |
| // 'IPAddressConfigType' and 'NameServersConfigType') to check correctness of |
| // the 'StaticIPConfig' field. |
| bool NetworkHasCorrectStaticIPConfig(base::Value::Dict* network); |
| |
| // Validates that the given field either exists or is recommended. |
| bool FieldShouldExistOrBeRecommended(const base::Value::Dict& object, |
| const std::string& field_name); |
| |
| bool OnlyOneFieldSet(const base::Value::Dict& object, |
| const std::string& field_name1, |
| const std::string& field_name2); |
| |
| bool ListFieldContainsValidValues( |
| const base::Value::Dict& object, |
| const std::string& field_name, |
| const std::vector<const char*>& valid_values); |
| |
| bool ValidateSSIDAndHexSSID(base::Value::Dict* object); |
| |
| // Returns true if |key| is a key of |dict|. Otherwise, returns false and, |
| // depending on |error_on_missing_field_| raises an error or a warning. |
| bool RequireField(const base::Value::Dict& dict, const std::string& key); |
| |
| // Returns true if the GUID is unique or if the GUID is not a string |
| // and false otherwise. The function also adds the GUID to a set in |
| // order to identify duplicates. |
| bool CheckGuidIsUniqueAndAddToSet(const base::Value::Dict& dict, |
| const std::string& kGUID, |
| std::set<std::string>* guids); |
| |
| // Prohibit global network configuration in user ONC imports. |
| bool IsGlobalNetworkConfigInUserImport(const base::Value::Dict& onc_object); |
| |
| void AddValidationIssue(bool is_error, const std::string& debug_info); |
| |
| const bool error_on_unknown_field_; |
| const bool error_on_wrong_recommended_; |
| const bool error_on_missing_field_; |
| const bool managed_onc_; |
| const bool log_warnings_; |
| |
| ::onc::ONCSource onc_source_ = ::onc::ONC_SOURCE_NONE; |
| |
| // The path of field names and indices to the current value. Indices |
| // are stored as strings in decimal notation. |
| std::vector<std::string> path_; |
| |
| // Accumulates all network GUIDs during validation. Used to identify |
| // duplicate GUIDs. |
| std::set<std::string> network_guids_; |
| |
| // Accumulates all certificate GUIDs during validation. Used to identify |
| // duplicate GUIDs. |
| std::set<std::string> certificate_guids_; |
| |
| // List of all validation issues that occurred within validation initiated by |
| // function ValidateAndRepairObject. |
| std::vector<ValidationIssue> validation_issues_; |
| }; |
| |
| } // namespace chromeos::onc |
| |
| #endif // CHROMEOS_COMPONENTS_ONC_ONC_VALIDATOR_H_ |