Index: chromeos/network/onc/onc_certificate_importer_impl.cc |
diff --git a/chromeos/network/onc/onc_certificate_importer_impl.cc b/chromeos/network/onc/onc_certificate_importer_impl.cc |
index 7bb18333aee9a004e67d0be61c7c28c671c06fd1..521595acd9ac2e2fbfeb4f60298d6df3bc7fb182 100644 |
--- a/chromeos/network/onc/onc_certificate_importer_impl.cc |
+++ b/chromeos/network/onc/onc_certificate_importer_impl.cc |
@@ -9,7 +9,14 @@ |
#include <pk11pub.h> |
#include "base/base64.h" |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/callback.h" |
+#include "base/location.h" |
#include "base/logging.h" |
+#include "base/sequenced_task_runner.h" |
+#include "base/single_thread_task_runner.h" |
+#include "base/thread_task_runner_handle.h" |
#include "base/values.h" |
#include "chromeos/network/network_event_log.h" |
#include "chromeos/network/onc/onc_utils.h" |
@@ -20,64 +27,83 @@ |
#include "net/cert/nss_cert_database.h" |
#include "net/cert/x509_certificate.h" |
-#define ONC_LOG_WARNING(message) \ |
- NET_LOG_DEBUG("ONC Certificate Import Warning", message) |
-#define ONC_LOG_ERROR(message) \ |
- NET_LOG_ERROR("ONC Certificate Import Error", message) |
- |
namespace chromeos { |
namespace onc { |
+namespace { |
+ |
+void CallBackOnOriginLoop( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& origin_loop, |
+ const CertificateImporter::DoneCallback& callback, |
+ bool success, |
+ const net::CertificateList& onc_trusted_certificates) { |
+ origin_loop->PostTask( |
+ FROM_HERE, base::Bind(callback, success, onc_trusted_certificates)); |
+} |
+ |
+} // namespace |
+ |
CertificateImporterImpl::CertificateImporterImpl( |
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner, |
net::NSSCertDatabase* target_nssdb) |
- : target_nssdb_(target_nssdb) { |
+ : task_runner_(task_runner), |
+ target_nssdb_(target_nssdb), |
+ weak_factory_(this) { |
CHECK(target_nssdb); |
} |
-bool CertificateImporterImpl::ImportCertificates( |
+CertificateImporterImpl::~CertificateImporterImpl() { |
+} |
+ |
+void CertificateImporterImpl::ImportCertificates( |
const base::ListValue& certificates, |
::onc::ONCSource source, |
- net::CertificateList* onc_trusted_certificates) { |
+ const DoneCallback& done_callback) { |
VLOG(2) << "ONC file has " << certificates.GetSize() << " certificates"; |
+ DoneCallback callback_on_origin_loop = |
+ base::Bind(&CallBackOnOriginLoop, |
+ base::ThreadTaskRunnerHandle::Get(), |
+ base::Bind(&CertificateImporterImpl::RunDoneCallback, |
+ weak_factory_.GetWeakPtr(), |
+ done_callback)); |
+ |
+ task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&ParseAndStoreCertificates, |
+ source, |
+ callback_on_origin_loop, |
+ base::Owned(certificates.DeepCopy()), |
+ target_nssdb_)); |
Joao da Silva
2014/09/15 12:38:24
This is essentially PostTaskAndReply, can you use
pneubeck (no reviews)
2014/09/17 12:44:21
Indeed, in this case something like
PostTaskAndRe
|
+} |
+// static |
+void CertificateImporterImpl::ParseAndStoreCertificates( |
+ ::onc::ONCSource source, |
+ const DoneCallback& done_callback, |
+ base::ListValue* certificates, |
+ net::NSSCertDatabase* nssdb) { |
// Web trust is only granted to certificates imported by the user. |
bool allow_trust_imports = source == ::onc::ONC_SOURCE_USER_IMPORT; |
- if (!ParseAndStoreCertificates(allow_trust_imports, |
- certificates, |
- onc_trusted_certificates, |
- NULL)) { |
- LOG(ERROR) << "Cannot parse some of the certificates in the ONC from " |
- << onc::GetSourceAsString(source); |
- return false; |
- } |
- return true; |
-} |
- |
-bool CertificateImporterImpl::ParseAndStoreCertificates( |
- bool allow_trust_imports, |
- const base::ListValue& certificates, |
- net::CertificateList* onc_trusted_certificates, |
- CertsByGUID* imported_server_and_ca_certs) { |
+ net::CertificateList onc_trusted_certificates; |
bool success = true; |
- for (size_t i = 0; i < certificates.GetSize(); ++i) { |
+ for (size_t i = 0; i < certificates->GetSize(); ++i) { |
const base::DictionaryValue* certificate = NULL; |
- certificates.GetDictionary(i, &certificate); |
+ certificates->GetDictionary(i, &certificate); |
DCHECK(certificate != NULL); |
VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate; |
if (!ParseAndStoreCertificate(allow_trust_imports, |
*certificate, |
- onc_trusted_certificates, |
- imported_server_and_ca_certs)) { |
+ nssdb, |
+ &onc_trusted_certificates)) { |
success = false; |
- ONC_LOG_ERROR( |
- base::StringPrintf("Cannot parse certificate at index %zu", i)); |
+ LOG(ERROR) << "Cannot parse certificate at index " << i; |
} else { |
VLOG(2) << "Successfully imported certificate at index " << i; |
} |
} |
- return success; |
+ |
+ done_callback.Run(success, onc_trusted_certificates); |
} |
// static |
@@ -143,11 +169,20 @@ bool CertificateImporterImpl::DeleteCertAndKeyByNickname( |
return result; |
} |
+void CertificateImporterImpl::RunDoneCallback( |
+ const CertificateImporter::DoneCallback& callback, |
+ bool success, |
+ const net::CertificateList& onc_trusted_certificates) { |
+ if (!success) |
+ NET_LOG_ERROR("ONC Certificate Import Error", ""); |
+ callback.Run(success, onc_trusted_certificates); |
+} |
+ |
bool CertificateImporterImpl::ParseAndStoreCertificate( |
bool allow_trust_imports, |
const base::DictionaryValue& certificate, |
- net::CertificateList* onc_trusted_certificates, |
- CertsByGUID* imported_server_and_ca_certs) { |
+ net::NSSCertDatabase* nssdb, |
+ net::CertificateList* onc_trusted_certificates) { |
// Get out the attributes of the given certificate. |
std::string guid; |
certificate.GetStringWithoutPathExpansion(::onc::certificate::kGUID, &guid); |
@@ -156,8 +191,8 @@ bool CertificateImporterImpl::ParseAndStoreCertificate( |
bool remove = false; |
if (certificate.GetBooleanWithoutPathExpansion(::onc::kRemove, &remove) && |
remove) { |
- if (!DeleteCertAndKeyByNickname(guid, target_nssdb_)) { |
- ONC_LOG_ERROR("Unable to delete certificate"); |
+ if (!DeleteCertAndKeyByNickname(guid, nssdb)) { |
+ LOG(ERROR) << "Unable to delete certificate"; |
return false; |
} else { |
return true; |
@@ -174,10 +209,10 @@ bool CertificateImporterImpl::ParseAndStoreCertificate( |
cert_type, |
guid, |
certificate, |
- onc_trusted_certificates, |
- imported_server_and_ca_certs); |
+ nssdb, |
+ onc_trusted_certificates); |
} else if (cert_type == ::onc::certificate::kClient) { |
- return ParseClientCertificate(guid, certificate); |
+ return ParseClientCertificate(guid, certificate, nssdb); |
} |
NOTREACHED(); |
@@ -189,8 +224,8 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
const std::string& cert_type, |
const std::string& guid, |
const base::DictionaryValue& certificate, |
- net::CertificateList* onc_trusted_certificates, |
- CertsByGUID* imported_server_and_ca_certs) { |
+ net::NSSCertDatabase* nssdb, |
+ net::CertificateList* onc_trusted_certificates) { |
bool web_trust_flag = false; |
const base::ListValue* trust_list = NULL; |
if (certificate.GetListWithoutPathExpansion(::onc::certificate::kTrustBits, |
@@ -208,8 +243,8 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
} else { |
// Trust bits should only increase trust and never restrict. Thus, |
// ignoring unknown bits should be safe. |
- ONC_LOG_WARNING("Certificate contains unknown trust type " + |
- trust_type); |
+ LOG(WARNING) << "Certificate contains unknown trust type " |
+ << trust_type; |
} |
} |
} |
@@ -217,7 +252,7 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
bool import_with_ssl_trust = false; |
if (web_trust_flag) { |
if (!allow_trust_imports) |
- ONC_LOG_WARNING("Web trust not granted for certificate: " + guid); |
+ LOG(WARNING) << "Web trust not granted for certificate: " << guid; |
else |
import_with_ssl_trust = true; |
} |
@@ -226,17 +261,16 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
if (!certificate.GetStringWithoutPathExpansion(::onc::certificate::kX509, |
&x509_data) || |
x509_data.empty()) { |
- ONC_LOG_ERROR( |
- "Certificate missing appropriate certificate data for type: " + |
- cert_type); |
+ LOG(ERROR) << "Certificate missing appropriate certificate data for type: " |
+ << cert_type; |
return false; |
} |
scoped_refptr<net::X509Certificate> x509_cert = |
DecodePEMCertificate(x509_data); |
if (!x509_cert.get()) { |
- ONC_LOG_ERROR("Unable to create certificate from PEM encoding, type: " + |
- cert_type); |
+ LOG(ERROR) << "Unable to create certificate from PEM encoding, type: " |
+ << cert_type; |
return false; |
} |
@@ -250,21 +284,19 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
: net::CA_CERT; |
VLOG(1) << "Certificate is already installed."; |
net::NSSCertDatabase::TrustBits missing_trust_bits = |
- trust & ~target_nssdb_->GetCertTrust(x509_cert.get(), net_cert_type); |
+ trust & ~nssdb->GetCertTrust(x509_cert.get(), net_cert_type); |
if (missing_trust_bits) { |
std::string error_reason; |
bool success = false; |
- if (target_nssdb_->IsReadOnly(x509_cert.get())) { |
+ if (nssdb->IsReadOnly(x509_cert.get())) { |
error_reason = " Certificate is stored read-only."; |
} else { |
- success = target_nssdb_->SetCertTrust(x509_cert.get(), |
- net_cert_type, |
- trust); |
+ success = nssdb->SetCertTrust(x509_cert.get(), net_cert_type, trust); |
} |
if (!success) { |
- ONC_LOG_ERROR("Certificate of type " + cert_type + |
- " was already present, but trust couldn't be set." + |
- error_reason); |
+ LOG(ERROR) << "Certificate of type " << cert_type |
+ << " was already present, but trust couldn't be set." |
+ << error_reason; |
} |
} |
} else { |
@@ -273,21 +305,19 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
net::NSSCertDatabase::ImportCertFailureList failures; |
bool success = false; |
if (cert_type == ::onc::certificate::kServer) |
- success = target_nssdb_->ImportServerCert(cert_list, trust, &failures); |
+ success = nssdb->ImportServerCert(cert_list, trust, &failures); |
else // Authority cert |
- success = target_nssdb_->ImportCACerts(cert_list, trust, &failures); |
+ success = nssdb->ImportCACerts(cert_list, trust, &failures); |
if (!failures.empty()) { |
std::string error_string = net::ErrorToString(failures[0].net_error); |
- ONC_LOG_ERROR( |
- base::StringPrintf("Error ( %s ) importing %s certificate", |
- error_string.c_str(), |
- cert_type.c_str())); |
+ LOG(ERROR) << "Error ( " << error_string |
+ << " ) importing certificate of type " << cert_type; |
return false; |
} |
if (!success) { |
- ONC_LOG_ERROR("Unknown error importing " + cert_type + " certificate."); |
+ LOG(ERROR) << "Unknown error importing " << cert_type << " certificate."; |
return false; |
} |
} |
@@ -295,56 +325,53 @@ bool CertificateImporterImpl::ParseServerOrCaCertificate( |
if (web_trust_flag && onc_trusted_certificates) |
onc_trusted_certificates->push_back(x509_cert); |
- if (imported_server_and_ca_certs) |
- (*imported_server_and_ca_certs)[guid] = x509_cert; |
- |
return true; |
} |
bool CertificateImporterImpl::ParseClientCertificate( |
const std::string& guid, |
- const base::DictionaryValue& certificate) { |
+ const base::DictionaryValue& certificate, |
+ net::NSSCertDatabase* nssdb) { |
std::string pkcs12_data; |
if (!certificate.GetStringWithoutPathExpansion(::onc::certificate::kPKCS12, |
&pkcs12_data) || |
pkcs12_data.empty()) { |
- ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); |
+ LOG(ERROR) << "PKCS12 data is missing for client certificate."; |
return false; |
} |
std::string decoded_pkcs12; |
if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { |
- ONC_LOG_ERROR( |
- "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\"."); |
+ LOG(ERROR) << "Unable to base64 decode PKCS#12 data: \"" << pkcs12_data |
+ << "\"."; |
return false; |
} |
// Since this has a private key, always use the private module. |
- crypto::ScopedPK11Slot private_slot(target_nssdb_->GetPrivateSlot()); |
+ crypto::ScopedPK11Slot private_slot(nssdb->GetPrivateSlot()); |
if (!private_slot) |
return false; |
scoped_refptr<net::CryptoModule> module( |
net::CryptoModule::CreateFromHandle(private_slot.get())); |
net::CertificateList imported_certs; |
- int import_result = target_nssdb_->ImportFromPKCS12( |
+ int import_result = nssdb->ImportFromPKCS12( |
module.get(), decoded_pkcs12, base::string16(), false, &imported_certs); |
if (import_result != net::OK) { |
std::string error_string = net::ErrorToString(import_result); |
- ONC_LOG_ERROR( |
- base::StringPrintf("Unable to import client certificate (error %s)", |
- error_string.c_str())); |
+ LOG(ERROR) << "Unable to import client certificate, error: " |
+ << error_string; |
return false; |
} |
if (imported_certs.size() == 0) { |
- ONC_LOG_WARNING("PKCS12 data contains no importable certificates."); |
+ LOG(WARNING) << "PKCS12 data contains no importable certificates."; |
return true; |
} |
if (imported_certs.size() != 1) { |
- ONC_LOG_WARNING("ONC File: PKCS12 data contains more than one certificate. " |
- "Only the first one will be imported."); |
+ LOG(WARNING) << "ONC File: PKCS12 data contains more than one certificate. " |
+ "Only the first one will be imported."; |
} |
scoped_refptr<net::X509Certificate> cert_result = imported_certs[0]; |
@@ -359,7 +386,7 @@ bool CertificateImporterImpl::ParseClientCertificate( |
PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); |
SECKEY_DestroyPrivateKey(private_key); |
} else { |
- ONC_LOG_WARNING("Unable to find private key for certificate."); |
+ LOG(WARNING) << "Unable to find private key for certificate."; |
} |
return true; |
} |