[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / chromeos / network / onc / onc_validator.cc
blobd9173398b84919978295965850786bc5654a6eea
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.
5 #include "chromeos/network/onc/onc_validator.h"
7 #include <algorithm>
8 #include <string>
10 #include "base/json/json_writer.h"
11 #include "base/logging.h"
12 #include "base/string_number_conversions.h"
13 #include "base/string_util.h"
14 #include "base/values.h"
15 #include "chromeos/network/onc/onc_constants.h"
16 #include "chromeos/network/onc/onc_signature.h"
18 namespace chromeos {
19 namespace onc {
21 namespace {
23 std::string ValueToString(const base::Value& value) {
24 std::string json;
25 base::JSONWriter::Write(&value, &json);
26 return json;
29 // Copied from policy/configuration_policy_handler.cc.
30 // TODO(pneubeck): move to a common place like base/.
31 std::string ValueTypeToString(Value::Type type) {
32 static const char* strings[] = {
33 "null",
34 "boolean",
35 "integer",
36 "double",
37 "string",
38 "binary",
39 "dictionary",
40 "list"
42 CHECK(static_cast<size_t>(type) < arraysize(strings));
43 return strings[type];
46 } // namespace
48 Validator::Validator(
49 bool error_on_unknown_field,
50 bool error_on_wrong_recommended,
51 bool error_on_missing_field,
52 bool managed_onc)
53 : error_on_unknown_field_(error_on_unknown_field),
54 error_on_wrong_recommended_(error_on_wrong_recommended),
55 error_on_missing_field_(error_on_missing_field),
56 managed_onc_(managed_onc) {
59 Validator::~Validator() {
62 scoped_ptr<base::DictionaryValue> Validator::ValidateAndRepairObject(
63 const OncValueSignature* object_signature,
64 const base::DictionaryValue& onc_object,
65 Result* result) {
66 CHECK(object_signature != NULL);
67 *result = VALID;
68 error_or_warning_found_ = false;
69 bool error = false;
70 scoped_ptr<base::Value> result_value =
71 MapValue(*object_signature, onc_object, &error);
72 if (error) {
73 *result = INVALID;
74 result_value.reset();
75 } else if (error_or_warning_found_) {
76 *result = VALID_WITH_WARNINGS;
78 // The return value should be NULL if, and only if, |result| equals INVALID.
79 DCHECK_EQ(result_value.get() == NULL, *result == INVALID);
81 base::DictionaryValue* result_dict = NULL;
82 if (result_value.get() != NULL) {
83 result_value.release()->GetAsDictionary(&result_dict);
84 CHECK(result_dict != NULL);
87 return make_scoped_ptr(result_dict);
90 scoped_ptr<base::Value> Validator::MapValue(
91 const OncValueSignature& signature,
92 const base::Value& onc_value,
93 bool* error) {
94 if (onc_value.GetType() != signature.onc_type) {
95 LOG(ERROR) << ErrorHeader() << "Found value '" << onc_value
96 << "' of type '" << ValueTypeToString(onc_value.GetType())
97 << "', but type '" << ValueTypeToString(signature.onc_type)
98 << "' is required.";
99 error_or_warning_found_ = *error = true;
100 return scoped_ptr<base::Value>();
103 scoped_ptr<base::Value> repaired =
104 Mapper::MapValue(signature, onc_value, error);
105 if (repaired.get() != NULL)
106 CHECK_EQ(repaired->GetType(), signature.onc_type);
107 return repaired.Pass();
110 scoped_ptr<base::DictionaryValue> Validator::MapObject(
111 const OncValueSignature& signature,
112 const base::DictionaryValue& onc_object,
113 bool* error) {
114 scoped_ptr<base::DictionaryValue> repaired(new base::DictionaryValue);
116 bool valid;
117 if (&signature == &kToplevelConfigurationSignature)
118 valid = ValidateToplevelConfiguration(onc_object, repaired.get());
119 else if (&signature == &kNetworkConfigurationSignature)
120 valid = ValidateNetworkConfiguration(onc_object, repaired.get());
121 else if (&signature == &kEthernetSignature)
122 valid = ValidateEthernet(onc_object, repaired.get());
123 else if (&signature == &kIPConfigSignature)
124 valid = ValidateIPConfig(onc_object, repaired.get());
125 else if (&signature == &kWiFiSignature)
126 valid = ValidateWiFi(onc_object, repaired.get());
127 else if (&signature == &kVPNSignature)
128 valid = ValidateVPN(onc_object, repaired.get());
129 else if (&signature == &kIPsecSignature)
130 valid = ValidateIPsec(onc_object, repaired.get());
131 else if (&signature == &kOpenVPNSignature)
132 valid = ValidateOpenVPN(onc_object, repaired.get());
133 else if (&signature == &kCertificatePatternSignature)
134 valid = ValidateCertificatePattern(onc_object, repaired.get());
135 else if (&signature == &kProxySettingsSignature)
136 valid = ValidateProxySettings(onc_object, repaired.get());
137 else if (&signature == &kProxyLocationSignature)
138 valid = ValidateProxyLocation(onc_object, repaired.get());
139 else if (&signature == &kEAPSignature)
140 valid = ValidateEAP(onc_object, repaired.get());
141 else if (&signature == &kCertificateSignature)
142 valid = ValidateCertificate(onc_object, repaired.get());
143 else
144 valid = ValidateObjectDefault(signature, onc_object, repaired.get());
146 if (valid) {
147 return repaired.Pass();
148 } else {
149 error_or_warning_found_ = *error = true;
150 return scoped_ptr<base::DictionaryValue>();
154 scoped_ptr<base::Value> Validator::MapField(
155 const std::string& field_name,
156 const OncValueSignature& object_signature,
157 const base::Value& onc_value,
158 bool* found_unknown_field,
159 bool* error) {
160 path_.push_back(field_name);
161 bool current_field_unknown = false;
162 scoped_ptr<base::Value> result = Mapper::MapField(
163 field_name, object_signature, onc_value, &current_field_unknown, error);
165 DCHECK_EQ(field_name, path_.back());
166 path_.pop_back();
168 if (current_field_unknown) {
169 error_or_warning_found_ = *found_unknown_field = true;
170 std::string message = MessageHeader(error_on_unknown_field_)
171 + "Field name '" + field_name + "' is unknown.";
172 if (error_on_unknown_field_)
173 LOG(ERROR) << message;
174 else
175 LOG(WARNING) << message;
178 return result.Pass();
181 scoped_ptr<base::ListValue> Validator::MapArray(
182 const OncValueSignature& array_signature,
183 const base::ListValue& onc_array,
184 bool* nested_error) {
185 bool nested_error_in_current_array = false;
186 scoped_ptr<base::ListValue> result = Mapper::MapArray(
187 array_signature, onc_array, &nested_error_in_current_array);
189 // Drop individual networks and certificates instead of rejecting all of
190 // the configuration.
191 if (nested_error_in_current_array &&
192 &array_signature != &kNetworkConfigurationListSignature &&
193 &array_signature != &kCertificateListSignature) {
194 *nested_error = nested_error_in_current_array;
196 return result.Pass();
199 scoped_ptr<base::Value> Validator::MapEntry(int index,
200 const OncValueSignature& signature,
201 const base::Value& onc_value,
202 bool* error) {
203 std::string str = base::IntToString(index);
204 path_.push_back(str);
205 scoped_ptr<base::Value> result =
206 Mapper::MapEntry(index, signature, onc_value, error);
207 DCHECK_EQ(str, path_.back());
208 path_.pop_back();
209 return result.Pass();
212 bool Validator::ValidateObjectDefault(
213 const OncValueSignature& signature,
214 const base::DictionaryValue& onc_object,
215 base::DictionaryValue* result) {
216 bool found_unknown_field = false;
217 bool nested_error_occured = false;
218 MapFields(signature, onc_object, &found_unknown_field, &nested_error_occured,
219 result);
221 if (found_unknown_field && error_on_unknown_field_) {
222 DVLOG(1) << "Unknown field names are errors: Aborting.";
223 return false;
226 if (nested_error_occured)
227 return false;
229 return ValidateRecommendedField(signature, result);
232 bool Validator::ValidateRecommendedField(
233 const OncValueSignature& object_signature,
234 base::DictionaryValue* result) {
235 CHECK(result != NULL);
237 scoped_ptr<base::ListValue> recommended;
238 base::Value* recommended_value;
239 // This remove passes ownership to |recommended_value|.
240 if (!result->RemoveWithoutPathExpansion(onc::kRecommended,
241 &recommended_value)) {
242 return true;
244 base::ListValue* recommended_list;
245 recommended_value->GetAsList(&recommended_list);
246 CHECK(recommended_list != NULL);
248 recommended.reset(recommended_list);
250 if (!managed_onc_) {
251 error_or_warning_found_ = true;
252 LOG(WARNING) << WarningHeader() << "Found the field '" << onc::kRecommended
253 << "' in an unmanaged ONC. Removing it.";
254 return true;
257 scoped_ptr<base::ListValue> repaired_recommended(new base::ListValue);
258 for (base::ListValue::iterator it = recommended->begin();
259 it != recommended->end(); ++it) {
260 std::string field_name;
261 if (!(*it)->GetAsString(&field_name)) {
262 NOTREACHED();
263 continue;
266 const OncFieldSignature* field_signature =
267 GetFieldSignature(object_signature, field_name);
269 bool found_error = false;
270 std::string error_cause;
271 if (field_signature == NULL) {
272 found_error = true;
273 error_cause = "unknown";
274 } else if (field_signature->value_signature->onc_type ==
275 base::Value::TYPE_DICTIONARY) {
276 found_error = true;
277 error_cause = "dictionary-typed";
280 if (found_error) {
281 error_or_warning_found_ = true;
282 path_.push_back(onc::kRecommended);
283 std::string message = MessageHeader(error_on_wrong_recommended_) +
284 "The " + error_cause + " field '" + field_name +
285 "' cannot be recommended.";
286 path_.pop_back();
287 if (error_on_wrong_recommended_) {
288 LOG(ERROR) << message;
289 return false;
290 } else {
291 LOG(WARNING) << message;
292 continue;
296 repaired_recommended->Append((*it)->DeepCopy());
299 result->Set(onc::kRecommended, repaired_recommended.release());
300 return true;
303 namespace {
305 std::string JoinStringRange(const char** range_begin,
306 const char** range_end,
307 const std::string& separator) {
308 std::vector<std::string> string_vector;
309 std::copy(range_begin, range_end, std::back_inserter(string_vector));
310 return JoinString(string_vector, separator);
313 } // namespace
315 bool Validator::FieldExistsAndHasNoValidValue(
316 const base::DictionaryValue& object,
317 const std::string &field_name,
318 const char** valid_values) {
319 std::string actual_value;
320 if (!object.GetStringWithoutPathExpansion(field_name, &actual_value))
321 return false;
323 const char** it = valid_values;
324 for (; *it != NULL; ++it) {
325 if (actual_value == *it)
326 return false;
328 error_or_warning_found_ = true;
329 std::string valid_values_str =
330 "[" + JoinStringRange(valid_values, it, ", ") + "]";
331 path_.push_back(field_name);
332 LOG(ERROR) << ErrorHeader() << "Found value '" << actual_value <<
333 "', but expected one of the values " << valid_values_str;
334 path_.pop_back();
335 return true;
338 bool Validator::FieldExistsAndIsNotInRange(const base::DictionaryValue& object,
339 const std::string &field_name,
340 int lower_bound,
341 int upper_bound) {
342 int actual_value;
343 if (!object.GetIntegerWithoutPathExpansion(field_name, &actual_value) ||
344 (lower_bound <= actual_value && actual_value <= upper_bound)) {
345 return false;
347 error_or_warning_found_ = true;
348 path_.push_back(field_name);
349 LOG(ERROR) << ErrorHeader() << "Found value '" << actual_value
350 << "', but expected a value in the range [" << lower_bound
351 << ", " << upper_bound << "] (boundaries inclusive)";
352 path_.pop_back();
353 return true;
356 bool Validator::RequireField(const base::DictionaryValue& dict,
357 const std::string& field_name) {
358 if (dict.HasKey(field_name))
359 return true;
360 error_or_warning_found_ = true;
361 LOG(ERROR) << ErrorHeader() << "The required field '" << field_name
362 << "' is missing.";
363 return false;
366 bool Validator::ValidateToplevelConfiguration(
367 const base::DictionaryValue& onc_object,
368 base::DictionaryValue* result) {
369 if (!ValidateObjectDefault(kToplevelConfigurationSignature,
370 onc_object, result)) {
371 return false;
374 static const char* kValidTypes[] =
375 { kUnencryptedConfiguration, kEncryptedConfiguration, NULL };
376 if (FieldExistsAndHasNoValidValue(*result, kType, kValidTypes))
377 return false;
379 bool allRequiredExist = true;
381 // Not part of the ONC spec yet:
382 // We don't require the type field and default to UnencryptedConfiguration.
383 std::string type = kUnencryptedConfiguration;
384 result->GetStringWithoutPathExpansion(kType, &type);
385 if (type == kUnencryptedConfiguration &&
386 !result->HasKey(kNetworkConfigurations) &&
387 !result->HasKey(kCertificates)) {
388 error_or_warning_found_ = true;
389 std::string message = MessageHeader(error_on_missing_field_) +
390 "Neither the field '" + kNetworkConfigurations + "' nor '" +
391 kCertificates + "is present, but at least one is required.";
392 if (error_on_missing_field_)
393 LOG(ERROR) << message;
394 else
395 LOG(WARNING) << message;
396 allRequiredExist = false;
399 return !error_on_missing_field_ || allRequiredExist;
402 bool Validator::ValidateNetworkConfiguration(
403 const base::DictionaryValue& onc_object,
404 base::DictionaryValue* result) {
405 if (!ValidateObjectDefault(kNetworkConfigurationSignature,
406 onc_object, result)) {
407 return false;
410 static const char* kValidTypes[] = { kEthernet, kVPN, kWiFi, NULL };
411 if (FieldExistsAndHasNoValidValue(*result, kType, kValidTypes))
412 return false;
414 bool allRequiredExist = RequireField(*result, kGUID);
416 bool remove = false;
417 result->GetBooleanWithoutPathExpansion(kRemove, &remove);
418 if (!remove) {
419 allRequiredExist &= RequireField(*result, kName);
420 allRequiredExist &= RequireField(*result, kType);
422 std::string type;
423 result->GetStringWithoutPathExpansion(kType, &type);
424 allRequiredExist &= type.empty() || RequireField(*result, type);
427 return !error_on_missing_field_ || allRequiredExist;
430 bool Validator::ValidateEthernet(
431 const base::DictionaryValue& onc_object,
432 base::DictionaryValue* result) {
433 using namespace onc::ethernet;
434 if (!ValidateObjectDefault(kEthernetSignature, onc_object, result))
435 return false;
437 static const char* kValidAuthentications[] = { kNone, k8021X, NULL };
438 if (FieldExistsAndHasNoValidValue(*result, kAuthentication,
439 kValidAuthentications)) {
440 return false;
443 bool allRequiredExist = true;
444 std::string auth;
445 result->GetStringWithoutPathExpansion(kAuthentication, &auth);
446 if (auth == k8021X)
447 allRequiredExist &= RequireField(*result, kEAP);
449 return !error_on_missing_field_ || allRequiredExist;
452 bool Validator::ValidateIPConfig(
453 const base::DictionaryValue& onc_object,
454 base::DictionaryValue* result) {
455 using namespace onc::ipconfig;
456 if (!ValidateObjectDefault(kIPConfigSignature, onc_object, result))
457 return false;
459 static const char* kValidTypes[] = { kIPv4, kIPv6, NULL };
460 if (FieldExistsAndHasNoValidValue(*result, ipconfig::kType, kValidTypes))
461 return false;
463 std::string type;
464 result->GetStringWithoutPathExpansion(ipconfig::kType, &type);
465 int lower_bound = 1;
466 // In case of missing type, choose higher upper_bound.
467 int upper_bound = (type == kIPv4) ? 32 : 128;
468 if (FieldExistsAndIsNotInRange(*result, kRoutingPrefix,
469 lower_bound, upper_bound)) {
470 return false;
473 bool allRequiredExist = RequireField(*result, kIPAddress) &
474 RequireField(*result, kRoutingPrefix) &
475 RequireField(*result, ipconfig::kType);
477 return !error_on_missing_field_ || allRequiredExist;
480 bool Validator::ValidateWiFi(
481 const base::DictionaryValue& onc_object,
482 base::DictionaryValue* result) {
483 using namespace onc::wifi;
484 if (!ValidateObjectDefault(kWiFiSignature, onc_object, result))
485 return false;
487 static const char* kValidSecurities[] =
488 { kNone, kWEP_PSK, kWEP_8021X, kWPA_PSK, kWPA_EAP, NULL };
489 if (FieldExistsAndHasNoValidValue(*result, kSecurity, kValidSecurities))
490 return false;
492 bool allRequiredExist = RequireField(*result, kSecurity) &
493 RequireField(*result, kSSID);
495 std::string security;
496 result->GetStringWithoutPathExpansion(kSecurity, &security);
497 if (security == kWEP_8021X || security == kWPA_EAP)
498 allRequiredExist &= RequireField(*result, kEAP);
499 else if (security == kWEP_PSK || security == kWPA_PSK)
500 allRequiredExist &= RequireField(*result, kPassphrase);
502 return !error_on_missing_field_ || allRequiredExist;
505 bool Validator::ValidateVPN(
506 const base::DictionaryValue& onc_object,
507 base::DictionaryValue* result) {
508 using namespace vpn;
509 if (!ValidateObjectDefault(kVPNSignature, onc_object, result))
510 return false;
512 static const char* kValidTypes[] =
513 { kIPsec, kTypeL2TP_IPsec, kOpenVPN, NULL };
514 if (FieldExistsAndHasNoValidValue(*result, vpn::kType, kValidTypes))
515 return false;
517 bool allRequiredExist = RequireField(*result, vpn::kType);
518 std::string type;
519 result->GetStringWithoutPathExpansion(vpn::kType, &type);
520 if (type == kOpenVPN) {
521 allRequiredExist &= RequireField(*result, kOpenVPN);
522 } else if (type == kIPsec) {
523 allRequiredExist &= RequireField(*result, kIPsec);
524 } else if (type == kTypeL2TP_IPsec) {
525 allRequiredExist &= RequireField(*result, kIPsec) &
526 RequireField(*result, kL2TP);
529 return !error_on_missing_field_ || allRequiredExist;
532 bool Validator::ValidateIPsec(
533 const base::DictionaryValue& onc_object,
534 base::DictionaryValue* result) {
535 using namespace onc::vpn;
536 using namespace onc::certificate;
537 if (!ValidateObjectDefault(kIPsecSignature, onc_object, result))
538 return false;
540 static const char* kValidAuthentications[] = { kPSK, kCert, NULL };
541 static const char* kValidCertTypes[] = { kRef, kPattern, NULL };
542 // Using strict bit-wise OR to check all conditions.
543 if (FieldExistsAndHasNoValidValue(*result, kAuthenticationType,
544 kValidAuthentications) |
545 FieldExistsAndHasNoValidValue(*result, kClientCertType,
546 kValidCertTypes)) {
547 return false;
550 bool allRequiredExist = RequireField(*result, kAuthenticationType) &
551 RequireField(*result, kIKEVersion);
552 std::string auth;
553 result->GetStringWithoutPathExpansion(kAuthenticationType, &auth);
554 if (auth == kCert) {
555 allRequiredExist &= RequireField(*result, kClientCertType) &
556 RequireField(*result, kServerCARef);
558 std::string cert_type;
559 result->GetStringWithoutPathExpansion(kClientCertType, &cert_type);
560 if (cert_type == kPattern)
561 allRequiredExist &= RequireField(*result, kClientCertPattern);
562 else if (cert_type == kRef)
563 allRequiredExist &= RequireField(*result, kClientCertRef);
565 return !error_on_missing_field_ || allRequiredExist;
568 bool Validator::ValidateOpenVPN(
569 const base::DictionaryValue& onc_object,
570 base::DictionaryValue* result) {
571 using namespace onc::vpn;
572 using namespace onc::openvpn;
573 using namespace onc::certificate;
574 if (!ValidateObjectDefault(kOpenVPNSignature, onc_object, result))
575 return false;
577 static const char* kValidAuthRetryValues[] =
578 { openvpn::kNone, kInteract, kNoInteract, NULL };
579 static const char* kValidCertTypes[] =
580 { certificate::kNone, kRef, kPattern, NULL };
581 static const char* kValidCertTlsValues[] =
582 { openvpn::kNone, openvpn::kServer, NULL };
584 // Using strict bit-wise OR to check all conditions.
585 if (FieldExistsAndHasNoValidValue(*result, kAuthRetry,
586 kValidAuthRetryValues) |
587 FieldExistsAndHasNoValidValue(*result, kClientCertType, kValidCertTypes) |
588 FieldExistsAndHasNoValidValue(*result, kRemoteCertTLS,
589 kValidCertTlsValues)) {
590 return false;
593 bool allRequiredExist = RequireField(*result, kClientCertType);
594 std::string cert_type;
595 result->GetStringWithoutPathExpansion(kClientCertType, &cert_type);
596 if (cert_type == kPattern)
597 allRequiredExist &= RequireField(*result, kClientCertPattern);
598 else if (cert_type == kRef)
599 allRequiredExist &= RequireField(*result, kClientCertRef);
601 return !error_on_missing_field_ || allRequiredExist;
604 bool Validator::ValidateCertificatePattern(
605 const base::DictionaryValue& onc_object,
606 base::DictionaryValue* result) {
607 using namespace onc::certificate;
608 if (!ValidateObjectDefault(kCertificatePatternSignature, onc_object, result))
609 return false;
611 bool allRequiredExist = true;
612 if (!result->HasKey(kSubject) && !result->HasKey(kIssuer) &&
613 !result->HasKey(kIssuerCARef)) {
614 error_or_warning_found_ = true;
615 allRequiredExist = false;
616 std::string message = MessageHeader(error_on_missing_field_) +
617 "None of the fields '" + kSubject + "', '" + kIssuer + "', and '" +
618 kIssuerCARef + "' is present, but at least one is required.";
619 if (error_on_missing_field_)
620 LOG(ERROR) << message;
621 else
622 LOG(WARNING) << message;
625 return !error_on_missing_field_ || allRequiredExist;
628 bool Validator::ValidateProxySettings(const base::DictionaryValue& onc_object,
629 base::DictionaryValue* result) {
630 using namespace onc::proxy;
631 if (!ValidateObjectDefault(kProxySettingsSignature, onc_object, result))
632 return false;
634 static const char* kValidTypes[] = { kDirect, kManual, kPAC, kWPAD, NULL };
635 if (FieldExistsAndHasNoValidValue(*result, proxy::kType, kValidTypes))
636 return false;
638 bool allRequiredExist = RequireField(*result, proxy::kType);
639 std::string type;
640 result->GetStringWithoutPathExpansion(proxy::kType, &type);
641 if (type == kManual)
642 allRequiredExist &= RequireField(*result, kManual);
643 else if (type == kPAC)
644 allRequiredExist &= RequireField(*result, kPAC);
646 return !error_on_missing_field_ || allRequiredExist;
649 bool Validator::ValidateProxyLocation(const base::DictionaryValue& onc_object,
650 base::DictionaryValue* result) {
651 using namespace onc::proxy;
652 if (!ValidateObjectDefault(kProxyLocationSignature, onc_object, result))
653 return false;
655 bool allRequiredExist = RequireField(*result, kHost) &
656 RequireField(*result, kPort);
658 return !error_on_missing_field_ || allRequiredExist;
661 bool Validator::ValidateEAP(const base::DictionaryValue& onc_object,
662 base::DictionaryValue* result) {
663 using namespace onc::eap;
664 using namespace onc::certificate;
665 if (!ValidateObjectDefault(kEAPSignature, onc_object, result))
666 return false;
668 static const char* kValidInnerValues[] =
669 { kAutomatic, kMD5, kMSCHAPv2, kPAP, NULL };
670 static const char* kValidOuterValues[] =
671 { kPEAP, kEAP_TLS, kEAP_TTLS, kLEAP, kEAP_SIM, kEAP_FAST, kEAP_AKA,
672 NULL };
673 static const char* kValidCertTypes[] = { kRef, kPattern, NULL };
675 // Using strict bit-wise OR to check all conditions.
676 if (FieldExistsAndHasNoValidValue(*result, kInner, kValidInnerValues) |
677 FieldExistsAndHasNoValidValue(*result, kOuter, kValidOuterValues) |
678 FieldExistsAndHasNoValidValue(*result, kClientCertType,
679 kValidCertTypes)) {
680 return false;
683 bool allRequiredExist = RequireField(*result, kOuter);
684 std::string cert_type;
685 result->GetStringWithoutPathExpansion(kClientCertType, &cert_type);
686 if (cert_type == kPattern)
687 allRequiredExist &= RequireField(*result, kClientCertPattern);
688 else if (cert_type == kRef)
689 allRequiredExist &= RequireField(*result, kClientCertRef);
691 return !error_on_missing_field_ || allRequiredExist;
694 bool Validator::ValidateCertificate(
695 const base::DictionaryValue& onc_object,
696 base::DictionaryValue* result) {
697 using namespace onc::certificate;
698 if (!ValidateObjectDefault(kCertificateSignature, onc_object, result))
699 return false;
701 static const char* kValidTypes[] = { kClient, kServer, kAuthority, NULL };
702 if (FieldExistsAndHasNoValidValue(*result, certificate::kType, kValidTypes))
703 return false;
705 bool allRequiredExist = RequireField(*result, kGUID);
707 bool remove = false;
708 result->GetBooleanWithoutPathExpansion(kRemove, &remove);
709 if (!remove) {
710 allRequiredExist &= RequireField(*result, certificate::kType);
712 std::string type;
713 result->GetStringWithoutPathExpansion(certificate::kType, &type);
714 if (type == kClient)
715 allRequiredExist &= RequireField(*result, kPKCS12);
716 else if (type == kServer || type == kAuthority)
717 allRequiredExist &= RequireField(*result, kX509);
720 return !error_on_missing_field_ || allRequiredExist;
723 std::string Validator::WarningHeader() {
724 return MessageHeader(false);
727 std::string Validator::ErrorHeader() {
728 return MessageHeader(true);
731 std::string Validator::MessageHeader(bool is_error) {
732 std::string path = path_.empty() ? "toplevel" : JoinString(path_, ".");
733 std::string message = "At " + path + ": ";
734 return message;
737 } // namespace onc
738 } // namespace chromeos