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 "chrome/browser/chromeos/cros/onc_network_parser.h" | 5 #include "chrome/browser/chromeos/cros/onc_network_parser.h" |
6 | 6 |
7 #include <keyhi.h> | 7 #include <keyhi.h> |
8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
9 | 9 |
10 #include "base/base64.h" | 10 #include "base/base64.h" |
11 #include "base/json/json_value_serializer.h" | 11 #include "base/json/json_value_serializer.h" |
12 #include "base/json/json_writer.h" // for debug output only. | 12 #include "base/json/json_writer.h" // for debug output only. |
13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "chrome/browser/chromeos/cros/native_network_constants.h" | 15 #include "chrome/browser/chromeos/cros/native_network_constants.h" |
16 #include "chrome/browser/chromeos/cros/native_network_parser.h" | 16 #include "chrome/browser/chromeos/cros/native_network_parser.h" |
17 #include "chrome/browser/chromeos/cros/network_library.h" | 17 #include "chrome/browser/chromeos/cros/network_library.h" |
18 #include "chrome/browser/chromeos/cros/onc_constants.h" | 18 #include "chrome/browser/chromeos/cros/onc_constants.h" |
19 #include "chrome/common/net/x509_certificate_model.h" | 19 #include "chrome/common/net/x509_certificate_model.h" |
| 20 #include "crypto/encryptor.h" |
| 21 #include "crypto/hmac.h" |
| 22 #include "crypto/scoped_nss_types.h" |
| 23 #include "crypto/symmetric_key.h" |
20 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
21 #include "net/base/cert_database.h" | 25 #include "net/base/cert_database.h" |
22 #include "net/base/crypto_module.h" | 26 #include "net/base/crypto_module.h" |
23 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
24 #include "net/base/x509_certificate.h" | 28 #include "net/base/x509_certificate.h" |
25 #include "third_party/cros_system_api/dbus/service_constants.h" | 29 #include "third_party/cros_system_api/dbus/service_constants.h" |
26 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
27 | 31 |
28 namespace chromeos { | 32 namespace chromeos { |
29 | 33 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 std::string value_json; | 196 std::string value_json; |
193 base::JSONWriter::Write(&value, false, &value_json); | 197 base::JSONWriter::Write(&value, false, &value_json); |
194 return value_json; | 198 return value_json; |
195 } | 199 } |
196 | 200 |
197 } // namespace | 201 } // namespace |
198 | 202 |
199 // -------------------- OncNetworkParser -------------------- | 203 // -------------------- OncNetworkParser -------------------- |
200 | 204 |
201 OncNetworkParser::OncNetworkParser(const std::string& onc_blob, | 205 OncNetworkParser::OncNetworkParser(const std::string& onc_blob, |
| 206 const std::string& passphrase, |
202 NetworkUIData::ONCSource onc_source) | 207 NetworkUIData::ONCSource onc_source) |
203 : NetworkParser(get_onc_mapper()), | 208 : NetworkParser(get_onc_mapper()), |
204 onc_source_(onc_source), | 209 onc_source_(onc_source), |
205 network_configs_(NULL), | 210 network_configs_(NULL), |
206 certificates_(NULL) { | 211 certificates_(NULL) { |
207 VLOG(2) << __func__ << ": OncNetworkParser called on " << onc_blob; | 212 VLOG(2) << __func__ << ": OncNetworkParser called on " << onc_blob; |
208 JSONStringValueSerializer deserializer(onc_blob); | 213 JSONStringValueSerializer deserializer(onc_blob); |
209 deserializer.set_allow_trailing_comma(true); | 214 deserializer.set_allow_trailing_comma(true); |
210 scoped_ptr<base::Value> root(deserializer.Deserialize(NULL, &parse_error_)); | 215 scoped_ptr<base::Value> root(deserializer.Deserialize(NULL, &parse_error_)); |
211 | 216 |
212 if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) { | 217 if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) { |
213 LOG(WARNING) << "OncNetworkParser received bad ONC file: " << parse_error_; | 218 LOG(WARNING) << "OncNetworkParser received bad ONC file: " << parse_error_; |
214 } else { | 219 } else { |
215 root_dict_.reset(static_cast<DictionaryValue*>(root.release())); | 220 root_dict_.reset(static_cast<DictionaryValue*>(root.release())); |
| 221 |
| 222 // Check and see if this is an encrypted ONC file. If so, decrypt it. |
| 223 std::string ciphertext_test; |
| 224 if (root_dict_->GetString("Ciphertext", &ciphertext_test)) |
| 225 root_dict_.reset(Decrypt(passphrase, root_dict_.get())); |
| 226 |
| 227 // Decryption failed, errors will be in parse_error_; |
| 228 if (!root_dict_.get()) |
| 229 return; |
| 230 |
216 // At least one of NetworkConfigurations or Certificates is required. | 231 // At least one of NetworkConfigurations or Certificates is required. |
217 bool has_network_configurations = | 232 bool has_network_configurations = |
218 root_dict_->GetList("NetworkConfigurations", &network_configs_); | 233 root_dict_->GetList("NetworkConfigurations", &network_configs_); |
219 bool has_certificates = | 234 bool has_certificates = |
220 root_dict_->GetList("Certificates", &certificates_); | 235 root_dict_->GetList("Certificates", &certificates_); |
221 VLOG(2) << "ONC file has " << GetNetworkConfigsSize() << " networks and " | 236 VLOG(2) << "ONC file has " << GetNetworkConfigsSize() << " networks and " |
222 << GetCertificatesSize() << " certificates"; | 237 << GetCertificatesSize() << " certificates"; |
223 LOG_IF(WARNING, (!has_network_configurations && !has_certificates)) | 238 LOG_IF(WARNING, (!has_network_configurations && !has_certificates)) |
224 << "ONC file has no NetworkConfigurations or Certificates."; | 239 << "ONC file has no NetworkConfigurations or Certificates."; |
225 } | 240 } |
226 } | 241 } |
227 | 242 |
228 OncNetworkParser::OncNetworkParser() | 243 OncNetworkParser::OncNetworkParser() |
229 : NetworkParser(get_onc_mapper()), | 244 : NetworkParser(get_onc_mapper()), |
230 network_configs_(NULL), | 245 network_configs_(NULL), |
231 certificates_(NULL) { | 246 certificates_(NULL) { |
232 } | 247 } |
233 | 248 |
234 OncNetworkParser::~OncNetworkParser() { | 249 OncNetworkParser::~OncNetworkParser() { |
235 } | 250 } |
236 | 251 |
237 // static | 252 // static |
238 const EnumMapper<PropertyIndex>* OncNetworkParser::property_mapper() { | 253 const EnumMapper<PropertyIndex>* OncNetworkParser::property_mapper() { |
239 return get_onc_mapper(); | 254 return get_onc_mapper(); |
240 } | 255 } |
241 | 256 |
| 257 base::DictionaryValue* OncNetworkParser::Decrypt( |
| 258 const std::string& passphrase, |
| 259 base::DictionaryValue* root) { |
| 260 const int kKeySizeInBits = 256; |
| 261 const int kMaxIterationCount = 500000; |
| 262 std::string onc_type; |
| 263 std::string initial_vector; |
| 264 std::string salt; |
| 265 std::string cipher; |
| 266 std::string stretch_method; |
| 267 std::string hmac_method; |
| 268 std::string hmac; |
| 269 int iterations; |
| 270 std::string ciphertext; |
| 271 |
| 272 if (!root->GetString("Ciphertext", &ciphertext) || |
| 273 !root->GetString("Cipher", &cipher) || |
| 274 !root->GetString("HMAC", &hmac) || |
| 275 !root->GetString("HMACMethod", &hmac_method) || |
| 276 !root->GetString("IV", &initial_vector) || |
| 277 !root->GetInteger("Iterations", &iterations) || |
| 278 !root->GetString("Salt", &salt) || |
| 279 !root->GetString("Stretch", &stretch_method) || |
| 280 !root->GetString("Type", &onc_type) || |
| 281 onc_type != "EncryptedConfiguration") { |
| 282 parse_error_ = l10n_util::GetStringUTF8( |
| 283 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_MALFORMED); |
| 284 return NULL; |
| 285 } |
| 286 |
| 287 if (hmac_method != "SHA1" || |
| 288 cipher != "AES256" || |
| 289 stretch_method != "PBKDF2") { |
| 290 parse_error_ = l10n_util::GetStringUTF8( |
| 291 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNSUPPORTED_ENCRYPTION); |
| 292 return NULL; |
| 293 } |
| 294 |
| 295 // Simply a sanity check to make sure we can't lock up the machine |
| 296 // for too long with a huge number. |
| 297 if (iterations > kMaxIterationCount) { |
| 298 parse_error_ = l10n_util::GetStringUTF8( |
| 299 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_TOO_MANY_ITERATIONS); |
| 300 return NULL; |
| 301 } |
| 302 |
| 303 if (!base::Base64Decode(salt, &salt)) { |
| 304 parse_error_ = l10n_util::GetStringUTF8( |
| 305 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE); |
| 306 return NULL; |
| 307 } |
| 308 |
| 309 scoped_ptr<crypto::SymmetricKey> key( |
| 310 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, |
| 311 passphrase, |
| 312 salt, |
| 313 iterations, |
| 314 kKeySizeInBits)); |
| 315 |
| 316 if (!base::Base64Decode(initial_vector, &initial_vector)) { |
| 317 parse_error_ = l10n_util::GetStringUTF8( |
| 318 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE); |
| 319 return NULL; |
| 320 } |
| 321 if (!base::Base64Decode(ciphertext, &ciphertext)) { |
| 322 parse_error_ = l10n_util::GetStringUTF8( |
| 323 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE); |
| 324 return NULL; |
| 325 } |
| 326 if (!base::Base64Decode(hmac, &hmac)) { |
| 327 parse_error_ = l10n_util::GetStringUTF8( |
| 328 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECODE); |
| 329 return NULL; |
| 330 } |
| 331 |
| 332 crypto::HMAC hmac_verifier(crypto::HMAC::SHA1); |
| 333 if (!hmac_verifier.Init(key.get()) || |
| 334 !hmac_verifier.Verify(ciphertext, hmac)) { |
| 335 parse_error_ = l10n_util::GetStringUTF8( |
| 336 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT); |
| 337 return NULL; |
| 338 } |
| 339 |
| 340 crypto::Encryptor decryptor; |
| 341 if (!decryptor.Init(key.get(), crypto::Encryptor::CBC, initial_vector)) { |
| 342 parse_error_ = l10n_util::GetStringUTF8( |
| 343 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT); |
| 344 return NULL; |
| 345 } |
| 346 |
| 347 std::string plaintext; |
| 348 if (!decryptor.Decrypt(ciphertext, &plaintext)) { |
| 349 parse_error_ = l10n_util::GetStringUTF8( |
| 350 IDS_NETWORK_CONFIG_ERROR_ENCRYPTED_ONC_UNABLE_TO_DECRYPT); |
| 351 return NULL; |
| 352 } |
| 353 |
| 354 // Now we've decrypted it, let's deserialize the decrypted data. |
| 355 JSONStringValueSerializer deserializer(plaintext); |
| 356 deserializer.set_allow_trailing_comma(true); |
| 357 scoped_ptr<base::Value> new_root(deserializer.Deserialize(NULL, |
| 358 &parse_error_)); |
| 359 if (!new_root.get() || !new_root->IsType(base::Value::TYPE_DICTIONARY)) { |
| 360 if (parse_error_.empty()) |
| 361 parse_error_ = l10n_util::GetStringUTF8( |
| 362 IDS_NETWORK_CONFIG_ERROR_NETWORK_PROP_DICT_MALFORMED); |
| 363 return NULL; |
| 364 } |
| 365 return static_cast<base::DictionaryValue*>(new_root.release()); |
| 366 } |
| 367 |
242 int OncNetworkParser::GetNetworkConfigsSize() const { | 368 int OncNetworkParser::GetNetworkConfigsSize() const { |
243 return network_configs_ ? network_configs_->GetSize() : 0; | 369 return network_configs_ ? network_configs_->GetSize() : 0; |
244 } | 370 } |
245 | 371 |
246 const base::DictionaryValue* OncNetworkParser::GetNetworkConfig(int n) { | 372 const base::DictionaryValue* OncNetworkParser::GetNetworkConfig(int n) { |
247 CHECK(network_configs_); | 373 CHECK(network_configs_); |
248 CHECK(static_cast<size_t>(n) < network_configs_->GetSize()); | 374 CHECK(static_cast<size_t>(n) < network_configs_->GetSize()); |
249 CHECK_GE(n, 0); | 375 CHECK_GE(n, 0); |
250 base::DictionaryValue* info = NULL; | 376 base::DictionaryValue* info = NULL; |
251 if (!network_configs_->GetDictionary(n, &info)) { | 377 if (!network_configs_->GetDictionary(n, &info)) { |
(...skipping 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1287 // on the value of AuthenticationType. | 1413 // on the value of AuthenticationType. |
1288 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK }, | 1414 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK }, |
1289 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN }, | 1415 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN }, |
1290 }; | 1416 }; |
1291 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser, | 1417 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser, |
1292 (table, arraysize(table), PROVIDER_TYPE_MAX)); | 1418 (table, arraysize(table), PROVIDER_TYPE_MAX)); |
1293 return parser.Get(type); | 1419 return parser.Get(type); |
1294 } | 1420 } |
1295 | 1421 |
1296 } // namespace chromeos | 1422 } // namespace chromeos |
OLD | NEW |