Chromium Code Reviews| Index: chromeos/network/onc/onc_utils.cc |
| diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc |
| index 79768268f09ec41f31b9502247deed0676cb0167..fb7759464be90fe55731e6b18f775f779c433630 100644 |
| --- a/chromeos/network/onc/onc_utils.cc |
| +++ b/chromeos/network/onc/onc_utils.cc |
| @@ -19,6 +19,7 @@ |
| #include "crypto/hmac.h" |
| #include "crypto/symmetric_key.h" |
| #include "net/cert/pem_tokenizer.h" |
| +#include "net/cert/x509_certificate.h" |
| #define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message) |
| #define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message) |
| @@ -347,9 +348,9 @@ bool ParseAndValidateOncForImport(const std::string& onc_blob, |
| return success; |
| } |
| -scoped_refptr<net::X509Certificate> DecodePEMCertificate( |
| - const std::string& pem_encoded, |
| - const std::string& nickname) { |
| +namespace { |
| + |
| +std::string DecodePEM(const std::string& pem_encoded) { |
| // The PEM block header used for DER certificates |
| static const char kCertificateHeader[] = "CERTIFICATE"; |
| // This is an older PEM marker for DER certificates. |
| @@ -369,18 +370,160 @@ scoped_refptr<net::X509Certificate> DecodePEMCertificate( |
| // to be no white space, and it has to only contain the base64-encoded data. |
| if (!base::Base64Decode(pem_encoded, &decoded)) { |
| LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded; |
| - return scoped_refptr<net::X509Certificate>(); |
| + return std::string(); |
| } |
| } |
| + return decoded; |
| +} |
| +} // namespace |
| + |
| +scoped_refptr<net::X509Certificate> DecodePEMCertificate( |
| + const std::string& pem_encoded) { |
| + std::string decoded = DecodePEM(pem_encoded); |
| scoped_refptr<net::X509Certificate> cert = |
| - net::X509Certificate::CreateFromBytesWithNickname(decoded.data(), |
| - decoded.size(), |
| - nickname.c_str()); |
| + net::X509Certificate::CreateFromBytes(decoded.data(), decoded.size()); |
| LOG_IF(ERROR, !cert) << "Couldn't create certificate from X509 data: " |
| << decoded; |
| return cert; |
| } |
| +namespace { |
| + |
| +bool ResolveSingleCertRef( |
| + const std::map<std::string, |
| + 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.
|
| + const std::string& key_guid_ref, |
| + const std::string& key_pem, |
| + base::DictionaryValue* dict) { |
| + std::string guid_ref; |
| + if (!dict->GetStringWithoutPathExpansion(key_guid_ref, &guid_ref)) |
| + return true; |
| + std::map<std::string, scoped_refptr<net::X509Certificate> >::const_iterator |
| + it = certs_by_guid.find(guid_ref); |
| + if (it == certs_by_guid.end()) { |
| + LOG(ERROR) << "Couldn't resolve certificate reference " << guid_ref; |
| + return false; |
| + } |
| + |
| + std::string pem_encoded; |
| + if (!net::X509Certificate::GetPEMEncoded(it->second->os_cert_handle(), |
| + &pem_encoded)) { |
| + LOG(ERROR) << "Couldn't PEM-encode certificate with GUID " << guid_ref; |
| + return false; |
| + } |
| + |
| + dict->SetStringWithoutPathExpansion(key_pem, pem_encoded); |
| + return true; |
| +} |
| + |
| +bool ResolveOpenVPNCaCertRefs( |
| + const std::map<std::string, |
| + scoped_refptr<net::X509Certificate> >& certs_by_guid, |
| + base::DictionaryValue* openvpn) { |
| + std::string guid_ref; |
| + if (!openvpn->GetStringWithoutPathExpansion(openvpn::kServerCARef, &guid_ref)) |
| + return true; |
| + std::map<std::string, scoped_refptr<net::X509Certificate> >::const_iterator |
| + it = certs_by_guid.find(guid_ref); |
| + if (it == certs_by_guid.end()) { |
| + LOG(ERROR) << "Couldn't resolve certificate reference " << guid_ref; |
| + return false; |
| + } |
| + |
| + std::string pem_encoded; |
| + if (!net::X509Certificate::GetPEMEncoded(it->second->os_cert_handle(), |
| + &pem_encoded)) { |
| + LOG(ERROR) << "Couldn't PEM-encode certificate with GUID " << guid_ref; |
| + return false; |
| + } |
| + |
| + scoped_ptr<base::ListValue> pem_list(new base::ListValue); |
| + pem_list->AppendString(pem_encoded); |
| + openvpn->SetWithoutPathExpansion(openvpn::kServerCAPEMs, pem_list.release()); |
| + return true; |
| +} |
| + |
| +bool ResolveServerCertRefsInObject( |
| + const std::map<std::string, |
| + scoped_refptr<net::X509Certificate> >& certs_by_guid, |
| + const OncValueSignature& signature, |
| + base::DictionaryValue* onc_object) { |
| + if (&signature == &kEAPSignature) { |
| + if (!ResolveSingleCertRef(certs_by_guid, eap::kServerCARef, |
| + eap::kServerCAPEM, onc_object)) { |
| + return false; |
| + } |
| + } else if (&signature == &kL2TPSignature) { |
| + if (!ResolveSingleCertRef(certs_by_guid, ipsec::kServerCARef, |
| + ipsec::kServerCAPEM, onc_object)) { |
| + return false; |
| + } |
| + } else if (&signature == &kL2TPSignature || |
| + &signature == &kOpenVPNSignature) { |
| + if (!ResolveSingleCertRef(certs_by_guid, vpn::kServerCertRef, |
| + vpn::kServerCertPEM, onc_object) || |
| + !ResolveOpenVPNCaCertRefs(certs_by_guid, onc_object)) { |
| + return false; |
| + } |
| + } |
| + |
| + // Recurse into nested objects. |
| + for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd(); |
| + it.Advance()) { |
| + base::DictionaryValue* inner_object = NULL; |
| + if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object)) |
| + continue; |
| + |
| + const OncFieldSignature* field_signature = |
| + GetFieldSignature(signature, it.key()); |
| + if (!field_signature) |
| + continue; |
| + |
| + if (!ResolveServerCertRefsInObject(certs_by_guid, |
| + *field_signature->value_signature, |
| + inner_object)) { |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| +bool ResolveServerCertRefsInNetworks( |
| + const std::map<std::string, |
| + scoped_refptr<net::X509Certificate> >& certs_by_guid, |
| + base::ListValue* network_configs) { |
| + bool success = true; |
| + for (base::ListValue::iterator it = network_configs->begin(); |
| + it != network_configs->end(); ) { |
| + base::DictionaryValue* network = NULL; |
| + (*it)->GetAsDictionary(&network); |
| + if (!ResolveServerCertRefsInNetwork(certs_by_guid, network)) { |
| + std::string guid; |
| + network->GetStringWithoutPathExpansion(network_config::kGUID, &guid); |
| + // This might happen even with correct validation, if the referenced |
| + // certificate couldn't be imported. |
| + LOG(ERROR) << "Couldn't resolve some certificate reference of network " |
| + << guid; |
| + it = network_configs->Erase(it, NULL); |
| + success = false; |
| + continue; |
| + } |
| + ++it; |
| + } |
| + return success; |
| +} |
| + |
| +bool ResolveServerCertRefsInNetwork( |
| + const std::map<std::string, |
| + scoped_refptr<net::X509Certificate> >& certs_by_guid, |
| + base::DictionaryValue* network_config) { |
| + return ResolveServerCertRefsInObject(certs_by_guid, |
| + kNetworkConfigurationSignature, |
| + network_config); |
| +} |
| + |
| } // namespace onc |
| } // namespace chromeos |