• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PrintHelp()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 
ReadDictionary(std::string filename)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 
main(int argc,const char * argv[])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