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 ¶ms = 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