OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/network/onc/onc_utils.h" | 5 #include "chromeos/network/onc/onc_utils.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/values.h" | 13 #include "base/values.h" |
14 #include "chromeos/network/network_event_log.h" | 14 #include "chromeos/network/network_event_log.h" |
15 #include "chromeos/network/onc/onc_mapper.h" | 15 #include "chromeos/network/onc/onc_mapper.h" |
16 #include "chromeos/network/onc/onc_signature.h" | 16 #include "chromeos/network/onc/onc_signature.h" |
17 #include "chromeos/network/onc/onc_utils.h" | 17 #include "chromeos/network/onc/onc_utils.h" |
18 #include "chromeos/network/onc/onc_validator.h" | 18 #include "chromeos/network/onc/onc_validator.h" |
| 19 #include "components/device_event_log/device_event_log.h" |
19 #include "crypto/encryptor.h" | 20 #include "crypto/encryptor.h" |
20 #include "crypto/hmac.h" | 21 #include "crypto/hmac.h" |
21 #include "crypto/symmetric_key.h" | 22 #include "crypto/symmetric_key.h" |
22 #include "net/cert/pem_tokenizer.h" | 23 #include "net/cert/pem_tokenizer.h" |
23 #include "net/cert/x509_certificate.h" | 24 #include "net/cert/x509_certificate.h" |
24 | 25 |
25 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message) | |
26 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message) | |
27 | |
28 using namespace ::onc; | 26 using namespace ::onc; |
29 | 27 |
30 namespace chromeos { | 28 namespace chromeos { |
31 namespace onc { | 29 namespace onc { |
32 | 30 |
33 namespace { | 31 namespace { |
34 | 32 |
35 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; | 33 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; |
36 const char kUnableToDecode[] = "Unable to decode encrypted ONC"; | 34 const char kUnableToDecode[] = "Unable to decode encrypted ONC"; |
37 | 35 |
38 } // namespace | 36 } // namespace |
39 | 37 |
40 const char kEmptyUnencryptedConfiguration[] = | 38 const char kEmptyUnencryptedConfiguration[] = |
41 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[]," | 39 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[]," |
42 "\"Certificates\":[]}"; | 40 "\"Certificates\":[]}"; |
43 | 41 |
44 scoped_ptr<base::DictionaryValue> ReadDictionaryFromJson( | 42 scoped_ptr<base::DictionaryValue> ReadDictionaryFromJson( |
45 const std::string& json) { | 43 const std::string& json) { |
46 std::string error; | 44 std::string error; |
47 base::Value* root = base::JSONReader::ReadAndReturnError( | 45 base::Value* root = base::JSONReader::ReadAndReturnError( |
48 json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error); | 46 json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error); |
49 | 47 |
50 base::DictionaryValue* dict_ptr = NULL; | 48 base::DictionaryValue* dict_ptr = nullptr; |
51 if (!root || !root->GetAsDictionary(&dict_ptr)) { | 49 if (!root || !root->GetAsDictionary(&dict_ptr)) { |
52 ONC_LOG_ERROR("Invalid JSON Dictionary: " + error); | 50 NET_LOG(ERROR) << "Invalid JSON Dictionary: " << error; |
53 delete root; | 51 delete root; |
54 } | 52 } |
55 | 53 |
56 return make_scoped_ptr(dict_ptr); | 54 return make_scoped_ptr(dict_ptr); |
57 } | 55 } |
58 | 56 |
59 scoped_ptr<base::DictionaryValue> Decrypt(const std::string& passphrase, | 57 scoped_ptr<base::DictionaryValue> Decrypt(const std::string& passphrase, |
60 const base::DictionaryValue& root) { | 58 const base::DictionaryValue& root) { |
61 const int kKeySizeInBits = 256; | 59 const int kKeySizeInBits = 256; |
62 const int kMaxIterationCount = 500000; | 60 const int kMaxIterationCount = 500000; |
(...skipping 10 matching lines...) Expand all Loading... |
73 if (!root.GetString(encrypted::kCiphertext, &ciphertext) || | 71 if (!root.GetString(encrypted::kCiphertext, &ciphertext) || |
74 !root.GetString(encrypted::kCipher, &cipher) || | 72 !root.GetString(encrypted::kCipher, &cipher) || |
75 !root.GetString(encrypted::kHMAC, &hmac) || | 73 !root.GetString(encrypted::kHMAC, &hmac) || |
76 !root.GetString(encrypted::kHMACMethod, &hmac_method) || | 74 !root.GetString(encrypted::kHMACMethod, &hmac_method) || |
77 !root.GetString(encrypted::kIV, &initial_vector) || | 75 !root.GetString(encrypted::kIV, &initial_vector) || |
78 !root.GetInteger(encrypted::kIterations, &iterations) || | 76 !root.GetInteger(encrypted::kIterations, &iterations) || |
79 !root.GetString(encrypted::kSalt, &salt) || | 77 !root.GetString(encrypted::kSalt, &salt) || |
80 !root.GetString(encrypted::kStretch, &stretch_method) || | 78 !root.GetString(encrypted::kStretch, &stretch_method) || |
81 !root.GetString(toplevel_config::kType, &onc_type) || | 79 !root.GetString(toplevel_config::kType, &onc_type) || |
82 onc_type != toplevel_config::kEncryptedConfiguration) { | 80 onc_type != toplevel_config::kEncryptedConfiguration) { |
83 | 81 NET_LOG(ERROR) << "Encrypted ONC malformed."; |
84 ONC_LOG_ERROR("Encrypted ONC malformed."); | 82 return nullptr; |
85 return scoped_ptr<base::DictionaryValue>(); | |
86 } | 83 } |
87 | 84 |
88 if (hmac_method != encrypted::kSHA1 || | 85 if (hmac_method != encrypted::kSHA1 || |
89 cipher != encrypted::kAES256 || | 86 cipher != encrypted::kAES256 || |
90 stretch_method != encrypted::kPBKDF2) { | 87 stretch_method != encrypted::kPBKDF2) { |
91 ONC_LOG_ERROR("Encrypted ONC unsupported encryption scheme."); | 88 NET_LOG(ERROR) << "Encrypted ONC unsupported encryption scheme."; |
92 return scoped_ptr<base::DictionaryValue>(); | 89 return nullptr; |
93 } | 90 } |
94 | 91 |
95 // Make sure iterations != 0, since that's not valid. | 92 // Make sure iterations != 0, since that's not valid. |
96 if (iterations == 0) { | 93 if (iterations == 0) { |
97 ONC_LOG_ERROR(kUnableToDecrypt); | 94 NET_LOG(ERROR) << kUnableToDecrypt; |
98 return scoped_ptr<base::DictionaryValue>(); | 95 return nullptr; |
99 } | 96 } |
100 | 97 |
101 // Simply a sanity check to make sure we can't lock up the machine | 98 // 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). | 99 // for too long with a huge number (or a negative number). |
103 if (iterations < 0 || iterations > kMaxIterationCount) { | 100 if (iterations < 0 || iterations > kMaxIterationCount) { |
104 ONC_LOG_ERROR("Too many iterations in encrypted ONC"); | 101 NET_LOG(ERROR) << "Too many iterations in encrypted ONC"; |
105 return scoped_ptr<base::DictionaryValue>(); | 102 return nullptr; |
106 } | 103 } |
107 | 104 |
108 if (!base::Base64Decode(salt, &salt)) { | 105 if (!base::Base64Decode(salt, &salt)) { |
109 ONC_LOG_ERROR(kUnableToDecode); | 106 NET_LOG(ERROR) << kUnableToDecode; |
110 return scoped_ptr<base::DictionaryValue>(); | 107 return nullptr; |
111 } | 108 } |
112 | 109 |
113 scoped_ptr<crypto::SymmetricKey> key( | 110 scoped_ptr<crypto::SymmetricKey> key( |
114 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, | 111 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, |
115 passphrase, | 112 passphrase, |
116 salt, | 113 salt, |
117 iterations, | 114 iterations, |
118 kKeySizeInBits)); | 115 kKeySizeInBits)); |
119 | 116 |
120 if (!base::Base64Decode(initial_vector, &initial_vector)) { | 117 if (!base::Base64Decode(initial_vector, &initial_vector)) { |
121 ONC_LOG_ERROR(kUnableToDecode); | 118 NET_LOG(ERROR) << kUnableToDecode; |
122 return scoped_ptr<base::DictionaryValue>(); | 119 return nullptr; |
123 } | 120 } |
124 if (!base::Base64Decode(ciphertext, &ciphertext)) { | 121 if (!base::Base64Decode(ciphertext, &ciphertext)) { |
125 ONC_LOG_ERROR(kUnableToDecode); | 122 NET_LOG(ERROR) << kUnableToDecode; |
126 return scoped_ptr<base::DictionaryValue>(); | 123 return nullptr; |
127 } | 124 } |
128 if (!base::Base64Decode(hmac, &hmac)) { | 125 if (!base::Base64Decode(hmac, &hmac)) { |
129 ONC_LOG_ERROR(kUnableToDecode); | 126 NET_LOG(ERROR) << kUnableToDecode; |
130 return scoped_ptr<base::DictionaryValue>(); | 127 return nullptr; |
131 } | 128 } |
132 | 129 |
133 crypto::HMAC hmac_verifier(crypto::HMAC::SHA1); | 130 crypto::HMAC hmac_verifier(crypto::HMAC::SHA1); |
134 if (!hmac_verifier.Init(key.get()) || | 131 if (!hmac_verifier.Init(key.get()) || |
135 !hmac_verifier.Verify(ciphertext, hmac)) { | 132 !hmac_verifier.Verify(ciphertext, hmac)) { |
136 ONC_LOG_ERROR(kUnableToDecrypt); | 133 NET_LOG(ERROR) << kUnableToDecrypt; |
137 return scoped_ptr<base::DictionaryValue>(); | 134 return nullptr; |
138 } | 135 } |
139 | 136 |
140 crypto::Encryptor decryptor; | 137 crypto::Encryptor decryptor; |
141 if (!decryptor.Init(key.get(), crypto::Encryptor::CBC, initial_vector)) { | 138 if (!decryptor.Init(key.get(), crypto::Encryptor::CBC, initial_vector)) { |
142 ONC_LOG_ERROR(kUnableToDecrypt); | 139 NET_LOG(ERROR) << kUnableToDecrypt; |
143 return scoped_ptr<base::DictionaryValue>(); | 140 return nullptr; |
144 } | 141 } |
145 | 142 |
146 std::string plaintext; | 143 std::string plaintext; |
147 if (!decryptor.Decrypt(ciphertext, &plaintext)) { | 144 if (!decryptor.Decrypt(ciphertext, &plaintext)) { |
148 ONC_LOG_ERROR(kUnableToDecrypt); | 145 NET_LOG(ERROR) << kUnableToDecrypt; |
149 return scoped_ptr<base::DictionaryValue>(); | 146 return nullptr; |
150 } | 147 } |
151 | 148 |
152 scoped_ptr<base::DictionaryValue> new_root = | 149 scoped_ptr<base::DictionaryValue> new_root = |
153 ReadDictionaryFromJson(plaintext); | 150 ReadDictionaryFromJson(plaintext); |
154 if (new_root.get() == NULL) { | 151 if (!new_root) { |
155 ONC_LOG_ERROR("Property dictionary malformed."); | 152 NET_LOG(ERROR) << "Property dictionary malformed."; |
156 return scoped_ptr<base::DictionaryValue>(); | 153 return nullptr; |
157 } | 154 } |
158 | 155 |
159 return new_root.Pass(); | 156 return new_root.Pass(); |
160 } | 157 } |
161 | 158 |
162 std::string GetSourceAsString(ONCSource source) { | 159 std::string GetSourceAsString(ONCSource source) { |
163 switch (source) { | 160 switch (source) { |
164 case ONC_SOURCE_UNKNOWN: | 161 case ONC_SOURCE_UNKNOWN: |
165 return "unknown"; | 162 return "unknown"; |
166 case ONC_SOURCE_NONE: | 163 case ONC_SOURCE_NONE: |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 ExpandField(eap::kAnonymousIdentity, substitution, onc_object); | 205 ExpandField(eap::kAnonymousIdentity, substitution, onc_object); |
209 ExpandField(eap::kIdentity, substitution, onc_object); | 206 ExpandField(eap::kIdentity, substitution, onc_object); |
210 } else if (&signature == &kL2TPSignature || | 207 } else if (&signature == &kL2TPSignature || |
211 &signature == &kOpenVPNSignature) { | 208 &signature == &kOpenVPNSignature) { |
212 ExpandField(vpn::kUsername, substitution, onc_object); | 209 ExpandField(vpn::kUsername, substitution, onc_object); |
213 } | 210 } |
214 | 211 |
215 // Recurse into nested objects. | 212 // Recurse into nested objects. |
216 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd(); | 213 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd(); |
217 it.Advance()) { | 214 it.Advance()) { |
218 base::DictionaryValue* inner_object = NULL; | 215 base::DictionaryValue* inner_object = nullptr; |
219 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object)) | 216 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object)) |
220 continue; | 217 continue; |
221 | 218 |
222 const OncFieldSignature* field_signature = | 219 const OncFieldSignature* field_signature = |
223 GetFieldSignature(signature, it.key()); | 220 GetFieldSignature(signature, it.key()); |
224 if (!field_signature) | 221 if (!field_signature) |
225 continue; | 222 continue; |
226 | 223 |
227 ExpandStringsInOncObject(*field_signature->value_signature, | 224 ExpandStringsInOncObject(*field_signature->value_signature, |
228 substitution, inner_object); | 225 substitution, inner_object); |
229 } | 226 } |
230 } | 227 } |
231 | 228 |
232 void ExpandStringsInNetworks(const StringSubstitution& substitution, | 229 void ExpandStringsInNetworks(const StringSubstitution& substitution, |
233 base::ListValue* network_configs) { | 230 base::ListValue* network_configs) { |
234 for (base::ListValue::iterator it = network_configs->begin(); | 231 for (base::Value* entry : *network_configs) { |
235 it != network_configs->end(); ++it) { | 232 base::DictionaryValue* network = nullptr; |
236 base::DictionaryValue* network = NULL; | 233 entry->GetAsDictionary(&network); |
237 (*it)->GetAsDictionary(&network); | |
238 DCHECK(network); | 234 DCHECK(network); |
239 ExpandStringsInOncObject( | 235 ExpandStringsInOncObject( |
240 kNetworkConfigurationSignature, substitution, network); | 236 kNetworkConfigurationSignature, substitution, network); |
241 } | 237 } |
242 } | 238 } |
243 | 239 |
244 void FillInHexSSIDFieldsInOncObject(const OncValueSignature& signature, | 240 void FillInHexSSIDFieldsInOncObject(const OncValueSignature& signature, |
245 base::DictionaryValue* onc_object) { | 241 base::DictionaryValue* onc_object) { |
246 if (&signature == &kWiFiSignature) | 242 if (&signature == &kWiFiSignature) |
247 FillInHexSSIDField(onc_object); | 243 FillInHexSSIDField(onc_object); |
(...skipping 16 matching lines...) Expand all Loading... |
264 } | 260 } |
265 | 261 |
266 void FillInHexSSIDField(base::DictionaryValue* wifi_fields) { | 262 void FillInHexSSIDField(base::DictionaryValue* wifi_fields) { |
267 std::string ssid_string; | 263 std::string ssid_string; |
268 if (wifi_fields->HasKey(::onc::wifi::kHexSSID) || | 264 if (wifi_fields->HasKey(::onc::wifi::kHexSSID) || |
269 !wifi_fields->GetStringWithoutPathExpansion(::onc::wifi::kSSID, | 265 !wifi_fields->GetStringWithoutPathExpansion(::onc::wifi::kSSID, |
270 &ssid_string)) { | 266 &ssid_string)) { |
271 return; | 267 return; |
272 } | 268 } |
273 if (ssid_string.empty()) { | 269 if (ssid_string.empty()) { |
274 ONC_LOG_ERROR("Found empty SSID field."); | 270 NET_LOG(ERROR) << "Found empty SSID field."; |
275 return; | 271 return; |
276 } | 272 } |
277 wifi_fields->SetStringWithoutPathExpansion( | 273 wifi_fields->SetStringWithoutPathExpansion( |
278 ::onc::wifi::kHexSSID, | 274 ::onc::wifi::kHexSSID, |
279 base::HexEncode(ssid_string.c_str(), ssid_string.size())); | 275 base::HexEncode(ssid_string.c_str(), ssid_string.size())); |
280 } | 276 } |
281 | 277 |
282 namespace { | 278 namespace { |
283 | 279 |
284 class OncMaskValues : public Mapper { | 280 class OncMaskValues : public Mapper { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded; | 344 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded; |
349 return std::string(); | 345 return std::string(); |
350 } | 346 } |
351 } | 347 } |
352 return decoded; | 348 return decoded; |
353 } | 349 } |
354 | 350 |
355 CertPEMsByGUIDMap GetServerAndCACertsByGUID( | 351 CertPEMsByGUIDMap GetServerAndCACertsByGUID( |
356 const base::ListValue& certificates) { | 352 const base::ListValue& certificates) { |
357 CertPEMsByGUIDMap certs_by_guid; | 353 CertPEMsByGUIDMap certs_by_guid; |
358 for (base::ListValue::const_iterator it = certificates.begin(); | 354 for (const base::Value* entry : certificates) { |
359 it != certificates.end(); ++it) { | 355 const base::DictionaryValue* cert = nullptr; |
360 base::DictionaryValue* cert = NULL; | 356 entry->GetAsDictionary(&cert); |
361 (*it)->GetAsDictionary(&cert); | |
362 | 357 |
363 std::string guid; | 358 std::string guid; |
364 cert->GetStringWithoutPathExpansion(certificate::kGUID, &guid); | 359 cert->GetStringWithoutPathExpansion(certificate::kGUID, &guid); |
365 std::string cert_type; | 360 std::string cert_type; |
366 cert->GetStringWithoutPathExpansion(certificate::kType, &cert_type); | 361 cert->GetStringWithoutPathExpansion(certificate::kType, &cert_type); |
367 if (cert_type != certificate::kServer && | 362 if (cert_type != certificate::kServer && |
368 cert_type != certificate::kAuthority) { | 363 cert_type != certificate::kAuthority) { |
369 continue; | 364 continue; |
370 } | 365 } |
371 std::string x509_data; | 366 std::string x509_data; |
372 cert->GetStringWithoutPathExpansion(certificate::kX509, &x509_data); | 367 cert->GetStringWithoutPathExpansion(certificate::kX509, &x509_data); |
373 | 368 |
374 std::string der = DecodePEM(x509_data); | 369 std::string der = DecodePEM(x509_data); |
375 std::string pem; | 370 std::string pem; |
376 if (der.empty() || !net::X509Certificate::GetPEMEncodedFromDER(der, &pem)) { | 371 if (der.empty() || !net::X509Certificate::GetPEMEncodedFromDER(der, &pem)) { |
377 LOG(ERROR) << "Certificate with GUID " << guid | 372 LOG(ERROR) << "Certificate with GUID " << guid |
378 << " is not in PEM encoding."; | 373 << " is not in PEM encoding."; |
379 continue; | 374 continue; |
380 } | 375 } |
381 certs_by_guid[guid] = pem; | 376 certs_by_guid[guid] = pem; |
382 } | 377 } |
383 | 378 |
384 return certs_by_guid; | 379 return certs_by_guid; |
385 } | 380 } |
386 | 381 |
387 void FillInHexSSIDFieldsInNetworks(base::ListValue* network_configs) { | 382 void FillInHexSSIDFieldsInNetworks(base::ListValue* network_configs) { |
388 for (base::ListValue::iterator it = network_configs->begin(); | 383 for (base::Value* entry : *network_configs) { |
389 it != network_configs->end(); ++it) { | 384 base::DictionaryValue* network = nullptr; |
390 base::DictionaryValue* network = NULL; | 385 entry->GetAsDictionary(&network); |
391 (*it)->GetAsDictionary(&network); | |
392 DCHECK(network); | 386 DCHECK(network); |
393 FillInHexSSIDFieldsInOncObject(kNetworkConfigurationSignature, network); | 387 FillInHexSSIDFieldsInOncObject(kNetworkConfigurationSignature, network); |
394 } | 388 } |
395 } | 389 } |
396 | 390 |
397 } // namespace | 391 } // namespace |
398 | 392 |
399 bool ParseAndValidateOncForImport(const std::string& onc_blob, | 393 bool ParseAndValidateOncForImport(const std::string& onc_blob, |
400 ONCSource onc_source, | 394 ONCSource onc_source, |
401 const std::string& passphrase, | 395 const std::string& passphrase, |
402 base::ListValue* network_configs, | 396 base::ListValue* network_configs, |
403 base::DictionaryValue* global_network_config, | 397 base::DictionaryValue* global_network_config, |
404 base::ListValue* certificates) { | 398 base::ListValue* certificates) { |
405 network_configs->Clear(); | 399 network_configs->Clear(); |
406 global_network_config->Clear(); | 400 global_network_config->Clear(); |
407 certificates->Clear(); | 401 certificates->Clear(); |
408 if (onc_blob.empty()) | 402 if (onc_blob.empty()) |
409 return true; | 403 return true; |
410 | 404 |
411 scoped_ptr<base::DictionaryValue> toplevel_onc = | 405 scoped_ptr<base::DictionaryValue> toplevel_onc = |
412 ReadDictionaryFromJson(onc_blob); | 406 ReadDictionaryFromJson(onc_blob); |
413 if (toplevel_onc.get() == NULL) { | 407 if (!toplevel_onc) { |
414 LOG(ERROR) << "ONC loaded from " << GetSourceAsString(onc_source) | 408 LOG(ERROR) << "ONC loaded from " << GetSourceAsString(onc_source) |
415 << " is not a valid JSON dictionary."; | 409 << " is not a valid JSON dictionary."; |
416 return false; | 410 return false; |
417 } | 411 } |
418 | 412 |
419 // Check and see if this is an encrypted ONC file. If so, decrypt it. | 413 // Check and see if this is an encrypted ONC file. If so, decrypt it. |
420 std::string onc_type; | 414 std::string onc_type; |
421 toplevel_onc->GetStringWithoutPathExpansion(toplevel_config::kType, | 415 toplevel_onc->GetStringWithoutPathExpansion(toplevel_config::kType, |
422 &onc_type); | 416 &onc_type); |
423 if (onc_type == toplevel_config::kEncryptedConfiguration) { | 417 if (onc_type == toplevel_config::kEncryptedConfiguration) { |
424 toplevel_onc = Decrypt(passphrase, *toplevel_onc); | 418 toplevel_onc = Decrypt(passphrase, *toplevel_onc); |
425 if (toplevel_onc.get() == NULL) { | 419 if (!toplevel_onc) { |
426 LOG(ERROR) << "Couldn't decrypt the ONC from " | 420 LOG(ERROR) << "Couldn't decrypt the ONC from " |
427 << GetSourceAsString(onc_source); | 421 << GetSourceAsString(onc_source); |
428 return false; | 422 return false; |
429 } | 423 } |
430 } | 424 } |
431 | 425 |
432 bool from_policy = (onc_source == ONC_SOURCE_USER_POLICY || | 426 bool from_policy = (onc_source == ONC_SOURCE_USER_POLICY || |
433 onc_source == ONC_SOURCE_DEVICE_POLICY); | 427 onc_source == ONC_SOURCE_DEVICE_POLICY); |
434 | 428 |
435 // Validate the ONC dictionary. We are liberal and ignore unknown field | 429 // Validate the ONC dictionary. We are liberal and ignore unknown field |
(...skipping 13 matching lines...) Expand all Loading... |
449 if (from_policy) { | 443 if (from_policy) { |
450 UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", | 444 UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", |
451 validation_result == Validator::VALID); | 445 validation_result == Validator::VALID); |
452 } | 446 } |
453 | 447 |
454 bool success = true; | 448 bool success = true; |
455 if (validation_result == Validator::VALID_WITH_WARNINGS) { | 449 if (validation_result == Validator::VALID_WITH_WARNINGS) { |
456 LOG(WARNING) << "ONC from " << GetSourceAsString(onc_source) | 450 LOG(WARNING) << "ONC from " << GetSourceAsString(onc_source) |
457 << " produced warnings."; | 451 << " produced warnings."; |
458 success = false; | 452 success = false; |
459 } else if (validation_result == Validator::INVALID || toplevel_onc == NULL) { | 453 } else if (validation_result == Validator::INVALID || !toplevel_onc) { |
460 LOG(ERROR) << "ONC from " << GetSourceAsString(onc_source) | 454 LOG(ERROR) << "ONC from " << GetSourceAsString(onc_source) |
461 << " is invalid and couldn't be repaired."; | 455 << " is invalid and couldn't be repaired."; |
462 return false; | 456 return false; |
463 } | 457 } |
464 | 458 |
465 base::ListValue* validated_certs = NULL; | 459 base::ListValue* validated_certs = nullptr; |
466 if (toplevel_onc->GetListWithoutPathExpansion(toplevel_config::kCertificates, | 460 if (toplevel_onc->GetListWithoutPathExpansion(toplevel_config::kCertificates, |
467 &validated_certs)) { | 461 &validated_certs)) { |
468 certificates->Swap(validated_certs); | 462 certificates->Swap(validated_certs); |
469 } | 463 } |
470 | 464 |
471 base::ListValue* validated_networks = NULL; | 465 base::ListValue* validated_networks = nullptr; |
472 if (toplevel_onc->GetListWithoutPathExpansion( | 466 if (toplevel_onc->GetListWithoutPathExpansion( |
473 toplevel_config::kNetworkConfigurations, &validated_networks)) { | 467 toplevel_config::kNetworkConfigurations, &validated_networks)) { |
474 FillInHexSSIDFieldsInNetworks(validated_networks); | 468 FillInHexSSIDFieldsInNetworks(validated_networks); |
475 | 469 |
476 CertPEMsByGUIDMap server_and_ca_certs = | 470 CertPEMsByGUIDMap server_and_ca_certs = |
477 GetServerAndCACertsByGUID(*certificates); | 471 GetServerAndCACertsByGUID(*certificates); |
478 | 472 |
479 if (!ResolveServerCertRefsInNetworks(server_and_ca_certs, | 473 if (!ResolveServerCertRefsInNetworks(server_and_ca_certs, |
480 validated_networks)) { | 474 validated_networks)) { |
481 LOG(ERROR) << "Some certificate references in the ONC policy for source " | 475 LOG(ERROR) << "Some certificate references in the ONC policy for source " |
482 << GetSourceAsString(onc_source) << " could not be resolved."; | 476 << GetSourceAsString(onc_source) << " could not be resolved."; |
483 success = false; | 477 success = false; |
484 } | 478 } |
485 | 479 |
486 network_configs->Swap(validated_networks); | 480 network_configs->Swap(validated_networks); |
487 } | 481 } |
488 | 482 |
489 base::DictionaryValue* validated_global_config = NULL; | 483 base::DictionaryValue* validated_global_config = nullptr; |
490 if (toplevel_onc->GetDictionaryWithoutPathExpansion( | 484 if (toplevel_onc->GetDictionaryWithoutPathExpansion( |
491 toplevel_config::kGlobalNetworkConfiguration, | 485 toplevel_config::kGlobalNetworkConfiguration, |
492 &validated_global_config)) { | 486 &validated_global_config)) { |
493 global_network_config->Swap(validated_global_config); | 487 global_network_config->Swap(validated_global_config); |
494 } | 488 } |
495 | 489 |
496 return success; | 490 return success; |
497 } | 491 } |
498 | 492 |
499 scoped_refptr<net::X509Certificate> DecodePEMCertificate( | 493 scoped_refptr<net::X509Certificate> DecodePEMCertificate( |
(...skipping 29 matching lines...) Expand all Loading... |
529 const std::string& key_pem, | 523 const std::string& key_pem, |
530 base::DictionaryValue* onc_object) { | 524 base::DictionaryValue* onc_object) { |
531 std::string guid_ref; | 525 std::string guid_ref; |
532 if (!onc_object->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref)) | 526 if (!onc_object->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref)) |
533 return true; | 527 return true; |
534 | 528 |
535 std::string pem_encoded; | 529 std::string pem_encoded; |
536 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded)) | 530 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded)) |
537 return false; | 531 return false; |
538 | 532 |
539 onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL); | 533 onc_object->RemoveWithoutPathExpansion(key_guid_ref, nullptr); |
540 onc_object->SetStringWithoutPathExpansion(key_pem, pem_encoded); | 534 onc_object->SetStringWithoutPathExpansion(key_pem, pem_encoded); |
541 return true; | 535 return true; |
542 } | 536 } |
543 | 537 |
544 bool ResolveCertRefList(const CertPEMsByGUIDMap& certs_by_guid, | 538 bool ResolveCertRefList(const CertPEMsByGUIDMap& certs_by_guid, |
545 const std::string& key_guid_ref_list, | 539 const std::string& key_guid_ref_list, |
546 const std::string& key_pem_list, | 540 const std::string& key_pem_list, |
547 base::DictionaryValue* onc_object) { | 541 base::DictionaryValue* onc_object) { |
548 const base::ListValue* guid_ref_list = NULL; | 542 const base::ListValue* guid_ref_list = nullptr; |
549 if (!onc_object->GetListWithoutPathExpansion(key_guid_ref_list, | 543 if (!onc_object->GetListWithoutPathExpansion(key_guid_ref_list, |
550 &guid_ref_list)) { | 544 &guid_ref_list)) { |
551 return true; | 545 return true; |
552 } | 546 } |
553 | 547 |
554 scoped_ptr<base::ListValue> pem_list(new base::ListValue); | 548 scoped_ptr<base::ListValue> pem_list(new base::ListValue); |
555 for (base::ListValue::const_iterator it = guid_ref_list->begin(); | 549 for (const base::Value* entry : *guid_ref_list) { |
556 it != guid_ref_list->end(); ++it) { | |
557 std::string guid_ref; | 550 std::string guid_ref; |
558 (*it)->GetAsString(&guid_ref); | 551 entry->GetAsString(&guid_ref); |
559 | 552 |
560 std::string pem_encoded; | 553 std::string pem_encoded; |
561 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded)) | 554 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded)) |
562 return false; | 555 return false; |
563 | 556 |
564 pem_list->AppendString(pem_encoded); | 557 pem_list->AppendString(pem_encoded); |
565 } | 558 } |
566 | 559 |
567 onc_object->RemoveWithoutPathExpansion(key_guid_ref_list, NULL); | 560 onc_object->RemoveWithoutPathExpansion(key_guid_ref_list, nullptr); |
568 onc_object->SetWithoutPathExpansion(key_pem_list, pem_list.release()); | 561 onc_object->SetWithoutPathExpansion(key_pem_list, pem_list.release()); |
569 return true; | 562 return true; |
570 } | 563 } |
571 | 564 |
572 bool ResolveSingleCertRefToList(const CertPEMsByGUIDMap& certs_by_guid, | 565 bool ResolveSingleCertRefToList(const CertPEMsByGUIDMap& certs_by_guid, |
573 const std::string& key_guid_ref, | 566 const std::string& key_guid_ref, |
574 const std::string& key_pem_list, | 567 const std::string& key_pem_list, |
575 base::DictionaryValue* onc_object) { | 568 base::DictionaryValue* onc_object) { |
576 std::string guid_ref; | 569 std::string guid_ref; |
577 if (!onc_object->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref)) | 570 if (!onc_object->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref)) |
578 return true; | 571 return true; |
579 | 572 |
580 std::string pem_encoded; | 573 std::string pem_encoded; |
581 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded)) | 574 if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded)) |
582 return false; | 575 return false; |
583 | 576 |
584 scoped_ptr<base::ListValue> pem_list(new base::ListValue); | 577 scoped_ptr<base::ListValue> pem_list(new base::ListValue); |
585 pem_list->AppendString(pem_encoded); | 578 pem_list->AppendString(pem_encoded); |
586 onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL); | 579 onc_object->RemoveWithoutPathExpansion(key_guid_ref, nullptr); |
587 onc_object->SetWithoutPathExpansion(key_pem_list, pem_list.release()); | 580 onc_object->SetWithoutPathExpansion(key_pem_list, pem_list.release()); |
588 return true; | 581 return true; |
589 } | 582 } |
590 | 583 |
591 // Resolves the reference list at |key_guid_refs| if present and otherwise the | 584 // Resolves the reference list at |key_guid_refs| if present and otherwise the |
592 // single reference at |key_guid_ref|. Returns whether the respective resolving | 585 // single reference at |key_guid_ref|. Returns whether the respective resolving |
593 // was successful. | 586 // was successful. |
594 bool ResolveCertRefsOrRefToList(const CertPEMsByGUIDMap& certs_by_guid, | 587 bool ResolveCertRefsOrRefToList(const CertPEMsByGUIDMap& certs_by_guid, |
595 const std::string& key_guid_refs, | 588 const std::string& key_guid_refs, |
596 const std::string& key_guid_ref, | 589 const std::string& key_guid_ref, |
597 const std::string& key_pem_list, | 590 const std::string& key_pem_list, |
598 base::DictionaryValue* onc_object) { | 591 base::DictionaryValue* onc_object) { |
599 if (onc_object->HasKey(key_guid_refs)) { | 592 if (onc_object->HasKey(key_guid_refs)) { |
600 if (onc_object->HasKey(key_guid_ref)) { | 593 if (onc_object->HasKey(key_guid_ref)) { |
601 LOG(ERROR) << "Found both " << key_guid_refs << " and " << key_guid_ref | 594 LOG(ERROR) << "Found both " << key_guid_refs << " and " << key_guid_ref |
602 << ". Ignoring and removing the latter."; | 595 << ". Ignoring and removing the latter."; |
603 onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL); | 596 onc_object->RemoveWithoutPathExpansion(key_guid_ref, nullptr); |
604 } | 597 } |
605 return ResolveCertRefList( | 598 return ResolveCertRefList( |
606 certs_by_guid, key_guid_refs, key_pem_list, onc_object); | 599 certs_by_guid, key_guid_refs, key_pem_list, onc_object); |
607 } | 600 } |
608 | 601 |
609 // Only resolve |key_guid_ref| if |key_guid_refs| isn't present. | 602 // Only resolve |key_guid_ref| if |key_guid_refs| isn't present. |
610 return ResolveSingleCertRefToList( | 603 return ResolveSingleCertRefToList( |
611 certs_by_guid, key_guid_ref, key_pem_list, onc_object); | 604 certs_by_guid, key_guid_ref, key_pem_list, onc_object); |
612 } | 605 } |
613 | 606 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 openvpn::kServerCARef, | 641 openvpn::kServerCARef, |
649 openvpn::kServerCAPEMs, | 642 openvpn::kServerCAPEMs, |
650 onc_object)) { | 643 onc_object)) { |
651 return false; | 644 return false; |
652 } | 645 } |
653 } | 646 } |
654 | 647 |
655 // Recurse into nested objects. | 648 // Recurse into nested objects. |
656 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd(); | 649 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd(); |
657 it.Advance()) { | 650 it.Advance()) { |
658 base::DictionaryValue* inner_object = NULL; | 651 base::DictionaryValue* inner_object = nullptr; |
659 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object)) | 652 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object)) |
660 continue; | 653 continue; |
661 | 654 |
662 const OncFieldSignature* field_signature = | 655 const OncFieldSignature* field_signature = |
663 GetFieldSignature(signature, it.key()); | 656 GetFieldSignature(signature, it.key()); |
664 if (!field_signature) | 657 if (!field_signature) |
665 continue; | 658 continue; |
666 | 659 |
667 if (!ResolveServerCertRefsInObject(certs_by_guid, | 660 if (!ResolveServerCertRefsInObject(certs_by_guid, |
668 *field_signature->value_signature, | 661 *field_signature->value_signature, |
669 inner_object)) { | 662 inner_object)) { |
670 return false; | 663 return false; |
671 } | 664 } |
672 } | 665 } |
673 return true; | 666 return true; |
674 } | 667 } |
675 | 668 |
676 } // namespace | 669 } // namespace |
677 | 670 |
678 bool ResolveServerCertRefsInNetworks(const CertPEMsByGUIDMap& certs_by_guid, | 671 bool ResolveServerCertRefsInNetworks(const CertPEMsByGUIDMap& certs_by_guid, |
679 base::ListValue* network_configs) { | 672 base::ListValue* network_configs) { |
680 bool success = true; | 673 bool success = true; |
681 for (base::ListValue::iterator it = network_configs->begin(); | 674 for (base::ListValue::iterator it = network_configs->begin(); |
682 it != network_configs->end(); ) { | 675 it != network_configs->end(); ) { |
683 base::DictionaryValue* network = NULL; | 676 base::DictionaryValue* network = nullptr; |
684 (*it)->GetAsDictionary(&network); | 677 (*it)->GetAsDictionary(&network); |
685 if (!ResolveServerCertRefsInNetwork(certs_by_guid, network)) { | 678 if (!ResolveServerCertRefsInNetwork(certs_by_guid, network)) { |
686 std::string guid; | 679 std::string guid; |
687 network->GetStringWithoutPathExpansion(network_config::kGUID, &guid); | 680 network->GetStringWithoutPathExpansion(network_config::kGUID, &guid); |
688 // This might happen even with correct validation, if the referenced | 681 // This might happen even with correct validation, if the referenced |
689 // certificate couldn't be imported. | 682 // certificate couldn't be imported. |
690 LOG(ERROR) << "Couldn't resolve some certificate reference of network " | 683 LOG(ERROR) << "Couldn't resolve some certificate reference of network " |
691 << guid; | 684 << guid; |
692 it = network_configs->Erase(it, NULL); | 685 it = network_configs->Erase(it, nullptr); |
693 success = false; | 686 success = false; |
694 continue; | 687 continue; |
695 } | 688 } |
696 ++it; | 689 ++it; |
697 } | 690 } |
698 return success; | 691 return success; |
699 } | 692 } |
700 | 693 |
701 bool ResolveServerCertRefsInNetwork(const CertPEMsByGUIDMap& certs_by_guid, | 694 bool ResolveServerCertRefsInNetwork(const CertPEMsByGUIDMap& certs_by_guid, |
702 base::DictionaryValue* network_config) { | 695 base::DictionaryValue* network_config) { |
(...skipping 29 matching lines...) Expand all Loading... |
732 // 'WiFi.AutoConnect' -> 'AutoConnect', 'WiFi.Recommended' | 725 // 'WiFi.AutoConnect' -> 'AutoConnect', 'WiFi.Recommended' |
733 property_basename = property_key.substr(pos + 1); | 726 property_basename = property_key.substr(pos + 1); |
734 recommended_property_key = | 727 recommended_property_key = |
735 property_key.substr(0, pos + 1) + ::onc::kRecommended; | 728 property_key.substr(0, pos + 1) + ::onc::kRecommended; |
736 } else { | 729 } else { |
737 // 'Name' -> 'Name', 'Recommended' | 730 // 'Name' -> 'Name', 'Recommended' |
738 property_basename = property_key; | 731 property_basename = property_key; |
739 recommended_property_key = ::onc::kRecommended; | 732 recommended_property_key = ::onc::kRecommended; |
740 } | 733 } |
741 | 734 |
742 const base::ListValue* recommended_keys = NULL; | 735 const base::ListValue* recommended_keys = nullptr; |
743 return (onc->GetList(recommended_property_key, &recommended_keys) && | 736 return (onc->GetList(recommended_property_key, &recommended_keys) && |
744 recommended_keys->Find(base::StringValue(property_basename)) != | 737 recommended_keys->Find(base::StringValue(property_basename)) != |
745 recommended_keys->end()); | 738 recommended_keys->end()); |
746 } | 739 } |
747 | 740 |
748 } // namespace onc | 741 } // namespace onc |
749 } // namespace chromeos | 742 } // namespace chromeos |
OLD | NEW |