Chromium Code Reviews| 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; |
| } |