1 // Copyright (c) 2011 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 <cstdio> 6 #include <iostream> 7 8 #include "base/basictypes.h" 9 #include "base/command_line.h" 10 #include "base/files/file_path.h" 11 #include "base/json/json_file_value_serializer.h" 12 #include "base/logging.h" 13 #include "base/values.h" 14 #include "chromeos/network/onc/onc_signature.h" 15 #include "chromeos/network/onc/onc_validator.h" 16 17 // Command line switches. 18 const char kSwitchErrorOnUnknownField[] = "error-on-unknown-field"; 19 const char kSwitchErrorOnWrongRecommended[] = "error-on-wrong-recommended"; 20 const char kSwitchErrorOnMissingField[] = "error-on-missing-field"; 21 const char kSwitchManagedOnc[] = "managed-onc"; 22 const char kSwitchUserPolicy[] = "user-policy"; 23 const char kSwitchDevicePolicy[] = "device-policy"; 24 const char kSwitchUserImport[] = "user-import"; 25 26 const char* kSwitches[] = { 27 kSwitchErrorOnUnknownField, 28 kSwitchErrorOnWrongRecommended, 29 kSwitchErrorOnMissingField, 30 kSwitchManagedOnc, 31 kSwitchUserPolicy, 32 kSwitchDevicePolicy, 33 kSwitchUserImport 34 }; 35 36 // Return codes. 37 enum ReturnCode { 38 kStatusValid = 0, 39 kStatusWarnings = 1, 40 kStatusInvalid = 2, 41 kStatusJsonError = 3, 42 kStatusArgumentError = 4, 43 }; 44 45 const char kToplevelConfiguration[] = "ToplevelConfiguration"; 46 const char kNetworkConfiguration[] = "NetworkConfiguration"; 47 const char kCertificate[] = "Certificate"; 48 const char* kTypes[] = { 49 kToplevelConfiguration, 50 kNetworkConfiguration, 51 kCertificate 52 }; 53 54 void PrintHelp() { 55 fprintf(stderr, 56 "Usage:\n" 57 " onc_validator [OPTION]... [TYPE] onc_file\n" 58 "\n" 59 "Valid TYPEs are:\n"); 60 for (size_t i = 0; i < arraysize(kTypes); ++i) 61 fprintf(stderr, " %s\n", kTypes[i]); 62 63 fprintf(stderr, 64 "\n" 65 "Valid OPTIONs are:\n"); 66 for (size_t i = 0; i < arraysize(kSwitches); ++i) 67 fprintf(stderr, " --%s\n", kSwitches[i]); 68 69 fprintf(stderr, 70 "\n" 71 "Exit status is one of:\n" 72 " %i File is valid without warnings.\n" 73 " %i File is valid with warnings,\n" 74 " i.e. there were errors which were degraded to warnings.\n" 75 " %i File is invalid.\n" 76 " %i File couldn't be read or is not a valid JSON dictionary.\n" 77 " %i Some command line arguments are wrong.\n", 78 kStatusValid, 79 kStatusWarnings, 80 kStatusInvalid, 81 kStatusJsonError, 82 kStatusArgumentError); 83 } 84 85 scoped_ptr<base::DictionaryValue> ReadDictionary(std::string filename) { 86 base::FilePath path(filename); 87 JSONFileValueSerializer serializer(path); 88 serializer.set_allow_trailing_comma(true); 89 90 base::DictionaryValue* dict = NULL; 91 92 std::string json_error; 93 base::Value* value = serializer.Deserialize(NULL, &json_error); 94 if (!value) { 95 LOG(ERROR) << "Couldn't json-deserialize file '" << filename 96 << "': " << json_error; 97 return make_scoped_ptr(dict); 98 } 99 100 if (!value->GetAsDictionary(&dict)) { 101 LOG(ERROR) << "File '" << filename 102 << "' does not contain a dictionary as expected, but type " 103 << value->GetType(); 104 } 105 106 return make_scoped_ptr(dict); 107 } 108 109 int main(int argc, const char* argv[]) { 110 CommandLine::Init(argc, argv); 111 112 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 113 CommandLine::StringVector args = command_line.GetArgs(); 114 if (args.size() != 2) { 115 PrintHelp(); 116 return kStatusArgumentError; 117 } 118 119 scoped_ptr<base::DictionaryValue> onc_object = ReadDictionary(args[1]); 120 121 if (!onc_object) 122 return kStatusJsonError; 123 124 chromeos::onc::Validator validator( 125 command_line.HasSwitch(kSwitchErrorOnUnknownField), 126 command_line.HasSwitch(kSwitchErrorOnWrongRecommended), 127 command_line.HasSwitch(kSwitchErrorOnMissingField), 128 command_line.HasSwitch(kSwitchManagedOnc)); 129 130 if (command_line.HasSwitch(kSwitchUserPolicy)) 131 validator.SetOncSource(::onc::ONC_SOURCE_USER_POLICY); 132 else if (command_line.HasSwitch(kSwitchDevicePolicy)) 133 validator.SetOncSource(::onc::ONC_SOURCE_DEVICE_POLICY); 134 else if (command_line.HasSwitch(kSwitchUserImport)) 135 validator.SetOncSource(::onc::ONC_SOURCE_USER_IMPORT); 136 137 std::string type_arg(args[0]); 138 const chromeos::onc::OncValueSignature* signature = NULL; 139 if (type_arg == kToplevelConfiguration) { 140 signature = &chromeos::onc::kToplevelConfigurationSignature; 141 } else if (type_arg == kNetworkConfiguration) { 142 signature = &chromeos::onc::kNetworkConfigurationSignature; 143 } else if (type_arg == kCertificate) { 144 signature = &chromeos::onc::kCertificateSignature; 145 } else { 146 LOG(ERROR) << "Unknown ONC type '" << type_arg << "'"; 147 return kStatusArgumentError; 148 } 149 150 chromeos::onc::Validator::Result result; 151 validator.ValidateAndRepairObject(signature, *onc_object, &result); 152 153 switch(result) { 154 case chromeos::onc::Validator::VALID: 155 return kStatusValid; 156 case chromeos::onc::Validator::VALID_WITH_WARNINGS: 157 return kStatusWarnings; 158 case chromeos::onc::Validator::INVALID: 159 return kStatusInvalid; 160 default: 161 CHECK(false); 162 } 163 } 164