Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtls_openssl.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "qx509_openssl_p.h"
6#include "qtls_openssl_p.h"
7
8#ifdef Q_OS_WIN
10#endif
11
12#include <QtNetwork/private/qsslpresharedkeyauthenticator_p.h>
13#include <QtNetwork/private/qsslcertificate_p.h>
14#include <QtNetwork/private/qocspresponse_p.h>
15#include <QtNetwork/private/qsslsocket_p.h>
16
17#include <QtNetwork/qsslpresharedkeyauthenticator.h>
18
19#include <QtCore/qscopedvaluerollback.h>
20#include <QtCore/qscopeguard.h>
21
22#include <algorithm>
23#include <cstring>
24
26
27using namespace Qt::StringLiterals;
28
29namespace {
30
31QSsl::AlertLevel tlsAlertLevel(int value)
32{
33 using QSsl::AlertLevel;
34
35 if (const char *typeString = q_SSL_alert_type_string(value)) {
36 // Documented to return 'W' for warning, 'F' for fatal,
37 // 'U' for unknown.
38 switch (typeString[0]) {
39 case 'W':
40 return AlertLevel::Warning;
41 case 'F':
42 return AlertLevel::Fatal;
43 default:;
44 }
45 }
46
47 return AlertLevel::Unknown;
48}
49
50QString tlsAlertDescription(int value)
51{
53 if (!description.size())
54 description = "no description provided"_L1;
55 return description;
56}
57
58QSsl::AlertType tlsAlertType(int value)
59{
60 // In case for some reason openssl gives us a value,
61 // which is not in our enum actually, we leave it to
62 // an application to handle (supposedly they have
63 // if or switch-statements).
64 return QSsl::AlertType(value & 0xff);
65}
66
67#ifdef Q_OS_WIN
68
69QSslCertificate findCertificateToFetch(const QList<QSslError> &tlsErrors, bool checkAIA)
70{
71 QSslCertificate certToFetch;
72
73 for (const auto &tlsError : tlsErrors) {
74 switch (tlsError.error()) {
75 case QSslError::UnableToGetLocalIssuerCertificate: // site presented intermediate cert, but root is unknown
76 case QSslError::SelfSignedCertificateInChain: // site presented a complete chain, but root is unknown
77 certToFetch = tlsError.certificate();
78 break;
81 //With these errors, we know it will be untrusted so save time by not asking windows
82 return QSslCertificate{};
83 default:
84#ifdef QSSLSOCKET_DEBUG
85 qCDebug(lcTlsBackend) << tlsError.errorString();
86#endif
87 //TODO - this part is strange.
88 break;
89 }
90 }
91
92 if (checkAIA) {
93 const auto extensions = certToFetch.extensions();
94 for (const auto &ext : extensions) {
95 if (ext.oid() == u"1.3.6.1.5.5.7.1.1") // See RFC 4325
96 return certToFetch;
97 }
98 //The only reason we check this extensions is because an application set trusted
99 //CA certificates explicitly, thus technically disabling CA fetch. So, if it's
100 //the case and an intermediate certificate is missing, and no extensions is
101 //present on the leaf certificate - we fail the handshake immediately.
102 return QSslCertificate{};
103 }
104
105 return certToFetch;
106}
107
108#endif // Q_OS_WIN
109
110} // unnamed namespace
111
112namespace QTlsPrivate {
113
114extern "C" {
115
116int q_X509Callback(int ok, X509_STORE_CTX *ctx)
117{
118 if (!ok) {
119 // Store the error and at which depth the error was detected.
120
121 using ErrorListPtr = QList<QSslErrorEntry> *;
122 ErrorListPtr errors = nullptr;
123
124 // Error list is attached to either 'SSL' or 'X509_STORE'.
125 if (X509_STORE *store = q_X509_STORE_CTX_get0_store(ctx)) // We try store first:
126 errors = ErrorListPtr(q_X509_STORE_get_ex_data(store, 0));
127
128 if (!errors) {
129 // Not found on store? Try SSL and its external data then. According to the OpenSSL's
130 // documentation:
131 //
132 // "Whenever a X509_STORE_CTX object is created for the verification of the
133 // peer's certificate during a handshake, a pointer to the SSL object is
134 // stored into the X509_STORE_CTX object to identify the connection affected.
135 // To retrieve this pointer the X509_STORE_CTX_get_ex_data() function can be
136 // used with the correct index."
139 if (SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data(
141
142 // We may be in a renegotiation, check if we are inside a call to SSL_read:
143 const auto tlsOffset = QTlsBackendOpenSSL::s_indexForSSLExtraData
145 auto tls = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, tlsOffset));
146 Q_ASSERT(tls);
147 if (tls->isInSslRead()) {
148 // We are in a renegotiation, make a note of this for later.
149 // We'll check that the certificate is the same as the one we got during
150 // the initial handshake
151 tls->setRenegotiated(true);
152 return 1;
153 }
154
155 errors = ErrorListPtr(q_SSL_get_ex_data(ssl, offset));
156 }
157 }
158
159 if (!errors) {
160 qCWarning(lcTlsBackend, "Neither X509_STORE, nor SSL contains error list, handshake failure");
161 return 0;
162 }
163
165 }
166 // Always return OK to allow verification to continue. We handle the
167 // errors gracefully after collecting all errors, after verification has
168 // completed.
169 return 1;
170}
171
172int q_X509CallbackDirect(int ok, X509_STORE_CTX *ctx)
173{
174 // Passed to SSL_CTX_set_verify()
175 // https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_verify.html
176 // Returns 0 to abort verification, 1 to continue.
177
178 // This is a new, experimental verification callback, reporting
179 // errors immediately and returning 0 or 1 depending on an application
180 // either ignoring or not ignoring verification errors as they come.
181 if (!ctx) {
182 qCWarning(lcTlsBackend, "Invalid store context (nullptr)");
183 return 0;
184 }
185
186 if (!ok) {
187 // "Whenever a X509_STORE_CTX object is created for the verification of the
188 // peer's certificate during a handshake, a pointer to the SSL object is
189 // stored into the X509_STORE_CTX object to identify the connection affected.
190 // To retrieve this pointer the X509_STORE_CTX_get_ex_data() function can be
191 // used with the correct index."
193 if (!ssl) {
194 qCWarning(lcTlsBackend, "No external data (SSL) found in X509 store object");
195 return 0;
196 }
197
200 auto crypto = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, offset));
201 if (!crypto) {
202 qCWarning(lcTlsBackend, "No external data (TlsCryptographOpenSSL) found in SSL object");
203 return 0;
204 }
205
206 return crypto->emitErrorFromCallback(ctx);
207 }
208 return 1;
209}
210
211#ifndef OPENSSL_NO_PSK
212static unsigned q_ssl_psk_client_callback(SSL *ssl, const char *hint, char *identity, unsigned max_identity_len,
213 unsigned char *psk, unsigned max_psk_len)
214{
216 return tls->pskClientTlsCallback(hint, identity, max_identity_len, psk, max_psk_len);
217}
218
219static unsigned int q_ssl_psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk,
220 unsigned int max_psk_len)
221{
223 Q_ASSERT(tls);
224 return tls->pskServerTlsCallback(identity, psk, max_psk_len);
225}
226
227#ifdef TLS1_3_VERSION
228static unsigned q_ssl_psk_restore_client(SSL *ssl, const char *hint, char *identity, unsigned max_identity_len,
229 unsigned char *psk, unsigned max_psk_len)
230{
231 Q_UNUSED(hint);
232 Q_UNUSED(identity);
233 Q_UNUSED(max_identity_len);
234 Q_UNUSED(psk);
235 Q_UNUSED(max_psk_len);
236
237#ifdef QT_DEBUG
238 auto tls = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, QTlsBackendOpenSSL::s_indexForSSLExtraData));
239 Q_ASSERT(tls);
240 Q_ASSERT(tls->d);
241 Q_ASSERT(tls->d->tlsMode() == QSslSocket::SslClientMode);
242#endif
243 unsigned retVal = 0;
244
245 // Let developers opt-in to having the normal PSK callback get called for TLS 1.3
246 // PSK (which works differently in a few ways, and is called at the start of every connection).
247 // When they do opt-in we just call the old callback from here.
248 if (qEnvironmentVariableIsSet("QT_USE_TLS_1_3_PSK"))
249 retVal = q_ssl_psk_client_callback(ssl, hint, identity, max_identity_len, psk, max_psk_len);
250
252
253 return retVal;
254}
255
256static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id,
257 size_t *idlen, SSL_SESSION **sess)
258{
259 Q_UNUSED(md);
260 Q_UNUSED(id);
261 Q_UNUSED(idlen);
262 Q_UNUSED(sess);
263
264#ifdef QT_DEBUG
265 auto *tls = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, QTlsBackendOpenSSL::s_indexForSSLExtraData));
266 Q_ASSERT(tls);
267 Q_ASSERT(tls->d);
268 Q_ASSERT(tls->d->tlsMode() == QSslSocket::SslClientMode);
269#endif
270
271 // Temporarily rebind the psk because it will be called next. The function will restore it.
272 q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_restore_client);
273
274 return 1; // need to return 1 or else "the connection setup fails."
275}
276
277int q_ssl_sess_set_new_cb(SSL *ssl, SSL_SESSION *session)
278{
279 if (!ssl) {
280 qCWarning(lcTlsBackend, "Invalid SSL (nullptr)");
281 return 0;
282 }
283 if (!session) {
284 qCWarning(lcTlsBackend, "Invalid SSL_SESSION (nullptr)");
285 return 0;
286 }
287
288 auto *tls = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, QTlsBackendOpenSSL::s_indexForSSLExtraData));
289 Q_ASSERT(tls);
290 return tls->handleNewSessionTicket(ssl);
291}
292#endif // TLS1_3_VERSION
293
294#endif // !OPENSSL_NO_PSK
295
296#if QT_CONFIG(ocsp)
297
298int qt_OCSP_status_server_callback(SSL *ssl, void *ocspRequest)
299{
300 Q_UNUSED(ocspRequest);
301 if (!ssl)
302 return SSL_TLSEXT_ERR_ALERT_FATAL;
303
304 auto crypto = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, QTlsBackendOpenSSL::s_indexForSSLExtraData));
305 if (!crypto)
306 return SSL_TLSEXT_ERR_ALERT_FATAL;
307
308 Q_ASSERT(crypto->d);
309 Q_ASSERT(crypto->d->tlsMode() == QSslSocket::SslServerMode);
310 const QByteArray &response = crypto->ocspResponseDer;
311 Q_ASSERT(response.size());
312
313 unsigned char *derCopy = static_cast<unsigned char *>(q_OPENSSL_malloc(size_t(response.size())));
314 if (!derCopy)
315 return SSL_TLSEXT_ERR_ALERT_FATAL;
316
317 std::copy(response.data(), response.data() + response.size(), derCopy);
318 // We don't check the return value: internally OpenSSL simply assigns the
319 // pointer (it assumes it now owns this memory btw!) and the length.
320 q_SSL_set_tlsext_status_ocsp_resp(ssl, derCopy, response.size());
321
322 return SSL_TLSEXT_ERR_OK;
323}
324
325#endif // ocsp
326
327void qt_AlertInfoCallback(const SSL *connection, int from, int value)
328{
329 // Passed to SSL_set_info_callback()
330 // https://www.openssl.org/docs/man1.1.1/man3/SSL_set_info_callback.html
331
332 if (!connection) {
333#ifdef QSSLSOCKET_DEBUG
334 qCWarning(lcTlsBackend, "Invalid 'connection' parameter (nullptr)");
335#endif // QSSLSOCKET_DEBUG
336 return;
337 }
338
341 auto crypto = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(connection, offset));
342 if (!crypto) {
343 // SSL_set_ex_data can fail:
344#ifdef QSSLSOCKET_DEBUG
345 qCWarning(lcTlsBackend, "No external data (socket backend) found for parameter 'connection'");
346#endif // QSSLSOCKET_DEBUG
347 return;
348 }
349
350 if (!(from & SSL_CB_ALERT)) {
351 // We only want to know about alerts (at least for now).
352 return;
353 }
354
355 if (from & SSL_CB_WRITE)
356 crypto->alertMessageSent(value);
357 else
358 crypto->alertMessageReceived(value);
359}
360
361} // extern "C"
362
363#if QT_CONFIG(ocsp)
364namespace {
365
366QSslError::SslError qt_OCSP_response_status_to_SslError(long code)
367{
368 switch (code) {
369 case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
371 case OCSP_RESPONSE_STATUS_INTERNALERROR:
373 case OCSP_RESPONSE_STATUS_TRYLATER:
375 case OCSP_RESPONSE_STATUS_SIGREQUIRED:
377 case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
379 case OCSP_RESPONSE_STATUS_SUCCESSFUL:
380 default:
381 return {};
382 }
383 Q_UNREACHABLE();
384}
385
386QOcspRevocationReason qt_OCSP_revocation_reason(int reason)
387{
388 switch (reason) {
389 case OCSP_REVOKED_STATUS_NOSTATUS:
391 case OCSP_REVOKED_STATUS_UNSPECIFIED:
393 case OCSP_REVOKED_STATUS_KEYCOMPROMISE:
395 case OCSP_REVOKED_STATUS_CACOMPROMISE:
397 case OCSP_REVOKED_STATUS_AFFILIATIONCHANGED:
399 case OCSP_REVOKED_STATUS_SUPERSEDED:
401 case OCSP_REVOKED_STATUS_CESSATIONOFOPERATION:
403 case OCSP_REVOKED_STATUS_CERTIFICATEHOLD:
405 case OCSP_REVOKED_STATUS_REMOVEFROMCRL:
407 default:
409 }
410
411 Q_UNREACHABLE();
412}
413
414bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert, X509 *issuer)
415{
416 // OCSP_basic_verify does verify that the responder is legit, the response is
417 // correctly signed, CertID is correct. But it does not know which certificate
418 // we were presented with by our peer, so it does not check if it's a response
419 // for our peer's certificate.
420 Q_ASSERT(singleResponse && peerCert && issuer);
421
422 const OCSP_CERTID *certId = q_OCSP_SINGLERESP_get0_id(singleResponse); // Does not increment refcount.
423 if (!certId) {
424 qCWarning(lcTlsBackend, "A SingleResponse without CertID");
425 return false;
426 }
427
428 ASN1_OBJECT *md = nullptr;
429 ASN1_INTEGER *reportedSerialNumber = nullptr;
430 const int result = q_OCSP_id_get0_info(nullptr, &md, nullptr, &reportedSerialNumber, const_cast<OCSP_CERTID *>(certId));
431 if (result != 1 || !md || !reportedSerialNumber) {
432 qCWarning(lcTlsBackend, "Failed to extract a hash and serial number from CertID structure");
433 return false;
434 }
435
436 if (!q_X509_get_serialNumber(peerCert)) {
437 // Is this possible at all? But we have to check this,
438 // ASN1_INTEGER_cmp (called from OCSP_id_cmp) dereferences
439 // without any checks at all.
440 qCWarning(lcTlsBackend, "No serial number in peer's ceritificate");
441 return false;
442 }
443
444 const int nid = q_OBJ_obj2nid(md);
445 if (nid == NID_undef) {
446 qCWarning(lcTlsBackend, "Unknown hash algorithm in CertID");
447 return false;
448 }
449
450 const EVP_MD *digest = q_EVP_get_digestbynid(nid); // Does not increment refcount.
451 if (!digest) {
452 qCWarning(lcTlsBackend) << "No digest for nid" << nid;
453 return false;
454 }
455
456 OCSP_CERTID *recreatedId = q_OCSP_cert_to_id(digest, peerCert, issuer);
457 if (!recreatedId) {
458 qCWarning(lcTlsBackend, "Failed to re-create CertID");
459 return false;
460 }
461 const QSharedPointer<OCSP_CERTID> guard(recreatedId, q_OCSP_CERTID_free);
462
463 if (q_OCSP_id_cmp(const_cast<OCSP_CERTID *>(certId), recreatedId)) {
464 qCDebug(lcTlsBackend, "Certificate ID mismatch");
465 return false;
466 }
467 // Bingo!
468 return true;
469}
470
471} // unnamed namespace
472#endif // ocsp
473
475{
476 destroySslContext();
477}
478
480{
481 Q_ASSERT(qObj);
482 Q_ASSERT(dObj);
483 q = qObj;
484 d = dObj;
485
486 ocspResponses.clear();
488
489 systemOrSslErrorDetected = false;
490 handshakeInterrupted = false;
491
492 fetchAuthorityInformation = false;
493 caToFetch.reset();
494}
495
496void TlsCryptographOpenSSL::checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext)
497{
498 if (!sslContextPointer)
499 sslContextPointer = std::move(tlsContext);
500}
501
502std::shared_ptr<QSslContext> TlsCryptographOpenSSL::sslContext() const
503{
504 return sslContextPointer;
505}
506
507QList<QSslError> TlsCryptographOpenSSL::tlsErrors() const
508{
509 return sslErrors;
510}
511
513{
514 if (!initSslContext()) {
515 Q_ASSERT(d);
516 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
517 QSslSocket::tr("Unable to init SSL Context: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
518 return;
519 }
520
521 // Start connecting. This will place outgoing data in the BIO, so we
522 // follow up with calling transmit().
524 transmit();
525}
526
528{
529 if (!initSslContext()) {
530 Q_ASSERT(d);
531 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
532 QSslSocket::tr("Unable to init SSL Context: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
533 return;
534 }
535
536 // Start connecting. This will place outgoing data in the BIO, so we
537 // follow up with calling transmit().
539 transmit();
540}
541
543{
544 // Check if the connection has been established. Get all errors from the
545 // verification stage.
546 Q_ASSERT(q);
547 Q_ASSERT(d);
548
549 using ScopedBool = QScopedValueRollback<bool>;
550
551 if (inSetAndEmitError)
552 return false;
553
554 const auto mode = d->tlsMode();
555
556 pendingFatalAlert = false;
557 errorsReportedFromCallback = false;
558 QList<QSslErrorEntry> lastErrors;
560
561 // SSL_set_ex_data can fail, but see the callback's code - we handle this there.
564
567 // Note, unlike errors as external data on SSL object, we do not unset
568 // a callback/ex-data if alert notifications are enabled: an alert can
569 // arrive after the handshake, for example, this happens when the server
570 // does not find a ClientCert or does not like it.
571
572 if (!lastErrors.isEmpty() || errorsReportedFromCallback)
574
575 // storePeerCertificate() if called above - would update the
576 // configuration with peer's certificates.
577 auto configuration = q->sslConfiguration();
578 if (!errorsReportedFromCallback) {
579 const auto &peerCertificateChain = configuration.peerCertificateChain();
580 for (const auto &currentError : std::as_const(lastErrors)) {
582 peerCertificateChain.value(currentError.depth)));
583 if (q->state() != QAbstractSocket::ConnectedState)
584 break;
585 }
586 }
587
588 errorList << lastErrors;
589
590 // Connection aborted during handshake phase.
591 if (q->state() != QAbstractSocket::ConnectedState)
592 return false;
593
594 // Check if we're encrypted or not.
595 if (result <= 0) {
596 switch (q_SSL_get_error(ssl, result)) {
597 case SSL_ERROR_WANT_READ:
598 case SSL_ERROR_WANT_WRITE:
599 // The handshake is not yet complete.
600 break;
601 default:
603#ifdef QSSLSOCKET_DEBUG
604 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::startHandshake: error!" << errorString;
605#endif
606 {
607 const ScopedBool bg(inSetAndEmitError, true);
608 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, errorString);
609 if (pendingFatalAlert) {
611 pendingFatalAlert = false;
612 }
613 }
614 q->abort();
615 }
616 return false;
617 }
618
619 // store peer certificate chain
621
622 // Start translating errors.
623 QList<QSslError> errors;
624
625 // Note, the storePeerCerificates() probably updated the configuration at this point.
626 configuration = q->sslConfiguration();
627 // Check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer)
628 const auto &peerCertificateChain = configuration.peerCertificateChain();
629 for (const QSslCertificate &cert : peerCertificateChain) {
632 errors << error;
633 emit q->peerVerifyError(error);
634 if (q->state() != QAbstractSocket::ConnectedState)
635 return false;
636 }
637 }
638
639 const bool doVerifyPeer = configuration.peerVerifyMode() == QSslSocket::VerifyPeer
640 || (configuration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
642
643#if QT_CONFIG(ocsp)
644 // For now it's always QSslSocket::SslClientMode - initSslContext() will bail out early,
645 // if it's enabled in QSslSocket::SslServerMode. This can change.
646 if (!configuration.peerCertificate().isNull() && configuration.ocspStaplingEnabled() && doVerifyPeer) {
647 if (!checkOcspStatus()) {
648 if (ocspErrors.isEmpty()) {
649 {
650 const ScopedBool bg(inSetAndEmitError, true);
651 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, ocspErrorDescription);
652 }
653 q->abort();
654 return false;
655 }
656
657 for (const QSslError &error : ocspErrors) {
658 errors << error;
659 emit q->peerVerifyError(error);
660 if (q->state() != QAbstractSocket::ConnectedState)
661 return false;
662 }
663 }
664 }
665#endif // ocsp
666
667 // Check the peer certificate itself. First try the subject's common name
668 // (CN) as a wildcard, then try all alternate subject name DNS entries the
669 // same way.
670 if (!configuration.peerCertificate().isNull()) {
671 // but only if we're a client connecting to a server
672 // if we're the server, don't check CN
673 const auto verificationPeerName = d->verificationName();
675 QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
676
677 if (!isMatchingHostname(configuration.peerCertificate(), peerName)) {
678 // No matches in common names or alternate names.
679 QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate());
680 errors << error;
681 emit q->peerVerifyError(error);
682 if (q->state() != QAbstractSocket::ConnectedState)
683 return false;
684 }
685 }
686 } else {
687 // No peer certificate presented. Report as error if the socket
688 // expected one.
689 if (doVerifyPeer) {
691 errors << error;
692 emit q->peerVerifyError(error);
693 if (q->state() != QAbstractSocket::ConnectedState)
694 return false;
695 }
696 }
697
698 // Translate errors from the error list into QSslErrors.
699 errors.reserve(errors.size() + errorList.size());
700 for (const auto &error : std::as_const(errorList))
701 errors << X509CertificateOpenSSL::openSSLErrorToQSslError(error.code, peerCertificateChain.value(error.depth));
702
703 if (!errors.isEmpty()) {
704 sslErrors = errors;
705#ifdef Q_OS_WIN
708 // !fetchEnabled is a special case scenario, when we potentially have a missing
709 // intermediate certificate and a recoverable chain, but on demand cert loading
710 // was disabled by setCaCertificates call. For this scenario we check if "Authority
711 // Information Access" is present - wincrypt can deal with such certificates.
712 QSslCertificate certToFetch;
713 if (doVerifyPeer && !d->verifyErrorsHaveBeenIgnored())
714 certToFetch = findCertificateToFetch(sslErrors, !fetchEnabled);
715
716 //Skip this if not using system CAs, or if the SSL errors are configured in advance to be ignorable
717 if (!certToFetch.isNull()) {
718 fetchAuthorityInformation = !fetchEnabled;
719 //Windows desktop versions starting from vista ship with minimal set of roots and download on demand
720 //from the windows update server CA roots that are trusted by MS. It also can fetch a missing intermediate
721 //in case "Authority Information Access" extension is present.
722 //
723 //However, this is only transparent if using WinINET - we have to trigger it
724 //ourselves.
725 fetchCaRootForCert(certToFetch);
726 return false;
727 }
728#endif // Q_OS_WIN
729 if (!checkSslErrors())
730 return false;
731 // A slot, attached to sslErrors signal can call
732 // abort/close/disconnetFromHost/etc; no need to
733 // continue handshake then.
734 if (q->state() != QAbstractSocket::ConnectedState)
735 return false;
736 } else {
737 sslErrors.clear();
738 }
739
741 return true;
742}
743
745{
746 handshakeInterrupted = false;
747}
748
750{
751 fetchAuthorityInformation = false;
752 caToFetch.reset();
753}
754
756{
757 Q_ASSERT(q);
758 Q_ASSERT(d);
759
760 auto *plainSocket = d->plainTcpSocket();
761 Q_ASSERT(plainSocket);
762
763 const auto mode = d->tlsMode();
764
765 // if we have a max read buffer size, reset the plain socket's to match
766 if (const auto maxSize = d->maxReadBufferSize())
767 plainSocket->setReadBufferSize(maxSize);
768
769 if (q_SSL_session_reused(ssl))
770 QTlsBackend::setPeerSessionShared(d, true);
771
772#ifdef QT_DECRYPT_SSL_TRAFFIC
773 if (q_SSL_get_session(ssl)) {
774 size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), nullptr, 0);
775 size_t client_random_len = q_SSL_get_client_random(ssl, nullptr, 0);
776 QByteArray masterKey(int(master_key_len), Qt::Uninitialized); // Will not overflow
777 QByteArray clientRandom(int(client_random_len), Qt::Uninitialized); // Will not overflow
778
780 reinterpret_cast<unsigned char*>(masterKey.data()),
781 masterKey.size());
782 q_SSL_get_client_random(ssl, reinterpret_cast<unsigned char *>(clientRandom.data()),
783 clientRandom.size());
784
785 QByteArray debugLineClientRandom("CLIENT_RANDOM ");
786 debugLineClientRandom.append(clientRandom.toHex().toUpper());
787 debugLineClientRandom.append(" ");
788 debugLineClientRandom.append(masterKey.toHex().toUpper());
789 debugLineClientRandom.append("\n");
790
791 QString sslKeyFile = QDir::tempPath() + "/qt-ssl-keys"_L1;
792 QFile file(sslKeyFile);
794 qCWarning(lcTlsBackend) << "could not open file" << sslKeyFile << "for appending";
795 if (!file.write(debugLineClientRandom))
796 qCWarning(lcTlsBackend) << "could not write to file" << sslKeyFile;
797 file.close();
798 } else {
799 qCWarning(lcTlsBackend, "could not decrypt SSL traffic");
800 }
801#endif // QT_DECRYPT_SSL_TRAFFIC
802
803 const auto &configuration = q->sslConfiguration();
804 // Cache this SSL session inside the QSslContext
805 if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionSharing))) {
806 if (!sslContextPointer->cacheSession(ssl)) {
807 sslContextPointer.reset(); // we could not cache the session
808 } else {
809 // Cache the session for permanent usage as well
810 if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionPersistence))) {
811 if (!sslContextPointer->sessionASN1().isEmpty())
812 QTlsBackend::setSessionAsn1(d, sslContextPointer->sessionASN1());
813 QTlsBackend::setSessionLifetimeHint(d, sslContextPointer->sessionTicketLifeTimeHint());
814 }
815 }
816 }
817
818#if !defined(OPENSSL_NO_NEXTPROTONEG)
819
820 QTlsBackend::setAlpnStatus(d, sslContextPointer->npnContext().status);
821 if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
822 // we could not agree -> be conservative and use HTTP/1.1
823 // T.P.: I have to admit, this is a really strange notion of 'conservative',
824 // given the protocol-neutral nature of ALPN/NPN.
825 QTlsBackend::setNegotiatedProtocol(d, QByteArrayLiteral("http/1.1"));
826 } else {
827 const unsigned char *proto = nullptr;
828 unsigned int proto_len = 0;
829
830 q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
831 if (proto_len && mode == QSslSocket::SslClientMode) {
832 // Client does not have a callback that sets it ...
833 QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
834 }
835
836 if (!proto_len) { // Test if NPN was more lucky ...
837 q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
838 }
839
840 if (proto_len)
841 QTlsBackend::setNegotiatedProtocol(d, QByteArray(reinterpret_cast<const char *>(proto), proto_len));
842 else
843 QTlsBackend::setNegotiatedProtocol(d,{});
844 }
845#endif // !defined(OPENSSL_NO_NEXTPROTONEG)
846
848 EVP_PKEY *key;
849 if (q_SSL_get_server_tmp_key(ssl, &key))
850 QTlsBackend::setEphemeralKey(d, QSslKey(key, QSsl::PublicKey));
851 }
852
853 d->setEncrypted(true);
854 emit q->encrypted();
856 d->setPendingClose(false);
857 q->disconnectFromHost();
858 }
859}
860
862{
863 Q_ASSERT(q);
864 Q_ASSERT(d);
865
866 using ScopedBool = QScopedValueRollback<bool>;
867
868 if (inSetAndEmitError)
869 return;
870
871 // If we don't have any SSL context, don't bother transmitting.
872 if (!ssl)
873 return;
874
875 auto &writeBuffer = d->tlsWriteBuffer();
876 auto &buffer = d->tlsBuffer();
877 auto *plainSocket = d->plainTcpSocket();
878 Q_ASSERT(plainSocket);
879 bool &emittedBytesWritten = d->tlsEmittedBytesWritten();
880
881 bool transmitting;
882 do {
883 transmitting = false;
884
885 // If the connection is secure, we can transfer data from the write
886 // buffer (in plain text) to the write BIO through SSL_write.
887 if (q->isEncrypted() && !writeBuffer.isEmpty()) {
888 qint64 totalBytesWritten = 0;
889 int nextDataBlockSize;
890 while ((nextDataBlockSize = writeBuffer.nextDataBlockSize()) > 0) {
891 int writtenBytes = q_SSL_write(ssl, writeBuffer.readPointer(), nextDataBlockSize);
892 if (writtenBytes <= 0) {
893 int error = q_SSL_get_error(ssl, writtenBytes);
894 //write can result in a want_write_error - not an error - continue transmitting
895 if (error == SSL_ERROR_WANT_WRITE) {
896 transmitting = true;
897 break;
898 } else if (error == SSL_ERROR_WANT_READ) {
899 //write can result in a want_read error, possibly due to renegotiation - not an error - stop transmitting
900 transmitting = false;
901 break;
902 } else {
903 // ### Better error handling.
904 const ScopedBool bg(inSetAndEmitError, true);
905 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
906 QSslSocket::tr("Unable to write data: %1").arg(
908 return;
909 }
910 }
911#ifdef QSSLSOCKET_DEBUG
912 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: encrypted" << writtenBytes << "bytes";
913#endif
914 writeBuffer.free(writtenBytes);
915 totalBytesWritten += writtenBytes;
916
917 if (writtenBytes < nextDataBlockSize) {
918 // break out of the writing loop and try again after we had read
919 transmitting = true;
920 break;
921 }
922 }
923
924 if (totalBytesWritten > 0) {
925 // Don't emit bytesWritten() recursively.
926 if (!emittedBytesWritten) {
927 emittedBytesWritten = true;
928 emit q->bytesWritten(totalBytesWritten);
929 emittedBytesWritten = false;
930 }
931 emit q->channelBytesWritten(0, totalBytesWritten);
932 }
933 }
934
935 // Check if we've got any data to be written to the socket.
936 QVarLengthArray<char, 4096> data;
937 int pendingBytes;
938 while (plainSocket->isValid() && (pendingBytes = q_BIO_pending(writeBio)) > 0
939 && plainSocket->openMode() != QIODevice::NotOpen) {
940 // Read encrypted data from the write BIO into a buffer.
941 data.resize(pendingBytes);
942 int encryptedBytesRead = q_BIO_read(writeBio, data.data(), pendingBytes);
943
944 // Write encrypted data from the buffer to the socket.
945 qint64 actualWritten = plainSocket->write(data.constData(), encryptedBytesRead);
946#ifdef QSSLSOCKET_DEBUG
947 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: wrote" << encryptedBytesRead
948 << "encrypted bytes to the socket" << actualWritten << "actual.";
949#endif
950 if (actualWritten < 0) {
951 //plain socket write fails if it was in the pending close state.
952 const ScopedBool bg(inSetAndEmitError, true);
953 setErrorAndEmit(d, plainSocket->error(), plainSocket->errorString());
954 return;
955 }
956 transmitting = true;
957 }
958
959 // Check if we've got any data to be read from the socket.
960 if (!q->isEncrypted() || !d->maxReadBufferSize() || buffer.size() < d->maxReadBufferSize())
961 while ((pendingBytes = plainSocket->bytesAvailable()) > 0) {
962 // Read encrypted data from the socket into a buffer.
963 data.resize(pendingBytes);
964 // just peek() here because q_BIO_write could write less data than expected
965 int encryptedBytesRead = plainSocket->peek(data.data(), pendingBytes);
966
967#ifdef QSSLSOCKET_DEBUG
968 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: read" << encryptedBytesRead << "encrypted bytes from the socket";
969#endif
970 // Write encrypted data from the buffer into the read BIO.
971 int writtenToBio = q_BIO_write(readBio, data.constData(), encryptedBytesRead);
972
973 // Throw away the results.
974 if (writtenToBio > 0) {
975 plainSocket->skip(writtenToBio);
976 } else {
977 // ### Better error handling.
978 const ScopedBool bg(inSetAndEmitError, true);
979 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
980 QSslSocket::tr("Unable to decrypt data: %1")
982 return;
983 }
984
985 transmitting = true;
986 }
987
988 // If the connection isn't secured yet, this is the time to retry the
989 // connect / accept.
990 if (!q->isEncrypted()) {
991#ifdef QSSLSOCKET_DEBUG
992 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: testing encryption";
993#endif
994 if (startHandshake()) {
995#ifdef QSSLSOCKET_DEBUG
996 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: encryption established";
997#endif
998 d->setEncrypted(true);
999 transmitting = true;
1000 } else if (plainSocket->state() != QAbstractSocket::ConnectedState) {
1001#ifdef QSSLSOCKET_DEBUG
1002 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: connection lost";
1003#endif
1004 break;
1005 } else if (d->isPaused()) {
1006 // just wait until the user continues
1007 return;
1008 } else {
1009#ifdef QSSLSOCKET_DEBUG
1010 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: encryption not done yet";
1011#endif
1012 }
1013 }
1014
1015 // If the request is small and the remote host closes the transmission
1016 // after sending, there's a chance that startHandshake() will already
1017 // have triggered a shutdown.
1018 if (!ssl)
1019 continue;
1020
1021 // We always read everything from the SSL decryption buffers, even if
1022 // we have a readBufferMaxSize. There's no point in leaving data there
1023 // just so that readBuffer.size() == readBufferMaxSize.
1024 int readBytes = 0;
1025 const int bytesToRead = 4096;
1026 do {
1027 if (q->readChannelCount() == 0) {
1028 // The read buffer is deallocated, don't try resize or write to it.
1029 break;
1030 }
1031 // Don't use SSL_pending(). It's very unreliable.
1032 inSslRead = true;
1033 readBytes = q_SSL_read(ssl, buffer.reserve(bytesToRead), bytesToRead);
1034 inSslRead = false;
1035 if (renegotiated) {
1036 renegotiated = false;
1037 X509 *x509 = q_SSL_get_peer_certificate(ssl);
1038 const auto peerCertificate =
1040 // Fail the renegotiate if the certificate has changed, else: continue.
1041 if (peerCertificate != q->peerCertificate()) {
1042 const ScopedBool bg(inSetAndEmitError, true);
1043 setErrorAndEmit(
1045 QSslSocket::tr(
1046 "TLS certificate unexpectedly changed during renegotiation!"));
1047 q->abort();
1048 return;
1049 }
1050 }
1051 if (readBytes > 0) {
1052#ifdef QSSLSOCKET_DEBUG
1053 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: decrypted" << readBytes << "bytes";
1054#endif
1055 buffer.chop(bytesToRead - readBytes);
1056
1057 if (bool *readyReadEmittedPointer = d->readyReadPointer())
1058 *readyReadEmittedPointer = true;
1059 emit q->readyRead();
1060 emit q->channelReadyRead(0);
1061 transmitting = true;
1062 continue;
1063 }
1064 buffer.chop(bytesToRead);
1065
1066 // Error.
1067 switch (q_SSL_get_error(ssl, readBytes)) {
1068 case SSL_ERROR_WANT_READ:
1069 case SSL_ERROR_WANT_WRITE:
1070 // Out of data.
1071 break;
1072 case SSL_ERROR_ZERO_RETURN:
1073 // The remote host closed the connection.
1074#ifdef QSSLSOCKET_DEBUG
1075 qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: remote disconnect";
1076#endif
1077 shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
1078 {
1079 const ScopedBool bg(inSetAndEmitError, true);
1081 QSslSocket::tr("The TLS/SSL connection has been closed"));
1082 }
1083 return;
1084 case SSL_ERROR_SYSCALL: // some IO error
1085 case SSL_ERROR_SSL: // error in the SSL library
1086 // we do not know exactly what the error is, nor whether we can recover from it,
1087 // so just return to prevent an endless loop in the outer "while" statement
1088 systemOrSslErrorDetected = true;
1089 {
1090 const ScopedBool bg(inSetAndEmitError, true);
1091 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
1092 QSslSocket::tr("Error while reading: %1")
1094 }
1095 return;
1096 default:
1097 // SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a
1098 // BIO_s_connect() or BIO_s_accept(), which we do not call.
1099 // SSL_ERROR_WANT_X509_LOOKUP: can only happen with a
1100 // SSL_CTX_set_client_cert_cb(), which we do not call.
1101 // So this default case should never be triggered.
1102 {
1103 const ScopedBool bg(inSetAndEmitError, true);
1104 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
1105 QSslSocket::tr("Error while reading: %1")
1107 }
1108 break;
1109 }
1110 } while (ssl && readBytes > 0);
1111 } while (ssl && transmitting);
1112}
1113
1115{
1116 if (ssl) {
1117 if (!shutdown && !q_SSL_in_init(ssl) && !systemOrSslErrorDetected) {
1118 if (q_SSL_shutdown(ssl) != 1) {
1119 // Some error may be queued, clear it.
1121 }
1122 shutdown = true;
1123 transmit();
1124 }
1125 }
1126 Q_ASSERT(d);
1127 auto *plainSocket = d->plainTcpSocket();
1128 Q_ASSERT(plainSocket);
1129 plainSocket->disconnectFromHost();
1130}
1131
1133{
1134 Q_ASSERT(d);
1135 auto *plainSocket = d->plainTcpSocket();
1136 Q_ASSERT(plainSocket);
1137 d->setEncrypted(false);
1138
1139 if (plainSocket->bytesAvailable() <= 0) {
1140 destroySslContext();
1141 } else {
1142 // Move all bytes into the plain buffer.
1143 const qint64 tmpReadBufferMaxSize = d->maxReadBufferSize();
1144 // Reset temporarily, so the plain socket buffer is completely drained:
1146 transmit();
1147 d->setMaxReadBufferSize(tmpReadBufferMaxSize);
1148 }
1149 //if there is still buffered data in the plain socket, don't destroy the ssl context yet.
1150 //it will be destroyed when the socket is deleted.
1151}
1152
1161
1163{
1164 if (!ssl)
1165 return QSsl::UnknownProtocol;
1166
1167 const int ver = q_SSL_version(ssl);
1168 switch (ver) {
1171 case 0x301:
1172 return QSsl::TlsV1_0;
1173 case 0x302:
1174 return QSsl::TlsV1_1;
1176 case 0x303:
1177 return QSsl::TlsV1_2;
1178 case 0x304:
1179 return QSsl::TlsV1_3;
1180 }
1181
1182 return QSsl::UnknownProtocol;
1183}
1184
1185QList<QOcspResponse> TlsCryptographOpenSSL::ocsps() const
1186{
1187 return ocspResponses;
1188}
1189
1191{
1192 Q_ASSERT(q);
1193 Q_ASSERT(d);
1194
1195 if (sslErrors.isEmpty())
1196 return true;
1197
1198 emit q->sslErrors(sslErrors);
1199
1200 const auto vfyMode = q->peerVerifyMode();
1201 const auto mode = d->tlsMode();
1202
1203 bool doVerifyPeer = vfyMode == QSslSocket::VerifyPeer || (vfyMode == QSslSocket::AutoVerifyPeer
1205 bool doEmitSslError = !d->verifyErrorsHaveBeenIgnored();
1206 // check whether we need to emit an SSL handshake error
1207 if (doVerifyPeer && doEmitSslError) {
1208 if (q->pauseMode() & QAbstractSocket::PauseOnSslErrors) {
1210 d->setPaused(true);
1211 } else {
1212 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
1213 auto *plainSocket = d->plainTcpSocket();
1214 Q_ASSERT(plainSocket);
1215 plainSocket->disconnectFromHost();
1216 }
1217 return false;
1218 }
1219 return true;
1220}
1221
1223{
1224 // If we return 1, this means we own the session, but we don't.
1225 // 0 would tell OpenSSL to deref (but they still have it in the
1226 // internal cache).
1228
1229 Q_ASSERT(q);
1230 Q_ASSERT(d);
1231
1232 if (q->sslConfiguration().testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
1233 // We silently ignore, do nothing, remove from cache.
1234 return 0;
1235 }
1236
1237 SSL_SESSION *currentSession = q_SSL_get_session(connection);
1238 if (!currentSession) {
1239 qCWarning(lcTlsBackend,
1240 "New session ticket callback, the session is invalid (nullptr)");
1241 return 0;
1242 }
1243
1244 if (q_SSL_version(connection) < 0x304) {
1245 // We only rely on this mechanics with TLS >= 1.3
1246 return 0;
1247 }
1248
1249#ifdef TLS1_3_VERSION
1250 if (!q_SSL_SESSION_is_resumable(currentSession)) {
1251 qCDebug(lcTlsBackend, "New session ticket, but the session is non-resumable");
1252 return 0;
1253 }
1254#endif // TLS1_3_VERSION
1255
1256 const int sessionSize = q_i2d_SSL_SESSION(currentSession, nullptr);
1257 if (sessionSize <= 0) {
1258 qCWarning(lcTlsBackend, "could not store persistent version of SSL session");
1259 return 0;
1260 }
1261
1262 // We have somewhat perverse naming, it's not a ticket, it's a session.
1263 QByteArray sessionTicket(sessionSize, 0);
1264 auto data = reinterpret_cast<unsigned char *>(sessionTicket.data());
1265 if (!q_i2d_SSL_SESSION(currentSession, &data)) {
1266 qCWarning(lcTlsBackend, "could not store persistent version of SSL session");
1267 return 0;
1268 }
1269
1270 QTlsBackend::setSessionAsn1(d, sessionTicket);
1271 QTlsBackend::setSessionLifetimeHint(d, q_SSL_SESSION_get_ticket_lifetime_hint(currentSession));
1272
1273 emit q->newSessionTicketReceived();
1274 return 0;
1275}
1276
1278{
1279 Q_ASSERT(q);
1280 Q_ASSERT(d);
1281
1282 const auto level = tlsAlertLevel(value);
1283 if (level == QSsl::AlertLevel::Fatal && !q->isEncrypted()) {
1284 // Note, this logic is handshake-time only:
1285 pendingFatalAlert = true;
1286 }
1287
1288 emit q->alertSent(level, tlsAlertType(value), tlsAlertDescription(value));
1289
1290}
1291
1293{
1294 Q_ASSERT(q);
1295
1296 emit q->alertReceived(tlsAlertLevel(value), tlsAlertType(value), tlsAlertDescription(value));
1297}
1298
1300{
1301 // Returns 0 to abort verification, 1 to continue despite error (as
1302 // OpenSSL expects from the verification callback).
1303 Q_ASSERT(q);
1304 Q_ASSERT(ctx);
1305
1306 using ScopedBool = QScopedValueRollback<bool>;
1307 // While we are not setting, we are emitting and in general -
1308 // we want to prevent accidental recursive startHandshake()
1309 // calls:
1310 const ScopedBool bg(inSetAndEmitError, true);
1311
1313 if (!x509) {
1314 qCWarning(lcTlsBackend, "Could not obtain the certificate (that failed to verify)");
1315 return 0;
1316 }
1317
1320 const QSslError tlsError = QTlsPrivate::X509CertificateOpenSSL::openSSLErrorToQSslError(errorAndDepth.code, certificate);
1321
1322 errorsReportedFromCallback = true;
1323 handshakeInterrupted = true;
1324 emit q->handshakeInterruptedOnError(tlsError);
1325
1326 // Conveniently so, we also can access 'lastErrors' external data set
1327 // in startHandshake, we store it for the case an application later
1328 // wants to check errors (ignored or not):
1331 if (auto errorList = static_cast<QList<QSslErrorEntry> *>(q_SSL_get_ex_data(ssl, offset)))
1332 errorList->append(errorAndDepth);
1333
1334 // An application is expected to ignore this error (by calling ignoreSslErrors)
1335 // in its directly connected slot:
1336 return !handshakeInterrupted;
1337}
1338
1340{
1341 Q_ASSERT(pendingFatalAlert);
1342 Q_ASSERT(d);
1343
1344 auto *plainSocket = d->plainTcpSocket();
1345
1346 pendingFatalAlert = false;
1347 QVarLengthArray<char, 4096> data;
1348 int pendingBytes = 0;
1349 while (plainSocket->isValid() && (pendingBytes = q_BIO_pending(writeBio)) > 0
1350 && plainSocket->openMode() != QIODevice::NotOpen) {
1351 // Read encrypted data from the write BIO into a buffer.
1352 data.resize(pendingBytes);
1353 const int bioReadBytes = q_BIO_read(writeBio, data.data(), pendingBytes);
1354
1355 // Write encrypted data from the buffer to the socket.
1356 qint64 actualWritten = plainSocket->write(data.constData(), bioReadBytes);
1357 if (actualWritten < 0)
1358 return;
1359 plainSocket->flush();
1360 }
1361}
1362
1363bool TlsCryptographOpenSSL::initSslContext()
1364{
1365 Q_ASSERT(q);
1366 Q_ASSERT(d);
1367
1368 // If no external context was set (e.g. by QHttpNetworkConnection) we will
1369 // create a new one.
1370 const auto mode = d->tlsMode();
1371 const auto configuration = q->sslConfiguration();
1372 if (!sslContextPointer)
1373 sslContextPointer = QSslContext::sharedFromConfiguration(mode, configuration, d->isRootsOnDemandAllowed());
1374
1375 if (sslContextPointer->error() != QSslError::NoError) {
1376 setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString());
1377 sslContextPointer.reset();
1378 return false;
1379 }
1380
1381 // Create and initialize SSL session
1382 if (!(ssl = sslContextPointer->createSsl())) {
1383 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
1384 QSslSocket::tr("Error creating SSL session, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
1385 return false;
1386 }
1387
1388 if (configuration.protocol() != QSsl::UnknownProtocol && mode == QSslSocket::SslClientMode) {
1389 const auto verificationPeerName = d->verificationName();
1390 // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
1391 QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
1392 if (tlsHostName.isEmpty())
1393 tlsHostName = d->tlsHostName();
1394 QByteArray ace = QUrl::toAce(tlsHostName);
1395 // only send the SNI header if the URL is valid and not an IP
1396 if (!ace.isEmpty()
1397 && !QHostAddress().setAddress(tlsHostName)
1398 && !(configuration.testSslOption(QSsl::SslOptionDisableServerNameIndication))) {
1399 // We don't send the trailing dot from the host header if present see
1400 // https://tools.ietf.org/html/rfc6066#section-3
1401 if (ace.endsWith('.'))
1402 ace.chop(1);
1403 if (!q_SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, ace.data()))
1404 qCWarning(lcTlsBackend, "could not set SSL_CTRL_SET_TLSEXT_HOSTNAME, Server Name Indication disabled");
1405 }
1406 }
1407
1408 // Clear the session.
1409 errorList.clear();
1410
1411 // Initialize memory BIOs for encryption and decryption.
1412 readBio = q_BIO_new(q_BIO_s_mem());
1413 writeBio = q_BIO_new(q_BIO_s_mem());
1414 if (!readBio || !writeBio) {
1415 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
1416 QSslSocket::tr("Error creating SSL session: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
1417 if (readBio)
1418 q_BIO_free(readBio);
1419 if (writeBio)
1420 q_BIO_free(writeBio);
1421 return false;
1422 }
1423
1424 // Assign the bios.
1425 q_SSL_set_bio(ssl, readBio, writeBio);
1426
1429 else
1431
1433
1434#ifndef OPENSSL_NO_PSK
1435 // Set the client callback for PSK
1438 else if (mode == QSslSocket::SslServerMode)
1440
1441#if OPENSSL_VERSION_NUMBER >= 0x10101006L
1442 // Set the client callback for TLSv1.3 PSK
1444 && QSslSocket::sslLibraryBuildVersionNumber() >= 0x10101006L) {
1445 q_SSL_set_psk_use_session_callback(ssl, &q_ssl_psk_use_session_callback);
1446 }
1447#endif // openssl version >= 0x10101006L
1448
1449#endif // OPENSSL_NO_PSK
1450
1451#if QT_CONFIG(ocsp)
1452 if (configuration.ocspStaplingEnabled()) {
1455 QSslSocket::tr("Server-side QSslSocket does not support OCSP stapling"));
1456 return false;
1457 }
1458 if (q_SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp) != 1) {
1459 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
1460 QSslSocket::tr("Failed to enable OCSP stapling"));
1461 return false;
1462 }
1463 }
1464
1466 const auto backendConfig = configuration.backendConfiguration();
1467 auto responsePos = backendConfig.find("Qt-OCSP-response");
1468 if (responsePos != backendConfig.end()) {
1469 // This is our private, undocumented 'API' we use for the auto-testing of
1470 // OCSP-stapling. It must be a der-encoded OCSP response, presumably set
1471 // by tst_QOcsp.
1472 const QVariant data(responsePos.value());
1473 if (data.canConvert<QByteArray>())
1474 ocspResponseDer = data.toByteArray();
1475 }
1476
1477 if (ocspResponseDer.size()) {
1480 QSslSocket::tr("Client-side sockets do not send OCSP responses"));
1481 return false;
1482 }
1483 }
1484#endif // ocsp
1485
1486 return true;
1487}
1488
1489void TlsCryptographOpenSSL::destroySslContext()
1490{
1491 if (ssl) {
1492 if (!q_SSL_in_init(ssl) && !systemOrSslErrorDetected) {
1493 // We do not send a shutdown alert here. Just mark the session as
1494 // resumable for qhttpnetworkconnection's "optimization", otherwise
1495 // OpenSSL won't start a session resumption.
1496 if (q_SSL_shutdown(ssl) != 1) {
1497 // Some error may be queued, clear it.
1498 const auto errors = QTlsBackendOpenSSL::getErrorsFromOpenSsl();
1499 Q_UNUSED(errors);
1500 }
1501 }
1502 q_SSL_free(ssl);
1503 ssl = nullptr;
1504 }
1505 sslContextPointer.reset();
1506}
1507
1509{
1510 Q_ASSERT(d);
1511
1512 // Store the peer certificate and chain. For clients, the peer certificate
1513 // chain includes the peer certificate; for servers, it doesn't. Both the
1514 // peer certificate and the chain may be empty if the peer didn't present
1515 // any certificate.
1516 X509 *x509 = q_SSL_get_peer_certificate(ssl);
1517
1518 const auto peerCertificate = QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509);
1519 QTlsBackend::storePeerCertificate(d, peerCertificate);
1520 q_X509_free(x509);
1521 auto peerCertificateChain = q->peerCertificateChain();
1522 if (peerCertificateChain.isEmpty()) {
1523 peerCertificateChain = QTlsPrivate::X509CertificateOpenSSL::stackOfX509ToQSslCertificates(q_SSL_get_peer_cert_chain(ssl));
1524 if (!peerCertificate.isNull() && d->tlsMode() == QSslSocket::SslServerMode)
1525 peerCertificateChain.prepend(peerCertificate);
1526 QTlsBackend::storePeerCertificateChain(d, peerCertificateChain);
1527 }
1528}
1529
1530#if QT_CONFIG(ocsp)
1531
1532bool TlsCryptographOpenSSL::checkOcspStatus()
1533{
1534 Q_ASSERT(ssl);
1535 Q_ASSERT(d);
1536
1537 const auto &configuration = q->sslConfiguration();
1538 Q_ASSERT(d->tlsMode() == QSslSocket::SslClientMode); // See initSslContext() for SslServerMode
1539 Q_ASSERT(configuration.peerVerifyMode() != QSslSocket::VerifyNone);
1540
1541 const auto clearErrorQueue = qScopeGuard([] {
1543 });
1544
1545 ocspResponses.clear();
1546 ocspErrorDescription.clear();
1547 ocspErrors.clear();
1548
1549 const unsigned char *responseData = nullptr;
1550 const long responseLength = q_SSL_get_tlsext_status_ocsp_resp(ssl, &responseData);
1551 if (responseLength <= 0 || !responseData) {
1553 return false;
1554 }
1555
1556 OCSP_RESPONSE *response = q_d2i_OCSP_RESPONSE(nullptr, &responseData, responseLength);
1557 if (!response) {
1558 // Treat this as a fatal SslHandshakeError.
1559 ocspErrorDescription = QSslSocket::tr("Failed to decode OCSP response");
1560 return false;
1561 }
1562 const QSharedPointer<OCSP_RESPONSE> responseGuard(response, q_OCSP_RESPONSE_free);
1563
1564 const int ocspStatus = q_OCSP_response_status(response);
1565 if (ocspStatus != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
1566 // It's not a definitive response, it's an error message (not signed by the responder).
1567 ocspErrors.push_back(QSslError(qt_OCSP_response_status_to_SslError(ocspStatus)));
1568 return false;
1569 }
1570
1571 OCSP_BASICRESP *basicResponse = q_OCSP_response_get1_basic(response);
1572 if (!basicResponse) {
1573 // SslHandshakeError.
1574 ocspErrorDescription = QSslSocket::tr("Failed to extract basic OCSP response");
1575 return false;
1576 }
1577 const QSharedPointer<OCSP_BASICRESP> basicResponseGuard(basicResponse, q_OCSP_BASICRESP_free);
1578
1579 SSL_CTX *ctx = q_SSL_get_SSL_CTX(ssl); // Does not increment refcount.
1580 Q_ASSERT(ctx);
1581 X509_STORE *store = q_SSL_CTX_get_cert_store(ctx); // Does not increment refcount.
1582 if (!store) {
1583 // SslHandshakeError.
1584 ocspErrorDescription = QSslSocket::tr("No certificate verification store, cannot verify OCSP response");
1585 return false;
1586 }
1587
1588 STACK_OF(X509) *peerChain = q_SSL_get_peer_cert_chain(ssl); // Does not increment refcount.
1589 X509 *peerX509 = q_SSL_get_peer_certificate(ssl);
1590 Q_ASSERT(peerChain || peerX509);
1591 const QSharedPointer<X509> peerX509Guard(peerX509, q_X509_free);
1592 // OCSP_basic_verify with 0 as verificationFlags:
1593 //
1594 // 0) Tries to find the OCSP responder's certificate in either peerChain
1595 // or basicResponse->certs. If not found, verification fails.
1596 // 1) It checks the signature using the responder's public key.
1597 // 2) Then it tries to validate the responder's cert (building a chain
1598 // etc.)
1599 // 3) It checks CertID in response.
1600 // 4) Ensures the responder is authorized to sign the status respond.
1601 //
1602 // Note, OpenSSL prior to 1.0.2b would only use bs->certs to
1603 // verify the responder's chain (see their commit 4ba9a4265bd).
1604 // Working this around - is too much fuss for ancient versions we
1605 // are dropping quite soon anyway.
1606 const unsigned long verificationFlags = 0;
1607 const int success = q_OCSP_basic_verify(basicResponse, peerChain, store, verificationFlags);
1608 if (success <= 0)
1610
1611 if (q_OCSP_resp_count(basicResponse) != 1) {
1613 return false;
1614 }
1615
1616 OCSP_SINGLERESP *singleResponse = q_OCSP_resp_get0(basicResponse, 0);
1617 if (!singleResponse) {
1618 ocspErrors.clear();
1619 // A fatal problem -> SslHandshakeError.
1620 ocspErrorDescription = QSslSocket::tr("Failed to decode a SingleResponse from OCSP status response");
1621 return false;
1622 }
1623
1624 // Let's make sure the response is for the correct certificate - we
1625 // can re-create this CertID using our peer's certificate and its
1626 // issuer's public key.
1627 ocspResponses.push_back(QOcspResponse());
1628 QOcspResponsePrivate *dResponse = ocspResponses.back().d.data();
1629 dResponse->subjectCert = configuration.peerCertificate();
1630 bool matchFound = false;
1631 if (dResponse->subjectCert.isSelfSigned()) {
1632 dResponse->signerCert = configuration.peerCertificate();
1633 matchFound = qt_OCSP_certificate_match(singleResponse, peerX509, peerX509);
1634 } else {
1635 const STACK_OF(X509) *certs = q_SSL_get_peer_cert_chain(ssl);
1636 if (!certs) // Oh, what a cataclysm! Last try:
1637 certs = q_OCSP_resp_get0_certs(basicResponse);
1638 if (certs) {
1639 // It could be the first certificate in 'certs' is our peer's
1640 // certificate. Since it was not captured by the 'self-signed' branch
1641 // above, the CertID will not match and we'll just iterate on to the
1642 // next certificate. So we start from 0, not 1.
1643 for (int i = 0, e = q_sk_X509_num(certs); i < e; ++i) {
1644 X509 *issuer = q_sk_X509_value(certs, i);
1645 matchFound = qt_OCSP_certificate_match(singleResponse, peerX509, issuer);
1646 if (matchFound) {
1647 if (q_X509_check_issued(issuer, peerX509) == X509_V_OK) {
1648 dResponse->signerCert = QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(issuer);
1649 break;
1650 }
1651 matchFound = false;
1652 }
1653 }
1654 }
1655 }
1656
1657 if (!matchFound) {
1658 dResponse->signerCert.clear();
1659 ocspErrors.push_back({QSslError::OcspResponseCertIdUnknown, configuration.peerCertificate()});
1660 }
1661
1662 // Check if the response is valid time-wise:
1663 ASN1_GENERALIZEDTIME *revTime = nullptr;
1664 ASN1_GENERALIZEDTIME *thisUpdate = nullptr;
1665 ASN1_GENERALIZEDTIME *nextUpdate = nullptr;
1666 int reason;
1667 const int certStatus = q_OCSP_single_get0_status(singleResponse, &reason, &revTime, &thisUpdate, &nextUpdate);
1668 if (!thisUpdate) {
1669 // This is unexpected, treat as SslHandshakeError, OCSP_check_validity assumes this pointer
1670 // to be != nullptr.
1671 ocspErrors.clear();
1672 ocspResponses.clear();
1673 ocspErrorDescription = QSslSocket::tr("Failed to extract 'this update time' from the SingleResponse");
1674 return false;
1675 }
1676
1677 // OCSP_check_validity(this, next, nsec, maxsec) does this check:
1678 // this <= now <= next. They allow some freedom to account
1679 // for delays/time inaccuracy.
1680 // this > now + nsec ? -> NOT_YET_VALID
1681 // if maxsec >= 0:
1682 // now - maxsec > this ? -> TOO_OLD
1683 // now - nsec > next ? -> EXPIRED
1684 // next < this ? -> NEXT_BEFORE_THIS
1685 // OK.
1686 if (!q_OCSP_check_validity(thisUpdate, nextUpdate, 60, -1))
1687 ocspErrors.push_back({QSslError::OcspResponseExpired, configuration.peerCertificate()});
1688
1689 // And finally, the status:
1690 switch (certStatus) {
1691 case V_OCSP_CERTSTATUS_GOOD:
1692 // This certificate was not found among the revoked ones.
1693 dResponse->certificateStatus = QOcspCertificateStatus::Good;
1694 break;
1695 case V_OCSP_CERTSTATUS_REVOKED:
1696 dResponse->certificateStatus = QOcspCertificateStatus::Revoked;
1697 dResponse->revocationReason = qt_OCSP_revocation_reason(reason);
1698 ocspErrors.push_back({QSslError::CertificateRevoked, configuration.peerCertificate()});
1699 break;
1700 case V_OCSP_CERTSTATUS_UNKNOWN:
1701 dResponse->certificateStatus = QOcspCertificateStatus::Unknown;
1702 ocspErrors.push_back({QSslError::OcspStatusUnknown, configuration.peerCertificate()});
1703 }
1704
1705 return !ocspErrors.size();
1706}
1707
1708#endif // QT_CONFIG(ocsp)
1709
1710
1711unsigned TlsCryptographOpenSSL::pskClientTlsCallback(const char *hint, char *identity,
1712 unsigned max_identity_len,
1713 unsigned char *psk, unsigned max_psk_len)
1714{
1715 Q_ASSERT(q);
1716
1717 QSslPreSharedKeyAuthenticator authenticator;
1718 // Fill in some read-only fields (for the user)
1719 const int hintLength = hint ? int(std::strlen(hint)) : 0;
1720 QTlsBackend::setupClientPskAuth(&authenticator, hint, hintLength, max_identity_len, max_psk_len);
1721 // Let the client provide the remaining bits...
1722 emit q->preSharedKeyAuthenticationRequired(&authenticator);
1723
1724 // No PSK set? Return now to make the handshake fail
1725 if (authenticator.preSharedKey().isEmpty())
1726 return 0;
1727
1728 // Copy data back into OpenSSL
1729 const int identityLength = qMin(authenticator.identity().size(), authenticator.maximumIdentityLength());
1730 std::memcpy(identity, authenticator.identity().constData(), identityLength);
1731 identity[identityLength] = 0;
1732
1733 const int pskLength = qMin(authenticator.preSharedKey().size(), authenticator.maximumPreSharedKeyLength());
1734 std::memcpy(psk, authenticator.preSharedKey().constData(), pskLength);
1735 return pskLength;
1736}
1737
1738unsigned TlsCryptographOpenSSL::pskServerTlsCallback(const char *identity, unsigned char *psk,
1739 unsigned max_psk_len)
1740{
1741 Q_ASSERT(q);
1742
1743 QSslPreSharedKeyAuthenticator authenticator;
1744
1745 // Fill in some read-only fields (for the user)
1746 QTlsBackend::setupServerPskAuth(&authenticator, identity, q->sslConfiguration().preSharedKeyIdentityHint(),
1747 max_psk_len);
1748 emit q->preSharedKeyAuthenticationRequired(&authenticator);
1749
1750 // No PSK set? Return now to make the handshake fail
1751 if (authenticator.preSharedKey().isEmpty())
1752 return 0;
1753
1754 // Copy data back into OpenSSL
1755 const int pskLength = qMin(authenticator.preSharedKey().size(), authenticator.maximumPreSharedKeyLength());
1756 std::memcpy(psk, authenticator.preSharedKey().constData(), pskLength);
1757 return pskLength;
1758}
1759
1761{
1762 return inSslRead;
1763}
1764
1766{
1767 this->renegotiated = renegotiated;
1768}
1769
1770#ifdef Q_OS_WIN
1771
1772void TlsCryptographOpenSSL::fetchCaRootForCert(const QSslCertificate &cert)
1773{
1774 Q_ASSERT(d);
1775 Q_ASSERT(q);
1776
1777 //The root certificate is downloaded from windows update, which blocks for 15 seconds in the worst case
1778 //so the request is done in a worker thread.
1779 QList<QSslCertificate> customRoots;
1780 if (fetchAuthorityInformation)
1781 customRoots = q->sslConfiguration().caCertificates();
1782
1783 //Remember we are fetching and what we are fetching:
1784 caToFetch = cert;
1785
1786 QWindowsCaRootFetcher *fetcher = new QWindowsCaRootFetcher(cert, d->tlsMode(), customRoots,
1787 q->peerVerifyName());
1788 connect(fetcher, &QWindowsCaRootFetcher::finished, this, &TlsCryptographOpenSSL::caRootLoaded,
1792 d->setPaused(true);
1793}
1794
1795void TlsCryptographOpenSSL::caRootLoaded(QSslCertificate cert, QSslCertificate trustedRoot)
1796{
1797 if (caToFetch != cert) {
1798 //Ooops, something from the previous connection attempt, ignore!
1799 return;
1800 }
1801
1802 Q_ASSERT(d);
1803 Q_ASSERT(q);
1804
1805 //Done, fetched already:
1806 caToFetch.reset();
1807
1808 if (fetchAuthorityInformation) {
1809 if (!q->sslConfiguration().caCertificates().contains(trustedRoot))
1810 trustedRoot = QSslCertificate{};
1811 fetchAuthorityInformation = false;
1812 }
1813
1814 if (!trustedRoot.isNull() && !trustedRoot.isBlacklisted()) {
1816 //Add the new root cert to default cert list for use by future sockets
1817 auto defaultConfig = QSslConfiguration::defaultConfiguration();
1818 defaultConfig.addCaCertificate(trustedRoot);
1820 }
1821 //Add the new root cert to this socket for future connections
1822 QTlsBackend::addTustedRoot(d, trustedRoot);
1823 //Remove the broken chain ssl errors (as chain is verified by windows)
1824 for (int i=sslErrors.count() - 1; i >= 0; --i) {
1825 if (sslErrors.at(i).certificate() == cert) {
1826 switch (sslErrors.at(i).error()) {
1831 // error can be ignored if OS says the chain is trusted
1832 sslErrors.removeAt(i);
1833 break;
1834 default:
1835 // error cannot be ignored
1836 break;
1837 }
1838 }
1839 }
1840 }
1841
1842 auto *plainSocket = d->plainTcpSocket();
1843 Q_ASSERT(plainSocket);
1844 // Continue with remaining errors
1845 if (plainSocket)
1846 plainSocket->resume();
1847 d->setPaused(false);
1848 if (checkSslErrors() && ssl) {
1849 bool willClose = (d->isAutoStartingHandshake() && d->isPendingClose());
1851 if (!willClose)
1852 transmit();
1853 }
1854}
1855
1856#endif // Q_OS_WIN
1857
1858} // namespace QTlsPrivate
1859
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:611
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
void clear()
Clears the contents of the byte array and makes it null.
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
Definition qdir.cpp:2133
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
The QHostAddress class provides an IP address.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
void removeAt(qsizetype i)
Definition qlist.h:590
reference back()
Definition qlist.h:689
void push_back(parameter_type t)
Definition qlist.h:675
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
qsizetype count() const noexcept
Definition qlist.h:398
const T & constFirst() const noexcept
Definition qlist.h:647
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
QSslCertificate subjectCert
This class represents Online Certificate Status Protocol response.
T * data()
Returns a pointer to the shared data object.
Definition qshareddata.h:47
static Q_NETWORK_EXPORT bool isBlacklisted(const QSslCertificate &certificate)
The QSslCertificate class provides a convenient API for an X509 certificate.
The QSslCipher class represents an SSL cryptographic cipher.
Definition qsslcipher.h:22
static void setDefaultConfiguration(const QSslConfiguration &configuration)
Sets the default SSL configuration to be used in new SSL connections to be configuration.
static QSslConfiguration defaultConfiguration()
Returns the default SSL configuration to be used in new SSL connections.
static std::shared_ptr< QSslContext > sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
The QSslError class provides an SSL error.
Definition qsslerror.h:21
SslError error() const
Returns the type of the error.
QString errorString() const
Returns a short localized human-readable description of the error.
SslError
Describes all recognized errors that can occur during an SSL handshake.
Definition qsslerror.h:24
@ OcspResponseCannotBeTrusted
Definition qsslerror.h:58
@ OcspMalformedRequest
Definition qsslerror.h:52
@ OcspUnauthorized
Definition qsslerror.h:57
@ SelfSignedCertificate
Definition qsslerror.h:34
@ UnableToVerifyFirstCertificate
Definition qsslerror.h:37
@ CertificateRevoked
Definition qsslerror.h:38
@ OcspResponseExpired
Definition qsslerror.h:60
@ OcspResponseCertIdUnknown
Definition qsslerror.h:59
@ OcspSigRequred
Definition qsslerror.h:56
@ CertificateBlacklisted
Definition qsslerror.h:49
@ UnableToGetLocalIssuerCertificate
Definition qsslerror.h:36
@ OcspMalformedResponse
Definition qsslerror.h:53
@ OcspTryLater
Definition qsslerror.h:55
@ SelfSignedCertificateInChain
Definition qsslerror.h:35
@ HostNameMismatch
Definition qsslerror.h:47
@ OcspInternalError
Definition qsslerror.h:54
@ CertificateUntrusted
Definition qsslerror.h:42
@ OcspStatusUnknown
Definition qsslerror.h:61
@ OcspNoResponseFound
Definition qsslerror.h:51
@ NoPeerCertificate
Definition qsslerror.h:46
QSslCertificate certificate() const
Returns the certificate associated with this error, or a null certificate if the error does not relat...
The QSslKey class provides an interface for private and public keys.
Definition qsslkey.h:23
The QSslPreSharedKeyAuthenticator class provides authentication data for pre shared keys (PSK) cipher...
Q_NETWORK_EXPORT QByteArray preSharedKey() const
Returns the pre shared key.
Q_NETWORK_EXPORT int maximumIdentityLength() const
Returns the maximum length, in bytes, of the PSK client identity.
Q_NETWORK_EXPORT QByteArray identity() const
Returns the PSK client identity.
Q_NETWORK_EXPORT int maximumPreSharedKeyLength() const
Returns the maximum length, in bytes, of the pre shared key.
bool * readyReadPointer()
bool verifyErrorsHaveBeenIgnored()
void setEncrypted(bool enc)
void setMaxReadBufferSize(qint64 maxSize)
QTcpSocket * plainTcpSocket() const
QString verificationName() const
bool isAutoStartingHandshake() const
bool isRootsOnDemandAllowed() const
bool isPaused() const
qint64 maxReadBufferSize() const
bool & tlsEmittedBytesWritten()
QString tlsHostName() const
QRingBufferRef & tlsBuffer()
static bool rootCertOnDemandLoadingSupported()
void setPaused(bool p)
void setPendingClose(bool pc)
static void pauseSocketNotifiers(QSslSocket *)
QRingBufferRef & tlsWriteBuffer()
QSslSocket::SslMode tlsMode() const
bool isPendingClose() const
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition qsslsocket.h:29
static long sslLibraryBuildVersionNumber()
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QSslCipher qt_OpenSSL_cipher_to_QSslCipher(const SSL_CIPHER *cipher)
static void logAndClearErrorQueue()
static QString msgErrorsDuringHandshake()
static QString getErrorsFromOpenSsl()
static void setupClientPskAuth(QSslPreSharedKeyAuthenticator *auth, const char *hint, int hintLength, unsigned maxIdentityLen, unsigned maxPskLen)
static void setupServerPskAuth(QSslPreSharedKeyAuthenticator *auth, const char *identity, const QByteArray &identityHint, unsigned maxPskLen)
void checkSettingSslContext(std::shared_ptr< QSslContext > tlsContext) override
unsigned pskClientTlsCallback(const char *hint, char *identity, unsigned max_identity_len, unsigned char *psk, unsigned max_psk_len)
std::shared_ptr< QSslContext > sslContext() const override
int handleNewSessionTicket(SSL *connection)
QList< QOcspResponse > ocsps() const override
int emitErrorFromCallback(X509_STORE_CTX *ctx)
unsigned pskServerTlsCallback(const char *identity, unsigned char *psk, unsigned max_psk_len)
QSsl::SslProtocol sessionProtocol() const override
void init(QSslSocket *qObj, QSslSocketPrivate *dObj) override
QList< QSslError > tlsErrors() const override
void setRenegotiated(bool renegotiated)
QSslCipher sessionCipher() const override
static QSslErrorEntry errorEntryFromStoreContext(X509_STORE_CTX *ctx)
static QSslCertificate certificateFromX509(X509 *x)
static QSslError openSSLErrorToQSslError(int errorCode, const QSslCertificate &cert)
static QList< QSslCertificate > stackOfX509ToQSslCertificates(STACK_OF(X509) *x509)
static QByteArray toAce(const QString &domain, AceProcessingOptions options={})
Definition qurl.cpp:3064
\inmodule QtCore
Definition qvariant.h:65
void finished(QSslCertificate brokenChain, QSslCertificate caroot)
EGLContext ctx
@ PublicKey
Definition qssl.h:24
AlertLevel
Describes the level of an alert message.
Definition qssl.h:86
@ SslOptionDisableSessionPersistence
Definition qssl.h:80
@ SslOptionDisableServerNameIndication
Definition qssl.h:77
@ SslOptionDisableSessionSharing
Definition qssl.h:79
AlertType
Enumerates possible codes that an alert message can have.
Definition qssl.h:93
SslProtocol
Describes the protocol of the cipher.
Definition qssl.h:50
@ TlsV1_3
Definition qssl.h:66
@ TlsV1_2
Definition qssl.h:53
@ UnknownProtocol
Definition qssl.h:69
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
static unsigned q_ssl_psk_client_callback(SSL *ssl, const char *hint, char *identity, unsigned max_identity_len, unsigned char *psk, unsigned max_psk_len)
void qt_AlertInfoCallback(const SSL *connection, int from, int value)
static unsigned int q_ssl_psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len)
int q_X509CallbackDirect(int ok, X509_STORE_CTX *ctx)
@ QueuedConnection
constexpr Initialization Uninitialized
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_DEPRECATED
#define QT_WARNING_PUSH
DBusConnection const char DBusError * error
DBusConnection * connection
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
QOcspRevocationReason
GLenum mode
GLenum GLuint GLint level
GLuint64 key
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLenum GLuint GLintptr offset
GLuint writeBuffer
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
SSL_CTX int void * arg
void q_SSL_free(SSL *a)
void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
int q_SSL_in_init(const SSL *s)
const SSL_CIPHER * q_SSL_get_current_cipher(SSL *a)
int q_OBJ_obj2nid(const ASN1_OBJECT *a)
SSL_CTX * q_SSL_get_SSL_CTX(SSL *a)
void * q_X509_STORE_get_ex_data(X509_STORE *r, int idx)
int q_SSL_get_ex_data_X509_STORE_CTX_idx()
int q_SSL_session_reused(SSL *a)
X509 * q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
void q_SSL_set_connect_state(SSL *a)
#define q_SSL_get_server_tmp_key(ssl, key)
#define q_sk_X509_num(st)
int q_SSL_get_error(SSL *a, int b)
X509 * q_SSL_get_peer_certificate(SSL *a)
void * q_X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
int q_SSL_accept(SSL *a)
#define q_OPENSSL_malloc(num)
void q_SSL_set_accept_state(SSL *a)
STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx)
int q_SSL_shutdown(SSL *a)
BIO * q_BIO_new(const BIO_METHOD *a)
X509_STORE * q_SSL_CTX_get_cert_store(const SSL_CTX *a)
void q_SSL_set_psk_use_session_callback(SSL *s, q_SSL_psk_use_session_cb_func_t)
unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session)
#define q_EVP_get_digestbynid(a)
int q_SSL_write(SSL *a, const void *b, int c)
int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
const char * q_SSL_alert_desc_string_long(int value)
long q_SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg)
void * q_SSL_get_ex_data(const SSL *ssl, int idx)
SSL_SESSION * q_SSL_get_session(const SSL *ssl)
#define q_BIO_pending(b)
ASN1_INTEGER * q_X509_get_serialNumber(X509 *a)
int q_SSL_read(SSL *a, void *b, int c)
int q_X509_check_issued(X509 *a, X509 *b)
int q_SSL_version(const SSL *a)
const BIO_METHOD * q_BIO_s_mem()
const char * q_SSL_alert_type_string(int value)
void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned *len)
int q_BIO_read(BIO *a, void *b, int c)
void q_SSL_set_bio(SSL *a, BIO *b, BIO *c)
void q_X509_free(X509 *a)
int q_SSL_connect(SSL *a)
size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen)
void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback)
#define q_sk_X509_value(st, i)
int q_BIO_write(BIO *a, const void *b, int c)
void q_SSL_set_info_callback(SSL *ssl, void(*cb)(const SSL *ssl, int type, int val))
X509_STORE * q_X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
void q_SSL_set_psk_client_callback(SSL *ssl, q_psk_client_callback_t callback)
int q_BIO_free(BIO *a)
int q_SSL_set_ex_data(SSL *ssl, int idx, void *arg)
#define q_SSL_set_tlsext_status_type(ssl, type)
size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define emit
#define Q_UNUSED(x)
long long qint64
Definition qtypes.h:60
QFile file
[0]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QList< QSslCertificate > cert
[0]
const auto certs
[1]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...