ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chromeos / network / onc / onc_utils.cc
blob6045ef17f9a7faac4d7eb42b7fb3475004621860
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_utils.h"
7 #include "base/base64.h"
8 #include "base/json/json_reader.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/values.h"
14 #include "chromeos/network/network_event_log.h"
15 #include "chromeos/network/onc/onc_mapper.h"
16 #include "chromeos/network/onc/onc_signature.h"
17 #include "chromeos/network/onc/onc_utils.h"
18 #include "chromeos/network/onc/onc_validator.h"
19 #include "crypto/encryptor.h"
20 #include "crypto/hmac.h"
21 #include "crypto/symmetric_key.h"
22 #include "net/cert/pem_tokenizer.h"
23 #include "net/cert/x509_certificate.h"
25 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message)
26 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message)
28 using namespace ::onc;
30 namespace chromeos {
31 namespace onc {
33 namespace {
35 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC";
36 const char kUnableToDecode[] = "Unable to decode encrypted ONC";
38 } // namespace
40 const char kEmptyUnencryptedConfiguration[] =
41 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[],"
42 "\"Certificates\":[]}";
44 scoped_ptr<base::DictionaryValue> ReadDictionaryFromJson(
45 const std::string& json) {
46 std::string error;
47 base::Value* root = base::JSONReader::ReadAndReturnError(
48 json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error);
50 base::DictionaryValue* dict_ptr = NULL;
51 if (!root || !root->GetAsDictionary(&dict_ptr)) {
52 ONC_LOG_ERROR("Invalid JSON Dictionary: " + error);
53 delete root;
56 return make_scoped_ptr(dict_ptr);
59 scoped_ptr<base::DictionaryValue> Decrypt(const std::string& passphrase,
60 const base::DictionaryValue& root) {
61 const int kKeySizeInBits = 256;
62 const int kMaxIterationCount = 500000;
63 std::string onc_type;
64 std::string initial_vector;
65 std::string salt;
66 std::string cipher;
67 std::string stretch_method;
68 std::string hmac_method;
69 std::string hmac;
70 int iterations;
71 std::string ciphertext;
73 if (!root.GetString(encrypted::kCiphertext, &ciphertext) ||
74 !root.GetString(encrypted::kCipher, &cipher) ||
75 !root.GetString(encrypted::kHMAC, &hmac) ||
76 !root.GetString(encrypted::kHMACMethod, &hmac_method) ||
77 !root.GetString(encrypted::kIV, &initial_vector) ||
78 !root.GetInteger(encrypted::kIterations, &iterations) ||
79 !root.GetString(encrypted::kSalt, &salt) ||
80 !root.GetString(encrypted::kStretch, &stretch_method) ||
81 !root.GetString(toplevel_config::kType, &onc_type) ||
82 onc_type != toplevel_config::kEncryptedConfiguration) {
84 ONC_LOG_ERROR("Encrypted ONC malformed.");
85 return scoped_ptr<base::DictionaryValue>();
88 if (hmac_method != encrypted::kSHA1 ||
89 cipher != encrypted::kAES256 ||
90 stretch_method != encrypted::kPBKDF2) {
91 ONC_LOG_ERROR("Encrypted ONC unsupported encryption scheme.");
92 return scoped_ptr<base::DictionaryValue>();
95 // Make sure iterations != 0, since that's not valid.
96 if (iterations == 0) {
97 ONC_LOG_ERROR(kUnableToDecrypt);
98 return scoped_ptr<base::DictionaryValue>();
101 // Simply a sanity check to make sure we can't lock up the machine
102 // for too long with a huge number (or a negative number).
103 if (iterations < 0 || iterations > kMaxIterationCount) {
104 ONC_LOG_ERROR("Too many iterations in encrypted ONC");
105 return scoped_ptr<base::DictionaryValue>();
108 if (!base::Base64Decode(salt, &salt)) {
109 ONC_LOG_ERROR(kUnableToDecode);
110 return scoped_ptr<base::DictionaryValue>();
113 scoped_ptr<crypto::SymmetricKey> key(
114 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
115 passphrase,
116 salt,
117 iterations,
118 kKeySizeInBits));
120 if (!base::Base64Decode(initial_vector, &initial_vector)) {
121 ONC_LOG_ERROR(kUnableToDecode);
122 return scoped_ptr<base::DictionaryValue>();
124 if (!base::Base64Decode(ciphertext, &ciphertext)) {
125 ONC_LOG_ERROR(kUnableToDecode);
126 return scoped_ptr<base::DictionaryValue>();
128 if (!base::Base64Decode(hmac, &hmac)) {
129 ONC_LOG_ERROR(kUnableToDecode);
130 return scoped_ptr<base::DictionaryValue>();
133 crypto::HMAC hmac_verifier(crypto::HMAC::SHA1);
134 if (!hmac_verifier.Init(key.get()) ||
135 !hmac_verifier.Verify(ciphertext, hmac)) {
136 ONC_LOG_ERROR(kUnableToDecrypt);
137 return scoped_ptr<base::DictionaryValue>();
140 crypto::Encryptor decryptor;
141 if (!decryptor.Init(key.get(), crypto::Encryptor::CBC, initial_vector)) {
142 ONC_LOG_ERROR(kUnableToDecrypt);
143 return scoped_ptr<base::DictionaryValue>();
146 std::string plaintext;
147 if (!decryptor.Decrypt(ciphertext, &plaintext)) {
148 ONC_LOG_ERROR(kUnableToDecrypt);
149 return scoped_ptr<base::DictionaryValue>();
152 scoped_ptr<base::DictionaryValue> new_root =
153 ReadDictionaryFromJson(plaintext);
154 if (new_root.get() == NULL) {
155 ONC_LOG_ERROR("Property dictionary malformed.");
156 return scoped_ptr<base::DictionaryValue>();
159 return new_root.Pass();
162 std::string GetSourceAsString(ONCSource source) {
163 switch (source) {
164 case ONC_SOURCE_UNKNOWN:
165 return "unknown";
166 case ONC_SOURCE_NONE:
167 return "none";
168 case ONC_SOURCE_DEVICE_POLICY:
169 return "device policy";
170 case ONC_SOURCE_USER_POLICY:
171 return "user policy";
172 case ONC_SOURCE_USER_IMPORT:
173 return "user import";
175 NOTREACHED() << "unknown ONC source " << source;
176 return "unknown";
179 void ExpandField(const std::string& fieldname,
180 const StringSubstitution& substitution,
181 base::DictionaryValue* onc_object) {
182 std::string user_string;
183 if (!onc_object->GetStringWithoutPathExpansion(fieldname, &user_string))
184 return;
186 std::string login_id;
187 if (substitution.GetSubstitute(substitutes::kLoginIDField, &login_id)) {
188 ReplaceSubstringsAfterOffset(&user_string, 0,
189 substitutes::kLoginIDField,
190 login_id);
193 std::string email;
194 if (substitution.GetSubstitute(substitutes::kEmailField, &email)) {
195 ReplaceSubstringsAfterOffset(&user_string, 0,
196 substitutes::kEmailField,
197 email);
200 onc_object->SetStringWithoutPathExpansion(fieldname, user_string);
203 void ExpandStringsInOncObject(
204 const OncValueSignature& signature,
205 const StringSubstitution& substitution,
206 base::DictionaryValue* onc_object) {
207 if (&signature == &kEAPSignature) {
208 ExpandField(eap::kAnonymousIdentity, substitution, onc_object);
209 ExpandField(eap::kIdentity, substitution, onc_object);
210 } else if (&signature == &kL2TPSignature ||
211 &signature == &kOpenVPNSignature) {
212 ExpandField(vpn::kUsername, substitution, onc_object);
215 // Recurse into nested objects.
216 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
217 it.Advance()) {
218 base::DictionaryValue* inner_object = NULL;
219 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object))
220 continue;
222 const OncFieldSignature* field_signature =
223 GetFieldSignature(signature, it.key());
224 if (!field_signature)
225 continue;
227 ExpandStringsInOncObject(*field_signature->value_signature,
228 substitution, inner_object);
232 void ExpandStringsInNetworks(const StringSubstitution& substitution,
233 base::ListValue* network_configs) {
234 for (base::ListValue::iterator it = network_configs->begin();
235 it != network_configs->end(); ++it) {
236 base::DictionaryValue* network = NULL;
237 (*it)->GetAsDictionary(&network);
238 DCHECK(network);
239 ExpandStringsInOncObject(
240 kNetworkConfigurationSignature, substitution, network);
244 void FillInHexSSIDFieldsInOncObject(const OncValueSignature& signature,
245 base::DictionaryValue* onc_object) {
246 if (&signature == &kWiFiSignature)
247 FillInHexSSIDField(onc_object);
249 // Recurse into nested objects.
250 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
251 it.Advance()) {
252 base::DictionaryValue* inner_object = nullptr;
253 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object))
254 continue;
256 const OncFieldSignature* field_signature =
257 GetFieldSignature(signature, it.key());
258 if (!field_signature)
259 continue;
261 FillInHexSSIDFieldsInOncObject(*field_signature->value_signature,
262 inner_object);
266 void FillInHexSSIDField(base::DictionaryValue* wifi_fields) {
267 if (!wifi_fields->HasKey(::onc::wifi::kHexSSID)) {
268 std::string ssid_string;
269 wifi_fields->GetStringWithoutPathExpansion(::onc::wifi::kSSID,
270 &ssid_string);
271 wifi_fields->SetStringWithoutPathExpansion(
272 ::onc::wifi::kHexSSID,
273 base::HexEncode(ssid_string.c_str(), ssid_string.size()));
277 namespace {
279 class OncMaskValues : public Mapper {
280 public:
281 static scoped_ptr<base::DictionaryValue> Mask(
282 const OncValueSignature& signature,
283 const base::DictionaryValue& onc_object,
284 const std::string& mask) {
285 OncMaskValues masker(mask);
286 bool unused_error;
287 return masker.MapObject(signature, onc_object, &unused_error);
290 protected:
291 explicit OncMaskValues(const std::string& mask)
292 : mask_(mask) {
295 scoped_ptr<base::Value> MapField(const std::string& field_name,
296 const OncValueSignature& object_signature,
297 const base::Value& onc_value,
298 bool* found_unknown_field,
299 bool* error) override {
300 if (FieldIsCredential(object_signature, field_name)) {
301 return scoped_ptr<base::Value>(new base::StringValue(mask_));
302 } else {
303 return Mapper::MapField(field_name, object_signature, onc_value,
304 found_unknown_field, error);
308 // Mask to insert in place of the sensitive values.
309 std::string mask_;
312 } // namespace
314 scoped_ptr<base::DictionaryValue> MaskCredentialsInOncObject(
315 const OncValueSignature& signature,
316 const base::DictionaryValue& onc_object,
317 const std::string& mask) {
318 return OncMaskValues::Mask(signature, onc_object, mask);
321 namespace {
323 std::string DecodePEM(const std::string& pem_encoded) {
324 // The PEM block header used for DER certificates
325 const char kCertificateHeader[] = "CERTIFICATE";
327 // This is an older PEM marker for DER certificates.
328 const char kX509CertificateHeader[] = "X509 CERTIFICATE";
330 std::vector<std::string> pem_headers;
331 pem_headers.push_back(kCertificateHeader);
332 pem_headers.push_back(kX509CertificateHeader);
334 net::PEMTokenizer pem_tokenizer(pem_encoded, pem_headers);
335 std::string decoded;
336 if (pem_tokenizer.GetNext()) {
337 decoded = pem_tokenizer.data();
338 } else {
339 // If we failed to read the data as a PEM file, then try plain base64 decode
340 // in case the PEM marker strings are missing. For this to work, there has
341 // to be no white space, and it has to only contain the base64-encoded data.
342 if (!base::Base64Decode(pem_encoded, &decoded)) {
343 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded;
344 return std::string();
347 return decoded;
350 CertPEMsByGUIDMap GetServerAndCACertsByGUID(
351 const base::ListValue& certificates) {
352 CertPEMsByGUIDMap certs_by_guid;
353 for (base::ListValue::const_iterator it = certificates.begin();
354 it != certificates.end(); ++it) {
355 base::DictionaryValue* cert = NULL;
356 (*it)->GetAsDictionary(&cert);
358 std::string guid;
359 cert->GetStringWithoutPathExpansion(certificate::kGUID, &guid);
360 std::string cert_type;
361 cert->GetStringWithoutPathExpansion(certificate::kType, &cert_type);
362 if (cert_type != certificate::kServer &&
363 cert_type != certificate::kAuthority) {
364 continue;
366 std::string x509_data;
367 cert->GetStringWithoutPathExpansion(certificate::kX509, &x509_data);
369 std::string der = DecodePEM(x509_data);
370 std::string pem;
371 if (der.empty() || !net::X509Certificate::GetPEMEncodedFromDER(der, &pem)) {
372 LOG(ERROR) << "Certificate with GUID " << guid
373 << " is not in PEM encoding.";
374 continue;
376 certs_by_guid[guid] = pem;
379 return certs_by_guid;
382 void FillInHexSSIDFieldsInNetworks(base::ListValue* network_configs) {
383 for (base::ListValue::iterator it = network_configs->begin();
384 it != network_configs->end(); ++it) {
385 base::DictionaryValue* network = NULL;
386 (*it)->GetAsDictionary(&network);
387 DCHECK(network);
388 FillInHexSSIDFieldsInOncObject(kNetworkConfigurationSignature, network);
392 } // namespace
394 bool ParseAndValidateOncForImport(const std::string& onc_blob,
395 ONCSource onc_source,
396 const std::string& passphrase,
397 base::ListValue* network_configs,
398 base::DictionaryValue* global_network_config,
399 base::ListValue* certificates) {
400 network_configs->Clear();
401 global_network_config->Clear();
402 certificates->Clear();
403 if (onc_blob.empty())
404 return true;
406 scoped_ptr<base::DictionaryValue> toplevel_onc =
407 ReadDictionaryFromJson(onc_blob);
408 if (toplevel_onc.get() == NULL) {
409 LOG(ERROR) << "ONC loaded from " << GetSourceAsString(onc_source)
410 << " is not a valid JSON dictionary.";
411 return false;
414 // Check and see if this is an encrypted ONC file. If so, decrypt it.
415 std::string onc_type;
416 toplevel_onc->GetStringWithoutPathExpansion(toplevel_config::kType,
417 &onc_type);
418 if (onc_type == toplevel_config::kEncryptedConfiguration) {
419 toplevel_onc = Decrypt(passphrase, *toplevel_onc);
420 if (toplevel_onc.get() == NULL) {
421 LOG(ERROR) << "Couldn't decrypt the ONC from "
422 << GetSourceAsString(onc_source);
423 return false;
427 bool from_policy = (onc_source == ONC_SOURCE_USER_POLICY ||
428 onc_source == ONC_SOURCE_DEVICE_POLICY);
430 // Validate the ONC dictionary. We are liberal and ignore unknown field
431 // names and ignore invalid field names in kRecommended arrays.
432 Validator validator(false, // Ignore unknown fields.
433 false, // Ignore invalid recommended field names.
434 true, // Fail on missing fields.
435 from_policy);
436 validator.SetOncSource(onc_source);
438 Validator::Result validation_result;
439 toplevel_onc = validator.ValidateAndRepairObject(
440 &kToplevelConfigurationSignature,
441 *toplevel_onc,
442 &validation_result);
444 if (from_policy) {
445 UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation",
446 validation_result == Validator::VALID);
449 bool success = true;
450 if (validation_result == Validator::VALID_WITH_WARNINGS) {
451 LOG(WARNING) << "ONC from " << GetSourceAsString(onc_source)
452 << " produced warnings.";
453 success = false;
454 } else if (validation_result == Validator::INVALID || toplevel_onc == NULL) {
455 LOG(ERROR) << "ONC from " << GetSourceAsString(onc_source)
456 << " is invalid and couldn't be repaired.";
457 return false;
460 base::ListValue* validated_certs = NULL;
461 if (toplevel_onc->GetListWithoutPathExpansion(toplevel_config::kCertificates,
462 &validated_certs)) {
463 certificates->Swap(validated_certs);
466 base::ListValue* validated_networks = NULL;
467 if (toplevel_onc->GetListWithoutPathExpansion(
468 toplevel_config::kNetworkConfigurations, &validated_networks)) {
469 FillInHexSSIDFieldsInNetworks(validated_networks);
471 CertPEMsByGUIDMap server_and_ca_certs =
472 GetServerAndCACertsByGUID(*certificates);
474 if (!ResolveServerCertRefsInNetworks(server_and_ca_certs,
475 validated_networks)) {
476 LOG(ERROR) << "Some certificate references in the ONC policy for source "
477 << GetSourceAsString(onc_source) << " could not be resolved.";
478 success = false;
481 network_configs->Swap(validated_networks);
484 base::DictionaryValue* validated_global_config = NULL;
485 if (toplevel_onc->GetDictionaryWithoutPathExpansion(
486 toplevel_config::kGlobalNetworkConfiguration,
487 &validated_global_config)) {
488 global_network_config->Swap(validated_global_config);
491 return success;
494 scoped_refptr<net::X509Certificate> DecodePEMCertificate(
495 const std::string& pem_encoded) {
496 std::string decoded = DecodePEM(pem_encoded);
497 scoped_refptr<net::X509Certificate> cert =
498 net::X509Certificate::CreateFromBytes(decoded.data(), decoded.size());
499 LOG_IF(ERROR, !cert.get()) << "Couldn't create certificate from X509 data: "
500 << decoded;
501 return cert;
504 namespace {
506 bool GUIDRefToPEMEncoding(const CertPEMsByGUIDMap& certs_by_guid,
507 const std::string& guid_ref,
508 std::string* pem_encoded) {
509 CertPEMsByGUIDMap::const_iterator it = certs_by_guid.find(guid_ref);
510 if (it == certs_by_guid.end()) {
511 LOG(ERROR) << "Couldn't resolve certificate reference " << guid_ref;
512 return false;
514 *pem_encoded = it->second;
515 if (pem_encoded->empty()) {
516 LOG(ERROR) << "Couldn't PEM-encode certificate with GUID " << guid_ref;
517 return false;
519 return true;
522 bool ResolveSingleCertRef(const CertPEMsByGUIDMap& certs_by_guid,
523 const std::string& key_guid_ref,
524 const std::string& key_pem,
525 base::DictionaryValue* onc_object) {
526 std::string guid_ref;
527 if (!onc_object->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref))
528 return true;
530 std::string pem_encoded;
531 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded))
532 return false;
534 onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL);
535 onc_object->SetStringWithoutPathExpansion(key_pem, pem_encoded);
536 return true;
539 bool ResolveCertRefList(const CertPEMsByGUIDMap& certs_by_guid,
540 const std::string& key_guid_ref_list,
541 const std::string& key_pem_list,
542 base::DictionaryValue* onc_object) {
543 const base::ListValue* guid_ref_list = NULL;
544 if (!onc_object->GetListWithoutPathExpansion(key_guid_ref_list,
545 &guid_ref_list)) {
546 return true;
549 scoped_ptr<base::ListValue> pem_list(new base::ListValue);
550 for (base::ListValue::const_iterator it = guid_ref_list->begin();
551 it != guid_ref_list->end(); ++it) {
552 std::string guid_ref;
553 (*it)->GetAsString(&guid_ref);
555 std::string pem_encoded;
556 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded))
557 return false;
559 pem_list->AppendString(pem_encoded);
562 onc_object->RemoveWithoutPathExpansion(key_guid_ref_list, NULL);
563 onc_object->SetWithoutPathExpansion(key_pem_list, pem_list.release());
564 return true;
567 bool ResolveSingleCertRefToList(const CertPEMsByGUIDMap& certs_by_guid,
568 const std::string& key_guid_ref,
569 const std::string& key_pem_list,
570 base::DictionaryValue* onc_object) {
571 std::string guid_ref;
572 if (!onc_object->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref))
573 return true;
575 std::string pem_encoded;
576 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded))
577 return false;
579 scoped_ptr<base::ListValue> pem_list(new base::ListValue);
580 pem_list->AppendString(pem_encoded);
581 onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL);
582 onc_object->SetWithoutPathExpansion(key_pem_list, pem_list.release());
583 return true;
586 // Resolves the reference list at |key_guid_refs| if present and otherwise the
587 // single reference at |key_guid_ref|. Returns whether the respective resolving
588 // was successful.
589 bool ResolveCertRefsOrRefToList(const CertPEMsByGUIDMap& certs_by_guid,
590 const std::string& key_guid_refs,
591 const std::string& key_guid_ref,
592 const std::string& key_pem_list,
593 base::DictionaryValue* onc_object) {
594 if (onc_object->HasKey(key_guid_refs)) {
595 if (onc_object->HasKey(key_guid_ref)) {
596 LOG(ERROR) << "Found both " << key_guid_refs << " and " << key_guid_ref
597 << ". Ignoring and removing the latter.";
598 onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL);
600 return ResolveCertRefList(
601 certs_by_guid, key_guid_refs, key_pem_list, onc_object);
604 // Only resolve |key_guid_ref| if |key_guid_refs| isn't present.
605 return ResolveSingleCertRefToList(
606 certs_by_guid, key_guid_ref, key_pem_list, onc_object);
609 bool ResolveServerCertRefsInObject(const CertPEMsByGUIDMap& certs_by_guid,
610 const OncValueSignature& signature,
611 base::DictionaryValue* onc_object) {
612 if (&signature == &kCertificatePatternSignature) {
613 if (!ResolveCertRefList(certs_by_guid,
614 client_cert::kIssuerCARef,
615 client_cert::kIssuerCAPEMs,
616 onc_object)) {
617 return false;
619 } else if (&signature == &kEAPSignature) {
620 if (!ResolveCertRefsOrRefToList(certs_by_guid,
621 eap::kServerCARefs,
622 eap::kServerCARef,
623 eap::kServerCAPEMs,
624 onc_object)) {
625 return false;
627 } else if (&signature == &kIPsecSignature) {
628 if (!ResolveCertRefsOrRefToList(certs_by_guid,
629 ipsec::kServerCARefs,
630 ipsec::kServerCARef,
631 ipsec::kServerCAPEMs,
632 onc_object)) {
633 return false;
635 } else if (&signature == &kIPsecSignature ||
636 &signature == &kOpenVPNSignature) {
637 if (!ResolveSingleCertRef(certs_by_guid,
638 openvpn::kServerCertRef,
639 openvpn::kServerCertPEM,
640 onc_object) ||
641 !ResolveCertRefsOrRefToList(certs_by_guid,
642 openvpn::kServerCARefs,
643 openvpn::kServerCARef,
644 openvpn::kServerCAPEMs,
645 onc_object)) {
646 return false;
650 // Recurse into nested objects.
651 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
652 it.Advance()) {
653 base::DictionaryValue* inner_object = NULL;
654 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object))
655 continue;
657 const OncFieldSignature* field_signature =
658 GetFieldSignature(signature, it.key());
659 if (!field_signature)
660 continue;
662 if (!ResolveServerCertRefsInObject(certs_by_guid,
663 *field_signature->value_signature,
664 inner_object)) {
665 return false;
668 return true;
671 } // namespace
673 bool ResolveServerCertRefsInNetworks(const CertPEMsByGUIDMap& certs_by_guid,
674 base::ListValue* network_configs) {
675 bool success = true;
676 for (base::ListValue::iterator it = network_configs->begin();
677 it != network_configs->end(); ) {
678 base::DictionaryValue* network = NULL;
679 (*it)->GetAsDictionary(&network);
680 if (!ResolveServerCertRefsInNetwork(certs_by_guid, network)) {
681 std::string guid;
682 network->GetStringWithoutPathExpansion(network_config::kGUID, &guid);
683 // This might happen even with correct validation, if the referenced
684 // certificate couldn't be imported.
685 LOG(ERROR) << "Couldn't resolve some certificate reference of network "
686 << guid;
687 it = network_configs->Erase(it, NULL);
688 success = false;
689 continue;
691 ++it;
693 return success;
696 bool ResolveServerCertRefsInNetwork(const CertPEMsByGUIDMap& certs_by_guid,
697 base::DictionaryValue* network_config) {
698 return ResolveServerCertRefsInObject(certs_by_guid,
699 kNetworkConfigurationSignature,
700 network_config);
703 NetworkTypePattern NetworkTypePatternFromOncType(const std::string& type) {
704 if (type == ::onc::network_type::kAllTypes)
705 return NetworkTypePattern::Default();
706 if (type == ::onc::network_type::kCellular)
707 return NetworkTypePattern::Cellular();
708 if (type == ::onc::network_type::kEthernet)
709 return NetworkTypePattern::Ethernet();
710 if (type == ::onc::network_type::kVPN)
711 return NetworkTypePattern::VPN();
712 if (type == ::onc::network_type::kWiFi)
713 return NetworkTypePattern::WiFi();
714 if (type == ::onc::network_type::kWimax)
715 return NetworkTypePattern::Wimax();
716 if (type == ::onc::network_type::kWireless)
717 return NetworkTypePattern::Wireless();
718 NOTREACHED();
719 return NetworkTypePattern::Default();
722 bool IsRecommendedValue(const base::DictionaryValue* onc,
723 const std::string& property_key) {
724 std::string property_basename, recommended_property_key;
725 size_t pos = property_key.find_last_of('.');
726 if (pos != std::string::npos) {
727 // 'WiFi.AutoConnect' -> 'AutoConnect', 'WiFi.Recommended'
728 property_basename = property_key.substr(pos + 1);
729 recommended_property_key =
730 property_key.substr(0, pos + 1) + ::onc::kRecommended;
731 } else {
732 // 'Name' -> 'Name', 'Recommended'
733 property_basename = property_key;
734 recommended_property_key = ::onc::kRecommended;
737 const base::ListValue* recommended_keys = NULL;
738 return (onc->GetList(recommended_property_key, &recommended_keys) &&
739 recommended_keys->Find(base::StringValue(property_basename)) !=
740 recommended_keys->end());
743 } // namespace onc
744 } // namespace chromeos