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

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: Clean up 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_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chromeos/network/network_event_log.h" 13 #include "chromeos/network/network_event_log.h"
14 #include "chromeos/network/onc/onc_mapper.h" 14 #include "chromeos/network/onc/onc_mapper.h"
15 #include "chromeos/network/onc/onc_signature.h" 15 #include "chromeos/network/onc/onc_signature.h"
16 #include "chromeos/network/onc/onc_utils.h" 16 #include "chromeos/network/onc/onc_utils.h"
17 #include "chromeos/network/onc/onc_validator.h" 17 #include "chromeos/network/onc/onc_validator.h"
18 #include "crypto/encryptor.h" 18 #include "crypto/encryptor.h"
19 #include "crypto/hmac.h" 19 #include "crypto/hmac.h"
20 #include "crypto/symmetric_key.h" 20 #include "crypto/symmetric_key.h"
21 #include "net/cert/pem_tokenizer.h" 21 #include "net/cert/pem_tokenizer.h"
22 #include "net/cert/x509_certificate.h"
22 23
23 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message) 24 #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message)
24 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message) 25 #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message)
25 26
26 namespace chromeos { 27 namespace chromeos {
27 namespace onc { 28 namespace onc {
28 29
29 namespace { 30 namespace {
30 31
31 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; 32 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC";
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 341
341 base::ListValue* validated_networks = NULL; 342 base::ListValue* validated_networks = NULL;
342 if (toplevel_onc->GetListWithoutPathExpansion( 343 if (toplevel_onc->GetListWithoutPathExpansion(
343 toplevel_config::kNetworkConfigurations, &validated_networks)) { 344 toplevel_config::kNetworkConfigurations, &validated_networks)) {
344 network_configs->Swap(validated_networks); 345 network_configs->Swap(validated_networks);
345 } 346 }
346 347
347 return success; 348 return success;
348 } 349 }
349 350
350 scoped_refptr<net::X509Certificate> DecodePEMCertificate( 351 namespace {
351 const std::string& pem_encoded, 352
352 const std::string& nickname) { 353 std::string DecodePEM(const std::string& pem_encoded) {
353 // The PEM block header used for DER certificates 354 // The PEM block header used for DER certificates
354 static const char kCertificateHeader[] = "CERTIFICATE"; 355 static const char kCertificateHeader[] = "CERTIFICATE";
355 // This is an older PEM marker for DER certificates. 356 // This is an older PEM marker for DER certificates.
356 static const char kX509CertificateHeader[] = "X509 CERTIFICATE"; 357 static const char kX509CertificateHeader[] = "X509 CERTIFICATE";
357 358
358 std::vector<std::string> pem_headers; 359 std::vector<std::string> pem_headers;
359 pem_headers.push_back(kCertificateHeader); 360 pem_headers.push_back(kCertificateHeader);
360 pem_headers.push_back(kX509CertificateHeader); 361 pem_headers.push_back(kX509CertificateHeader);
361 362
362 net::PEMTokenizer pem_tokenizer(pem_encoded, pem_headers); 363 net::PEMTokenizer pem_tokenizer(pem_encoded, pem_headers);
363 std::string decoded; 364 std::string decoded;
364 if (pem_tokenizer.GetNext()) { 365 if (pem_tokenizer.GetNext()) {
365 decoded = pem_tokenizer.data(); 366 decoded = pem_tokenizer.data();
366 } else { 367 } else {
367 // If we failed to read the data as a PEM file, then try plain base64 decode 368 // 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 369 // 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. 370 // to be no white space, and it has to only contain the base64-encoded data.
370 if (!base::Base64Decode(pem_encoded, &decoded)) { 371 if (!base::Base64Decode(pem_encoded, &decoded)) {
371 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded; 372 LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded;
372 return scoped_refptr<net::X509Certificate>(); 373 return std::string();
373 } 374 }
374 } 375 }
376 return decoded;
377 }
375 378
379 } // namespace
380
381 scoped_refptr<net::X509Certificate> DecodePEMCertificate(
382 const std::string& pem_encoded) {
383 std::string decoded = DecodePEM(pem_encoded);
376 scoped_refptr<net::X509Certificate> cert = 384 scoped_refptr<net::X509Certificate> cert =
377 net::X509Certificate::CreateFromBytesWithNickname(decoded.data(), 385 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: " 386 LOG_IF(ERROR, !cert) << "Couldn't create certificate from X509 data: "
381 << decoded; 387 << decoded;
382 return cert; 388 return cert;
383 } 389 }
384 390
391 namespace {
392
393 bool ResolveSingleCertRef(
394 const std::map<std::string,
395 scoped_refptr<net::X509Certificate> >& certs_by_guid,
stevenjb 2013/06/28 18:00:27 Use typedef here and below
pneubeck (no reviews) 2013/07/01 15:12:14 Done.
396 const std::string& key_guid_ref,
397 const std::string& key_pem,
398 base::DictionaryValue* dict) {
399 std::string guid_ref;
400 if (!dict->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref))
401 return true;
402 std::map<std::string, scoped_refptr<net::X509Certificate> >::const_iterator
403 it = certs_by_guid.find(guid_ref);
404 if (it == certs_by_guid.end()) {
405 LOG(ERROR) << "Couldn't resolve certificate reference " << guid_ref;
406 return false;
407 }
408
409 std::string pem_encoded;
410 if (!net::X509Certificate::GetPEMEncoded(it->second->os_cert_handle(),
411 &pem_encoded)) {
412 LOG(ERROR) << "Couldn't PEM-encode certificate with GUID " << guid_ref;
413 return false;
414 }
415
416 dict->SetStringWithoutPathExpansion(key_pem, pem_encoded);
417 return true;
418 }
419
420 bool ResolveOpenVPNCaCertRefs(
421 const std::map<std::string,
422 scoped_refptr<net::X509Certificate> >& certs_by_guid,
423 base::DictionaryValue* openvpn) {
424 std::string guid_ref;
425 if (!openvpn->GetStringWithoutPathExpansion(openvpn::kServerCARef, &guid_ref))
426 return true;
427 std::map<std::string, scoped_refptr<net::X509Certificate> >::const_iterator
428 it = certs_by_guid.find(guid_ref);
429 if (it == certs_by_guid.end()) {
430 LOG(ERROR) << "Couldn't resolve certificate reference " << guid_ref;
431 return false;
432 }
433
434 std::string pem_encoded;
435 if (!net::X509Certificate::GetPEMEncoded(it->second->os_cert_handle(),
436 &pem_encoded)) {
437 LOG(ERROR) << "Couldn't PEM-encode certificate with GUID " << guid_ref;
438 return false;
439 }
440
441 scoped_ptr<base::ListValue> pem_list(new base::ListValue);
442 pem_list->AppendString(pem_encoded);
443 openvpn->SetWithoutPathExpansion(openvpn::kServerCAPEMs, pem_list.release());
444 return true;
445 }
446
447 bool ResolveServerCertRefsInObject(
448 const std::map<std::string,
449 scoped_refptr<net::X509Certificate> >& certs_by_guid,
450 const OncValueSignature& signature,
451 base::DictionaryValue* onc_object) {
452 if (&signature == &kEAPSignature) {
453 if (!ResolveSingleCertRef(certs_by_guid, eap::kServerCARef,
454 eap::kServerCAPEM, onc_object)) {
455 return false;
456 }
457 } else if (&signature == &kL2TPSignature) {
458 if (!ResolveSingleCertRef(certs_by_guid, ipsec::kServerCARef,
459 ipsec::kServerCAPEM, onc_object)) {
460 return false;
461 }
462 } else if (&signature == &kL2TPSignature ||
463 &signature == &kOpenVPNSignature) {
464 if (!ResolveSingleCertRef(certs_by_guid, vpn::kServerCertRef,
465 vpn::kServerCertPEM, onc_object) ||
466 !ResolveOpenVPNCaCertRefs(certs_by_guid, 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