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

Unified 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: removed automation part. Created 7 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: chromeos/network/onc/onc_utils.cc
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 3feb9139c462b679a1e8a0f4f087e9e8c84a47d6..9e66005e8dbd550953870955977aefdfc33ad38a 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -8,6 +8,7 @@
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chromeos/network/network_event_log.h"
@@ -19,6 +20,7 @@
#include "crypto/encryptor.h"
#include "crypto/hmac.h"
#include "crypto/symmetric_key.h"
+#include "net/base/hash_value.h"
#define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message)
#define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message)
@@ -354,5 +356,147 @@ bool ParseAndValidateOncForImport(
return success;
}
+std::string GetHexFingerprintOfCert(const net::X509Certificate& cert) {
+ net::SHA1HashValue fingerprint = cert.fingerprint();
+ return base::HexEncode(fingerprint.data, sizeof(fingerprint.data));
+}
+
+net::X509Certificate* FindCertByFingerprint(
+ const net::CertificateList& cert_list, const std::string& fingerprint) {
+ net::X509Certificate* found = NULL;
+ for (net::CertificateList::const_iterator it = cert_list.begin();
+ it != cert_list.end(); ++it) {
+ if (GetHexFingerprintOfCert(**it) != fingerprint)
+ continue;
+ if (found != NULL) {
+ LOG(ERROR) << "Certificate fingerprints collided.";
+ return NULL;
+ }
+ found = it->get();
+ }
+ return found;
+}
+
+std::string GetPEMEncodedCertFromFingerprint(
+ const net::CertificateList& cert_list,
+ const std::string& fingerprint) {
+ net::X509Certificate* cert = FindCertByFingerprint(cert_list, fingerprint);
+ if (!cert) {
+ LOG(ERROR) << "Couldn't find a certificate with fingerprint "
+ << fingerprint;
+ return std::string();
+ }
+
+ std::string pem_encoded_cert;
+ if (!cert->GetPEMEncoded(&pem_encoded_cert)) {
+ LOG(ERROR) << "Couldn't PEM-encode certificate with fingerprint "
+ << fingerprint;
+ return std::string();
+ }
+
+ return pem_encoded_cert;
+}
+
+namespace {
+
+bool ResolveCertRef(
+ const std::map<std::string,
+ scoped_refptr<net::X509Certificate> >& certs_by_guid,
+ const std::string& key_guid_ref,
+ const std::string& key_fingerprint,
+ 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;
+ }
+
+ dict->SetStringWithoutPathExpansion(
+ key_fingerprint,
+ GetHexFingerprintOfCert(*it->second));
+ 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 (!ResolveCertRef(certs_by_guid, eap::kServerCARef,
+ eap::kServerCAFingerprint, onc_object)) {
+ return false;
+ }
+ } else if (&signature == &kL2TPSignature ||
+ &signature == &kOpenVPNSignature) {
+ if (!ResolveCertRef(certs_by_guid, vpn::kServerCARef,
+ vpn::kServerCAFingerprint, onc_object) ||
+ !ResolveCertRef(certs_by_guid, vpn::kServerCertRef,
+ vpn::kServerCertFingerprint, 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

Powered by Google App Engine
This is Rietveld 408576698