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"
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"
23 std::string
ValueToString(const base::Value
& value
) {
25 base::JSONWriter::Write(&value
, &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
[] = {
42 CHECK(static_cast<size_t>(type
) < arraysize(strings
));
49 bool error_on_unknown_field
,
50 bool error_on_wrong_recommended
,
51 bool error_on_missing_field
,
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
,
66 CHECK(object_signature
!= NULL
);
68 error_or_warning_found_
= false;
70 scoped_ptr
<base::Value
> result_value
=
71 MapValue(*object_signature
, onc_object
, &error
);
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
,
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
)
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
,
114 scoped_ptr
<base::DictionaryValue
> repaired(new base::DictionaryValue
);
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());
144 valid
= ValidateObjectDefault(signature
, onc_object
, repaired
.get());
147 return repaired
.Pass();
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
,
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
, ¤t_field_unknown
, error
);
165 DCHECK_EQ(field_name
, path_
.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
;
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
,
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());
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
,
221 if (found_unknown_field
&& error_on_unknown_field_
) {
222 DVLOG(1) << "Unknown field names are errors: Aborting.";
226 if (nested_error_occured
)
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
)) {
244 base::ListValue
* recommended_list
;
245 recommended_value
->GetAsList(&recommended_list
);
246 CHECK(recommended_list
!= NULL
);
248 recommended
.reset(recommended_list
);
251 error_or_warning_found_
= true;
252 LOG(WARNING
) << WarningHeader() << "Found the field '" << onc::kRecommended
253 << "' in an unmanaged ONC. Removing it.";
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
)) {
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
) {
273 error_cause
= "unknown";
274 } else if (field_signature
->value_signature
->onc_type
==
275 base::Value::TYPE_DICTIONARY
) {
277 error_cause
= "dictionary-typed";
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.";
287 if (error_on_wrong_recommended_
) {
288 LOG(ERROR
) << message
;
291 LOG(WARNING
) << message
;
296 repaired_recommended
->Append((*it
)->DeepCopy());
299 result
->Set(onc::kRecommended
, repaired_recommended
.release());
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
);
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
))
323 const char** it
= valid_values
;
324 for (; *it
!= NULL
; ++it
) {
325 if (actual_value
== *it
)
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
;
338 bool Validator::FieldExistsAndIsNotInRange(const base::DictionaryValue
& object
,
339 const std::string
&field_name
,
343 if (!object
.GetIntegerWithoutPathExpansion(field_name
, &actual_value
) ||
344 (lower_bound
<= actual_value
&& actual_value
<= upper_bound
)) {
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)";
356 bool Validator::RequireField(const base::DictionaryValue
& dict
,
357 const std::string
& field_name
) {
358 if (dict
.HasKey(field_name
))
360 error_or_warning_found_
= true;
361 LOG(ERROR
) << ErrorHeader() << "The required field '" << field_name
366 bool Validator::ValidateToplevelConfiguration(
367 const base::DictionaryValue
& onc_object
,
368 base::DictionaryValue
* result
) {
369 if (!ValidateObjectDefault(kToplevelConfigurationSignature
,
370 onc_object
, result
)) {
374 static const char* kValidTypes
[] =
375 { kUnencryptedConfiguration
, kEncryptedConfiguration
, NULL
};
376 if (FieldExistsAndHasNoValidValue(*result
, kType
, kValidTypes
))
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
;
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
)) {
410 static const char* kValidTypes
[] = { kEthernet
, kVPN
, kWiFi
, NULL
};
411 if (FieldExistsAndHasNoValidValue(*result
, kType
, kValidTypes
))
414 bool allRequiredExist
= RequireField(*result
, kGUID
);
417 result
->GetBooleanWithoutPathExpansion(kRemove
, &remove
);
419 allRequiredExist
&= RequireField(*result
, kName
);
420 allRequiredExist
&= RequireField(*result
, kType
);
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
))
437 static const char* kValidAuthentications
[] = { kNone
, k8021X
, NULL
};
438 if (FieldExistsAndHasNoValidValue(*result
, kAuthentication
,
439 kValidAuthentications
)) {
443 bool allRequiredExist
= true;
445 result
->GetStringWithoutPathExpansion(kAuthentication
, &auth
);
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
))
459 static const char* kValidTypes
[] = { kIPv4
, kIPv6
, NULL
};
460 if (FieldExistsAndHasNoValidValue(*result
, ipconfig::kType
, kValidTypes
))
464 result
->GetStringWithoutPathExpansion(ipconfig::kType
, &type
);
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
)) {
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
))
487 static const char* kValidSecurities
[] =
488 { kNone
, kWEP_PSK
, kWEP_8021X
, kWPA_PSK
, kWPA_EAP
, NULL
};
489 if (FieldExistsAndHasNoValidValue(*result
, kSecurity
, kValidSecurities
))
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
) {
509 if (!ValidateObjectDefault(kVPNSignature
, onc_object
, result
))
512 static const char* kValidTypes
[] =
513 { kIPsec
, kTypeL2TP_IPsec
, kOpenVPN
, NULL
};
514 if (FieldExistsAndHasNoValidValue(*result
, vpn::kType
, kValidTypes
))
517 bool allRequiredExist
= RequireField(*result
, vpn::kType
);
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
))
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
,
550 bool allRequiredExist
= RequireField(*result
, kAuthenticationType
) &
551 RequireField(*result
, kIKEVersion
);
553 result
->GetStringWithoutPathExpansion(kAuthenticationType
, &auth
);
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
))
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
)) {
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
))
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
;
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
))
634 static const char* kValidTypes
[] = { kDirect
, kManual
, kPAC
, kWPAD
, NULL
};
635 if (FieldExistsAndHasNoValidValue(*result
, proxy::kType
, kValidTypes
))
638 bool allRequiredExist
= RequireField(*result
, proxy::kType
);
640 result
->GetStringWithoutPathExpansion(proxy::kType
, &type
);
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
))
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
))
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
,
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
,
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
))
701 static const char* kValidTypes
[] = { kClient
, kServer
, kAuthority
, NULL
};
702 if (FieldExistsAndHasNoValidValue(*result
, certificate::kType
, kValidTypes
))
705 bool allRequiredExist
= RequireField(*result
, kGUID
);
708 result
->GetBooleanWithoutPathExpansion(kRemove
, &remove
);
710 allRequiredExist
&= RequireField(*result
, certificate::kType
);
713 result
->GetStringWithoutPathExpansion(certificate::kType
, &type
);
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
+ ": ";
738 } // namespace chromeos