Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(717)

Side by Side Diff: chromeos/network/onc/onc_utils.cc

Issue 16946002: Resolve certificate references in ONC by PEM. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed tests. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_util.h" 12 #include "base/strings/string_util.h"
12 #include "base/values.h" 13 #include "base/values.h"
13 #include "chromeos/network/network_event_log.h" 14 #include "chromeos/network/network_event_log.h"
14 #include "chromeos/network/onc/onc_mapper.h" 15 #include "chromeos/network/onc/onc_mapper.h"
15 #include "chromeos/network/onc/onc_signature.h" 16 #include "chromeos/network/onc/onc_signature.h"
16 #include "chromeos/network/onc/onc_utils.h" 17 #include "chromeos/network/onc/onc_utils.h"
17 #include "chromeos/network/onc/onc_validator.h" 18 #include "chromeos/network/onc/onc_validator.h"
18 #include "crypto/encryptor.h" 19 #include "crypto/encryptor.h"
19 #include "crypto/hmac.h" 20 #include "crypto/hmac.h"
20 #include "crypto/symmetric_key.h" 21 #include "crypto/symmetric_key.h"
22 #include "net/base/hash_value.h"
21 #include "net/cert/pem_tokenizer.h" 23 #include "net/cert/pem_tokenizer.h"
24 #include "net/cert/x509_certificate.h"
22 25
23 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message) 26 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message)
24 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message) 27 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message)
25 28
26 namespace chromeos { 29 namespace chromeos {
27 namespace onc { 30 namespace onc {
28 31
29 namespace { 32 namespace {
30 33
31 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; 34 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC";
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 343
341 base::ListValue* validated_networks = NULL; 344 base::ListValue* validated_networks = NULL;
342 if (toplevel_onc->GetListWithoutPathExpansion( 345 if (toplevel_onc->GetListWithoutPathExpansion(
343 toplevel_config::kNetworkConfigurations, &validated_networks)) { 346 toplevel_config::kNetworkConfigurations, &validated_networks)) {
344 network_configs->Swap(validated_networks); 347 network_configs->Swap(validated_networks);
345 } 348 }
346 349
347 return success; 350 return success;
348 } 351 }
349 352
353 std::string GetHexFingerprintOfCert(const net::X509Certificate& cert) {
354 net::SHA1HashValue fingerprint = cert.fingerprint();
355 return base::HexEncode(fingerprint.data, sizeof(fingerprint.data));
356 }
357
358 net::X509Certificate* FindCertByFingerprint(
359 const net::CertificateList& cert_list, const std::string& fingerprint) {
360 net::X509Certificate* found = NULL;
361 for (net::CertificateList::const_iterator it = cert_list.begin();
362 it != cert_list.end(); ++it) {
363 if (GetHexFingerprintOfCert(**it) != fingerprint)
364 continue;
365 if (found != NULL) {
366 LOG(ERROR) << "Fingerprint not unique in list.";
Mattias Nissler (ping if slow) 2013/06/24 12:45:09 Rather, cert present twice in list. I don't think
pneubeck (no reviews) 2013/06/24 15:35:41 Done.
367 return NULL;
368 }
369 found = it->get();
370 }
371 return found;
372 }
373
374 std::string GetPEMEncodedCertFromFingerprint(
375 const net::CertificateList& cert_list,
376 const std::string& fingerprint) {
377 net::X509Certificate* cert = FindCertByFingerprint(cert_list, fingerprint);
378 if (!cert) {
379 LOG(ERROR) << "Couldn't find a certificate with fingerprint "
380 << fingerprint;
381 return std::string();
382 }
383
384 std::string pem_encoded_cert;
385 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(),
386 &pem_encoded_cert)) {
387 LOG(ERROR) << "Couldn't PEM-encode certificate with fingerprint "
388 << fingerprint;
389 return std::string();
390 }
391
392 return pem_encoded_cert;
393 }
394
350 scoped_refptr<net::X509Certificate> DecodePEMCertificate( 395 scoped_refptr<net::X509Certificate> DecodePEMCertificate(
351 const std::string& pem_encoded, 396 const std::string& pem_encoded) {
352 const std::string& nickname) {
353 // The PEM block header used for DER certificates 397 // The PEM block header used for DER certificates
354 static const char kCertificateHeader[] = "CERTIFICATE"; 398 static const char kCertificateHeader[] = "CERTIFICATE";
355 // This is an older PEM marker for DER certificates. 399 // This is an older PEM marker for DER certificates.
356 static const char kX509CertificateHeader[] = "X509 CERTIFICATE"; 400 static const char kX509CertificateHeader[] = "X509 CERTIFICATE";
357 401
358 std::vector<std::string> pem_headers; 402 std::vector<std::string> pem_headers;
359 pem_headers.push_back(kCertificateHeader); 403 pem_headers.push_back(kCertificateHeader);
360 pem_headers.push_back(kX509CertificateHeader); 404 pem_headers.push_back(kX509CertificateHeader);
361 405
362 net::PEMTokenizer pem_tokenizer(pem_encoded, pem_headers); 406 net::PEMTokenizer pem_tokenizer(pem_encoded, pem_headers);
363 std::string decoded; 407 std::string decoded;
364 if (pem_tokenizer.GetNext()) { 408 if (pem_tokenizer.GetNext()) {
365 decoded = pem_tokenizer.data(); 409 decoded = pem_tokenizer.data();
366 } else { 410 } else {
367 // If we failed to read the data as a PEM file, then try plain base64 decode 411 // If we failed to read the data as a PEM file, then try plain base64 decode
368 // in case the PEM marker strings are missing. For this to work, there has 412 // in case the PEM marker strings are missing. For this to work, there has
369 // to be no white space, and it has to only contain the base64-encoded data. 413 // to be no white space, and it has to only contain the base64-encoded data.
370 if (!base::Base64Decode(pem_encoded, &decoded)) { 414 if (!base::Base64Decode(pem_encoded, &decoded)) {
371 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded; 415 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded;
372 return scoped_refptr<net::X509Certificate>(); 416 return scoped_refptr<net::X509Certificate>();
373 } 417 }
374 } 418 }
375 419
376 scoped_refptr<net::X509Certificate> cert = 420 scoped_refptr<net::X509Certificate> cert =
377 net::X509Certificate::CreateFromBytesWithNickname(decoded.data(), 421 net::X509Certificate::CreateFromBytes(decoded.data(), decoded.size());
378 decoded.size(),
379 nickname.c_str());
380 LOG_IF(ERROR, !cert) << "Couldn't create certificate from X509 data: " 422 LOG_IF(ERROR, !cert) << "Couldn't create certificate from X509 data: "
381 << decoded; 423 << decoded;
382 return cert; 424 return cert;
383 } 425 }
384 426
427 namespace {
428
429 bool ResolveCertRef(
430 const std::map<std::string,
431 scoped_refptr<net::X509Certificate> >& certs_by_guid,
432 const std::string& key_guid_ref,
433 const std::string& key_fingerprint,
434 base::DictionaryValue* dict) {
435 std::string guid_ref;
436 if (!dict->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref))
437 return true;
438 std::map<std::string, scoped_refptr<net::X509Certificate> >::const_iterator
439 it = certs_by_guid.find(guid_ref);
440 if (it == certs_by_guid.end()) {
441 LOG(ERROR) << "Couldn't resolve certificate reference " << guid_ref;
442 return false;
443 }
444
445 dict->SetStringWithoutPathExpansion(
446 key_fingerprint,
447 GetHexFingerprintOfCert(*it->second));
448 return true;
449 }
450
451 bool ResolveServerCertRefsInObject(
452 const std::map<std::string,
453 scoped_refptr<net::X509Certificate> >& certs_by_guid,
454 const OncValueSignature& signature,
455 base::DictionaryValue* onc_object) {
456 if (&signature == &kEAPSignature) {
457 if (!ResolveCertRef(certs_by_guid, eap::kServerCARef,
458 eap::kServerCAFingerprint, onc_object)) {
459 return false;
460 }
461 } else if (&signature == &kL2TPSignature ||
462 &signature == &kOpenVPNSignature) {
463 if (!ResolveCertRef(certs_by_guid, vpn::kServerCARef,
464 vpn::kServerCAFingerprint, onc_object) ||
465 !ResolveCertRef(certs_by_guid, vpn::kServerCertRef,
466 vpn::kServerCertFingerprint, onc_object)) {
467 return false;;
468 }
469 }
470
471 // Recurse into nested objects.
472 for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
473 it.Advance()) {
474 base::DictionaryValue* inner_object = NULL;
475 if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object))
476 continue;
477
478 const OncFieldSignature* field_signature =
479 GetFieldSignature(signature, it.key());
480 if (!field_signature)
481 continue;
482
483 if (!ResolveServerCertRefsInObject(certs_by_guid,
484 *field_signature->value_signature,
485 inner_object)) {
486 return false;
487 }
488 }
489 return true;
490 }
491
492 } // namespace
493
494 bool ResolveServerCertRefsInNetworks(
495 const std::map<std::string,
496 scoped_refptr<net::X509Certificate> >& certs_by_guid,
497 base::ListValue* network_configs) {
498 bool success = true;
499 for (base::ListValue::iterator it = network_configs->begin();
500 it != network_configs->end(); ) {
501 base::DictionaryValue* network = NULL;
502 (*it)->GetAsDictionary(&network);
503 if (!ResolveServerCertRefsInNetwork(certs_by_guid, network)) {
504 std::string guid;
505 network->GetStringWithoutPathExpansion(network_config::kGUID, &guid);
506 // This might happen even with correct validation, if the referenced
507 // certificate couldn't be imported.
508 LOG(ERROR) << "Couldn't resolve some certificate reference of network "
509 << guid;
510 it = network_configs->Erase(it, NULL);
511 success = false;
512 continue;
513 }
514 ++it;
515 }
516 return success;
517 }
518
519 bool ResolveServerCertRefsInNetwork(
520 const std::map<std::string,
521 scoped_refptr<net::X509Certificate> >& certs_by_guid,
522 base::DictionaryValue* network_config) {
523 return ResolveServerCertRefsInObject(certs_by_guid,
524 kNetworkConfigurationSignature,
525 network_config);
526 }
527
385 } // namespace onc 528 } // namespace onc
386 } // namespace chromeos 529 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698