1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
5 ** Copyright (C) 2014 Governikus GmbH & Co. KG.
6 ** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
7 ** Contact: https://www.qt.io/licensing/
8 **
9 ** This file is part of the QtNetwork module of the Qt Toolkit.
10 **
11 ** $QT_BEGIN_LICENSE:LGPL$
12 ** Commercial License Usage
13 ** Licensees holding valid commercial Qt licenses may use this file in
14 ** accordance with the commercial license agreement provided with the
15 ** Software or, alternatively, in accordance with the terms contained in
16 ** a written agreement between you and The Qt Company. For licensing terms
17 ** and conditions see https://www.qt.io/terms-conditions. For further
18 ** information use the contact form at https://www.qt.io/contact-us.
19 **
20 ** GNU Lesser General Public License Usage
21 ** Alternatively, this file may be used under the terms of the GNU Lesser
22 ** General Public License version 3 as published by the Free Software
23 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
24 ** packaging of this file. Please review the following information to
25 ** ensure the GNU Lesser General Public License version 3 requirements
26 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 2.0 or (at your option) the GNU General
31 ** Public license version 3 or any later version approved by the KDE Free
32 ** Qt Foundation. The licenses are as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
34 ** included in the packaging of this file. Please review the following
35 ** information to ensure the GNU General Public License requirements will
36 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
37 ** https://www.gnu.org/licenses/gpl-3.0.html.
38 **
39 ** $QT_END_LICENSE$
40 **
41 ****************************************************************************/
42 
43 #include <QtNetwork/qsslsocket.h>
44 #include <QtNetwork/qssldiffiehellmanparameters.h>
45 
46 #include "private/qssl_p.h"
47 #include "private/qsslsocket_p.h"
48 #include "private/qsslcontext_openssl_p.h"
49 #include "private/qsslsocket_openssl_p.h"
50 #include "private/qsslsocket_openssl_symbols_p.h"
51 #include "private/qssldiffiehellmanparameters_p.h"
52 
53 #include <vector>
54 
55 QT_BEGIN_NAMESPACE
56 
Q_GLOBAL_STATIC(bool,forceSecurityLevel)57 Q_GLOBAL_STATIC(bool, forceSecurityLevel)
58 
59 Q_NETWORK_EXPORT void qt_ForceTlsSecurityLevel()
60 {
61     *forceSecurityLevel() = true;
62 }
63 
64 // defined in qsslsocket_openssl.cpp:
65 extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
66 extern QString getErrorsFromOpenSsl();
67 
68 #if QT_CONFIG(dtls)
69 // defined in qdtls_openssl.cpp:
70 namespace dtlscallbacks
71 {
72 extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
73 extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
74                                           unsigned *cookieLength);
75 extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
76                                         unsigned cookieLength);
77 }
78 #endif // dtls
79 
80 #ifdef TLS1_3_VERSION
81 extern "C" int q_ssl_sess_set_new_cb(SSL *context, SSL_SESSION *session);
82 #endif // TLS1_3_VERSION
83 
84 // Defined in qsslsocket.cpp
85 QList<QSslCipher> q_getDefaultDtlsCiphers();
86 
msgErrorSettingBackendConfig(const QString & why)87 static inline QString msgErrorSettingBackendConfig(const QString &why)
88 {
89     return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why);
90 }
91 
msgErrorSettingEllipticCurves(const QString & why)92 static inline QString msgErrorSettingEllipticCurves(const QString &why)
93 {
94     return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
95 }
96 
QSslContext()97 QSslContext::QSslContext()
98     : ctx(nullptr),
99     pkey(nullptr),
100     session(nullptr),
101     m_sessionTicketLifeTimeHint(-1)
102 {
103 }
104 
~QSslContext()105 QSslContext::~QSslContext()
106 {
107     if (ctx)
108         // This will decrement the reference count by 1 and free the context eventually when possible
109         q_SSL_CTX_free(ctx);
110 
111     if (pkey)
112         q_EVP_PKEY_free(pkey);
113 
114     if (session)
115         q_SSL_SESSION_free(session);
116 }
117 
fromConfiguration(QSslSocket::SslMode mode,const QSslConfiguration & configuration,bool allowRootCertOnDemandLoading)118 QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
119 {
120     QSslContext *sslContext = new QSslContext();
121     initSslContext(sslContext, mode, configuration, allowRootCertOnDemandLoading);
122     return sslContext;
123 }
124 
sharedFromConfiguration(QSslSocket::SslMode mode,const QSslConfiguration & configuration,bool allowRootCertOnDemandLoading)125 QSharedPointer<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
126 {
127     QSharedPointer<QSslContext> sslContext = QSharedPointer<QSslContext>::create();
128     initSslContext(sslContext.data(), mode, configuration, allowRootCertOnDemandLoading);
129     return sslContext;
130 }
131 
132 #ifndef OPENSSL_NO_NEXTPROTONEG
133 
next_proto_cb(SSL *,unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)134 static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen,
135                          const unsigned char *in, unsigned int inlen, void *arg)
136 {
137     QSslContext::NPNContext *ctx = reinterpret_cast<QSslContext::NPNContext *>(arg);
138 
139     // comment out to debug:
140 //    QList<QByteArray> supportedVersions;
141 //    for (unsigned int i = 0; i < inlen; ) {
142 //        QByteArray version(reinterpret_cast<const char *>(&in[i+1]), in[i]);
143 //        supportedVersions << version;
144 //        i += in[i] + 1;
145 //    }
146 
147     int proto = q_SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len);
148     switch (proto) {
149     case OPENSSL_NPN_UNSUPPORTED:
150         ctx->status = QSslConfiguration::NextProtocolNegotiationNone;
151         break;
152     case OPENSSL_NPN_NEGOTIATED:
153         ctx->status = QSslConfiguration::NextProtocolNegotiationNegotiated;
154         break;
155     case OPENSSL_NPN_NO_OVERLAP:
156         ctx->status = QSslConfiguration::NextProtocolNegotiationUnsupported;
157         break;
158     default:
159         qCWarning(lcSsl, "OpenSSL sent unknown NPN status");
160     }
161 
162     return SSL_TLSEXT_ERR_OK;
163 }
164 
npnContext() const165 QSslContext::NPNContext QSslContext::npnContext() const
166 {
167     return m_npnContext;
168 }
169 #endif // !OPENSSL_NO_NEXTPROTONEG
170 
171 
172 
173 // Needs to be deleted by caller
createSsl()174 SSL* QSslContext::createSsl()
175 {
176     SSL* ssl = q_SSL_new(ctx);
177     q_SSL_clear(ssl);
178 
179     if (!session && !sessionASN1().isEmpty()
180             && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
181         const unsigned char *data = reinterpret_cast<const unsigned char *>(m_sessionASN1.constData());
182         session = q_d2i_SSL_SESSION(nullptr, &data, m_sessionASN1.size());
183         // 'session' has refcount 1 already, set by the function above
184     }
185 
186     if (session) {
187         // Try to resume the last session we cached
188         if (!q_SSL_set_session(ssl, session)) {
189             qCWarning(lcSsl, "could not set SSL session");
190             q_SSL_SESSION_free(session);
191             session = nullptr;
192         }
193     }
194 
195 #ifndef OPENSSL_NO_NEXTPROTONEG
196     QList<QByteArray> protocols = sslConfiguration.d->nextAllowedProtocols;
197     if (!protocols.isEmpty()) {
198         m_supportedNPNVersions.clear();
199         for (int a = 0; a < protocols.count(); ++a) {
200             if (protocols.at(a).size() > 255) {
201                 qCWarning(lcSsl) << "TLS NPN extension" << protocols.at(a)
202                                  << "is too long and will be ignored.";
203                 continue;
204             } else if (protocols.at(a).isEmpty()) {
205                 continue;
206             }
207             m_supportedNPNVersions.append(protocols.at(a).size()).append(protocols.at(a));
208         }
209         if (m_supportedNPNVersions.size()) {
210             m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data());
211             m_npnContext.len = m_supportedNPNVersions.count();
212             m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
213             // Callback's type has a parameter 'const unsigned char ** out'
214             // since it was introduced in 1.0.2. Internally, OpenSSL's own code
215             // (tests/examples) cast it to unsigned char * (since it's 'out').
216             // We just re-use our NPN callback and cast here:
217             typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *,
218                                             const unsigned char *, unsigned int, void *);
219             // With ALPN callback is for a server side only, for a client m_npnContext.status
220             // will stay in NextProtocolNegotiationNone.
221             q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
222             // Client:
223             q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
224             // And in case our peer does not support ALPN, but supports NPN:
225             q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
226         }
227     }
228 #endif // !OPENSSL_NO_NEXTPROTONEG
229 
230     return ssl;
231 }
232 
233 // We cache exactly one session here
cacheSession(SSL * ssl)234 bool QSslContext::cacheSession(SSL* ssl)
235 {
236     // don't cache the same session again
237     if (session && session == q_SSL_get_session(ssl))
238         return true;
239 
240     // decrease refcount of currently stored session
241     // (this might happen if there are several concurrent handshakes in flight)
242     if (session)
243         q_SSL_SESSION_free(session);
244 
245     // cache the session the caller gave us and increase reference count
246     session = q_SSL_get1_session(ssl);
247 
248     if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
249         int sessionSize = q_i2d_SSL_SESSION(session, nullptr);
250         if (sessionSize > 0) {
251             m_sessionASN1.resize(sessionSize);
252             unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
253             if (!q_i2d_SSL_SESSION(session, &data))
254                 qCWarning(lcSsl, "could not store persistent version of SSL session");
255             m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
256         }
257     }
258 
259     return (session != nullptr);
260 }
261 
sessionASN1() const262 QByteArray QSslContext::sessionASN1() const
263 {
264     return m_sessionASN1;
265 }
266 
setSessionASN1(const QByteArray & session)267 void QSslContext::setSessionASN1(const QByteArray &session)
268 {
269     m_sessionASN1 = session;
270 }
271 
sessionTicketLifeTimeHint() const272 int QSslContext::sessionTicketLifeTimeHint() const
273 {
274     return m_sessionTicketLifeTimeHint;
275 }
276 
error() const277 QSslError::SslError QSslContext::error() const
278 {
279     return errorCode;
280 }
281 
errorString() const282 QString QSslContext::errorString() const
283 {
284     return errorStr;
285 }
286 
initSslContext(QSslContext * sslContext,QSslSocket::SslMode mode,const QSslConfiguration & configuration,bool allowRootCertOnDemandLoading)287 void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode,
288                                  const QSslConfiguration &configuration,
289                                  bool allowRootCertOnDemandLoading)
290 {
291     sslContext->sslConfiguration = configuration;
292     sslContext->errorCode = QSslError::NoError;
293 
294     bool client = (mode == QSslSocket::SslClientMode);
295 
296     bool reinitialized = false;
297     bool unsupportedProtocol = false;
298     bool isDtls = false;
299 init_context:
300     if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
301         // SSL 2 is no longer supported, but chosen deliberately -> error
302         sslContext->ctx = nullptr;
303         unsupportedProtocol = true;
304     } else if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) {
305         // SSL 3 is no longer supported, but chosen deliberately -> error
306         sslContext->ctx = nullptr;
307         unsupportedProtocol = true;
308     } else {
309         switch (sslContext->sslConfiguration.protocol()) {
310         case QSsl::DtlsV1_0:
311         case QSsl::DtlsV1_0OrLater:
312         case QSsl::DtlsV1_2:
313         case QSsl::DtlsV1_2OrLater:
314 #if QT_CONFIG(dtls)
315             isDtls = true;
316             sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
317 #else // dtls
318             sslContext->ctx = nullptr;
319             unsupportedProtocol = true;
320             qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
321 
322 #endif // dtls
323             break;
324         case QSsl::TlsV1_3:
325         case QSsl::TlsV1_3OrLater:
326 #if !defined(TLS1_3_VERSION)
327             qCWarning(lcSsl, "TLS 1.3 is not supported");
328             sslContext->ctx = nullptr;
329             unsupportedProtocol = true;
330             break;
331 #endif // TLS1_3_VERSION
332         default:
333             // The ssl options will actually control the supported methods
334             sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
335         }
336     }
337 
338     if (!sslContext->ctx) {
339         // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
340         // by re-initializing the library.
341         if (!reinitialized) {
342             reinitialized = true;
343             if (q_OPENSSL_init_ssl(0, nullptr) == 1)
344                 goto init_context;
345         }
346 
347         sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
348             unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
349         );
350         sslContext->errorCode = QSslError::UnspecifiedError;
351         return;
352     }
353 
354     // A nasty hacked OpenSSL using a level that will make our auto-tests fail:
355     if (q_SSL_CTX_get_security_level(sslContext->ctx) > 1 && *forceSecurityLevel())
356         q_SSL_CTX_set_security_level(sslContext->ctx, 1);
357 
358     const long anyVersion =
359 #if QT_CONFIG(dtls)
360                             isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
361 #else
362                             TLS_ANY_VERSION;
363 #endif // dtls
364     long minVersion = anyVersion;
365     long maxVersion = anyVersion;
366 
367     switch (sslContext->sslConfiguration.protocol()) {
368     case QSsl::TlsV1_0:
369         minVersion = TLS1_VERSION;
370         maxVersion = TLS1_VERSION;
371         break;
372     case QSsl::TlsV1_1:
373         minVersion = TLS1_1_VERSION;
374         maxVersion = TLS1_1_VERSION;
375         break;
376     case QSsl::TlsV1_2:
377         minVersion = TLS1_2_VERSION;
378         maxVersion = TLS1_2_VERSION;
379         break;
380     case QSsl::TlsV1_3:
381 #ifdef TLS1_3_VERSION
382         minVersion = TLS1_3_VERSION;
383         maxVersion = TLS1_3_VERSION;
384 #else
385         // This protocol is not supported by OpenSSL 1.1 and we handle
386         // it as an error (see the code above).
387         Q_UNREACHABLE();
388 #endif // TLS1_3_VERSION
389         break;
390     // Ranges:
391     case QSsl::TlsV1SslV3:
392     case QSsl::AnyProtocol:
393     case QSsl::SecureProtocols:
394     case QSsl::TlsV1_0OrLater:
395         minVersion = TLS1_VERSION;
396         maxVersion = 0;
397         break;
398     case QSsl::TlsV1_1OrLater:
399         minVersion = TLS1_1_VERSION;
400         maxVersion = 0;
401         break;
402     case QSsl::TlsV1_2OrLater:
403         minVersion = TLS1_2_VERSION;
404         maxVersion = 0;
405         break;
406     case QSsl::DtlsV1_0:
407         minVersion = DTLS1_VERSION;
408         maxVersion = DTLS1_VERSION;
409         break;
410     case QSsl::DtlsV1_0OrLater:
411 #ifdef DTLS_MAX_VERSION
412         minVersion = DTLS1_VERSION;
413         maxVersion = DTLS_MAX_VERSION;
414 #else
415         Q_UNREACHABLE();
416 #endif // DTLS_MAX_VERSION
417         break;
418     case QSsl::DtlsV1_2:
419 #ifdef DTLS1_2_VERSION
420         minVersion = DTLS1_2_VERSION;
421         maxVersion = DTLS1_2_VERSION;
422 #else
423         Q_UNREACHABLE();
424 #endif // DTLS1_2_VERSION
425         break;
426     case QSsl::DtlsV1_2OrLater:
427 #if defined(DTLS1_2_VERSION) && defined(DTLS_MAX_VERSION)
428         minVersion = DTLS1_2_VERSION;
429         maxVersion = DTLS_MAX_VERSION;
430 #else
431         Q_UNREACHABLE();
432 #endif // DTLS1_2_VERSION && DTLS_MAX_VERSION
433         break;
434     case QSsl::TlsV1_3OrLater:
435 #ifdef TLS1_3_VERSION
436         minVersion = TLS1_3_VERSION;
437         maxVersion = 0;
438         break;
439 #else
440         // This protocol is not supported by OpenSSL 1.1 and we handle
441         // it as an error (see the code above).
442         Q_UNREACHABLE();
443         break;
444 #endif // TLS1_3_VERSION
445     case QSsl::SslV2:
446     case QSsl::SslV3:
447         // These protocols are not supported, and we handle
448         // them as an error (see the code above).
449         Q_UNREACHABLE();
450         break;
451     case QSsl::UnknownProtocol:
452         break;
453     }
454 
455     if (minVersion != anyVersion
456         && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
457         sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
458         sslContext->errorCode = QSslError::UnspecifiedError;
459         return;
460     }
461 
462     if (maxVersion != anyVersion
463         && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
464         sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
465         sslContext->errorCode = QSslError::UnspecifiedError;
466         return;
467     }
468 
469     // Enable bug workarounds.
470     long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
471     q_SSL_CTX_set_options(sslContext->ctx, options);
472 
473     // Tell OpenSSL to release memory early
474     // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
475     q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
476 
477     auto filterCiphers = [](const QList<QSslCipher> &ciphers, bool selectTls13)
478     {
479         QByteArray cipherString;
480         bool first = true;
481 
482         for (const QSslCipher &cipher : qAsConst(ciphers)) {
483             const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater;
484             if (selectTls13 != isTls13Cipher)
485                 continue;
486 
487             if (first)
488                 first = false;
489             else
490                 cipherString.append(':');
491             cipherString.append(cipher.name().toLatin1());
492         }
493         return cipherString;
494     };
495 
496     // Initialize ciphers
497     QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
498     if (ciphers.isEmpty())
499         ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers();
500 
501     const QByteArray preTls13Ciphers = filterCiphers(ciphers, false);
502 
503     if (preTls13Ciphers.size()) {
504         if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) {
505             sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
506             sslContext->errorCode = QSslError::UnspecifiedError;
507             return;
508         }
509     }
510 
511     const QByteArray tls13Ciphers = filterCiphers(ciphers, true);
512 #ifdef TLS1_3_VERSION
513     if (tls13Ciphers.size()) {
514         if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) {
515             sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
516             sslContext->errorCode = QSslError::UnspecifiedError;
517             return;
518         }
519     }
520 #endif // TLS1_3_VERSION
521     if (!preTls13Ciphers.size() && !tls13Ciphers.size()) {
522         sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QStringLiteral(""));
523         sslContext->errorCode = QSslError::UnspecifiedError;
524         return;
525     }
526 
527     const QDateTime now = QDateTime::currentDateTimeUtc();
528 
529     // Add all our CAs to this store.
530     const auto caCertificates = sslContext->sslConfiguration.caCertificates();
531     for (const QSslCertificate &caCertificate : caCertificates) {
532         // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
533         //
534         // If several CA certificates matching the name, key identifier, and
535         // serial number condition are available, only the first one will be
536         // examined. This may lead to unexpected results if the same CA
537         // certificate is available with different expiration dates. If a
538         // ``certificate expired'' verification error occurs, no other
539         // certificate will be searched. Make sure to not have expired
540         // certificates mixed with valid ones.
541         //
542         // See also: QSslSocketBackendPrivate::verify()
543         if (caCertificate.expiryDate() >= now) {
544             q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
545         }
546     }
547 
548     if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
549         // tell OpenSSL the directories where to look up the root certs on demand
550         const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
551         int success = 1;
552 #if OPENSSL_VERSION_MAJOR < 3
553         for (const QByteArray &unixDir : unixDirs) {
554             if ((success = q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData())) != 1)
555                 break;
556         }
557 #else
558         for (const QByteArray &unixDir : unixDirs) {
559             if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1)
560                 break;
561         }
562 #endif // OPENSSL_VERSION_MAJOR
563         if (success != 1) {
564             const auto qtErrors = QSslSocketBackendPrivate::getErrorsFromOpenSsl();
565             qCWarning(lcSsl) << "An error encountered while to set root certificates location:"
566                               << qtErrors;
567         }
568     }
569 
570     if (!sslContext->sslConfiguration.localCertificate().isNull()) {
571         // Require a private key as well.
572         if (sslContext->sslConfiguration.privateKey().isNull()) {
573             sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
574             sslContext->errorCode = QSslError::UnspecifiedError;
575             return;
576         }
577 
578         // Load certificate
579         if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
580             sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
581             sslContext->errorCode = QSslError::UnspecifiedError;
582             return;
583         }
584 
585         if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
586             sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
587         } else {
588             // Load private key
589             sslContext->pkey = q_EVP_PKEY_new();
590             // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
591             // this lead to a memory leak. Now we use the *_set1_* functions which do not
592             // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
593             if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
594                 q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
595             else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
596                 q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
597 #ifndef OPENSSL_NO_EC
598             else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
599                 q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
600 #endif
601         }
602 
603         if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
604             sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
605             sslContext->errorCode = QSslError::UnspecifiedError;
606             return;
607         }
608         if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
609             sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey
610 
611         // Check if the certificate matches the private key.
612         if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
613             sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
614             sslContext->errorCode = QSslError::UnspecifiedError;
615             return;
616         }
617 
618         // If we have any intermediate certificates then we need to add them to our chain
619         bool first = true;
620         for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
621             if (first) {
622                 first = false;
623                 continue;
624             }
625             q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
626                            q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
627         }
628     }
629 
630     // Initialize peer verification, different callbacks, TLS/DTLS verification first
631     // (note, all these set_some_callback do not have return value):
632     if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
633         q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
634     } else {
635         q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER,
636 #if QT_CONFIG(dtls)
637                              isDtls ? dtlscallbacks::q_X509DtlsCallback :
638 #endif // dtls
639                              q_X509Callback);
640     }
641 
642 #ifdef TLS1_3_VERSION
643     // NewSessionTicket callback:
644     if (mode == QSslSocket::SslClientMode && !isDtls) {
645         q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb);
646         q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
647     }
648 
649 #endif // TLS1_3_VERSION
650 
651 #if QT_CONFIG(dtls)
652     // DTLS cookies:
653     if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
654         q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
655         q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
656     }
657 #endif // dtls
658 
659     // Set verification depth.
660     if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
661         q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
662 
663     // set persisted session if the user set it
664     if (!configuration.sessionTicket().isEmpty())
665         sslContext->setSessionASN1(configuration.sessionTicket());
666 
667     // Set temp DH params
668     QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
669 
670     if (!dhparams.isValid()) {
671         sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
672         sslContext->errorCode = QSslError::UnspecifiedError;
673         return;
674     }
675 
676     if (!dhparams.isEmpty()) {
677         const QByteArray &params = dhparams.d->derData;
678         const char *ptr = params.constData();
679         DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr),
680                                 params.length());
681         if (dh == nullptr)
682             qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
683         q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
684         q_DH_free(dh);
685     }
686 
687 #ifndef OPENSSL_NO_PSK
688     if (!client)
689         q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
690 #endif // !OPENSSL_NO_PSK
691 
692     const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
693     if (!qcurves.isEmpty()) {
694 #ifdef OPENSSL_NO_EC
695         sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
696         sslContext->errorCode = QSslError::UnspecifiedError;
697         return;
698 #else
699         // Set the curves to be used.
700         std::vector<int> curves;
701         curves.reserve(qcurves.size());
702         for (const auto &sslCurve : qcurves)
703             curves.push_back(sslCurve.id);
704         if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
705             sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
706             sslContext->errorCode = QSslError::UnspecifiedError;
707             return;
708         }
709 #endif
710     }
711 
712     applyBackendConfig(sslContext);
713 }
714 
715 #if QT_CONFIG(ocsp)
716 extern "C" int qt_OCSP_status_server_callback(SSL *ssl, void *); // Defined in qsslsocket_openssl.cpp.
717 #endif // ocsp
718 // static
applyBackendConfig(QSslContext * sslContext)719 void QSslContext::applyBackendConfig(QSslContext *sslContext)
720 {
721     const QMap<QByteArray, QVariant> &conf = sslContext->sslConfiguration.backendConfiguration();
722     if (conf.isEmpty())
723         return;
724 
725 #if QT_CONFIG(ocsp)
726     auto ocspResponsePos = conf.find("Qt-OCSP-response");
727     if (ocspResponsePos != conf.end()) {
728         // This is our private, undocumented configuration option, existing only for
729         // the purpose of testing OCSP status responses. We don't even check this
730         // callback was set. If no - the test must fail.
731         q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, qt_OCSP_status_server_callback);
732         if (conf.size() == 1)
733             return;
734     }
735 #endif // ocsp
736 
737 #ifndef LIBRESSL_VERSION_NUMBER
738     QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
739     if (cctx) {
740         q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
741         q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
742 
743         for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
744             if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd().
745                 continue;
746 
747             if (!i.value().canConvert(QMetaType::QByteArray)) {
748                 sslContext->errorCode = QSslError::UnspecifiedError;
749                 sslContext->errorStr = msgErrorSettingBackendConfig(
750                 QSslSocket::tr("Expecting QByteArray for %1").arg(
751                                QString::fromUtf8(i.key())));
752                 return;
753             }
754 
755             const QByteArray &value = i.value().toByteArray();
756             const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
757             if (result == 2)
758                 continue;
759 
760             sslContext->errorCode = QSslError::UnspecifiedError;
761             switch (result) {
762             case 0:
763                 sslContext->errorStr = msgErrorSettingBackendConfig(
764                     QSslSocket::tr("An error occurred attempting to set %1 to %2").arg(
765                         QString::fromUtf8(i.key()), QString::fromUtf8(value)));
766                 return;
767             case 1:
768                 sslContext->errorStr = msgErrorSettingBackendConfig(
769                     QSslSocket::tr("Wrong value for %1 (%2)").arg(
770                         QString::fromUtf8(i.key()), QString::fromUtf8(value)));
771                 return;
772             default:
773                 sslContext->errorStr = msgErrorSettingBackendConfig(
774                     QSslSocket::tr("Unrecognized command %1 = %2").arg(
775                         QString::fromUtf8(i.key()), QString::fromUtf8(value)));
776                 return;
777             }
778         }
779 
780         if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
781             sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed"));
782             sslContext->errorCode = QSslError::UnspecifiedError;
783         }
784     } else
785 #endif // LIBRESSL_VERSION_NUMBER
786     {
787         sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed"));
788         sslContext->errorCode = QSslError::UnspecifiedError;
789     }
790 }
791 
792 QT_END_NAMESPACE
793