summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslsocket_openssl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl/qsslsocket_openssl.cpp')
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp392
1 files changed, 46 insertions, 346 deletions
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index ab82cdcfc9..2d771b5637 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2014 Governikus GmbH & Co. KG
** Contact: https://www.qt.io/licensing/
**
@@ -54,7 +54,6 @@
****************************************************************************/
//#define QSSLSOCKET_DEBUG
-//#define QT_DECRYPT_SSL_TRAFFIC
#include "qssl_p.h"
#include "qsslsocket_openssl_p.h"
@@ -97,70 +96,6 @@ bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
#endif
-/* \internal
-
- From OpenSSL's thread(3) manual page:
-
- OpenSSL can safely be used in multi-threaded applications provided that at
- least two callback functions are set.
-
- locking_function(int mode, int n, const char *file, int line) is needed to
- perform locking on shared data structures. (Note that OpenSSL uses a
- number of global data structures that will be implicitly shared
- whenever multiple threads use OpenSSL.) Multi-threaded
- applications will crash at random if it is not set. ...
- ...
- id_function(void) is a function that returns a thread ID. It is not
- needed on Windows nor on platforms where getpid() returns a different
- ID for each thread (most notably Linux)
-*/
-class QOpenSslLocks
-{
-public:
- inline QOpenSslLocks()
- : initLocker(QMutex::Recursive),
- locksLocker(QMutex::Recursive)
- {
- QMutexLocker locker(&locksLocker);
- int numLocks = q_CRYPTO_num_locks();
- locks = new QMutex *[numLocks];
- memset(locks, 0, numLocks * sizeof(QMutex *));
- }
- inline ~QOpenSslLocks()
- {
- QMutexLocker locker(&locksLocker);
- for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
- delete locks[i];
- delete [] locks;
-
- QSslSocketPrivate::deinitialize();
- }
- inline QMutex *lock(int num)
- {
- QMutexLocker locker(&locksLocker);
- QMutex *tmp = locks[num];
- if (!tmp)
- tmp = locks[num] = new QMutex(QMutex::Recursive);
- return tmp;
- }
-
- QMutex *globalLock()
- {
- return &locksLocker;
- }
-
- QMutex *initLock()
- {
- return &initLocker;
- }
-
-private:
- QMutex initLocker;
- QMutex locksLocker;
- QMutex **locks;
-};
-Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
-
QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
{
QString errorString;
@@ -175,20 +110,6 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
}
extern "C" {
-static void locking_function(int mode, int lockNumber, const char *, int)
-{
- QMutex *mutex = openssl_locks()->lock(lockNumber);
-
- // Lock or unlock it
- if (mode & CRYPTO_LOCK)
- mutex->lock();
- else
- mutex->unlock();
-}
-static unsigned long id_function()
-{
- return (quintptr)QThread::currentThreadId();
-}
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
static unsigned int q_ssl_psk_client_callback(SSL *ssl,
@@ -227,7 +148,7 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
destroySslContext();
}
-QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
+QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher)
{
QSslCipher ciph;
@@ -268,12 +189,12 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *ciph
}
// static
-inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx) {
- QSslErrorEntry result = {
+inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx)
+{
+ return {
q_X509_STORE_CTX_get_error(ctx),
q_X509_STORE_CTX_get_error_depth(ctx)
};
- return result;
}
// ### This list is shared between all threads, and protected by a
@@ -283,6 +204,7 @@ struct QSslErrorList
QMutex mutex;
QVector<QSslErrorEntry> errors;
};
+
Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
@@ -290,6 +212,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
if (!ok) {
// Store the error and at which depth the error was detected.
_q_sslErrorList()->errors << QSslErrorEntry::fromStoreContext(ctx);
+#if !QT_CONFIG(opensslv11)
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "verification error: dumping bad certificate";
qCDebug(lcSsl) << QSslCertificatePrivate::QSslCertificate_from_X509(q_X509_STORE_CTX_get_current_cert(ctx)).toPem();
@@ -310,9 +233,10 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
<< "ST=" << cert.subjectInfo(QSslCertificate::StateOrProvinceName);
qCDebug(lcSsl) << "Valid:" << cert.effectiveDate() << '-' << cert.expiryDate();
}
-#endif
+#endif // QSSLSOCKET_DEBUG
+#endif // !QT_CONFIG(opensslv11)
}
- // Always return OK to allow verification to continue. We're handle the
+ // Always return OK to allow verification to continue. We handle the
// errors gracefully after collecting all errors, after verification has
// completed.
return 1;
@@ -397,7 +321,7 @@ bool QSslSocketBackendPrivate::initSslContext()
if (configuration.protocol != QSsl::SslV2 &&
configuration.protocol != QSsl::SslV3 &&
configuration.protocol != QSsl::UnknownProtocol &&
- mode == QSslSocket::SslClientMode && q_SSLeay() >= 0x00090806fL) {
+ mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryVersionNumber() >= 0x00090806fL) {
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
if (tlsHostName.isEmpty())
@@ -438,13 +362,13 @@ bool QSslSocketBackendPrivate::initSslContext()
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
// Save a pointer to this object into the SSL structure.
- if (q_SSLeay() >= 0x10001000L)
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L)
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
// Set the client callback for PSK
- if (q_SSLeay() >= 0x10001000L) {
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L) {
if (mode == QSslSocket::SslClientMode)
q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
else if (mode == QSslSocket::SslServerMode)
@@ -466,16 +390,6 @@ void QSslSocketBackendPrivate::destroySslContext()
/*!
\internal
-*/
-void QSslSocketPrivate::deinitialize()
-{
- q_CRYPTO_set_id_callback(0);
- q_CRYPTO_set_locking_callback(0);
- q_ERR_free_strings();
-}
-
-/*!
- \internal
Does the minimum amount of initialization to determine whether SSL
is supported or not.
@@ -486,91 +400,6 @@ bool QSslSocketPrivate::supportsSsl()
return ensureLibraryLoaded();
}
-bool QSslSocketPrivate::ensureLibraryLoaded()
-{
- if (!q_resolveOpenSslSymbols())
- return false;
-
- // Check if the library itself needs to be initialized.
- QMutexLocker locker(openssl_locks()->initLock());
-
- if (!s_libraryLoaded) {
- s_libraryLoaded = true;
-
- // Initialize OpenSSL.
- q_CRYPTO_set_id_callback(id_function);
- q_CRYPTO_set_locking_callback(locking_function);
- if (q_SSL_library_init() != 1)
- return false;
- q_SSL_load_error_strings();
- q_OpenSSL_add_all_algorithms();
-
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- if (q_SSLeay() >= 0x10001000L)
- QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
-#endif
-
- // Initialize OpenSSL's random seed.
- if (!q_RAND_status()) {
- qWarning("Random number generator not seeded, disabling SSL support");
- return false;
- }
- }
- return true;
-}
-
-void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
-{
- QMutexLocker locker(openssl_locks()->initLock());
- if (s_loadedCiphersAndCerts)
- return;
- s_loadedCiphersAndCerts = true;
-
- resetDefaultCiphers();
- resetDefaultEllipticCurves();
-
-#if QT_CONFIG(library)
- //load symbols needed to receive certificates from system store
-#if defined(Q_OS_WIN)
- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
- if (hLib) {
- ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
- ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
- ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
- } else {
- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
- }
-#elif defined(Q_OS_QNX)
- s_loadRootCertsOnDemand = true;
-#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
- // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
- QList<QByteArray> dirs = unixRootCertDirectories();
- QStringList symLinkFilter;
- symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
- for (int a = 0; a < dirs.count(); ++a) {
- QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
- if (iterator.hasNext()) {
- s_loadRootCertsOnDemand = true;
- break;
- }
- }
-#endif
-#endif // QT_CONFIG(library)
- // if on-demand loading was not enabled, load the certs now
- if (!s_loadRootCertsOnDemand)
- setDefaultCaCertificates(systemCaCertificates());
-#ifdef Q_OS_WIN
- //Enabled for fetching additional root certs from windows update on windows 6+
- //This flag is set false by setDefaultCaCertificates() indicating the app uses
- //its own cert bundle rather than the system one.
- //Same logic that disables the unix on demand cert loading.
- //Unlike unix, we do preload the certificates from the cert store.
- if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
- s_loadRootCertsOnDemand = true;
-#endif
-}
/*!
\internal
@@ -587,26 +416,6 @@ void QSslSocketPrivate::ensureInitialized()
ensureCiphersAndCertsLoaded();
}
-long QSslSocketPrivate::sslLibraryVersionNumber()
-{
- if (!supportsSsl())
- return 0;
-
- return q_SSLeay();
-}
-
-QString QSslSocketPrivate::sslLibraryVersionString()
-{
- if (!supportsSsl())
- return QString();
-
- const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
- if (!versionString)
- return QString();
-
- return QString::fromLatin1(versionString);
-}
-
long QSslSocketPrivate::sslLibraryBuildVersionNumber()
{
return OPENSSL_VERSION_NUMBER;
@@ -628,7 +437,11 @@ QString QSslSocketPrivate::sslLibraryBuildVersionString()
*/
void QSslSocketPrivate::resetDefaultCiphers()
{
+#if QT_CONFIG(opensslv11)
+ SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method());
+#else
SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
+#endif
SSL *mySsl = q_SSL_new(myCtx);
QList<QSslCipher> ciphers;
@@ -664,7 +477,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
QVector<QSslEllipticCurve> curves;
#ifndef OPENSSL_NO_EC
- const size_t curveCount = q_EC_get_builtin_curves(NULL, 0);
+ const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
@@ -698,13 +511,14 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
HCERTSTORE hSystemStore;
hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
- if(hSystemStore) {
- PCCERT_CONTEXT pc = NULL;
- while(1) {
- pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
- if(!pc)
+ if (hSystemStore) {
+ PCCERT_CONTEXT pc = nullptr;
+ while (1) {
+ pc = ptrCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
+ if (!pc)
break;
- QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
+ QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
+ static_cast<int>(pc->cbCertEncoded));
QSslCertificate cert(der, QSsl::Der);
systemCerts.append(cert);
}
@@ -891,10 +705,9 @@ void QSslSocketBackendPrivate::transmit()
// Write encrypted data from the buffer into the read BIO.
int writtenToBio = q_BIO_write(readBio, data.constData(), encryptedBytesRead);
- // do the actual read() here and throw away the results.
+ // Throw away the results.
if (writtenToBio > 0) {
- // ### TODO: make this cheaper by not making it memcpy. E.g. make it work with data=0x0 or make it work with seek
- plainSocket->read(data.data(), writtenToBio);
+ plainSocket->skip(writtenToBio);
} else {
// ### Better error handling.
setErrorAndEmit(QAbstractSocket::SslInternalError,
@@ -943,15 +756,15 @@ void QSslSocketBackendPrivate::transmit()
// we have a readBufferMaxSize. There's no point in leaving data there
// just so that readBuffer.size() == readBufferMaxSize.
int readBytes = 0;
- data.resize(4096);
- ::memset(data.data(), 0, data.size());
+ const int bytesToRead = 4096;
do {
// Don't use SSL_pending(). It's very unreliable.
- if ((readBytes = q_SSL_read(ssl, data.data(), data.size())) > 0) {
+ readBytes = q_SSL_read(ssl, buffer.reserve(bytesToRead), bytesToRead);
+ if (readBytes > 0) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocketBackendPrivate::transmit: decrypted" << readBytes << "bytes";
#endif
- buffer.append(data.constData(), readBytes);
+ buffer.chop(bytesToRead - readBytes);
if (readyReadEmittedPointer)
*readyReadEmittedPointer = true;
@@ -960,6 +773,7 @@ void QSslSocketBackendPrivate::transmit()
transmitting = true;
continue;
}
+ buffer.chop(bytesToRead);
// Error.
switch (q_SSL_get_error(ssl, readBytes)) {
@@ -1502,14 +1316,8 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
{
if (!ssl)
return QSslCipher();
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- // FIXME This is fairly evil, but needed to keep source level compatibility
- // with the OpenSSL 0.9.x implementation at maximum -- some other functions
- // don't take a const SSL_CIPHER* when they should
- SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
-#else
- SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
-#endif
+
+ const SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
}
@@ -1535,112 +1343,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
return QSsl::UnknownProtocol;
}
-void QSslSocketBackendPrivate::continueHandshake()
-{
- Q_Q(QSslSocket);
- // if we have a max read buffer size, reset the plain socket's to match
- if (readBufferMaxSize)
- plainSocket->setReadBufferSize(readBufferMaxSize);
-
- if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
- configuration.peerSessionShared = true;
-
-#ifdef QT_DECRYPT_SSL_TRAFFIC
- if (ssl->session && ssl->s3) {
- const char *mk = reinterpret_cast<const char *>(ssl->session->master_key);
- QByteArray masterKey(mk, ssl->session->master_key_length);
- const char *random = reinterpret_cast<const char *>(ssl->s3->client_random);
- QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
-
- // different format, needed for e.g. older Wireshark versions:
-// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id);
-// QByteArray sessionID(sid, ssl->session->session_id_length);
-// QByteArray debugLineRSA("RSA Session-ID:");
-// debugLineRSA.append(sessionID.toHex().toUpper());
-// debugLineRSA.append(" Master-Key:");
-// debugLineRSA.append(masterKey.toHex().toUpper());
-// debugLineRSA.append("\n");
-
- QByteArray debugLineClientRandom("CLIENT_RANDOM ");
- debugLineClientRandom.append(clientRandom.toHex().toUpper());
- debugLineClientRandom.append(" ");
- debugLineClientRandom.append(masterKey.toHex().toUpper());
- debugLineClientRandom.append("\n");
-
- QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
- QFile file(sslKeyFile);
- if (!file.open(QIODevice::Append))
- qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
- if (!file.write(debugLineClientRandom))
- qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
- file.close();
- } else {
- qCWarning(lcSsl, "could not decrypt SSL traffic");
- }
-#endif
-
- // Cache this SSL session inside the QSslContext
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
- if (!sslContextPointer->cacheSession(ssl)) {
- sslContextPointer.clear(); // we could not cache the session
- } else {
- // Cache the session for permanent usage as well
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
- if (!sslContextPointer->sessionASN1().isEmpty())
- configuration.sslSession = sslContextPointer->sessionASN1();
- configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
- }
- }
- }
-
-#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
-
- configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
- if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
- // we could not agree -> be conservative and use HTTP/1.1
- configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
- } else {
- const unsigned char *proto = 0;
- unsigned int proto_len = 0;
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L) {
- q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
- if (proto_len && mode == QSslSocket::SslClientMode) {
- // Client does not have a callback that sets it ...
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
- }
- }
-
- if (!proto_len) { // Test if NPN was more lucky ...
-#else
- {
-#endif
- q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
- }
-
- if (proto_len)
- configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
- else
- configuration.nextNegotiatedProtocol.clear();
- }
-#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
-
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
- EVP_PKEY *key;
- if (q_SSL_get_server_tmp_key(ssl, &key))
- configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
- }
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
-
- connectionEncrypted = true;
- emit q->encrypted();
- if (autoStartHandshake && pendingClose) {
- pendingClose = false;
- q->disconnectFromHost();
- }
-}
-
QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
{
ensureInitialized();
@@ -1694,12 +1396,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex);
// Register a custom callback to get all verification errors.
- X509_STORE_set_verify_cb_func(certStore, q_X509Callback);
+ q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
// Build the chain of intermediate certificates
STACK_OF(X509) *intermediates = 0;
if (certificateChain.length() > 1) {
- intermediates = (STACK_OF(X509) *) q_sk_new_null();
+ intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
if (!intermediates) {
q_X509_STORE_free(certStore);
@@ -1713,11 +1415,8 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
first = false;
continue;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
-#else
- q_sk_push( (STACK *)intermediates, reinterpret_cast<char *>(cert.handle()));
-#endif
+
+ q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
}
}
@@ -1741,11 +1440,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
(void) q_X509_verify_cert(storeContext);
q_X509_STORE_CTX_free(storeContext);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- q_sk_free( (_STACK *) intermediates);
-#else
- q_sk_free( (STACK *) intermediates);
-#endif
+ q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
// Now process the errors
const auto errorList = std::move(_q_sslErrorList()->errors);
@@ -1819,7 +1514,8 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
// Convert to Qt types
if (!key->d->fromEVP_PKEY(pkey)) {
qCWarning(lcSsl, "Unable to convert private key");
- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
+ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
+ reinterpret_cast<void (*)(void *)>(q_OPENSSL_sk_free));
q_X509_free(x509);
q_EVP_PKEY_free(pkey);
q_PKCS12_free(p12);
@@ -1834,7 +1530,11 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
*caCertificates = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(ca);
// Clean up
- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
+ // TODO: verify ASAP, in the past we had sk_pop_free with q_OPENSSL_sk_free
+ // which seems to be blatantly wrong and even crashes with 1.1.
+ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
+ reinterpret_cast<void (*)(void *)>(q_X509_free));
+
q_X509_free(x509);
q_EVP_PKEY_free(pkey);
q_PKCS12_free(p12);