summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorVijith Kini <vijith@claysol.com>2018-12-07 09:30:38 +0530
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-01-23 14:24:07 +0000
commitbe0fb77baf98f773928b4ff9d08a13c83f189564 (patch)
tree2a84528dd03fda0e44df790f7aa52f242f423b2e /src/core
parente11adebe6f4f76a3e3253b33314a2b4635dc3e65 (diff)
Add in-memory client cert store implementation
Qt applications using webengine can now use a specific client certificate without affecting(or using) the native certificate store. It sounds useful for consumer applications where the application wants to identify itself to the server as the application and not as a specific user. Change-Id: Ib4fcdfd48e00051e3215f90be8701978902b1fbf Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/api/core_api.pro1
-rw-r--r--src/core/api/qwebengineclientcertificatestore.h77
-rw-r--r--src/core/client_cert_override_key.cpp137
-rw-r--r--src/core/client_cert_override_key_p.h52
-rw-r--r--src/core/client_cert_override_p.h63
-rw-r--r--src/core/content_browser_client_qt.cpp26
-rw-r--r--src/core/core_chromium.pri4
-rw-r--r--src/core/qtwebengine.gni1
-rw-r--r--src/core/qwebengineclientcertificatestore.cpp282
9 files changed, 620 insertions, 23 deletions
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 38dc6b39d..b5bb93847 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -32,6 +32,7 @@ gcc: QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter
HEADERS = \
qwebenginecallback.h \
qwebenginecallback_p.h \
+ qwebengineclientcertificatestore.h \
qtwebenginecoreglobal.h \
qtwebenginecoreglobal_p.h \
qwebenginecookiestore.h \
diff --git a/src/core/api/qwebengineclientcertificatestore.h b/src/core/api/qwebengineclientcertificatestore.h
new file mode 100644
index 000000000..82607ea70
--- /dev/null
+++ b/src/core/api/qwebengineclientcertificatestore.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBENGINECLIENTCERTIFICATESTORE_H
+#define QWEBENGINECLIENTCERTIFICATESTORE_H
+
+#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+
+#include <QtNetwork/qsslcertificate.h>
+#include <QtNetwork/qsslkey.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QWebEngineClientCertificateStoreData;
+
+class QWEBENGINECORE_EXPORT QWebEngineClientCertificateStore {
+
+public:
+ struct Entry {
+ QSslKey privateKey;
+ QSslCertificate certificate;
+ };
+
+ static QWebEngineClientCertificateStore *getInstance();
+ void add(const QSslCertificate &certificate, const QSslKey &privateKey);
+ QList<Entry> toList() const;
+ void remove(Entry entry);
+ void clear();
+
+private:
+ static QWebEngineClientCertificateStore *m_instance;
+ Q_DISABLE_COPY(QWebEngineClientCertificateStore)
+
+ QWebEngineClientCertificateStore();
+ ~QWebEngineClientCertificateStore();
+ QWebEngineClientCertificateStoreData *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWebEngineClientCertificateStore_H
diff --git a/src/core/client_cert_override_key.cpp b/src/core/client_cert_override_key.cpp
new file mode 100644
index 000000000..99ddf7466
--- /dev/null
+++ b/src/core/client_cert_override_key.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLIENT_CERT_OVERRIDE_KEY_H
+#define CLIENT_CERT_OVERRIDE_KEY_H
+
+#include "client_cert_override_key_p.h"
+
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
+#include "third_party/boringssl/src/include/openssl/pem.h"
+
+#include <utility>
+#include <QByteArray>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "net/base/net_errors.h"
+#include "net/ssl/ssl_platform_key_util.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/threaded_ssl_private_key.h"
+
+namespace net {
+
+namespace {
+
+class SSLPlatformKeyOverride : public ThreadedSSLPrivateKey::Delegate {
+public:
+ SSLPlatformKeyOverride(const QByteArray &sslKeyInBytes)
+ {
+ mem_ = BIO_new_mem_buf(sslKeyInBytes, -1);
+ key_ = PEM_read_bio_PrivateKey(mem_, NULL, 0, NULL);
+ }
+
+ ~SSLPlatformKeyOverride() override {
+ if (key_)
+ EVP_PKEY_free(key_);
+ if (mem_)
+ BIO_free(mem_);
+ }
+
+ Error Sign(uint16_t algorithm,
+ base::span<const uint8_t> input,
+ std::vector<uint8_t>* signature) override {
+ bssl::ScopedEVP_MD_CTX ctx;
+ EVP_PKEY_CTX* pctx;
+ if (!EVP_DigestSignInit(ctx.get(), &pctx,
+ SSL_get_signature_algorithm_digest(algorithm),
+ nullptr, key_)) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+
+ if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
+ if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* hash length */)) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ }
+ size_t sig_len = 0;
+ if (!EVP_DigestSign(ctx.get(), NULL, &sig_len, input.data(), input.size()))
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ signature->resize(sig_len);
+ if (!EVP_DigestSign(ctx.get(), signature->data(), &sig_len, input.data(),
+ input.size())) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ signature->resize(sig_len);
+ return OK;
+ }
+
+ std::vector<uint16_t> GetAlgorithmPreferences() override {
+ return {
+ SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512,
+ SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256,
+ };
+ }
+
+private:
+ EVP_PKEY* key_;
+ BIO * mem_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyOverride);
+};
+
+} // namespace
+
+scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes) {
+ if (sslKeyInBytes.isEmpty())
+ return nullptr;
+
+ return base::MakeRefCounted<ThreadedSSLPrivateKey>(
+ std::make_unique<SSLPlatformKeyOverride>(sslKeyInBytes),
+ GetSSLPlatformKeyTaskRunner());
+}
+
+} // namespace net
+
+#endif
diff --git a/src/core/client_cert_override_key_p.h b/src/core/client_cert_override_key_p.h
new file mode 100644
index 000000000..7ac610be4
--- /dev/null
+++ b/src/core/client_cert_override_key_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLIENT_CERT_OVERRIDE_KEY_P_H
+#define CLIENT_CERT_OVERRIDE_KEY_P_H
+
+#include "net/ssl/ssl_private_key.h"
+
+#include <QByteArray>
+
+namespace net {
+ class SSLPrivateKey;
+ scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes);
+} // namespace net
+
+#endif
diff --git a/src/core/client_cert_override_p.h b/src/core/client_cert_override_p.h
new file mode 100644
index 000000000..b222bf810
--- /dev/null
+++ b/src/core/client_cert_override_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLIENT_CERT_OVERRIDE_P_H
+#define CLIENT_CERT_OVERRIDE_P_H
+
+#include "net/ssl/client_cert_store.h"
+#include "base/callback_forward.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+class SSLCertRequestInfo;
+class ClientCertOverrideStore : public ClientCertStore
+{
+public:
+ ClientCertOverrideStore();
+ virtual ~ClientCertOverrideStore() override;
+ void GetClientCerts(const SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback) override;
+private:
+ std::unique_ptr<net::ClientCertStore> getNativeStore();
+};
+} // namespace net
+
+#endif
+
+
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index beec6dd26..b5b2ca0fd 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -85,6 +85,7 @@
#include "qtwebengine/grit/qt_webengine_resources.h"
+#include "client_cert_override_p.h"
#include "profile_adapter.h"
#include "browser_main_parts_qt.h"
#include "browser_message_filter_qt.h"
@@ -113,18 +114,6 @@
#include "ui/base/resource/resource_bundle.h"
#endif
-#if defined(USE_NSS_CERTS)
-#include "net/ssl/client_cert_store_nss.h"
-#endif
-
-#if defined(OS_WIN)
-#include "net/ssl/client_cert_store_win.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "net/ssl/client_cert_store_mac.h"
-#endif
-
#if QT_CONFIG(webengine_pepper_plugins)
#include "content/public/browser/browser_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
@@ -381,17 +370,8 @@ std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertSt
{
if (!resource_context)
return nullptr;
-#if defined(USE_NSS_CERTS)
- // FIXME: Give it a proper callback for a password delegate.
- return std::unique_ptr<net::ClientCertStore>(
- new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory()));
-#elif defined(OS_WIN)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
-#elif defined(OS_MACOSX)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
-#else
- return nullptr;
-#endif
+
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertOverrideStore());
}
std::string ContentBrowserClientQt::GetApplicationLocale()
diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri
index 0aa7fd567..65ca793f9 100644
--- a/src/core/core_chromium.pri
+++ b/src/core/core_chromium.pri
@@ -48,6 +48,7 @@ SOURCES = \
browser_message_filter_qt.cpp \
certificate_error_controller.cpp \
chromium_overrides.cpp \
+ client_cert_override_key.cpp \
client_cert_select_controller.cpp \
clipboard_qt.cpp \
color_chooser_qt.cpp \
@@ -102,6 +103,7 @@ SOURCES = \
profile_io_data_qt.cpp \
quota_permission_context_qt.cpp \
quota_request_controller_impl.cpp \
+ qwebengineclientcertificatestore.cpp \
register_protocol_handler_request_controller_impl.cpp \
render_view_context_menu_qt.cpp \
render_view_observer_host_qt.cpp \
@@ -141,6 +143,8 @@ HEADERS = \
certificate_error_controller_p.h \
certificate_error_controller.h \
chromium_overrides.h \
+ client_cert_override_key_p.h \
+ client_cert_override_p.h \
client_cert_select_controller.h \
clipboard_qt.h \
color_chooser_qt.h \
diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni
index 14da1e6cf..57dfbec40 100644
--- a/src/core/qtwebengine.gni
+++ b/src/core/qtwebengine.gni
@@ -9,6 +9,7 @@ chromium_version = exec_script("//build/util/version.py", [ "-f", rebase_path("/
include_dirs = [
"//skia/config",
"//third_party",
+ "//third_party/boringssl/src/include",
"//third_party/skia/include/core"
]
diff --git a/src/core/qwebengineclientcertificatestore.cpp b/src/core/qwebengineclientcertificatestore.cpp
new file mode 100644
index 000000000..fb6cba78f
--- /dev/null
+++ b/src/core/qwebengineclientcertificatestore.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "api/qwebengineclientcertificatestore.h"
+#include "client_cert_override_key_p.h"
+#include "client_cert_override_p.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/callback_forward.h"
+
+#include "net/ssl/client_cert_store.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/cert/x509_certificate.h"
+
+#include "third_party/boringssl/src/include/openssl/pem.h"
+#include "third_party/boringssl/src/include/openssl/err.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+#if defined(USE_NSS_CERTS)
+#include "net/ssl/client_cert_store_nss.h"
+#endif
+
+#if defined(OS_WIN)
+#include "net/ssl/client_cert_store_win.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "net/ssl/client_cert_store_mac.h"
+#endif
+
+#include <QByteArray>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+typedef struct OverrideData {
+ QSslKey key;
+ QSslCertificate certificate;
+ scoped_refptr<net::X509Certificate> certPtr;
+ scoped_refptr<net::SSLPrivateKey> keyPtr;
+} OverrideData;
+
+struct QWebEngineClientCertificateStoreData {
+ QList<OverrideData*> deletedCerts;
+};
+
+static QList<OverrideData*> ClientCertOverrideData;
+QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance = NULL;
+
+/*!
+ \class QWebEngineClientCertificateStore::Entry
+ \inmodule QtWebEngineCore
+ \since 5.13
+ \brief This structure holds the certificate and the private key.
+*/
+
+/*!
+ \class QWebEngineClientCertificateStore
+ \inmodule QtWebEngineCore
+ \since 5.13
+ \brief The QWebEngineClientCertificateStore class provides an in-memory store for client certificates.
+
+ The class allows to store client certificates in an in-memory store.
+ When a web site requests an SSL client certificate, the QWebEnginePage::selectClientCertificate
+ signal is emitted with matching certificates from the native certificate store or the in-memory store.
+ The getInstance() method can be used to access the single instance of the class.
+*/
+
+QWebEngineClientCertificateStore::QWebEngineClientCertificateStore()
+{
+ this->d_ptr = new QWebEngineClientCertificateStoreData;
+}
+
+/*!
+ Destroys this QWebEngineClientCertificateStore object.
+*/
+
+QWebEngineClientCertificateStore::~QWebEngineClientCertificateStore()
+{
+ // Just in case user has not deleted in-memory certificates
+ clear();
+
+ qDeleteAll(d_ptr->deletedCerts);
+ delete d_ptr;
+}
+
+/*!
+ Returns an in-memory client certificate store.
+*/
+
+QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::getInstance()
+{
+ if (!m_instance)
+ m_instance = new QWebEngineClientCertificateStore;
+ return m_instance;
+}
+
+/*!
+ Adds a \a certificate with the \a privateKey to the in-memory client certificate store.
+*/
+
+void QWebEngineClientCertificateStore::add(const QSslCertificate &certificate, const QSslKey &privateKey)
+{
+
+ QByteArray sslKeyInBytes = privateKey.toPem();
+ QByteArray certInBytes = certificate.toDer();
+
+ OverrideData* data = new OverrideData;
+ data->keyPtr = net::WrapOpenSSLPrivateKey(sslKeyInBytes);
+ data->certPtr = net::X509Certificate::CreateFromBytes(
+ certInBytes.data(), certInBytes.length());
+ data->key = privateKey;
+ data->certificate = certificate;
+ ClientCertOverrideData.append(data);
+}
+
+/*!
+ Returns a list of private and public keys of client certificates in the in-memory store.
+ Returns an empty list if the in-memory store does not contain certificates.
+*/
+
+QList<QWebEngineClientCertificateStore::Entry> QWebEngineClientCertificateStore::toList() const
+{
+ QList<Entry> certificateList;
+ for (auto data : ClientCertOverrideData) {
+ Entry entry;
+ entry.certificate = data->certificate;
+ entry.privateKey = data->key;
+ certificateList.append(entry);
+ }
+ return certificateList;
+}
+
+/*!
+ Deletes all the instances of the client certificate in the in-memory client certificate store
+ that matches the certificate in the \a entry.
+*/
+
+void QWebEngineClientCertificateStore::remove(Entry entry)
+{
+ QMutableListIterator<OverrideData*> iterator(ClientCertOverrideData);
+ while (iterator.hasNext()) {
+ auto overrideData = iterator.next();
+ if (entry.certificate.toDer() == overrideData->certificate.toDer()) {
+ d_ptr->deletedCerts.append(overrideData);
+ iterator.remove();
+ }
+ }
+}
+
+/*!
+ Clears all the client certificates from the in-memory store.
+*/
+
+void QWebEngineClientCertificateStore::clear()
+{
+ for (auto data : ClientCertOverrideData)
+ d_ptr->deletedCerts.append(data);
+ ClientCertOverrideData.clear();
+}
+
+QT_END_NAMESPACE
+
+namespace net {
+
+namespace {
+
+class ClientCertIdentityOverride : public ClientCertIdentity {
+public:
+ ClientCertIdentityOverride(
+ scoped_refptr<net::X509Certificate> cert,
+ scoped_refptr<net::SSLPrivateKey> key)
+ : ClientCertIdentity(std::move(cert)),
+ key_(std::move(key)) {}
+ ~ClientCertIdentityOverride() override = default;
+
+ void AcquirePrivateKey(
+ const base::Callback<void(scoped_refptr<SSLPrivateKey>)>&
+ private_key_callback) override
+ {
+ private_key_callback.Run(key_);
+ }
+
+#if defined(OS_MACOSX)
+ SecIdentityRef sec_identity_ref() const override
+ {
+ return nullptr;
+ }
+#endif
+
+private:
+ scoped_refptr<net::SSLPrivateKey> key_;
+};
+
+} // namespace
+
+
+ClientCertOverrideStore::ClientCertOverrideStore()
+ : ClientCertStore()
+{
+}
+
+ClientCertOverrideStore::~ClientCertOverrideStore()
+{
+}
+
+void ClientCertOverrideStore::GetClientCerts(const SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback)
+{
+ // Look for certificates in memory store
+ for (int i = 0; i < ClientCertOverrideData.length(); i++) {
+ scoped_refptr<net::X509Certificate> cert = ClientCertOverrideData[i]->certPtr;
+ if (cert != NULL && cert->IsIssuedByEncoded(cert_request_info.cert_authorities)) {
+ ClientCertIdentityList selected_identities;
+ selected_identities.push_back(std::make_unique<ClientCertIdentityOverride>(cert, ClientCertOverrideData[i]->keyPtr));
+ callback.Run(std::move(selected_identities));
+ return;
+ }
+ }
+
+ // Continue with native cert store if matching certificate is not found in memory
+ std::unique_ptr<net::ClientCertStore> store = getNativeStore();
+ if (store != NULL) {
+ store->GetClientCerts(cert_request_info, callback);
+ return;
+ }
+
+ callback.Run(ClientCertIdentityList());
+ return;
+}
+
+std::unique_ptr<net::ClientCertStore> ClientCertOverrideStore::getNativeStore()
+{
+#if defined(USE_NSS_CERTS)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory()));
+#elif defined(OS_WIN)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
+#elif defined(OS_MACOSX)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
+#else
+ return nullptr;
+#endif
+}
+}