From e81cec40589aff1688917306ea0c57b3e85016d8 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 18 Apr 2016 10:41:31 +0530 Subject: [PATCH 1/7] app: api to import client certificate --- atom/browser/api/atom_api_app.cc | 69 ++++++- atom/browser/api/atom_api_app.h | 11 ++ atom/browser/atom_browser_client.cc | 30 --- .../browser/certificate_manager_model.cc | 177 ++++++++++++++++++ .../browser/certificate_manager_model.h | 116 ++++++++++++ filenames.gypi | 2 + 6 files changed, 374 insertions(+), 31 deletions(-) create mode 100644 chromium_src/chrome/browser/certificate_manager_model.cc create mode 100644 chromium_src/chrome/browser/certificate_manager_model.h diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 52d6ec3d338c..4cbae0885e9a 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -24,6 +24,7 @@ #include "base/command_line.h" #include "base/environment.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/path_service.h" #include "brightray/browser/brightray_paths.h" #include "chrome/common/chrome_paths.h" @@ -157,6 +158,43 @@ void PassLoginInformation(scoped_refptr login_handler, login_handler->CancelAuth(); } +net::CertificateList ImportCertsFromFile( + const base::FilePath& path) { + net::CertificateList certs; + if (path.empty()) + return certs; + + std::string cert_data; + if (!base::ReadFileToString(path, &cert_data)) + return certs; + + certs = net::X509Certificate::CreateCertificateListFromBytes( + cert_data.data(), cert_data.size(), + net::X509Certificate::FORMAT_AUTO); + + return certs; +} + +int ImportCertificateIntoCertStore( + CertificateManagerModel* model, + const base::FilePath& path, + const base::FilePath& ca_path, + const base::string16& password) { + LOG(WARNING) << "importing ...."; + + std::string file_data; + int result = -1; + net::CertificateList ca_certs; + net::NSSCertDatabase::ImportCertFailureList not_imported; + auto module = model->cert_db()->GetPublicModule(); + if (base::ReadFileToString(path, &file_data)) { + result &= model->ImportFromPKCS12(module, file_data, password, true); + ca_certs = ImportCertsFromFile(ca_path); + result &= model->ImportCACerts(ca_certs, net::NSSCertDatabase::TRUST_DEFAULT, ¬_imported); + } + return result; +} + } // namespace App::App() { @@ -369,6 +407,34 @@ bool App::MakeSingleInstance( } } +void App::ImportClientCertificate( + const base::FilePath& path, + const base::FilePath& ca_path, + + const base::string16& password, + const net::CompletionCallback& callback) { + auto browser_context = AtomBrowserMainParts::Get()->browser_context(); + if (!certificate_manager_model_) { + CertificateManagerModel::Create(browser_context, base::Bind(&App::OnCertificateManagerModelCreated, base::Unretained(this), path, ca_path, password, callback)); + return; + } + + int rv = ImportCertificateIntoCertStore(certificate_manager_model_.get(), path, ca_path, password); + callback.Run(rv); +} + +void App::OnCertificateManagerModelCreated( + const base::FilePath& path, + const base::FilePath& ca_path, + const base::string16& password, + const net::CompletionCallback& callback, + scoped_ptr model) { + certificate_manager_model_ = std::move(model); + + int rv = ImportCertificateIntoCertStore(certificate_manager_model_.get(), path, ca_path, password); + callback.Run(rv); +} + mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( v8::Isolate* isolate) { auto browser = base::Unretained(Browser::Get()); @@ -408,7 +474,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) - .SetMethod("makeSingleInstance", &App::MakeSingleInstance); + .SetMethod("makeSingleInstance", &App::MakeSingleInstance) + .SetMethod("importClientCertificate", &App::ImportClientCertificate); } // static diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 5025a3869dd4..b5c797df0030 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -11,9 +11,11 @@ #include "atom/browser/atom_browser_client.h" #include "atom/browser/browser_observer.h" #include "atom/common/native_mate_converters/callback.h" +#include "chrome/browser/certificate_manager_model.h" #include "chrome/browser/process_singleton.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" +#include "net/base/completion_callback.h" namespace base { class FilePath; @@ -41,6 +43,13 @@ class App : public AtomBrowserClient::Delegate, int render_process_id, int render_frame_id); + void OnCertificateManagerModelCreated( + const base::FilePath& path, + const base::FilePath& ca_path, + const base::string16& password, + const net::CompletionCallback& callback, + scoped_ptr model); + protected: App(); virtual ~App(); @@ -97,12 +106,14 @@ class App : public AtomBrowserClient::Delegate, bool MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback); std::string GetLocale(); + void ImportClientCertificate(const base::FilePath& path, const base::FilePath& ca_path, const base::string16& password, const net::CompletionCallback& callback); #if defined(OS_WIN) bool IsAeroGlassEnabled(); #endif scoped_ptr process_singleton_; + scoped_ptr certificate_manager_model_; DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 9a59c3f9d412..ddefd0688a2a 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -55,26 +55,6 @@ std::string g_custom_schemes = ""; // Custom schemes to be registered to handle service worker. std::string g_custom_service_worker_schemes = ""; -scoped_refptr ImportCertFromFile( - const base::FilePath& path) { - if (path.empty()) - return nullptr; - - std::string cert_data; - if (!base::ReadFileToString(path, &cert_data)) - return nullptr; - - net::CertificateList certs = - net::X509Certificate::CreateCertificateListFromBytes( - cert_data.data(), cert_data.size(), - net::X509Certificate::FORMAT_AUTO); - - if (certs.empty()) - return nullptr; - - return certs[0]; -} - } // namespace // static @@ -242,16 +222,6 @@ void AtomBrowserClient::SelectClientCertificate( content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate) { - // --client-certificate=`path` - auto cmd = base::CommandLine::ForCurrentProcess(); - if (cmd->HasSwitch(switches::kClientCertificate)) { - auto cert_path = cmd->GetSwitchValuePath(switches::kClientCertificate); - auto certificate = ImportCertFromFile(cert_path); - if (certificate.get()) - delegate->ContinueWithCertificate(certificate.get()); - return; - } - if (!cert_request_info->client_certs.empty() && delegate_) { delegate_->SelectClientCertificate( web_contents, cert_request_info, std::move(delegate)); diff --git a/chromium_src/chrome/browser/certificate_manager_model.cc b/chromium_src/chrome/browser/certificate_manager_model.cc new file mode 100644 index 000000000000..83ab12af7609 --- /dev/null +++ b/chromium_src/chrome/browser/certificate_manager_model.cc @@ -0,0 +1,177 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/certificate_manager_model.h" + +#include + +#include "base/bind.h" +#include "base/i18n/time_formatting.h" +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_context.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" +#include "net/base/crypto_module.h" +#include "net/base/net_errors.h" +#include "net/cert/nss_cert_database.h" +#include "net/cert/x509_certificate.h" +#include "ui/base/l10n/l10n_util.h" + +using content::BrowserThread; + +namespace { + +net::NSSCertDatabase* g_nss_cert_database = nullptr; + +net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext( + content::ResourceContext* context, + const base::Callback& callback) { + // This initialization is not thread safe. This CHECK ensures that this code + // is only run on a single thread. + CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + if (!g_nss_cert_database) { + // Linux has only a single persistent slot compared to ChromeOS's separate + // public and private slot. + // Redirect any slot usage to this persistent slot on Linux. + g_nss_cert_database = new net::NSSCertDatabase( + crypto::ScopedPK11Slot( + crypto::GetPersistentNSSKeySlot()) /* public slot */, + crypto::ScopedPK11Slot( + crypto::GetPersistentNSSKeySlot()) /* private slot */); + } + return g_nss_cert_database; +} + +} // namespace + +// CertificateManagerModel is created on the UI thread. It needs a +// NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which +// needs to be done on the IO thread. +// +// The initialization flow is roughly: +// +// UI thread IO Thread +// +// CertificateManagerModel::Create +// \--------------------------------------v +// CertificateManagerModel::GetCertDBOnIOThread +// | +// GetNSSCertDatabaseForResourceContext +// | +// CertificateManagerModel::DidGetCertDBOnIOThread +// | +// crypto::IsTPMTokenEnabledForNSS +// v--------------------------------------/ +// CertificateManagerModel::DidGetCertDBOnUIThread +// | +// new CertificateManagerModel +// | +// callback + +// static +void CertificateManagerModel::Create( + content::BrowserContext* browser_context, + const CreationCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&CertificateManagerModel::GetCertDBOnIOThread, + browser_context->GetResourceContext(), + callback)); +} + +CertificateManagerModel::CertificateManagerModel( + net::NSSCertDatabase* nss_cert_database, + bool is_user_db_available) + : cert_db_(nss_cert_database), + is_user_db_available_(is_user_db_available) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); +} + +CertificateManagerModel::~CertificateManagerModel() { +} + +int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module, + const std::string& data, + const base::string16& password, + bool is_extractable) { + return cert_db_->ImportFromPKCS12(module, data, password, + is_extractable, NULL); +} + +int CertificateManagerModel::ImportUserCert(const std::string& data) { + return cert_db_->ImportUserCert(data); +} + +bool CertificateManagerModel::ImportCACerts( + const net::CertificateList& certificates, + net::NSSCertDatabase::TrustBits trust_bits, + net::NSSCertDatabase::ImportCertFailureList* not_imported) { + return cert_db_->ImportCACerts(certificates, trust_bits, not_imported); +} + +bool CertificateManagerModel::ImportServerCert( + const net::CertificateList& certificates, + net::NSSCertDatabase::TrustBits trust_bits, + net::NSSCertDatabase::ImportCertFailureList* not_imported) { + return cert_db_->ImportServerCert(certificates, trust_bits, + not_imported); +} + +bool CertificateManagerModel::SetCertTrust( + const net::X509Certificate* cert, + net::CertType type, + net::NSSCertDatabase::TrustBits trust_bits) { + return cert_db_->SetCertTrust(cert, type, trust_bits); +} + +bool CertificateManagerModel::Delete(net::X509Certificate* cert) { + return cert_db_->DeleteCertAndKey(cert); +} + +// static +void CertificateManagerModel::DidGetCertDBOnUIThread( + net::NSSCertDatabase* cert_db, + bool is_user_db_available, + const CreationCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + scoped_ptr model(new CertificateManagerModel( + cert_db, is_user_db_available)); + callback.Run(std::move(model)); +} + +// static +void CertificateManagerModel::DidGetCertDBOnIOThread( + const CreationCallback& callback, + net::NSSCertDatabase* cert_db) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + bool is_user_db_available = !!cert_db->GetPublicSlot(); + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&CertificateManagerModel::DidGetCertDBOnUIThread, + cert_db, + is_user_db_available, + callback)); +} + +// static +void CertificateManagerModel::GetCertDBOnIOThread( + content::ResourceContext* context, + const CreationCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext( + context, + base::Bind(&CertificateManagerModel::DidGetCertDBOnIOThread, + callback)); + if (cert_db) + DidGetCertDBOnIOThread(callback, cert_db); +} diff --git a/chromium_src/chrome/browser/certificate_manager_model.h b/chromium_src/chrome/browser/certificate_manager_model.h new file mode 100644 index 000000000000..bd0d5ddfb291 --- /dev/null +++ b/chromium_src/chrome/browser/certificate_manager_model.h @@ -0,0 +1,116 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CERTIFICATE_MANAGER_MODEL_H_ +#define CHROME_BROWSER_CERTIFICATE_MANAGER_MODEL_H_ + +#include +#include + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string16.h" +#include "net/cert/nss_cert_database.h" + +namespace content { +class BrowserContext; +class ResourceContext; +} // namespace content + +// CertificateManagerModel provides the data to be displayed in the certificate +// manager dialog, and processes changes from the view. +class CertificateManagerModel { + public: + typedef base::Callback)> + CreationCallback; + + // Creates a CertificateManagerModel. The model will be passed to the callback + // when it is ready. The caller must ensure the model does not outlive the + // |browser_context|. + static void Create(content::BrowserContext* browser_context, + const CreationCallback& callback); + + ~CertificateManagerModel(); + + bool is_user_db_available() const { return is_user_db_available_; } + + // Accessor for read-only access to the underlying NSSCertDatabase. + const net::NSSCertDatabase* cert_db() const { return cert_db_; } + + // Import private keys and certificates from PKCS #12 encoded + // |data|, using the given |password|. If |is_extractable| is false, + // mark the private key as unextractable from the module. + // Returns a net error code on failure. + int ImportFromPKCS12(net::CryptoModule* module, const std::string& data, + const base::string16& password, bool is_extractable); + + // Import user certificate from DER encoded |data|. + // Returns a net error code on failure. + int ImportUserCert(const std::string& data); + + // Import CA certificates. + // Tries to import all the certificates given. The root will be trusted + // according to |trust_bits|. Any certificates that could not be imported + // will be listed in |not_imported|. + // |trust_bits| should be a bit field of TRUST* values from NSSCertDatabase. + // Returns false if there is an internal error, otherwise true is returned and + // |not_imported| should be checked for any certificates that were not + // imported. + bool ImportCACerts(const net::CertificateList& certificates, + net::NSSCertDatabase::TrustBits trust_bits, + net::NSSCertDatabase::ImportCertFailureList* not_imported); + + // Import server certificate. The first cert should be the server cert. Any + // additional certs should be intermediate/CA certs and will be imported but + // not given any trust. + // Any certificates that could not be imported will be listed in + // |not_imported|. + // |trust_bits| can be set to explicitly trust or distrust the certificate, or + // use TRUST_DEFAULT to inherit trust as normal. + // Returns false if there is an internal error, otherwise true is returned and + // |not_imported| should be checked for any certificates that were not + // imported. + bool ImportServerCert( + const net::CertificateList& certificates, + net::NSSCertDatabase::TrustBits trust_bits, + net::NSSCertDatabase::ImportCertFailureList* not_imported); + + // Set trust values for certificate. + // |trust_bits| should be a bit field of TRUST* values from NSSCertDatabase. + // Returns true on success or false on failure. + bool SetCertTrust(const net::X509Certificate* cert, + net::CertType type, + net::NSSCertDatabase::TrustBits trust_bits); + + // Delete the cert. Returns true on success. |cert| is still valid when this + // function returns. + bool Delete(net::X509Certificate* cert); + + private: + CertificateManagerModel(net::NSSCertDatabase* nss_cert_database, + bool is_user_db_available); + + // Methods used during initialization, see the comment at the top of the .cc + // file for details. + static void DidGetCertDBOnUIThread( + net::NSSCertDatabase* cert_db, + bool is_user_db_available, + const CreationCallback& callback); + static void DidGetCertDBOnIOThread( + const CreationCallback& callback, + net::NSSCertDatabase* cert_db); + static void GetCertDBOnIOThread(content::ResourceContext* context, + const CreationCallback& callback); + + net::NSSCertDatabase* cert_db_; + // Whether the certificate database has a public slot associated with the + // profile. If not set, importing certificates is not allowed with this model. + bool is_user_db_available_; + + DISALLOW_COPY_AND_ASSIGN(CertificateManagerModel); +}; + +#endif // CHROME_BROWSER_CERTIFICATE_MANAGER_MODEL_H_ diff --git a/filenames.gypi b/filenames.gypi index dd9edb409f59..4de1b366b4fc 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -390,6 +390,8 @@ 'atom/utility/atom_content_utility_client.h', 'chromium_src/chrome/browser/browser_process.cc', 'chromium_src/chrome/browser/browser_process.h', + 'chromium_src/chrome/browser/certificate_manager_model.cc', + 'chromium_src/chrome/browser/certificate_manager_model.h', 'chromium_src/chrome/browser/chrome_process_finder_win.cc', 'chromium_src/chrome/browser/chrome_process_finder_win.h', 'chromium_src/chrome/browser/chrome_notification_types.h', From 1240c83e40c925d643af7f20f6cc137a092f7ddb Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 18 Apr 2016 21:05:33 +0530 Subject: [PATCH 2/7] set trust bits for CA certs --- atom/browser/api/atom_api_app.cc | 89 +++++++++---------- atom/browser/api/atom_api_app.h | 7 +- atom/browser/atom_browser_client.cc | 1 - .../browser/certificate_manager_model.cc | 12 +-- .../browser/certificate_manager_model.h | 7 +- 5 files changed, 55 insertions(+), 61 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 4cbae0885e9a..1446d44ad006 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -15,10 +15,11 @@ #include "atom/browser/browser.h" #include "atom/browser/login_handler.h" #include "atom/common/native_mate_converters/callback.h" -#include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" +#include "atom/common/native_mate_converters/net_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" #include "base/command_line.h" @@ -158,41 +159,35 @@ void PassLoginInformation(scoped_refptr login_handler, login_handler->CancelAuth(); } -net::CertificateList ImportCertsFromFile( - const base::FilePath& path) { - net::CertificateList certs; - if (path.empty()) - return certs; - - std::string cert_data; - if (!base::ReadFileToString(path, &cert_data)) - return certs; - - certs = net::X509Certificate::CreateCertificateListFromBytes( - cert_data.data(), cert_data.size(), - net::X509Certificate::FORMAT_AUTO); - - return certs; -} - -int ImportCertificateIntoCertStore( +int ImportIntoCertStore( CertificateManagerModel* model, - const base::FilePath& path, - const base::FilePath& ca_path, - const base::string16& password) { - LOG(WARNING) << "importing ...."; + const base::DictionaryValue& options) { + std::string file_data, cert_path; + base::string16 password; + net::CertificateList imported_certs; + int rv; + options.GetString("clientCertificate", &cert_path); + options.GetString("password", &password); - std::string file_data; - int result = -1; - net::CertificateList ca_certs; - net::NSSCertDatabase::ImportCertFailureList not_imported; - auto module = model->cert_db()->GetPublicModule(); - if (base::ReadFileToString(path, &file_data)) { - result &= model->ImportFromPKCS12(module, file_data, password, true); - ca_certs = ImportCertsFromFile(ca_path); - result &= model->ImportCACerts(ca_certs, net::NSSCertDatabase::TRUST_DEFAULT, ¬_imported); + if (!cert_path.empty()) { + if (base::ReadFileToString(base::FilePath(cert_path), &file_data)) { + auto module = model->cert_db()->GetPublicModule(); + rv = model->ImportFromPKCS12(module, + file_data, + password, + true, + &imported_certs); + if (imported_certs.size() > 1) { + auto it = imported_certs.begin(); + ++it; // skip first which would be the client certificate. + for (; it != imported_certs.end(); ++it) + rv &= model->SetCertTrust(it->get(), + net::CA_CERT, + net::NSSCertDatabase::TRUSTED_SSL); + } + } } - return result; + return rv; } } // namespace @@ -408,30 +403,30 @@ bool App::MakeSingleInstance( } void App::ImportClientCertificate( - const base::FilePath& path, - const base::FilePath& ca_path, - - const base::string16& password, + const base::DictionaryValue& options, const net::CompletionCallback& callback) { auto browser_context = AtomBrowserMainParts::Get()->browser_context(); if (!certificate_manager_model_) { - CertificateManagerModel::Create(browser_context, base::Bind(&App::OnCertificateManagerModelCreated, base::Unretained(this), path, ca_path, password, callback)); + scoped_ptr copy = options.CreateDeepCopy(); + CertificateManagerModel::Create(browser_context, + base::Bind(&App::OnCertificateManagerModelCreated, + base::Unretained(this), + base::Passed(©), + callback)); return; } - int rv = ImportCertificateIntoCertStore(certificate_manager_model_.get(), path, ca_path, password); + int rv = ImportIntoCertStore(certificate_manager_model_.get(), options); callback.Run(rv); } void App::OnCertificateManagerModelCreated( - const base::FilePath& path, - const base::FilePath& ca_path, - const base::string16& password, + scoped_ptr options, const net::CompletionCallback& callback, scoped_ptr model) { certificate_manager_model_ = std::move(model); - - int rv = ImportCertificateIntoCertStore(certificate_manager_model_.get(), path, ca_path, password); + int rv = ImportIntoCertStore(certificate_manager_model_.get(), + *(options.get())); callback.Run(rv); } @@ -474,8 +469,10 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) - .SetMethod("makeSingleInstance", &App::MakeSingleInstance) - .SetMethod("importClientCertificate", &App::ImportClientCertificate); +#if defined(OS_LINUX) + .SetMethod("importClientCertificate", &App::ImportClientCertificate) +#endif + .SetMethod("makeSingleInstance", &App::MakeSingleInstance); } // static diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index b5c797df0030..ce66daedf100 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -44,9 +44,7 @@ class App : public AtomBrowserClient::Delegate, int render_frame_id); void OnCertificateManagerModelCreated( - const base::FilePath& path, - const base::FilePath& ca_path, - const base::string16& password, + scoped_ptr options, const net::CompletionCallback& callback, scoped_ptr model); @@ -106,7 +104,8 @@ class App : public AtomBrowserClient::Delegate, bool MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback); std::string GetLocale(); - void ImportClientCertificate(const base::FilePath& path, const base::FilePath& ca_path, const base::string16& password, const net::CompletionCallback& callback); + void ImportClientCertificate(const base::DictionaryValue& options, + const net::CompletionCallback& callback); #if defined(OS_WIN) bool IsAeroGlassEnabled(); diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index ddefd0688a2a..f4add58e3a89 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -37,7 +37,6 @@ #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" #include "content/public/common/web_preferences.h" -#include "net/cert/x509_certificate.h" #include "net/ssl/ssl_cert_request_info.h" #include "ppapi/host/ppapi_host.h" #include "ui/base/l10n/l10n_util.h" diff --git a/chromium_src/chrome/browser/certificate_manager_model.cc b/chromium_src/chrome/browser/certificate_manager_model.cc index 83ab12af7609..b0db6edc357c 100644 --- a/chromium_src/chrome/browser/certificate_manager_model.cc +++ b/chromium_src/chrome/browser/certificate_manager_model.cc @@ -7,10 +7,8 @@ #include #include "base/bind.h" -#include "base/i18n/time_formatting.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/resource_context.h" @@ -20,7 +18,6 @@ #include "net/base/net_errors.h" #include "net/cert/nss_cert_database.h" #include "net/cert/x509_certificate.h" -#include "ui/base/l10n/l10n_util.h" using content::BrowserThread; @@ -64,8 +61,6 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext( // GetNSSCertDatabaseForResourceContext // | // CertificateManagerModel::DidGetCertDBOnIOThread -// | -// crypto::IsTPMTokenEnabledForNSS // v--------------------------------------/ // CertificateManagerModel::DidGetCertDBOnUIThread // | @@ -100,9 +95,10 @@ CertificateManagerModel::~CertificateManagerModel() { int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module, const std::string& data, const base::string16& password, - bool is_extractable) { + bool is_extractable, + net::CertificateList* imported_certs) { return cert_db_->ImportFromPKCS12(module, data, password, - is_extractable, NULL); + is_extractable, imported_certs); } int CertificateManagerModel::ImportUserCert(const std::string& data) { @@ -121,7 +117,7 @@ bool CertificateManagerModel::ImportServerCert( net::NSSCertDatabase::TrustBits trust_bits, net::NSSCertDatabase::ImportCertFailureList* not_imported) { return cert_db_->ImportServerCert(certificates, trust_bits, - not_imported); + not_imported); } bool CertificateManagerModel::SetCertTrust( diff --git a/chromium_src/chrome/browser/certificate_manager_model.h b/chromium_src/chrome/browser/certificate_manager_model.h index bd0d5ddfb291..1eb350876803 100644 --- a/chromium_src/chrome/browser/certificate_manager_model.h +++ b/chromium_src/chrome/browser/certificate_manager_model.h @@ -44,8 +44,11 @@ class CertificateManagerModel { // |data|, using the given |password|. If |is_extractable| is false, // mark the private key as unextractable from the module. // Returns a net error code on failure. - int ImportFromPKCS12(net::CryptoModule* module, const std::string& data, - const base::string16& password, bool is_extractable); + int ImportFromPKCS12(net::CryptoModule* module, + const std::string& data, + const base::string16& password, + bool is_extractable, + net::CertificateList* imported_certs); // Import user certificate from DER encoded |data|. // Returns a net error code on failure. From 2ddac9352f48aa6ae386f8b1d001fe4b6c2ff2fd Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 18 Apr 2016 21:53:44 +0530 Subject: [PATCH 3/7] add spec --- spec/api-app-spec.js | 61 +++++++++ spec/fixtures/certificates/certs.cnf | 68 ++++++++++ spec/fixtures/certificates/client.p12 | Bin 0 -> 4149 bytes spec/fixtures/certificates/generate_certs.sh | 127 ++++++++++++++++++ spec/fixtures/certificates/intermediateCA.pem | 78 +++++++++++ spec/fixtures/certificates/rootCA.pem | 19 +++ spec/fixtures/certificates/server.key | 27 ++++ spec/fixtures/certificates/server.pem | 88 ++++++++++++ 8 files changed, 468 insertions(+) create mode 100644 spec/fixtures/certificates/certs.cnf create mode 100644 spec/fixtures/certificates/client.p12 create mode 100755 spec/fixtures/certificates/generate_certs.sh create mode 100644 spec/fixtures/certificates/intermediateCA.pem create mode 100644 spec/fixtures/certificates/rootCA.pem create mode 100644 spec/fixtures/certificates/server.key create mode 100644 spec/fixtures/certificates/server.pem diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index c237ef17238e..1f5452713bce 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -1,5 +1,7 @@ const assert = require('assert') const ChildProcess = require('child_process') +const https = require('https') +const fs = require('fs') const path = require('path') const remote = require('electron').remote @@ -87,6 +89,65 @@ describe('app module', function () { }) }) + describe('app.importClientCertificate', function () { + if (process.platform !== 'linux') + return + + this.timeout(5000) + + var port + var w = null + var certPath = path.join(__dirname, 'fixtures', 'certificates') + var options = { + key: fs.readFileSync(path.join(certPath, 'server.key')), + cert: fs.readFileSync(path.join(certPath, 'server.pem')), + ca: [ + fs.readFileSync(path.join(certPath, 'rootCA.pem')), + fs.readFileSync(path.join(certPath, 'intermediateCA.pem')) + ], + requestCert: true, + rejectUnauthorized: false + } + + var server = https.createServer(options, function (req, res) { + if (req.client.authorized) { + res.writeHead(200); + res.end('authorized'); + } + }) + server.listen(0, '127.0.0.1', function () { + port = server.address().port + }) + + afterEach(function () { + if (w != null) { + w.destroy() + } + w = null + }) + + it('can import certificate into platform cert store', function (done) { + let options = { + clientCertificate: path.join(certPath, 'client.p12'), + password: 'electron' + } + + w = new BrowserWindow({ + show: false + }) + + w.webContents.on('did-finish-load', function () { + server.close() + done() + }) + + app.importClientCertificate(options, function (result) { + assert(!result) + w.loadURL(`https://127.0.0.1:${port}`) + }) + }) + }) + describe('BrowserWindow events', function () { var w = null diff --git a/spec/fixtures/certificates/certs.cnf b/spec/fixtures/certificates/certs.cnf new file mode 100644 index 000000000000..d8b5c66e13a1 --- /dev/null +++ b/spec/fixtures/certificates/certs.cnf @@ -0,0 +1,68 @@ +ID=1 +CA_DIR=out + +[ca] +default_ca = ca_settings + +[ca_settings] +dir = ${ENV::CA_DIR} +database = $dir/${ENV::ID}-index.txt +new_certs_dir = $dir +serial = $dir/${ENV::ID}-serial +certificate = $dir/${ENV::ID}.pem +private_key = $dir/${ENV::ID}.key +RANDFILE = $dir/rand +default_md = sha256 +default_days = 3650 +policy = policy_anything +preserve = no + +[policy_anything] +# Default signing policy +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[req] +default_bits = 2048 +default_md = sha256 +string_mask = utf8only +distinguished_name = req_env_dn +prompt = no + +[user_cert] +basicConstraints = CA:FALSE +nsCertType = client +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[server_cert] +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ca_cert] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ca_intermediate_cert] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[req_env_dn] +commonName = ${ENV::COMMON_NAME} diff --git a/spec/fixtures/certificates/client.p12 b/spec/fixtures/certificates/client.p12 new file mode 100644 index 0000000000000000000000000000000000000000..7543c7d38904f15708eae001c285f1ab6be1e6e1 GIT binary patch literal 4149 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 B -> C (self-signed root) +# 2. D (end-entity) -> B -> C (self-signed root) + +try () { + echo "$@" + "$@" || exit 1 +} + +try mkdir out + +echo Create the serial number files and indices. +serial=1000 +for i in B C +do + try /bin/sh -c "echo $serial > out/$i-serial" + serial=$(expr $serial + 1) + touch out/$i-index.txt + touch out/$i-index.txt.attr +done + +echo Generate the keys. +for i in A B C D +do + try openssl genrsa -out out/$i.key 2048 +done + +echo Generate the C CSR +COMMON_NAME="Root CA" \ + CA_DIR=out \ + ID=C \ + try openssl req \ + -new \ + -key out/C.key \ + -out out/C.csr \ + -config certs.cnf + +echo C signs itself. +COMMON_NAME="Root CA" \ + CA_DIR=out \ + ID=C \ + try openssl x509 \ + -req -days 3650 \ + -in out/C.csr \ + -extensions ca_cert \ + -extfile certs.cnf \ + -signkey out/C.key \ + -out out/C.pem + +echo Generate the intermediates +COMMON_NAME="Intermediate CA" \ + CA_DIR=out \ + ID=B \ + try openssl req \ + -new \ + -key out/B.key \ + -out out/B.csr \ + -config certs.cnf + +COMMON_NAME="Root CA" \ + CA_DIR=out \ + ID=C \ + try openssl ca \ + -batch \ + -extensions ca_intermediate_cert \ + -in out/B.csr \ + -out out/B.pem \ + -config certs.cnf + +echo Generate the leaf certs +COMMON_NAME="Client Cert" \ + ID=A \ + try openssl req \ + -new \ + -key out/A.key \ + -out out/A.csr \ + -config certs.cnf + +echo B signs A +COMMON_NAME="Intermediate CA" \ + CA_DIR=out \ + ID=B \ + try openssl ca \ + -batch \ + -extensions user_cert \ + -in out/A.csr \ + -out out/A.pem \ + -config certs.cnf + +COMMON_NAME="localhost" \ + ID=D \ + try openssl req \ + -new \ + -key out/D.key \ + -out out/D.csr \ + -config certs.cnf + +echo B signs D +COMMON_NAME="Intermediate CA" \ + CA_DIR=out \ + ID=B \ + try openssl ca \ + -batch \ + -extensions server_cert \ + -in out/D.csr \ + -out out/D.pem \ + -config certs.cnf + +echo Package the client cert and private key into PKCS12 file +try /bin/sh -c "cat out/A.pem out/A.key out/B.pem out/C.pem > out/A-chain.pem" + +try openssl pkcs12 \ + -in out/A-chain.pem \ + -out client.p12 \ + -export \ + -passout pass:electron + +echo Package the certs +try cp out/C.pem rootCA.pem +try cp out/B.pem intermediateCA.pem +try cp out/D.key server.key +try cp out/D.pem server.pem + +try rm -rf out diff --git a/spec/fixtures/certificates/intermediateCA.pem b/spec/fixtures/certificates/intermediateCA.pem new file mode 100644 index 000000000000..58293f76da0b --- /dev/null +++ b/spec/fixtures/certificates/intermediateCA.pem @@ -0,0 +1,78 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root CA + Validity + Not Before: Apr 18 16:14:29 2016 GMT + Not After : Apr 16 16:14:29 2026 GMT + Subject: CN=Intermediate CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b6:42:02:13:25:40:13:a6:05:99:69:da:0c:c9: + a8:bf:86:3b:fc:c6:51:ba:64:65:7e:33:11:31:d5: + 03:45:30:4c:ca:49:d2:96:42:52:2f:f9:e6:6c:9a: + 50:1c:fe:fa:e2:e8:63:36:14:47:f7:49:9f:78:28: + 5e:1f:0b:9d:9e:f8:d3:33:77:06:4d:6d:14:c0:57: + 01:83:2b:ef:99:06:48:21:ec:c1:d7:05:48:2c:ea: + 83:06:6a:20:df:73:ce:8a:a5:e4:81:00:41:84:cf: + 89:81:78:2e:3a:bd:1b:fd:3e:96:08:8d:44:1b:00: + c8:d6:4e:7a:6a:75:c0:9b:3c:e0:fa:aa:3a:82:5b: + 3c:39:32:ca:4a:ba:82:bc:60:47:6f:e4:4a:fd:dc: + a0:72:8a:1b:fe:cd:2e:10:f4:27:4c:08:4e:d1:ed: + dc:08:b0:f8:1f:e4:fc:45:72:43:58:6e:dd:05:37: + 8c:04:a1:fb:64:f4:3f:90:bb:85:f2:4c:97:46:fd: + 1f:29:e5:19:d0:0f:24:fd:d1:00:c5:b6:be:da:84: + 62:77:be:db:67:f6:ec:98:5d:97:f5:df:0a:bd:b8: + 07:7f:0a:d5:92:29:1f:c4:b0:97:4f:e4:87:d7:a9: + 00:c9:61:d5:6c:cd:6a:fc:56:c3:f3:b7:ca:53:70: + 02:3f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A9:75:99:CF:9C:92:54:A4:4B:65:CD:3D:FC:93:98:8D:9E:09:1F:47 + X509v3 Authority Key Identifier: + keyid:E3:51:87:E3:CD:7A:B3:26:9F:8F:EC:62:D1:0E:15:0C:39:36:47:4F + + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 55:69:d6:1d:33:ad:ab:40:46:fd:34:02:c1:43:50:7b:90:ea: + f3:5f:4f:b6:2c:28:aa:72:e0:4b:36:2e:8f:44:93:15:52:14: + f6:61:b3:50:e0:ba:43:91:ba:a9:5d:ac:43:b7:52:ca:91:a3: + d7:0e:ac:a7:9e:ee:28:7f:2d:0f:93:b5:d9:23:35:68:54:29: + 2a:e7:3a:4c:41:24:d0:5e:2d:f3:1e:b9:52:f1:3e:16:76:93: + 89:6d:a1:4c:63:f5:4a:cc:08:36:61:29:0a:29:5f:f4:5a:55: + 98:10:b3:de:b3:90:f9:03:e5:bd:1b:61:01:a7:22:03:ae:0f: + 77:c4:a8:bf:31:b4:af:c8:c7:e3:25:a1:2b:b9:43:37:3b:08: + ea:c4:46:60:b8:5f:ee:2a:0d:ce:18:75:63:ba:32:28:84:f4: + 56:95:1b:c5:f9:46:7e:14:2e:83:5e:a9:ff:b2:80:ca:25:fd: + 22:90:b5:de:bd:e6:f1:0c:ee:7e:09:71:0d:82:6a:ca:2f:9c: + 96:45:73:3a:65:bc:d8:9d:e0:61:01:5d:a8:de:de:61:8c:82: + 52:0c:ef:97:39:b3:13:c6:7d:d0:c0:f5:6d:c8:70:5b:96:e8: + 99:31:d8:75:3a:21:58:ab:01:21:9e:38:8e:53:ff:f8:48:a7: + af:01:9a:93 +-----BEGIN CERTIFICATE----- +MIIDDjCCAfagAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v +dCBDQTAeFw0xNjA0MTgxNjE0MjlaFw0yNjA0MTYxNjE0MjlaMBoxGDAWBgNVBAMM +D0ludGVybWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALZCAhMlQBOmBZlp2gzJqL+GO/zGUbpkZX4zETHVA0UwTMpJ0pZCUi/55myaUBz+ ++uLoYzYUR/dJn3goXh8LnZ740zN3Bk1tFMBXAYMr75kGSCHswdcFSCzqgwZqIN9z +zoql5IEAQYTPiYF4Ljq9G/0+lgiNRBsAyNZOemp1wJs84PqqOoJbPDkyykq6grxg +R2/kSv3coHKKG/7NLhD0J0wITtHt3Aiw+B/k/EVyQ1hu3QU3jASh+2T0P5C7hfJM +l0b9HynlGdAPJP3RAMW2vtqEYne+22f27Jhdl/XfCr24B38K1ZIpH8Swl0/kh9ep +AMlh1WzNavxWw/O3ylNwAj8CAwEAAaNmMGQwHQYDVR0OBBYEFKl1mc+cklSkS2XN +PfyTmI2eCR9HMB8GA1UdIwQYMBaAFONRh+PNerMmn4/sYtEOFQw5NkdPMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IB +AQBVadYdM62rQEb9NALBQ1B7kOrzX0+2LCiqcuBLNi6PRJMVUhT2YbNQ4LpDkbqp +XaxDt1LKkaPXDqynnu4ofy0Pk7XZIzVoVCkq5zpMQSTQXi3zHrlS8T4WdpOJbaFM +Y/VKzAg2YSkKKV/0WlWYELPes5D5A+W9G2EBpyIDrg93xKi/MbSvyMfjJaEruUM3 +OwjqxEZguF/uKg3OGHVjujIohPRWlRvF+UZ+FC6DXqn/soDKJf0ikLXevebxDO5+ +CXENgmrKL5yWRXM6ZbzYneBhAV2o3t5hjIJSDO+XObMTxn3QwPVtyHBbluiZMdh1 +OiFYqwEhnjiOU//4SKevAZqT +-----END CERTIFICATE----- diff --git a/spec/fixtures/certificates/rootCA.pem b/spec/fixtures/certificates/rootCA.pem new file mode 100644 index 000000000000..5c77fe61cd0f --- /dev/null +++ b/spec/fixtures/certificates/rootCA.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCjCCAfKgAwIBAgIJAOcWbv0WHll0MA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV +BAMMB1Jvb3QgQ0EwHhcNMTYwNDE4MTYxNDI5WhcNMjYwNDE2MTYxNDI5WjASMRAw +DgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +0iZvelv6MjxqdmQsAmKqIfc5gvQjYB3CqWlEH3g5czPFBMMtmOI9czlk+0jc1VEf +t1SKst7zwe1rpxFArgudV45NBHQH3ZlzkLeO7Ol2kPzlyMHNJ70vT3CBitKnLl4B +bg7xf6kDQQlC3/QeWxvbR5cvp131uwcpXKdJ9k4dwpfS2BKiRb5Uk46DgX5kGaka +q/tQ2F7b6AlAoTq608tZBuOInkg2tTbGe9PDWSL8oMZRwCSbF543SAR45zjWBa0k +ymY31VvlYbEd/3lfE5Mrn/JwZQpTKOfcOI//kUkcClJVpSMObh4eiy1oNjqcJ4KR +/4hkY7oTQCA7zWD34jQpkQIDAQABo2MwYTAdBgNVHQ4EFgQU41GH4816syafj+xi +0Q4VDDk2R08wHwYDVR0jBBgwFoAU41GH4816syafj+xi0Q4VDDk2R08wDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEBADrt +1bSbOYxDmB1x9KaHNFVSzs0XsipsbZW/XTqtNMPMFXh+I57NVptVanCwcfU5zmOF +AjL+R8v0NkPU9+6nSM2PYqWxEavf0f6pkxIj+ThFwtVwXEKocPG9RFUvZNZv+rSH +yAnzuAzFI71EsT9VgJGHI0pgPjrGbSlNfb0OJFOlwtbGWGofmg+N6hHcx5nVKlgL +ZWLtYT+/mT2pSGuIpJtdnuUv0vcrRa4mxAa8NPF4+Qpi6yErkfogE+T4RYf2L4rp +CaRIFicLoNUmwK0nCerJaPFLwGkiNGNX81CHnw3+xLisSPvxze2ZRA0DhUWUGInq +grjWDMO9P1hPWu5jmbo= +-----END CERTIFICATE----- diff --git a/spec/fixtures/certificates/server.key b/spec/fixtures/certificates/server.key new file mode 100644 index 000000000000..719bfc8797df --- /dev/null +++ b/spec/fixtures/certificates/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuByk7Ib6anz0xOFRqyogGsTTEAAGduquIckVFajDHrk7vdq+ +TflkDp+UhbISqu1rj0OuaqODxiPSSw5fHClqNKpjhHS1ry86knS847BGwrByY0oa +zBdN0UgtWiXOK+iCuSI9p0KSIORJ3Y70pUZmm12EHRwb0tANv4ogYxjAxwnyqYgn +PnrDsoyCh/Cb4Fu8XucrnepYbInXi6yOdwTuivTx9qy7tlQzvYJ2LLEUIJdBtCUZ +dZkxky9CJUbfu5rm6PFvbLII5YCSlpXLxg9bumZCR1z9IXE6rLYcJIp3HIquR2cN +tAs9M8OHuR5V6vhUG51bP3aTkg3asJVdUe10dwIDAQABAoIBAQCJGINSwZv86blW +VbX7r+2iIUhNVMd7i3tJGzQBId7RpPswf49P/tIb9YaiG5y8/PgoAS0CqWn5hDkW +vMfj747vUqWyPzn/DjseTaFOJrg6RyuWddsIeJ3wpj9nLlmc5pFZDH8+alrn9TZv +rgDMhWTocjVre7/YNibWpyNAx3DdhG5DzNVLnu1R68d5k3JutQVqm01xCAV9ne9n +xE1RB5Z1xLvpQfW2qLYT0yFB7Xxw8awGyzVesPhGW1aa5F4urQjdCt2baa06Xolu +T3wXJ6wA9BuF2KOCi8DxELDaXoB//+82HafgWbOWIhJFOzEZaMNqZkfS/GbCgpEr +mE2r8zGBAoGBAOHNcUPgnIIeGdgFZZvL3Ge3Hp5mi2Vd2KBkAPNCjVSXeCu57yRC +SetlYuZlIhd7o+wdxUmWtg73DU19eDXJsOjXgNAoJfT9Zsyi4RClmJ0FRcSzvFU/ +m/TKrBbnFFAI+1pKwDnQ7envuRiTECFSsvKqdr8hddx0cPCgDtbe+75BAoGBANC7 +4ozkgsUTtdojz0DYBYBwUjN1gUETIhl91tt+48hmmEedROWDQDCT9gJfpAVFe1I6 +RyKKJnBcgNDJ7mqPUB1f5xb5rtaZS1owPNYTi3GrdVVg3lAf0j5ch8XoRJn/plnL +M0Sj5lLMviHJjyk8CPHbnE2k2vERAW4/SgzfA3S3AoGAHx55Jamm6CfN1/+maTpH +PeP2zE3FmEq+uBwQJXZek/HsFdqiIpUgKtjmMGpvsFzR0pCnx+SFYrqZkrxf/Mm3 +H9/TWNyvnnvt1vX7npez2LAJVXqP0g/aJnpoDR/7pKwYN/FlXJJ2t27aS5C5AF6t +WtQzWVP7Mk654e+tG9/PQgECgYEAiTCT7EpccK9NvLwAgfv5UbuBK3U1qNGsfdip +mMZDa/mSaK9DEx462DLHZDP8F8LdFORc0KTAMuV5fMDbxInA/C2GMyGT+lPypKpD +sehSpDku+xiZxUvE4VvrmPXZ8OWILkhRv/GBdjY/WPGi+FUPA/d1Ocr6Y6rrp8xN +HTyOhu0CgYBKxTSH6RCQsm8Q8uqmcP7cwe6fciTC0c2CRRqlzuXeseG72MBRDk/8 +P1jtOIlIsax/8NwNm5ReAiLgVn/h6/YgN4fpMkV1XIaH4j7HiGf5CWgOTWxS9jWA +cV09H22BaNkT0fZ71IlXQI11cVRodX0g4cJXeuyTxY9OkMd6cGs8+A== +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certificates/server.pem b/spec/fixtures/certificates/server.pem new file mode 100644 index 000000000000..117be807e528 --- /dev/null +++ b/spec/fixtures/certificates/server.pem @@ -0,0 +1,88 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Intermediate CA + Validity + Not Before: Apr 18 16:14:29 2016 GMT + Not After : Apr 16 16:14:29 2026 GMT + Subject: CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b8:1c:a4:ec:86:fa:6a:7c:f4:c4:e1:51:ab:2a: + 20:1a:c4:d3:10:00:06:76:ea:ae:21:c9:15:15:a8: + c3:1e:b9:3b:bd:da:be:4d:f9:64:0e:9f:94:85:b2: + 12:aa:ed:6b:8f:43:ae:6a:a3:83:c6:23:d2:4b:0e: + 5f:1c:29:6a:34:aa:63:84:74:b5:af:2f:3a:92:74: + bc:e3:b0:46:c2:b0:72:63:4a:1a:cc:17:4d:d1:48: + 2d:5a:25:ce:2b:e8:82:b9:22:3d:a7:42:92:20:e4: + 49:dd:8e:f4:a5:46:66:9b:5d:84:1d:1c:1b:d2:d0: + 0d:bf:8a:20:63:18:c0:c7:09:f2:a9:88:27:3e:7a: + c3:b2:8c:82:87:f0:9b:e0:5b:bc:5e:e7:2b:9d:ea: + 58:6c:89:d7:8b:ac:8e:77:04:ee:8a:f4:f1:f6:ac: + bb:b6:54:33:bd:82:76:2c:b1:14:20:97:41:b4:25: + 19:75:99:31:93:2f:42:25:46:df:bb:9a:e6:e8:f1: + 6f:6c:b2:08:e5:80:92:96:95:cb:c6:0f:5b:ba:66: + 42:47:5c:fd:21:71:3a:ac:b6:1c:24:8a:77:1c:8a: + ae:47:67:0d:b4:0b:3d:33:c3:87:b9:1e:55:ea:f8: + 54:1b:9d:5b:3f:76:93:92:0d:da:b0:95:5d:51:ed: + 74:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Cert Type: + SSL Server + Netscape Comment: + OpenSSL Generated Server Certificate + X509v3 Subject Key Identifier: + 1D:60:82:FA:3A:EC:27:91:BA:8D:F5:ED:B2:E3:85:0B:22:5A:8E:38 + X509v3 Authority Key Identifier: + keyid:A9:75:99:CF:9C:92:54:A4:4B:65:CD:3D:FC:93:98:8D:9E:09:1F:47 + DirName:/CN=Root CA + serial:10:01 + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: sha256WithRSAEncryption + 89:90:3d:2c:b8:0d:36:63:68:9a:cd:f9:14:56:94:d9:18:11: + b5:08:35:af:f9:34:cd:70:db:7d:66:06:e3:57:9b:06:8f:11: + d6:ea:ac:a6:07:db:ae:a2:c0:66:69:84:d8:2d:3c:cc:d7:4d: + 3c:75:60:4f:98:fc:56:df:30:39:c6:55:2c:73:92:9e:0c:b5: + 7c:75:40:5d:21:aa:01:c1:8a:03:86:eb:d7:02:7d:f5:7b:12: + cc:18:90:23:ad:8f:d7:05:18:6d:f0:11:a8:6b:27:fd:4c:07: + 07:53:f5:7f:f7:a2:e5:18:1e:4e:90:1b:10:5f:f3:5c:cb:c7: + 37:63:d0:d5:1d:3a:65:66:24:ee:0e:ce:7f:b1:fb:ee:17:d0: + b5:4d:64:2f:5a:9c:bc:7a:1c:c0:b4:0f:32:c9:a9:5c:cb:57: + 26:fd:49:39:8d:f2:89:54:c4:92:b5:35:ec:fe:cf:87:07:a6: + 84:01:98:00:e4:2a:44:26:b7:48:00:11:d3:e4:5a:c1:ad:46: + 36:53:f9:28:b7:e4:c5:bb:66:88:ab:8e:cc:30:d0:96:aa:3e: + c1:12:6a:8f:fa:6d:19:15:f4:90:66:54:62:84:97:06:2d:5c: + b9:18:71:90:f4:ca:4c:8c:a5:8b:32:14:93:89:f1:93:f4:00: + bd:1d:42:4f +-----BEGIN CERTIFICATE----- +MIIDgjCCAmqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UEAwwPSW50 +ZXJtZWRpYXRlIENBMB4XDTE2MDQxODE2MTQyOVoXDTI2MDQxNjE2MTQyOVowFDES +MBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAuByk7Ib6anz0xOFRqyogGsTTEAAGduquIckVFajDHrk7vdq+TflkDp+UhbIS +qu1rj0OuaqODxiPSSw5fHClqNKpjhHS1ry86knS847BGwrByY0oazBdN0UgtWiXO +K+iCuSI9p0KSIORJ3Y70pUZmm12EHRwb0tANv4ogYxjAxwnyqYgnPnrDsoyCh/Cb +4Fu8XucrnepYbInXi6yOdwTuivTx9qy7tlQzvYJ2LLEUIJdBtCUZdZkxky9CJUbf +u5rm6PFvbLII5YCSlpXLxg9bumZCR1z9IXE6rLYcJIp3HIquR2cNtAs9M8OHuR5V +6vhUG51bP3aTkg3asJVdUe10dwIDAQABo4HXMIHUMAkGA1UdEwQCMAAwEQYJYIZI +AYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBT +ZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFB1ggvo67CeRuo317bLjhQsiWo44 +MDsGA1UdIwQ0MDKAFKl1mc+cklSkS2XNPfyTmI2eCR9HoRakFDASMRAwDgYDVQQD +DAdSb290IENBggIQATAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH +AwEwDQYJKoZIhvcNAQELBQADggEBAImQPSy4DTZjaJrN+RRWlNkYEbUINa/5NM1w +231mBuNXmwaPEdbqrKYH266iwGZphNgtPMzXTTx1YE+Y/FbfMDnGVSxzkp4MtXx1 +QF0hqgHBigOG69cCffV7EswYkCOtj9cFGG3wEahrJ/1MBwdT9X/3ouUYHk6QGxBf +81zLxzdj0NUdOmVmJO4Ozn+x++4X0LVNZC9anLx6HMC0DzLJqVzLVyb9STmN8olU +xJK1Nez+z4cHpoQBmADkKkQmt0gAEdPkWsGtRjZT+Si35MW7Zoirjsww0JaqPsES +ao/6bRkV9JBmVGKElwYtXLkYcZD0ykyMpYsyFJOJ8ZP0AL0dQk8= +-----END CERTIFICATE----- From 919be67cd2ad481668815d065174c88fff9e2343 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 18 Apr 2016 22:26:37 +0530 Subject: [PATCH 4/7] remove --client-certificate flag --- atom/browser/api/atom_api_app.cc | 7 +++---- atom/common/options_switches.cc | 3 --- atom/common/options_switches.h | 1 - docs/api/chrome-command-line-switches.md | 4 ---- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 1446d44ad006..d6afbb366e04 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -179,11 +179,11 @@ int ImportIntoCertStore( &imported_certs); if (imported_certs.size() > 1) { auto it = imported_certs.begin(); - ++it; // skip first which would be the client certificate. + ++it; // skip first which would be the client certificate. for (; it != imported_certs.end(); ++it) rv &= model->SetCertTrust(it->get(), - net::CA_CERT, - net::NSSCertDatabase::TRUSTED_SSL); + net::CA_CERT, + net::NSSCertDatabase::TRUSTED_SSL); } } } @@ -491,7 +491,6 @@ void AppendSwitch(const std::string& switch_string, mate::Arguments* args) { auto command_line = base::CommandLine::ForCurrentProcess(); if (switch_string == atom::switches::kPpapiFlashPath || - switch_string == atom::switches::kClientCertificate || switch_string == switches::kLogNetLog) { base::FilePath path; args->GetNext(&path); diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index ce28cc98facf..562171d51f25 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -119,9 +119,6 @@ const char kPpapiFlashPath[] = "ppapi-flash-path"; // Ppapi Flash version. const char kPpapiFlashVersion[] = "ppapi-flash-version"; -// Path to client certificate. -const char kClientCertificate[] = "client-certificate"; - // Disable HTTP cache. const char kDisableHttpCache[] = "disable-http-cache"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 52d64c00d51a..5746a7bbfe54 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -68,7 +68,6 @@ namespace switches { extern const char kEnablePlugins[]; extern const char kPpapiFlashPath[]; extern const char kPpapiFlashVersion[]; -extern const char kClientCertificate[]; extern const char kDisableHttpCache[]; extern const char kRegisterStandardSchemes[]; extern const char kRegisterServiceWorkerSchemes[]; diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index 65f096eac6e0..8e8aa38e62dc 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -15,10 +15,6 @@ app.on('ready', function() { }); ``` -## --client-certificate=`path` - -Sets the `path` of client certificate file. - ## --ignore-connections-limit=`domains` Ignore the connections limit for `domains` list separated by `,`. From 2c0494dcef0b483061bbdf07f09e39d1774d20a0 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 18 Apr 2016 22:57:37 +0530 Subject: [PATCH 5/7] fix spec --- spec/api-app-spec.js | 15 ++++++++++----- spec/fixtures/certificates/certs.cnf | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 1f5452713bce..8923d2d214fa 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -95,7 +95,6 @@ describe('app module', function () { this.timeout(5000) - var port var w = null var certPath = path.join(__dirname, 'fixtures', 'certificates') var options = { @@ -115,9 +114,6 @@ describe('app module', function () { res.end('authorized'); } }) - server.listen(0, '127.0.0.1', function () { - port = server.address().port - }) afterEach(function () { if (w != null) { @@ -141,9 +137,18 @@ describe('app module', function () { done() }) + app.on('select-client-certificate', function (event, webContents, url, list, callback) { + assert.equal(list.length, 1) + assert.equal(list[0].issuerName, 'Intermediate CA') + callback(list[0]) + }) + app.importClientCertificate(options, function (result) { assert(!result) - w.loadURL(`https://127.0.0.1:${port}`) + server.listen(0, '127.0.0.1', function () { + var port = server.address().port + w.loadURL(`https://127.0.0.1:${port}`) + }) }) }) }) diff --git a/spec/fixtures/certificates/certs.cnf b/spec/fixtures/certificates/certs.cnf index d8b5c66e13a1..76ef8d073f9d 100644 --- a/spec/fixtures/certificates/certs.cnf +++ b/spec/fixtures/certificates/certs.cnf @@ -15,7 +15,7 @@ RANDFILE = $dir/rand default_md = sha256 default_days = 3650 policy = policy_anything -preserve = no +preserve = no [policy_anything] # Default signing policy @@ -32,7 +32,7 @@ default_bits = 2048 default_md = sha256 string_mask = utf8only distinguished_name = req_env_dn -prompt = no +prompt = no [user_cert] basicConstraints = CA:FALSE From 2d8286515defc2e201fe319768d3dab1fdc30606 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 19 Apr 2016 10:47:28 +0530 Subject: [PATCH 6/7] expose api only on platforms using nss cert database --- atom/browser/api/atom_api_app.cc | 8 ++++++-- atom/browser/api/atom_api_app.h | 13 ++++++++++++- electron.gyp | 3 +++ filenames.gypi | 6 ++++-- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index d6afbb366e04..46402d7f9b28 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -159,13 +159,14 @@ void PassLoginInformation(scoped_refptr login_handler, login_handler->CancelAuth(); } +#if defined(USE_NSS_CERTS) int ImportIntoCertStore( CertificateManagerModel* model, const base::DictionaryValue& options) { std::string file_data, cert_path; base::string16 password; net::CertificateList imported_certs; - int rv; + int rv = -1; options.GetString("clientCertificate", &cert_path); options.GetString("password", &password); @@ -189,6 +190,7 @@ int ImportIntoCertStore( } return rv; } +#endif } // namespace @@ -402,6 +404,7 @@ bool App::MakeSingleInstance( } } +#if defined(USE_NSS_CERTS) void App::ImportClientCertificate( const base::DictionaryValue& options, const net::CompletionCallback& callback) { @@ -429,6 +432,7 @@ void App::OnCertificateManagerModelCreated( *(options.get())); callback.Run(rv); } +#endif mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( v8::Isolate* isolate) { @@ -469,7 +473,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("allowNTLMCredentialsForAllDomains", &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) -#if defined(OS_LINUX) +#if defined(USE_NSS_CERTS) .SetMethod("importClientCertificate", &App::ImportClientCertificate) #endif .SetMethod("makeSingleInstance", &App::MakeSingleInstance); diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index ce66daedf100..acaa64a3437e 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -11,12 +11,15 @@ #include "atom/browser/atom_browser_client.h" #include "atom/browser/browser_observer.h" #include "atom/common/native_mate_converters/callback.h" -#include "chrome/browser/certificate_manager_model.h" #include "chrome/browser/process_singleton.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "native_mate/handle.h" #include "net/base/completion_callback.h" +#if defined(USE_NSS_CERTS) +#include "chrome/browser/certificate_manager_model.h" +#endif + namespace base { class FilePath; } @@ -43,10 +46,12 @@ class App : public AtomBrowserClient::Delegate, int render_process_id, int render_frame_id); +#if defined(USE_NSS_CERTS) void OnCertificateManagerModelCreated( scoped_ptr options, const net::CompletionCallback& callback, scoped_ptr model); +#endif protected: App(); @@ -104,15 +109,21 @@ class App : public AtomBrowserClient::Delegate, bool MakeSingleInstance( const ProcessSingleton::NotificationCallback& callback); std::string GetLocale(); + +#if defined(USE_NSS_CERTS) void ImportClientCertificate(const base::DictionaryValue& options, const net::CompletionCallback& callback); +#endif #if defined(OS_WIN) bool IsAeroGlassEnabled(); #endif scoped_ptr process_singleton_; + +#if defined(USE_NSS_CERTS) scoped_ptr certificate_manager_model_; +#endif DISALLOW_COPY_AND_ASSIGN(App); }; diff --git a/electron.gyp b/electron.gyp index 7a431028f198..11a35490923b 100644 --- a/electron.gyp +++ b/electron.gyp @@ -310,6 +310,9 @@ ], }], # OS=="mac" and mas_build==1 ['OS=="linux"', { + 'sources': [ + '<@(lib_sources_nss)', + ], 'link_settings': { 'ldflags': [ # Make binary search for libraries under current directory, so we diff --git a/filenames.gypi b/filenames.gypi index 4de1b366b4fc..a1c704c348b1 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -390,8 +390,6 @@ 'atom/utility/atom_content_utility_client.h', 'chromium_src/chrome/browser/browser_process.cc', 'chromium_src/chrome/browser/browser_process.h', - 'chromium_src/chrome/browser/certificate_manager_model.cc', - 'chromium_src/chrome/browser/certificate_manager_model.h', 'chromium_src/chrome/browser/chrome_process_finder_win.cc', 'chromium_src/chrome/browser/chrome_process_finder_win.h', 'chromium_src/chrome/browser/chrome_notification_types.h', @@ -519,6 +517,10 @@ '<@(native_mate_files)', '<(SHARED_INTERMEDIATE_DIR)/atom_natives.h', ], + 'lib_sources_nss': [ + 'chromium_src/chrome/browser/certificate_manager_model.cc', + 'chromium_src/chrome/browser/certificate_manager_model.h', + ], 'lib_sources_win': [ 'chromium_src/chrome/browser/ui/views/color_chooser_dialog.cc', 'chromium_src/chrome/browser/ui/views/color_chooser_dialog.h', From 794d1207547dd422dc4791ab09deaaf7283155bf Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 20 Apr 2016 08:45:49 +0530 Subject: [PATCH 7/7] rename importClientCertificate => importCertificate --- atom/browser/api/atom_api_app.cc | 6 +++--- atom/browser/api/atom_api_app.h | 4 ++-- docs/api/app.md | 12 ++++++++++++ spec/api-app-spec.js | 6 +++--- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 46402d7f9b28..9d0aa792e607 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -167,7 +167,7 @@ int ImportIntoCertStore( base::string16 password; net::CertificateList imported_certs; int rv = -1; - options.GetString("clientCertificate", &cert_path); + options.GetString("certificate", &cert_path); options.GetString("password", &password); if (!cert_path.empty()) { @@ -405,7 +405,7 @@ bool App::MakeSingleInstance( } #if defined(USE_NSS_CERTS) -void App::ImportClientCertificate( +void App::ImportCertificate( const base::DictionaryValue& options, const net::CompletionCallback& callback) { auto browser_context = AtomBrowserMainParts::Get()->browser_context(); @@ -474,7 +474,7 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) #if defined(USE_NSS_CERTS) - .SetMethod("importClientCertificate", &App::ImportClientCertificate) + .SetMethod("importCertificate", &App::ImportCertificate) #endif .SetMethod("makeSingleInstance", &App::MakeSingleInstance); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index acaa64a3437e..d4102521c0b4 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -111,8 +111,8 @@ class App : public AtomBrowserClient::Delegate, std::string GetLocale(); #if defined(USE_NSS_CERTS) - void ImportClientCertificate(const base::DictionaryValue& options, - const net::CompletionCallback& callback); + void ImportCertificate(const base::DictionaryValue& options, + const net::CompletionCallback& callback); #endif #if defined(OS_WIN) diff --git a/docs/api/app.md b/docs/api/app.md index 84eeed51d6cc..c8ddb47bd315 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -514,6 +514,18 @@ if (browserOptions.transparent) { This method returns `true` if the system is in Dark Mode, and `false` otherwise. +### `app.importCertificate(options, callback)` _LINUX_ + +* `options` Object + * `certificate` String - Path for the pkcs12 file. + * `password` String - Passphrase for the certificate. +* `callback` Function + * `result` Integer - Result of import. + +Imports the certificate in pkcs12 format into the platform certificate store. +`callback` is called with the `result` of import operation, a value of `0` indicates +success while any other value indicates failure according to chromium [net_error_list](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h). + ### `app.commandLine.appendSwitch(switch[, value])` Append a switch (with optional `value`) to Chromium's command line. diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 8923d2d214fa..1c20ef8e4523 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -89,7 +89,7 @@ describe('app module', function () { }) }) - describe('app.importClientCertificate', function () { + describe('app.importCertificate', function () { if (process.platform !== 'linux') return @@ -124,7 +124,7 @@ describe('app module', function () { it('can import certificate into platform cert store', function (done) { let options = { - clientCertificate: path.join(certPath, 'client.p12'), + certificate: path.join(certPath, 'client.p12'), password: 'electron' } @@ -143,7 +143,7 @@ describe('app module', function () { callback(list[0]) }) - app.importClientCertificate(options, function (result) { + app.importCertificate(options, function (result) { assert(!result) server.listen(0, '127.0.0.1', function () { var port = server.address().port