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
qsslsocket.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2014 BlackBerry Limited. All rights reserved.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5
6//#define QSSLSOCKET_DEBUG
7
347#include "qssl_p.h"
348#include "qsslsocket.h"
349#include "qsslcipher.h"
350#include "qocspresponse.h"
351#include "qtlsbackend_p.h"
352#include "qsslconfiguration_p.h"
353#include "qsslsocket_p.h"
354
355#include <QtCore/qdebug.h>
356#include <QtCore/qdir.h>
357#include <QtCore/qmutex.h>
358#include <QtCore/qurl.h>
359#include <QtCore/qelapsedtimer.h>
360#include <QtNetwork/qhostaddress.h>
361#include <QtNetwork/qhostinfo.h>
362
364
365using namespace Qt::StringLiterals;
366
367#ifdef Q_OS_VXWORKS
368constexpr auto isVxworks = true;
369#else
370constexpr auto isVxworks = false;
371#endif
372
374{
375public:
379 {
380#if QT_CONFIG(dtls)
382#endif // dtls
383 }
384
386 QList<QSslCipher> supportedCiphers;
387 QList<QSslEllipticCurve> supportedEllipticCurves;
388 QExplicitlySharedDataPointer<QSslConfigurationPrivate> config;
389 QExplicitlySharedDataPointer<QSslConfigurationPrivate> dtlsConfig;
390};
392
393
399 : QTcpSocket(*new QSslSocketPrivate, parent)
400{
401 Q_D(QSslSocket);
402#ifdef QSSLSOCKET_DEBUG
403 qCDebug(lcSsl) << "QSslSocket::QSslSocket(" << parent << "), this =" << (void *)this;
404#endif
405 d->q_ptr = this;
406 d->init();
407}
408
413{
414 Q_D(QSslSocket);
415#ifdef QSSLSOCKET_DEBUG
416 qCDebug(lcSsl) << "QSslSocket::~QSslSocket(), this =" << (void *)this;
417#endif
418 delete d->plainSocket;
419 d->plainSocket = nullptr;
420}
421
435{
436 Q_D(QSslSocket);
437 if (!d->paused)
438 return;
439 // continuing might emit signals, rather do this through the event loop
440 QMetaObject::invokeMethod(this, "_q_resumeImplementation", Qt::QueuedConnection);
441}
442
485{
486 Q_D(QSslSocket);
487 if (d->state == ConnectedState || d->state == ConnectingState) {
488 qCWarning(lcSsl,
489 "QSslSocket::connectToHostEncrypted() called when already connecting/connected");
490 return;
491 }
492
493 if (!supportsSsl()) {
494 qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
495 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
496 return;
497 }
498
499 if (!d->verifyProtocolSupported("QSslSocket::connectToHostEncrypted:"))
500 return;
501
502 d->init();
503 d->autoStartHandshake = true;
504 d->initialized = true;
505
506 // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
507 // establish the connection immediately (i.e., first attempt).
508 connectToHost(hostName, port, mode, protocol);
509}
510
523 const QString &sslPeerName, OpenMode mode,
524 NetworkLayerProtocol protocol)
525{
526 Q_D(QSslSocket);
527 if (d->state == ConnectedState || d->state == ConnectingState) {
528 qCWarning(lcSsl,
529 "QSslSocket::connectToHostEncrypted() called when already connecting/connected");
530 return;
531 }
532
533 if (!supportsSsl()) {
534 qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
535 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
536 return;
537 }
538
539 d->init();
540 d->autoStartHandshake = true;
541 d->initialized = true;
542 d->verificationPeerName = sslPeerName;
543
544 // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
545 // establish the connection immediately (i.e., first attempt).
546 connectToHost(hostName, port, mode, protocol);
547}
548
561bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state, OpenMode openMode)
562{
563 Q_D(QSslSocket);
564#ifdef QSSLSOCKET_DEBUG
565 qCDebug(lcSsl) << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ','
566 << state << ',' << openMode << ')';
567#endif
568 if (!d->plainSocket)
569 d->createPlainSocket(openMode);
570 bool retVal = d->plainSocket->setSocketDescriptor(socketDescriptor, state, openMode);
571 d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
572 d->setError(d->plainSocket->error(), d->plainSocket->errorString());
575 setLocalPort(d->plainSocket->localPort());
576 setLocalAddress(d->plainSocket->localAddress());
577 setPeerPort(d->plainSocket->peerPort());
578 setPeerAddress(d->plainSocket->peerAddress());
579 setPeerName(d->plainSocket->peerName());
580 d->readChannelCount = d->plainSocket->readChannelCount();
581 d->writeChannelCount = d->plainSocket->writeChannelCount();
582 return retVal;
583}
584
592{
593 Q_D(QSslSocket);
594 if (d->plainSocket)
595 d->plainSocket->setSocketOption(option, value);
596}
597
605{
606 Q_D(QSslSocket);
607 if (d->plainSocket)
608 return d->plainSocket->socketOption(option);
609 else
610 return QVariant();
611}
612
624{
625 Q_D(const QSslSocket);
626 return d->mode;
627}
628
645{
646 Q_D(const QSslSocket);
647 return d->connectionEncrypted;
648}
649
656{
657 Q_D(const QSslSocket);
658 return d->configuration.protocol;
659}
660
667{
668 Q_D(QSslSocket);
669 d->configuration.protocol = protocol;
670}
671
687{
688 Q_D(const QSslSocket);
689 return d->configuration.peerVerifyMode;
690}
691
710{
711 Q_D(QSslSocket);
712 d->configuration.peerVerifyMode = mode;
713}
714
729{
730 Q_D(const QSslSocket);
731 return d->configuration.peerVerifyDepth;
732}
733
748{
749 Q_D(QSslSocket);
750 if (depth < 0) {
751 qCWarning(lcSsl, "QSslSocket::setPeerVerifyDepth: cannot set negative depth of %d", depth);
752 return;
753 }
754 d->configuration.peerVerifyDepth = depth;
755}
756
766{
767 Q_D(const QSslSocket);
768 return d->verificationPeerName;
769}
770
780{
781 Q_D(QSslSocket);
782 d->verificationPeerName = hostName;
783}
784
792{
793 Q_D(const QSslSocket);
794 if (d->mode == UnencryptedMode)
795 return QAbstractSocket::bytesAvailable() + (d->plainSocket ? d->plainSocket->bytesAvailable() : 0);
797}
798
806{
807 Q_D(const QSslSocket);
808 if (d->mode == UnencryptedMode)
809 return d->plainSocket ? d->plainSocket->bytesToWrite() : 0;
810 return d->writeBuffer.size();
811}
812
821{
822 Q_D(const QSslSocket);
823 if (d->mode == UnencryptedMode)
824 return 0;
825 return d->plainSocket->bytesAvailable();
826}
827
835{
836 Q_D(const QSslSocket);
837 if (d->mode == UnencryptedMode)
838 return 0;
839 return d->plainSocket->bytesToWrite();
840}
841
849{
850 Q_D(const QSslSocket);
851 if (d->mode == UnencryptedMode)
852 return QAbstractSocket::canReadLine() || (d->plainSocket && d->plainSocket->canReadLine());
854}
855
860{
861#ifdef QSSLSOCKET_DEBUG
862 qCDebug(lcSsl) << "QSslSocket::close()";
863#endif
864 Q_D(QSslSocket);
865
866 // On Windows, CertGetCertificateChain is probably still doing its
867 // job, if the socket is re-used, we want to ignore its reported
868 // root CA.
869 if (auto *backend = d->backend.get())
870 backend->cancelCAFetch();
871
872 if (!d->abortCalled && (encryptedBytesToWrite() || !d->writeBuffer.isEmpty()))
873 flush();
874 if (d->plainSocket) {
875 if (d->abortCalled)
876 d->plainSocket->abort();
877 else
878 d->plainSocket->close();
879 }
881
882 // must be cleared, reading/writing not possible on closed socket:
883 d->buffer.clear();
884 d->writeBuffer.clear();
885}
886
891{
892 Q_D(const QSslSocket);
893 if (d->mode == UnencryptedMode)
894 return QAbstractSocket::atEnd() && (!d->plainSocket || d->plainSocket->atEnd());
895 return QAbstractSocket::atEnd();
896}
897
904{
905 Q_D(QSslSocket);
906 d->readBufferMaxSize = size;
907
908 if (d->plainSocket)
909 d->plainSocket->setReadBufferSize(size);
910}
911
927{
928 Q_D(const QSslSocket);
929
930 // create a deep copy of our configuration
932 copy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
933 copy->sessionCipher = d->sessionCipher();
934 copy->sessionProtocol = d->sessionProtocol();
935
936 return QSslConfiguration(copy);
937}
938
952{
953 Q_D(QSslSocket);
954 d->configuration.localCertificateChain = configuration.localCertificateChain();
955 d->configuration.privateKey = configuration.privateKey();
956 d->configuration.ciphers = configuration.ciphers();
957 d->configuration.ellipticCurves = configuration.ellipticCurves();
958 d->configuration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
959 d->configuration.dhParams = configuration.diffieHellmanParameters();
960 d->configuration.caCertificates = configuration.caCertificates();
961 d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
962 d->configuration.peerVerifyMode = configuration.peerVerifyMode();
963 d->configuration.protocol = configuration.protocol();
964 d->configuration.backendConfig = configuration.backendConfiguration();
965 d->configuration.sslOptions = configuration.d->sslOptions;
966 d->configuration.sslSession = configuration.sessionTicket();
967 d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
968 d->configuration.nextAllowedProtocols = configuration.allowedNextProtocols();
969 d->configuration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
970 d->configuration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
971#if QT_CONFIG(ocsp)
972 d->configuration.ocspStaplingEnabled = configuration.ocspStaplingEnabled();
973#endif
974#if QT_CONFIG(openssl)
975 d->configuration.reportFromCallback = configuration.handshakeMustInterruptOnError();
976 d->configuration.missingCertIsFatal = configuration.missingCertificateIsFatal();
977#endif // openssl
978 // if the CA certificates were set explicitly (either via
979 // QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
980 // we cannot load the certificates on demand
981 if (!configuration.d->allowRootCertOnDemandLoading) {
982 d->allowRootCertOnDemandLoading = false;
983 d->configuration.allowRootCertOnDemandLoading = false;
984 }
985}
986
994void QSslSocket::setLocalCertificateChain(const QList<QSslCertificate> &localChain)
995{
996 Q_D(QSslSocket);
997 d->configuration.localCertificateChain = localChain;
998}
999
1007QList<QSslCertificate> QSslSocket::localCertificateChain() const
1008{
1009 Q_D(const QSslSocket);
1010 return d->configuration.localCertificateChain;
1011}
1012
1033{
1034 Q_D(QSslSocket);
1035 d->configuration.localCertificateChain = QList<QSslCertificate>();
1036 d->configuration.localCertificateChain += certificate;
1037}
1038
1054
1062{
1063 Q_D(const QSslSocket);
1064 if (d->configuration.localCertificateChain.isEmpty())
1065 return QSslCertificate();
1066 return d->configuration.localCertificateChain[0];
1067}
1068
1095{
1096 Q_D(const QSslSocket);
1097 return d->configuration.peerCertificate;
1098}
1099
1123QList<QSslCertificate> QSslSocket::peerCertificateChain() const
1124{
1125 Q_D(const QSslSocket);
1126 return d->configuration.peerCertificateChain;
1127}
1128
1146{
1147 Q_D(const QSslSocket);
1148 return d->sessionCipher();
1149}
1150
1160{
1161 Q_D(const QSslSocket);
1162 return d->sessionProtocol();
1163}
1164
1174QList<QOcspResponse> QSslSocket::ocspResponses() const
1175{
1176 Q_D(const QSslSocket);
1177 if (const auto *backend = d->backend.get())
1178 return backend->ocsps();
1179 return {};
1180}
1181
1196{
1197 Q_D(QSslSocket);
1198 d->configuration.privateKey = key;
1199}
1200
1222 QSsl::EncodingFormat format, const QByteArray &passPhrase)
1223{
1226 qCWarning(lcSsl, "QSslSocket::setPrivateKey: Couldn't open file for reading");
1227 return;
1228 }
1229
1230 QSslKey key(file.readAll(), algorithm, format, QSsl::PrivateKey, passPhrase);
1231 if (key.isNull()) {
1232 qCWarning(lcSsl, "QSslSocket::setPrivateKey: "
1233 "The specified file does not contain a valid key");
1234 return;
1235 }
1236
1237 Q_D(QSslSocket);
1238 d->configuration.privateKey = key;
1239}
1240
1247{
1248 Q_D(const QSslSocket);
1249 return d->configuration.privateKey;
1250}
1251
1260{
1261 Q_D(QSslSocket);
1262 if (!d->plainSocket)
1263 return false;
1264 bool retVal = d->plainSocket->waitForConnected(msecs);
1265 if (!retVal) {
1266 setSocketState(d->plainSocket->state());
1267 d->setError(d->plainSocket->error(), d->plainSocket->errorString());
1268 }
1269 return retVal;
1270}
1271
1289{
1290 Q_D(QSslSocket);
1291 if (!d->plainSocket || d->connectionEncrypted)
1292 return false;
1293 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1294 return false;
1295 if (!d->verifyProtocolSupported("QSslSocket::waitForEncrypted:"))
1296 return false;
1297
1298 QElapsedTimer stopWatch;
1299 stopWatch.start();
1300
1301 if (d->plainSocket->state() != QAbstractSocket::ConnectedState) {
1302 // Wait until we've entered connected state.
1303 if (!d->plainSocket->waitForConnected(msecs))
1304 return false;
1305 }
1306
1307 while (!d->connectionEncrypted) {
1308 // Start the handshake, if this hasn't been started yet.
1309 if (d->mode == UnencryptedMode)
1311 // Loop, waiting until the connection has been encrypted or an error
1312 // occurs.
1313 if (!d->plainSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed())))
1314 return false;
1315 }
1316 return d->connectionEncrypted;
1317}
1318
1323{
1324 Q_D(QSslSocket);
1325 if (!d->plainSocket)
1326 return false;
1327 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1328 return d->plainSocket->waitForReadyRead(msecs);
1329
1330 // This function must return true if and only if readyRead() *was* emitted.
1331 // So we initialize "readyReadEmitted" to false and check if it was set to true.
1332 // waitForReadyRead() could be called recursively, so we can't use the same variable
1333 // (the inner waitForReadyRead() may fail, but the outer one still succeeded)
1334 bool readyReadEmitted = false;
1335 bool *previousReadyReadEmittedPointer = d->readyReadEmittedPointer;
1336 d->readyReadEmittedPointer = &readyReadEmitted;
1337
1338 QElapsedTimer stopWatch;
1339 stopWatch.start();
1340
1341 if (!d->connectionEncrypted) {
1342 // Wait until we've entered encrypted mode, or until a failure occurs.
1343 if (!waitForEncrypted(msecs)) {
1344 d->readyReadEmittedPointer = previousReadyReadEmittedPointer;
1345 return false;
1346 }
1347 }
1348
1349 if (!d->writeBuffer.isEmpty()) {
1350 // empty our cleartext write buffer first
1351 d->transmit();
1352 }
1353
1354 // test readyReadEmitted first because either operation above
1355 // (waitForEncrypted or transmit) may have set it
1356 while (!readyReadEmitted &&
1357 d->plainSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
1358 }
1359
1360 d->readyReadEmittedPointer = previousReadyReadEmittedPointer;
1361 return readyReadEmitted;
1362}
1363
1368{
1369 Q_D(QSslSocket);
1370 if (!d->plainSocket)
1371 return false;
1372 if (d->mode == UnencryptedMode)
1373 return d->plainSocket->waitForBytesWritten(msecs);
1374
1375 QElapsedTimer stopWatch;
1376 stopWatch.start();
1377
1378 if (!d->connectionEncrypted) {
1379 // Wait until we've entered encrypted mode, or until a failure occurs.
1380 if (!waitForEncrypted(msecs))
1381 return false;
1382 }
1383 if (!d->writeBuffer.isEmpty()) {
1384 // empty our cleartext write buffer first
1385 d->transmit();
1386 }
1387
1388 return d->plainSocket->waitForBytesWritten(qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
1389}
1390
1399{
1400 Q_D(QSslSocket);
1401
1402 // require calling connectToHost() before waitForDisconnected()
1403 if (state() == UnconnectedState) {
1404 qCWarning(lcSsl, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState");
1405 return false;
1406 }
1407
1408 if (!d->plainSocket)
1409 return false;
1410 // Forward to the plain socket unless the connection is secure.
1411 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1412 return d->plainSocket->waitForDisconnected(msecs);
1413
1414 QElapsedTimer stopWatch;
1415 stopWatch.start();
1416
1417 if (!d->connectionEncrypted) {
1418 // Wait until we've entered encrypted mode, or until a failure occurs.
1419 if (!waitForEncrypted(msecs))
1420 return false;
1421 }
1422 // We are delaying the disconnect, if the write buffer is not empty.
1423 // So, start the transmission.
1424 if (!d->writeBuffer.isEmpty())
1425 d->transmit();
1426
1427 // At this point, the socket might be disconnected, if disconnectFromHost()
1428 // was called just after the connectToHostEncrypted() call. Also, we can
1429 // lose the connection as a result of the transmit() call.
1430 if (state() == UnconnectedState)
1431 return true;
1432
1433 bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
1434 if (!retVal) {
1435 setSocketState(d->plainSocket->state());
1436 d->setError(d->plainSocket->error(), d->plainSocket->errorString());
1437 }
1438 return retVal;
1439}
1440
1451QList<QSslError> QSslSocket::sslHandshakeErrors() const
1452{
1453 Q_D(const QSslSocket);
1454 if (const auto *backend = d->backend.get())
1455 return backend->tlsErrors();
1456 return {};
1457}
1458
1468
1476{
1477 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1478 return tlsBackend->tlsLibraryVersionNumber();
1479
1480 return -1;
1481}
1482
1490{
1491 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1492 return tlsBackend->tlsLibraryVersionString();
1493 return {};
1494}
1495
1504{
1505 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1506 return tlsBackend->tlsLibraryBuildVersionNumber();
1507 return -1;
1508}
1509
1519{
1520 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1521 return tlsBackend->tlsLibraryBuildVersionString();
1522
1523 return {};
1524}
1525
1535{
1537}
1538
1565
1580{
1581 if (!backendName.size()) {
1582 qCWarning(lcSsl, "Invalid parameter (backend name cannot be an empty string)");
1583 return false;
1584 }
1585
1588 qCWarning(lcSsl) << "Cannot set backend named" << backendName
1589 << "as active, another backend is already in use";
1590 locker.unlock();
1591 return activeBackend() == backendName;
1592 }
1593
1595 qCWarning(lcSsl) << "Cannot set unavailable backend named" << backendName
1596 << "as active";
1597 return false;
1598 }
1599
1601
1602 return true;
1603}
1604
1618
1627{
1628 const auto versions = supportedProtocols(backendName);
1629 return versions.contains(protocol);
1630}
1631
1640QList<QSsl::ImplementedClass> QSslSocket::implementedClasses(const QString &backendName)
1641{
1643}
1644
1657
1665QList<QSsl::SupportedFeature> QSslSocket::supportedFeatures(const QString &backendName)
1666{
1668}
1669
1681
1696{
1697 Q_D(QSslSocket);
1698 if (d->mode != UnencryptedMode) {
1699 qCWarning(lcSsl,
1700 "QSslSocket::startClientEncryption: cannot start handshake on non-plain connection");
1701 return;
1702 }
1703 if (state() != ConnectedState) {
1704 qCWarning(lcSsl,
1705 "QSslSocket::startClientEncryption: cannot start handshake when not connected");
1706 return;
1707 }
1708
1709 if (!supportsSsl()) {
1710 qCWarning(lcSsl, "QSslSocket::startClientEncryption: TLS initialization failed");
1711 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
1712 return;
1713 }
1714
1715 if (!d->verifyProtocolSupported("QSslSocket::startClientEncryption:"))
1716 return;
1717
1718#ifdef QSSLSOCKET_DEBUG
1719 qCDebug(lcSsl) << "QSslSocket::startClientEncryption()";
1720#endif
1721 d->mode = SslClientMode;
1722 emit modeChanged(d->mode);
1723 d->startClientEncryption();
1724}
1725
1747{
1748 Q_D(QSslSocket);
1749 if (d->mode != UnencryptedMode) {
1750 qCWarning(lcSsl, "QSslSocket::startServerEncryption: cannot start handshake on non-plain connection");
1751 return;
1752 }
1753#ifdef QSSLSOCKET_DEBUG
1754 qCDebug(lcSsl) << "QSslSocket::startServerEncryption()";
1755#endif
1756 if (!supportsSsl()) {
1757 qCWarning(lcSsl, "QSslSocket::startServerEncryption: TLS initialization failed");
1758 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
1759 return;
1760 }
1761 if (!d->verifyProtocolSupported("QSslSocket::startServerEncryption"))
1762 return;
1763
1764 d->mode = SslServerMode;
1765 emit modeChanged(d->mode);
1766 d->startServerEncryption();
1767}
1768
1795{
1796 Q_D(QSslSocket);
1797 d->ignoreAllSslErrors = true;
1798}
1799
1821void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
1822{
1823 Q_D(QSslSocket);
1824 d->ignoreErrorsList = errors;
1825}
1826
1827
1839{
1840 Q_D(QSslSocket);
1841 if (auto *backend = d->backend.get())
1842 backend->enableHandshakeContinuation();
1843}
1844
1848void QSslSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode, NetworkLayerProtocol protocol)
1849{
1850 Q_D(QSslSocket);
1851 d->preferredNetworkLayerProtocol = protocol;
1852 if (!d->initialized)
1853 d->init();
1854 d->initialized = false;
1855
1856#ifdef QSSLSOCKET_DEBUG
1857 qCDebug(lcSsl) << "QSslSocket::connectToHost("
1858 << hostName << ',' << port << ',' << openMode << ')';
1859#endif
1860 if (!d->plainSocket) {
1861#ifdef QSSLSOCKET_DEBUG
1862 qCDebug(lcSsl) << "\tcreating internal plain socket";
1863#endif
1864 d->createPlainSocket(openMode);
1865 }
1866#ifndef QT_NO_NETWORKPROXY
1867 d->plainSocket->setProtocolTag(d->protocolTag);
1868 d->plainSocket->setProxy(proxy());
1869#endif
1871 d->readChannelCount = d->writeChannelCount = 0;
1872 d->plainSocket->connectToHost(hostName, port, openMode, d->preferredNetworkLayerProtocol);
1873 d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
1874}
1875
1880{
1881 Q_D(QSslSocket);
1882#ifdef QSSLSOCKET_DEBUG
1883 qCDebug(lcSsl) << "QSslSocket::disconnectFromHost()";
1884#endif
1885 if (!d->plainSocket)
1886 return;
1887 if (d->state == UnconnectedState)
1888 return;
1889 if (d->mode == UnencryptedMode && !d->autoStartHandshake) {
1890 d->plainSocket->disconnectFromHost();
1891 return;
1892 }
1893 if (d->state <= ConnectingState) {
1894 d->pendingClose = true;
1895 return;
1896 }
1897 // Make sure we don't process any signal from the CA fetcher
1898 // (Windows):
1899 if (auto *backend = d->backend.get())
1900 backend->cancelCAFetch();
1901
1902 // Perhaps emit closing()
1903 if (d->state != ClosingState) {
1904 d->state = ClosingState;
1905 emit stateChanged(d->state);
1906 }
1907
1908 if (!d->writeBuffer.isEmpty()) {
1909 d->pendingClose = true;
1910 return;
1911 }
1912
1913 if (d->mode == UnencryptedMode) {
1914 d->plainSocket->disconnectFromHost();
1915 } else {
1916 d->disconnectFromHost();
1917 }
1918}
1919
1924{
1925 Q_D(QSslSocket);
1926 qint64 readBytes = 0;
1927
1928 if (d->mode == UnencryptedMode && !d->autoStartHandshake) {
1929 readBytes = d->plainSocket->read(data, maxlen);
1930#ifdef QSSLSOCKET_DEBUG
1931 qCDebug(lcSsl) << "QSslSocket::readData(" << (void *)data << ',' << maxlen << ") =="
1932 << readBytes;
1933#endif
1934 } else {
1935 // possibly trigger another transmit() to decrypt more data from the socket
1936 if (d->plainSocket->bytesAvailable() || d->hasUndecryptedData())
1937 QMetaObject::invokeMethod(this, "_q_flushReadBuffer", Qt::QueuedConnection);
1938 else if (d->state != QAbstractSocket::ConnectedState)
1939 return maxlen ? qint64(-1) : qint64(0);
1940 }
1941
1942 return readBytes;
1943}
1944
1949{
1950 Q_D(QSslSocket);
1951#ifdef QSSLSOCKET_DEBUG
1952 qCDebug(lcSsl) << "QSslSocket::writeData(" << (void *)data << ',' << len << ')';
1953#endif
1954 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1955 return d->plainSocket->write(data, len);
1956
1957 d->write(data, len);
1958
1959 // make sure we flush to the plain socket's buffer
1960 if (!d->flushTriggered) {
1961 d->flushTriggered = true;
1962 QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
1963 }
1964
1965 return len;
1966}
1967
1969
1974 : initialized(false)
1975 , mode(QSslSocket::UnencryptedMode)
1976 , autoStartHandshake(false)
1977 , connectionEncrypted(false)
1978 , ignoreAllSslErrors(false)
1979 , readyReadEmittedPointer(nullptr)
1980 , allowRootCertOnDemandLoading(true)
1981 , plainSocket(nullptr)
1982 , paused(false)
1983 , flushTriggered(false)
1984{
1986 // If the global configuration doesn't allow root certificates to be loaded
1987 // on demand then we have to disable it for this socket as well.
1990
1991 const auto *tlsBackend = tlsBackendInUse();
1992 if (!tlsBackend) {
1993 qCWarning(lcSsl, "No TLS backend is available");
1994 return;
1995 }
1996 backend.reset(tlsBackend->createTlsCryptograph());
1997 if (!backend.get()) {
1998 qCWarning(lcSsl) << "The backend named" << tlsBackend->backendName()
1999 << "does not support TLS";
2000 }
2001}
2002
2009
2014{
2015 if (const auto *tlsBackend = tlsBackendInUse())
2016 return tlsBackend->implementedClasses().contains(QSsl::ImplementedClass::Socket);
2017 return false;
2018}
2019
2027{
2028 if (!supportsSsl())
2029 return;
2030
2031 const auto *tlsBackend = tlsBackendInUse();
2033 tlsBackend->ensureInitialized();
2034}
2035
2040{
2041 // TLSTODO: delete those data members.
2043 autoStartHandshake = false;
2044 connectionEncrypted = false;
2045 ignoreAllSslErrors = false;
2046 abortCalled = false;
2047 pendingClose = false;
2048 flushTriggered = false;
2049 // We don't want to clear the ignoreErrorsList, so
2050 // that it is possible setting it before connecting.
2051
2052 buffer.clear();
2053 writeBuffer.clear();
2056
2057 if (backend.get()) {
2058 Q_ASSERT(q_ptr);
2059 backend->init(static_cast<QSslSocket *>(q_ptr), this);
2060 }
2061}
2062
2067{
2068 auto protocolName = "DTLS"_L1;
2069 switch (configuration.protocol) {
2071 // UnknownProtocol, according to our docs, is for cipher whose protocol is unknown.
2072 // Should not be used when configuring QSslSocket.
2073 protocolName = "UnknownProtocol"_L1;
2074 Q_FALLTHROUGH();
2077 case QSsl::DtlsV1_0:
2078 case QSsl::DtlsV1_2:
2079 case QSsl::DtlsV1_0OrLater:
2081 qCWarning(lcSsl) << where << "QSslConfiguration with unexpected protocol" << protocolName;
2083 QSslSocket::tr("Attempted to use an unsupported protocol."));
2084 return false;
2086 default:
2087 return true;
2088 }
2089}
2090
2095{
2097 QMutexLocker locker(&globalData()->mutex);
2098 return globalData()->config->ciphers;
2099}
2100
2105{
2107 QMutexLocker locker(&globalData()->mutex);
2108 return globalData()->supportedCiphers;
2109}
2110
2114void QSslSocketPrivate::setDefaultCiphers(const QList<QSslCipher> &ciphers)
2115{
2116 QMutexLocker locker(&globalData()->mutex);
2117 globalData()->config.detach();
2118 globalData()->config->ciphers = ciphers;
2119}
2120
2124void QSslSocketPrivate::setDefaultSupportedCiphers(const QList<QSslCipher> &ciphers)
2125{
2126 QMutexLocker locker(&globalData()->mutex);
2127 globalData()->config.detach();
2128 globalData()->supportedCiphers = ciphers;
2129}
2130
2135{
2136 const auto *tlsBackend = tlsBackendInUse();
2137 if (!tlsBackend)
2138 return;
2139
2140 auto ids = tlsBackend->ellipticCurvesIds();
2141 if (!ids.size())
2142 return;
2143
2144 QList<QSslEllipticCurve> curves;
2145 curves.reserve(ids.size());
2146 for (int id : ids) {
2147 QSslEllipticCurve curve;
2148 curve.id = id;
2149 curves.append(curve);
2150 }
2151
2152 // Set the list of supported ECs, but not the list
2153 // of *default* ECs. OpenSSL doesn't like forcing an EC for the wrong
2154 // ciphersuite, so don't try it -- leave the empty list to mean
2155 // "the implementation will choose the most suitable one".
2157}
2158
2162void QSslSocketPrivate::setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers)
2163{
2164 QMutexLocker locker(&globalData()->mutex);
2165 globalData()->dtlsConfig.detach();
2166 globalData()->dtlsConfig->ciphers = ciphers;
2167}
2168
2173{
2175 QMutexLocker locker(&globalData()->mutex);
2176 return globalData()->dtlsConfig->ciphers;
2177}
2178
2183{
2185 const QMutexLocker locker(&globalData()->mutex);
2186 return globalData()->supportedEllipticCurves;
2187}
2188
2192void QSslSocketPrivate::setDefaultSupportedEllipticCurves(const QList<QSslEllipticCurve> &curves)
2193{
2194 const QMutexLocker locker(&globalData()->mutex);
2195 globalData()->config.detach();
2196 globalData()->dtlsConfig.detach();
2197 globalData()->supportedEllipticCurves = curves;
2198}
2199
2204{
2206 QMutexLocker locker(&globalData()->mutex);
2207 return globalData()->config->caCertificates;
2208}
2209
2213void QSslSocketPrivate::setDefaultCaCertificates(const QList<QSslCertificate> &certs)
2214{
2216 QMutexLocker locker(&globalData()->mutex);
2217 globalData()->config.detach();
2218 globalData()->config->caCertificates = certs;
2219 globalData()->dtlsConfig.detach();
2220 globalData()->dtlsConfig->caCertificates = certs;
2221 // when the certificates are set explicitly, we do not want to
2222 // load the system certificates on demand
2224}
2225
2230{
2232 QMutexLocker locker(&globalData()->mutex);
2233 if (globalData()->config->caCertificates.contains(cert))
2234 return;
2235 globalData()->config.detach();
2236 globalData()->config->caCertificates += cert;
2237 globalData()->dtlsConfig.detach();
2238 globalData()->dtlsConfig->caCertificates += cert;
2239}
2240
2244void QSslSocketPrivate::addDefaultCaCertificates(const QList<QSslCertificate> &certs)
2245{
2247 QMutexLocker locker(&globalData()->mutex);
2248 globalData()->config.detach();
2249 globalData()->config->caCertificates += certs;
2250 globalData()->dtlsConfig.detach();
2251 globalData()->dtlsConfig->caCertificates += certs;
2252}
2253
2263
2268{
2270 QMutexLocker locker(&globalData()->mutex);
2271 if (globalData()->config == configuration.d)
2272 return; // nothing to do
2273
2274 globalData()->config = const_cast<QSslConfigurationPrivate*>(configuration.d.constData());
2275}
2276
2281{
2283 QMutexLocker locker(&globalData()->mutex);
2284 const QSslConfigurationPrivate *global = globalData()->config.constData();
2285
2286 if (!global)
2287 return;
2288
2289 ptr->ref.storeRelaxed(1);
2290 ptr->peerCertificate = global->peerCertificate;
2291 ptr->peerCertificateChain = global->peerCertificateChain;
2292 ptr->localCertificateChain = global->localCertificateChain;
2293 ptr->privateKey = global->privateKey;
2294 ptr->sessionCipher = global->sessionCipher;
2295 ptr->sessionProtocol = global->sessionProtocol;
2296 ptr->ciphers = global->ciphers;
2297 ptr->caCertificates = global->caCertificates;
2298 ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
2299 ptr->protocol = global->protocol;
2300 ptr->peerVerifyMode = global->peerVerifyMode;
2301 ptr->peerVerifyDepth = global->peerVerifyDepth;
2302 ptr->sslOptions = global->sslOptions;
2303 ptr->ellipticCurves = global->ellipticCurves;
2304 ptr->backendConfig = global->backendConfig;
2305#if QT_CONFIG(dtls)
2306 ptr->dtlsCookieEnabled = global->dtlsCookieEnabled;
2307#endif
2308#if QT_CONFIG(ocsp)
2309 ptr->ocspStaplingEnabled = global->ocspStaplingEnabled;
2310#endif
2311#if QT_CONFIG(openssl)
2312 ptr->reportFromCallback = global->reportFromCallback;
2313 ptr->missingCertIsFatal = global->missingCertIsFatal;
2314#endif
2315}
2316
2321{
2323 QMutexLocker locker(&globalData()->mutex);
2324
2325 return QSslConfiguration(globalData()->dtlsConfig.data());
2326}
2327
2332{
2334 QMutexLocker locker(&globalData()->mutex);
2335 if (globalData()->dtlsConfig == configuration.d)
2336 return; // nothing to do
2337
2338 globalData()->dtlsConfig = const_cast<QSslConfigurationPrivate*>(configuration.d.constData());
2339}
2340
2344void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode)
2345{
2346 Q_Q(QSslSocket);
2347 q->setOpenMode(openMode); // <- from QIODevice
2348 q->setSocketState(QAbstractSocket::UnconnectedState);
2349 q->setSocketError(QAbstractSocket::UnknownSocketError);
2350 q->setLocalPort(0);
2351 q->setLocalAddress(QHostAddress());
2352 q->setPeerPort(0);
2353 q->setPeerAddress(QHostAddress());
2354 q->setPeerName(QString());
2355
2356 plainSocket = new QTcpSocket(q);
2357 q->connect(plainSocket, SIGNAL(connected()),
2360 q->connect(plainSocket, SIGNAL(hostFound()),
2363 q->connect(plainSocket, SIGNAL(disconnected()),
2366 q->connect(plainSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
2369 q->connect(plainSocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
2372 q->connect(plainSocket, SIGNAL(readyRead()),
2375 q->connect(plainSocket, SIGNAL(channelReadyRead(int)),
2381 q->connect(plainSocket, SIGNAL(channelBytesWritten(int,qint64)),
2384 q->connect(plainSocket, SIGNAL(readChannelFinished()),
2387#ifndef QT_NO_NETWORKPROXY
2390#endif
2391
2392 buffer.clear();
2393 writeBuffer.clear();
2394 connectionEncrypted = false;
2398 q->setReadBufferSize(readBufferMaxSize);
2399}
2400
2402{
2403 if (!socket->d_func()->plainSocket)
2404 return;
2406}
2407
2409{
2410 if (!socket->d_func()->plainSocket)
2411 return;
2413}
2414
2416{
2417 return paused;
2418}
2419
2421{
2422 paused = p;
2423}
2424
2425bool QSslSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
2426{
2427 // this function is called from QAbstractSocket::bind
2428 if (!initialized)
2429 init();
2430 initialized = false;
2431
2432#ifdef QSSLSOCKET_DEBUG
2433 qCDebug(lcSsl) << "QSslSocket::bind(" << address << ',' << port << ',' << mode << ')';
2434#endif
2435 if (!plainSocket) {
2436#ifdef QSSLSOCKET_DEBUG
2437 qCDebug(lcSsl) << "\tcreating internal plain socket";
2438#endif
2440 }
2441 bool ret = plainSocket->bind(address, port, mode);
2446 return ret;
2447}
2448
2453{
2454 Q_Q(QSslSocket);
2455 q->setLocalPort(plainSocket->localPort());
2456 q->setLocalAddress(plainSocket->localAddress());
2457 q->setPeerPort(plainSocket->peerPort());
2458 q->setPeerAddress(plainSocket->peerAddress());
2459 q->setPeerName(plainSocket->peerName());
2463
2464#ifdef QSSLSOCKET_DEBUG
2465 qCDebug(lcSsl) << "QSslSocket::_q_connectedSlot()";
2466 qCDebug(lcSsl) << "\tstate =" << q->state();
2467 qCDebug(lcSsl) << "\tpeer =" << q->peerName() << q->peerAddress() << q->peerPort();
2468 qCDebug(lcSsl) << "\tlocal =" << QHostInfo::fromName(q->localAddress().toString()).hostName()
2469 << q->localAddress() << q->localPort();
2470#endif
2471
2473 q->startClientEncryption();
2474
2475 emit q->connected();
2476
2478 pendingClose = false;
2479 q->disconnectFromHost();
2480 }
2481}
2482
2487{
2488 Q_Q(QSslSocket);
2489#ifdef QSSLSOCKET_DEBUG
2490 qCDebug(lcSsl) << "QSslSocket::_q_hostFoundSlot()";
2491 qCDebug(lcSsl) << "\tstate =" << q->state();
2492#endif
2493 emit q->hostFound();
2494}
2495
2500{
2501 Q_Q(QSslSocket);
2502#ifdef QSSLSOCKET_DEBUG
2503 qCDebug(lcSsl) << "QSslSocket::_q_disconnectedSlot()";
2504 qCDebug(lcSsl) << "\tstate =" << q->state();
2505#endif
2506 disconnected();
2507 emit q->disconnected();
2508
2509 q->setLocalPort(0);
2510 q->setLocalAddress(QHostAddress());
2511 q->setPeerPort(0);
2512 q->setPeerAddress(QHostAddress());
2513 q->setPeerName(QString());
2515}
2516
2521{
2522 Q_Q(QSslSocket);
2523#ifdef QSSLSOCKET_DEBUG
2524 qCDebug(lcSsl) << "QSslSocket::_q_stateChangedSlot(" << state << ')';
2525#endif
2526 q->setSocketState(state);
2527 emit q->stateChanged(state);
2528}
2529
2534{
2535 Q_UNUSED(error);
2536#ifdef QSSLSOCKET_DEBUG
2537 Q_Q(QSslSocket);
2538 qCDebug(lcSsl) << "QSslSocket::_q_errorSlot(" << error << ')';
2539 qCDebug(lcSsl) << "\tstate =" << q->state();
2540 qCDebug(lcSsl) << "\terrorString =" << q->errorString();
2541#endif
2542 // this moves encrypted bytes from plain socket into our buffer
2544 qint64 tmpReadBufferMaxSize = readBufferMaxSize;
2545 readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained
2546 transmit();
2547 readBufferMaxSize = tmpReadBufferMaxSize;
2548 }
2549
2551}
2552
2557{
2558 Q_Q(QSslSocket);
2559#ifdef QSSLSOCKET_DEBUG
2560 qCDebug(lcSsl) << "QSslSocket::_q_readyReadSlot() -" << plainSocket->bytesAvailable() << "bytes available";
2561#endif
2565 emit q->readyRead();
2566 return;
2567 }
2568
2569 transmit();
2570}
2571
2576{
2577 Q_Q(QSslSocket);
2579 emit q->channelReadyRead(channel);
2580}
2581
2586{
2587 Q_Q(QSslSocket);
2588#ifdef QSSLSOCKET_DEBUG
2589 qCDebug(lcSsl) << "QSslSocket::_q_bytesWrittenSlot(" << written << ')';
2590#endif
2591
2593 emit q->bytesWritten(written);
2594 else
2595 emit q->encryptedBytesWritten(written);
2597 q->disconnectFromHost();
2598}
2599
2604{
2605 Q_Q(QSslSocket);
2607 emit q->channelBytesWritten(channel, written);
2608}
2609
2614{
2615 Q_Q(QSslSocket);
2616 emit q->readChannelFinished();
2617}
2618
2623{
2624 Q_Q(QSslSocket);
2625
2626 // need to notice if knock-on effects of this flush (e.g. a readReady() via transmit())
2627 // make another necessary, so clear flag before calling:
2628 flushTriggered = false;
2629 if (!writeBuffer.isEmpty())
2630 q->flush();
2631}
2632
2637{
2638 // trigger a read from the plainSocket into SSL
2640 transmit();
2641}
2642
2647{
2648 if (plainSocket)
2650 paused = false;
2651 if (!connectionEncrypted) {
2654 } else {
2655 const auto sslErrors = backend->tlsErrors();
2656 Q_ASSERT(!sslErrors.isEmpty());
2657 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
2659 return;
2660 }
2661 }
2662 transmit();
2663}
2664
2669{
2670 Q_ASSERT(backend.get());
2671
2672 bool doEmitSslError;
2673 if (!ignoreErrorsList.empty()) {
2674 // check whether the errors we got are all in the list of expected errors
2675 // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
2676 // was called)
2677 const auto &sslErrors = backend->tlsErrors();
2678 doEmitSslError = false;
2679 for (int a = 0; a < sslErrors.size(); a++) {
2680 if (!ignoreErrorsList.contains(sslErrors.at(a))) {
2681 doEmitSslError = true;
2682 break;
2683 }
2684 }
2685 } else {
2686 // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and
2687 // we get an SSL error, emit a signal unless we ignored all errors (by calling
2688 // QSslSocket::ignoreSslErrors() )
2689 doEmitSslError = !ignoreAllSslErrors;
2690 }
2691 return !doEmitSslError;
2692}
2693
2701
2706{
2707 return pendingClose;
2708}
2709
2714{
2715 pendingClose = pc;
2716}
2717
2725
2730{
2731 readBufferMaxSize = maxSize;
2732}
2733
2738{
2739 connectionEncrypted = enc;
2740}
2741
2749
2757
2765
2773
2775{
2776 return backend.get() && backend->hasUndecryptedData();
2777}
2778
2783{
2785 //unencrypted mode - do not use QIODevice::peek, as it reads ahead data from the plain socket
2786 //peek at data already in the QIODevice buffer (from a previous read)
2787 qint64 r = buffer.peek(data, maxSize, transactionPos);
2788 if (r == maxSize)
2789 return r;
2790 data += r;
2791 //peek at data in the plain socket
2792 if (plainSocket) {
2793 qint64 r2 = plainSocket->peek(data, maxSize - r);
2794 if (r2 < 0)
2795 return (r > 0 ? r : r2);
2796 return r + r2;
2797 }
2798
2799 return -1;
2800 } else {
2801 //encrypted mode - the socket engine will read and decrypt data into the QIODevice buffer
2802 return QTcpSocketPrivate::peek(data, maxSize);
2803 }
2804}
2805
2810{
2812 //unencrypted mode - do not use QIODevice::peek, as it reads ahead data from the plain socket
2813 //peek at data already in the QIODevice buffer (from a previous read)
2815 ret.reserve(maxSize);
2816 ret.resize(buffer.peek(ret.data(), maxSize, transactionPos));
2817 if (ret.size() == maxSize)
2818 return ret;
2819 //peek at data in the plain socket
2820 if (plainSocket)
2821 return ret + plainSocket->peek(maxSize - ret.size());
2822
2823 return QByteArray();
2824 } else {
2825 //encrypted mode - the socket engine will read and decrypt data into the QIODevice buffer
2826 return QTcpSocketPrivate::peek(maxSize);
2827 }
2828}
2829
2834{
2835 Q_D(QSslSocket);
2836
2837 if (d->mode == QSslSocket::UnencryptedMode && !d->autoStartHandshake)
2838 return d->plainSocket->skip(maxSize);
2839
2840 // In encrypted mode, the SSL backend writes decrypted data directly into the
2841 // QIODevice's read buffer. As this buffer is always emptied by the caller,
2842 // we need to wait for more incoming data.
2843 return (d->state == QAbstractSocket::ConnectedState) ? Q_INT64_C(0) : Q_INT64_C(-1);
2844}
2845
2850{
2851#ifdef QSSLSOCKET_DEBUG
2852 qCDebug(lcSsl) << "QSslSocketPrivate::flush()";
2853#endif
2855 // encrypt any unencrypted bytes in our buffer
2856 transmit();
2857 }
2858
2859 return plainSocket && plainSocket->flush();
2860}
2861
2866{
2867 if (backend.get())
2868 backend->startClientEncryption();
2869}
2870
2875{
2876 if (backend.get())
2877 backend->startServerEncryption();
2878}
2879
2884{
2885 if (backend.get())
2886 backend->transmit();
2887}
2888
2893{
2894 if (backend.get())
2895 backend->disconnectFromHost();
2896}
2897
2902{
2903 if (backend.get())
2904 backend->disconnected();
2905}
2906
2911{
2912 if (backend.get())
2913 return backend->sessionCipher();
2914
2915 return {};
2916}
2917
2922{
2923 if (backend.get())
2924 return backend->sessionProtocol();
2925
2926 return QSsl::UnknownProtocol;
2927}
2928
2933{
2934 if (backend.get())
2935 backend->continueHandshake();
2936}
2937
2945
2953
2958{
2959 const auto ba = [](const auto &cstr) constexpr {
2960 return QByteArray::fromRawData(std::begin(cstr), std::size(cstr) - 1);
2961 };
2962 static const QByteArray dirs[] = {
2963 ba("/etc/ssl/certs/"), // (K)ubuntu, OpenSUSE, Mandriva ...
2964 ba("/usr/lib/ssl/certs/"), // Gentoo, Mandrake
2965 ba("/usr/share/ssl/"), // Centos, Redhat, SuSE
2966 ba("/usr/local/ssl/"), // Normal OpenSSL Tarball
2967 ba("/var/ssl/certs/"), // AIX
2968 ba("/usr/local/ssl/certs/"), // Solaris
2969 ba("/etc/openssl/certs/"), // BlackBerry
2970 ba("/opt/openssl/certs/"), // HP-UX
2971 ba("/etc/ssl/"), // OpenBSD
2972 };
2973 QList<QByteArray> result = QList<QByteArray>::fromReadOnlyData(dirs);
2974 if constexpr (isVxworks) {
2975 static QByteArray vxworksCertsDir = qgetenv("VXWORKS_CERTS_DIR");
2976 if (!vxworksCertsDir.isEmpty())
2977 result.push_back(vxworksCertsDir);
2978 }
2979 return result;
2980}
2981
2985void QSslSocketPrivate::checkSettingSslContext(QSslSocket* socket, std::shared_ptr<QSslContext> tlsContext)
2986{
2987 if (!socket)
2988 return;
2989
2990 if (auto *backend = socket->d_func()->backend.get())
2991 backend->checkSettingSslContext(tlsContext);
2992}
2993
2998{
2999 if (!socket)
3000 return {};
3001
3002 if (const auto *backend = socket->d_func()->backend.get())
3003 return backend->sslContext();
3004
3005 return {};
3006}
3007
3009{
3010 QHostAddress hostAddress(peerName);
3011 if (!hostAddress.isNull()) {
3012 const auto subjectAlternativeNames = cert.subjectAlternativeNames();
3013 const auto ipAddresses = subjectAlternativeNames.equal_range(QSsl::AlternativeNameEntryType::IpAddressEntry);
3014
3015 for (auto it = ipAddresses.first; it != ipAddresses.second; it++) {
3017 return true;
3018 }
3019 }
3020
3021 const QString lowerPeerName = QString::fromLatin1(QUrl::toAce(peerName));
3022 const QStringList commonNames = cert.subjectInfo(QSslCertificate::CommonName);
3023
3024 for (const QString &commonName : commonNames) {
3025 if (isMatchingHostname(commonName, lowerPeerName))
3026 return true;
3027 }
3028
3029 const auto subjectAlternativeNames = cert.subjectAlternativeNames();
3030 const auto altNames = subjectAlternativeNames.equal_range(QSsl::DnsEntry);
3031 for (auto it = altNames.first; it != altNames.second; ++it) {
3032 if (isMatchingHostname(*it, lowerPeerName))
3033 return true;
3034 }
3035
3036 return false;
3037}
3038
3044{
3045 qsizetype wildcard = cn.indexOf(u'*');
3046
3047 // Check this is a wildcard cert, if not then just compare the strings
3048 if (wildcard < 0)
3049 return QLatin1StringView(QUrl::toAce(cn)) == hostname;
3050
3051 qsizetype firstCnDot = cn.indexOf(u'.');
3052 qsizetype secondCnDot = cn.indexOf(u'.', firstCnDot+1);
3053
3054 // Check at least 3 components
3055 if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.size()))
3056 return false;
3057
3058 // Check * is last character of 1st component (ie. there's a following .)
3059 if (wildcard+1 != firstCnDot)
3060 return false;
3061
3062 // Check only one star
3063 if (cn.lastIndexOf(u'*') != wildcard)
3064 return false;
3065
3066 // Reject wildcard character embedded within the A-labels or U-labels of an internationalized
3067 // domain name (RFC6125 section 7.2)
3068 if (cn.startsWith("xn--"_L1, Qt::CaseInsensitive))
3069 return false;
3070
3071 // Check characters preceding * (if any) match
3072 if (wildcard && QStringView{hostname}.left(wildcard).compare(QStringView{cn}.left(wildcard), Qt::CaseInsensitive) != 0)
3073 return false;
3074
3075 // Check characters following first . match
3076 qsizetype hnDot = hostname.indexOf(u'.');
3077 if (QStringView{hostname}.mid(hnDot + 1) != QStringView{cn}.mid(firstCnDot + 1)
3078 && QStringView{hostname}.mid(hnDot + 1) != QLatin1StringView(QUrl::toAce(cn.mid(firstCnDot + 1)))) {
3079 return false;
3080 }
3081
3082 // Check if the hostname is an IP address, if so then wildcards are not allowed
3083 QHostAddress addr(hostname);
3084 if (!addr.isNull())
3085 return false;
3086
3087 // Ok, I guess this was a wildcard CN and the hostname matches.
3088 return true;
3089}
3090
3095{
3096 const QMutexLocker locker(&backendMutex);
3097 if (tlsBackend)
3098 return tlsBackend;
3099
3100 if (!activeBackendName.size())
3102
3103 if (!activeBackendName.size()) {
3104 qCWarning(lcSsl, "No functional TLS backend was found");
3105 return nullptr;
3106 }
3107
3109 if (tlsBackend) {
3111 const QMutexLocker locker(&backendMutex);
3112 tlsBackend = nullptr;
3113 },
3115 }
3116 return tlsBackend;
3117}
3118
3123{
3124 return mode;
3125}
3126
3134
3142
3147{
3148 return hostName;
3149}
3150
3155
3160{
3161 if (const auto *tlsBackend = tlsBackendInUse())
3162 return tlsBackend->systemCaCertificates();
3163 return {};
3164}
3165
3167
3168#include "moc_qsslsocket.cpp"
IOBluetoothL2CAPChannel * channel
bool connected
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) override
static void pauseSocketNotifiers(QAbstractSocket *)
QAbstractSocket::SocketState state
static void resumeSocketNotifiers(QAbstractSocket *)
void setErrorAndEmit(QAbstractSocket::SocketError errorCode, const QString &errorString)
SocketState
This enum describes the different states in which a socket can be.
bool flush()
This function writes as much as possible from the internal write buffer to the underlying network soc...
void stateChanged(QAbstractSocket::SocketState)
This signal is emitted whenever QAbstractSocket's state changes.
quint16 peerPort() const
Returns the port of the connected peer if the socket is in ConnectedState; otherwise returns 0.
virtual qintptr socketDescriptor() const
Returns the native socket descriptor of the QAbstractSocket object if this is available; otherwise re...
void setPeerPort(quint16 port)
qint64 bytesAvailable() const override
Returns the number of incoming bytes that are waiting to be read.
QHostAddress localAddress() const
Returns the host address of the local socket if available; otherwise returns QHostAddress::Null.
QString peerName() const
Returns the name of the peer as specified by connectToHost(), or an empty QString if connectToHost() ...
QNetworkProxy proxy() const
virtual bool bind(const QHostAddress &address, quint16 port=0, BindMode mode=DefaultForPlatform)
virtual void disconnectFromHost()
Attempts to close the socket.
void setPeerAddress(const QHostAddress &address)
void setLocalPort(quint16 port)
void setLocalAddress(const QHostAddress &address)
SocketState state() const
Returns the state of the socket.
SocketError
This enum describes the socket errors that can occur.
void setSocketState(SocketState state)
Sets the state of the socket to state.
quint16 localPort() const
Returns the host port number (in native byte order) of the local socket if available; otherwise retur...
void setPeerName(const QString &name)
virtual void resume()
SocketError error() const
Returns the type of error that last occurred.
QHostAddress peerAddress() const
Returns the address of the connected peer if the socket is in ConnectedState; otherwise returns QHost...
The QAuthenticator class provides an authentication object.
\inmodule QtCore
Definition qbytearray.h:57
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:634
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:409
\inmodule QtCore
void start() noexcept
\typealias QElapsedTimer::Duration Synonym for std::chrono::nanoseconds.
\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.
bool isEqual(const QHostAddress &address, ConversionMode mode=TolerantConversion) const
static QHostInfo fromName(const QString &name)
Looks up the IP address(es) for the given host name.
qint64 peek(char *data, qint64 maxLength, qint64 pos=0) const
Definition qiodevice_p.h:84
QIODevice::OpenMode openMode
qint64 transactionPos
Definition qiodevice_p.h:55
virtual qint64 peek(char *data, qint64 maxSize)
QRingBufferRef buffer
Definition qiodevice_p.h:92
QRingBufferRef writeBuffer
Definition qiodevice_p.h:93
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
int writeChannelCount() const
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
void setOpenMode(QIODeviceBase::OpenMode openMode)
Sets the OpenMode of the device to openMode.
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
QIODeviceBase::OpenMode openMode() const
Returns the mode in which the device has been opened; i.e.
qint64 peek(char *data, qint64 maxlen)
QString errorString() const
Returns a human-readable description of the last device error that occurred.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i....
int readChannelCount() const
virtual bool canReadLine() const
Returns true if a complete line of data can be read from the device; otherwise returns false.
bool empty() const noexcept
Definition qlist.h:685
static QList< T > fromReadOnlyData(const T(&t)[N]) noexcept
Definition qlist.h:729
void detach()
Definition qlist.h:426
void clear()
Definition qlist.h:434
\inmodule QtCore
Definition qmutex.h:313
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:319
\inmodule QtCore
Definition qmutex.h:281
The QNetworkProxy class provides a network layer proxy.
QObject * q_ptr
Definition qobject.h:72
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
const T * constData() const noexcept
Returns a const pointer to the shared data object.
Definition qshareddata.h:51
The QSslCertificate class provides a convenient API for an X509 certificate.
void clear()
Clears the contents of this certificate, making it a null certificate.
The QSslCipher class represents an SSL cryptographic cipher.
Definition qsslcipher.h:22
static QSslConfiguration defaultConfiguration()
static void setDefaultDtlsConfiguration(const QSslConfiguration &configuration)
static void deepCopyDefaultConfiguration(QSslConfigurationPrivate *config)
QList< QSslCertificate > peerCertificateChain
static void setDefaultConfiguration(const QSslConfiguration &configuration)
static QSslConfiguration defaultDtlsConfiguration()
The QSslConfiguration class holds the configuration and state of an SSL connection.
QList< QByteArray > allowedNextProtocols() const
QList< QSslCertificate > caCertificates() const
Returns this connection's CA certificate database.
bool ocspStaplingEnabled() const
QList< QSslCertificate > localCertificateChain() const
Returns the certificate chain to be presented to the peer during the SSL handshake process.
QSslSocket::PeerVerifyMode peerVerifyMode() const
Returns the verify mode.
QSsl::SslProtocol protocol() const
Returns the protocol setting for this SSL configuration.
QSslDiffieHellmanParameters diffieHellmanParameters() const
QByteArray preSharedKeyIdentityHint() const
int sessionTicketLifeTimeHint() const
int peerVerifyDepth() const
Returns the maximum number of certificates in the peer's certificate chain to be checked during the S...
QByteArray nextNegotiatedProtocol() const
QSslKey privateKey() const
Returns the \l {QSslKey} {SSL key} assigned to this connection or a null key if none has been assigne...
QList< QSslEllipticCurve > ellipticCurves() const
QList< QSslCipher > ciphers() const
Returns this connection's current cryptographic cipher suite.
QByteArray sessionTicket() const
bool handshakeMustInterruptOnError() const
bool missingCertificateIsFatal() const
QMap< QByteArray, QVariant > backendConfiguration() const
NextProtocolNegotiationStatus nextProtocolNegotiationStatus() const
Represents an elliptic curve for use by elliptic-curve cipher algorithms.
The QSslKey class provides an interface for private and public keys.
Definition qsslkey.h:23
QExplicitlySharedDataPointer< QSslConfigurationPrivate > dtlsConfig
QExplicitlySharedDataPointer< QSslConfigurationPrivate > config
QList< QSslEllipticCurve > supportedEllipticCurves
QList< QSslCipher > supportedCiphers
bool * readyReadPointer()
bool verifyErrorsHaveBeenIgnored()
static void setDefaultCaCertificates(const QList< QSslCertificate > &certs)
void setEncrypted(bool enc)
static void setDefaultDtlsCiphers(const QList< QSslCipher > &ciphers)
static bool supportsSsl()
void setMaxReadBufferSize(qint64 maxSize)
static void addDefaultCaCertificate(const QSslCertificate &cert)
QTcpSocket * plainTcpSocket() const
QTcpSocket * plainSocket
QString verificationName() const
void _q_readChannelFinishedSlot()
QSslCipher sessionCipher() const
bool isAutoStartingHandshake() const
bool * readyReadEmittedPointer
static QTlsBackend * tlsBackendInUse()
static void setDefaultCiphers(const QList< QSslCipher > &ciphers)
static void resumeSocketNotifiers(QSslSocket *)
QString verificationPeerName
qint64 peek(char *data, qint64 maxSize) override
void _q_channelReadyReadSlot(int)
static void setRootCertOnDemandLoadingSupported(bool supported)
bool isRootsOnDemandAllowed() const
static std::shared_ptr< QSslContext > sslContext(QSslSocket *socket)
static QList< QSslCertificate > defaultCaCertificates()
QSslSocket::SslMode mode
bool allowRootCertOnDemandLoading
bool isPaused() const
static void ensureInitialized()
qint64 maxReadBufferSize() const
bool & tlsEmittedBytesWritten()
QString tlsHostName() const
static QList< QByteArray > unixRootCertDirectories()
std::unique_ptr< QTlsPrivate::TlsCryptograph > backend
bool flush() override
QRingBufferRef & tlsBuffer()
static QList< QSslCipher > defaultDtlsCiphers()
bool verifyProtocolSupported(const char *where)
static void checkSettingSslContext(QSslSocket *, std::shared_ptr< QSslContext >)
static QList< QSslCipher > supportedCiphers()
void _q_stateChangedSlot(QAbstractSocket::SocketState)
static bool rootCertOnDemandLoadingSupported()
static QString activeBackendName
static QList< QSslEllipticCurve > supportedEllipticCurves()
static void addDefaultCaCertificates(const QList< QSslCertificate > &certs)
static QMutex backendMutex
void _q_errorSlot(QAbstractSocket::SocketError)
void _q_resumeImplementation()
void setPaused(bool p)
void createPlainSocket(QIODevice::OpenMode openMode)
void setPendingClose(bool pc)
virtual ~QSslSocketPrivate()
static void pauseSocketNotifiers(QSslSocket *)
bool hasUndecryptedData() const
void _q_bytesWrittenSlot(qint64)
QRingBufferRef & tlsWriteBuffer()
QSsl::SslProtocol sessionProtocol() const
void _q_channelBytesWrittenSlot(int, qint64)
QList< QSslError > ignoreErrorsList
static QList< QSslCertificate > systemCaCertificates()
static void resetDefaultEllipticCurves()
static void setDefaultSupportedEllipticCurves(const QList< QSslEllipticCurve > &curves)
static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName)
static bool s_loadRootCertsOnDemand
QSslSocket::SslMode tlsMode() const
static QList< QSslCipher > defaultCiphers()
static void setDefaultSupportedCiphers(const QList< QSslCipher > &ciphers)
bool bind(const QHostAddress &address, quint16, QAbstractSocket::BindMode) override
static QTlsBackend * tlsBackend
bool isPendingClose() const
QSslConfigurationPrivate configuration
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition qsslsocket.h:29
QList< QSslCertificate > peerCertificateChain() const
Returns the peer's chain of digital certificates, or an empty list of certificates.
void resume() override
\reimp
static QString sslLibraryBuildVersionString()
static QList< QSsl::ImplementedClass > implementedClasses(const QString &backendName={})
QSslConfiguration sslConfiguration() const
void setLocalCertificateChain(const QList< QSslCertificate > &localChain)
Sets the certificate chain to be presented to the peer during the SSL handshake to be localChain.
bool isEncrypted() const
Returns true if the socket is encrypted; otherwise, false is returned.
bool canReadLine() const override
\reimp
void disconnectFromHost() override
QList< QOcspResponse > ocspResponses() const
bool waitForReadyRead(int msecs=30000) override
\reimp
static bool setActiveBackend(const QString &backendName)
bool waitForBytesWritten(int msecs=30000) override
\reimp
void setPrivateKey(const QSslKey &key)
Sets the socket's private \l {QSslKey} {key} to key.
qint64 skipData(qint64 maxSize) override
\reimp
static QList< QSsl::SslProtocol > supportedProtocols(const QString &backendName={})
virtual void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value) override
QSslCipher sessionCipher() const
Returns the socket's cryptographic \l {QSslCipher} {cipher}, or a null cipher if the connection isn't...
void startServerEncryption()
Starts a delayed SSL handshake for a server connection.
QString peerVerifyName() const
void ignoreSslErrors()
This slot tells QSslSocket to ignore errors during QSslSocket's handshake phase and continue connecti...
bool setSocketDescriptor(qintptr socketDescriptor, SocketState state=ConnectedState, OpenMode openMode=ReadWrite) override
Initializes QSslSocket with the native socket descriptor socketDescriptor.
static long sslLibraryVersionNumber()
QSslSocket::PeerVerifyMode peerVerifyMode() const
SslMode
Describes the connection modes available for QSslSocket.
Definition qsslsocket.h:33
@ UnencryptedMode
Definition qsslsocket.h:34
void setPeerVerifyMode(QSslSocket::PeerVerifyMode mode)
SslMode mode() const
Returns the current mode for the socket; either UnencryptedMode, where QSslSocket behaves identially ...
qint64 writeData(const char *data, qint64 len) override
\reimp
QSsl::SslProtocol protocol() const
Returns the socket's SSL protocol.
QList< QSslError > sslHandshakeErrors() const
static QList< QSsl::SupportedFeature > supportedFeatures(const QString &backendName={})
qint64 bytesToWrite() const override
\reimp
int peerVerifyDepth() const
bool waitForEncrypted(int msecs=30000)
Waits until the socket has completed the SSL handshake and has emitted encrypted(),...
qint64 readData(char *data, qint64 maxlen) override
\reimp
qint64 encryptedBytesAvailable() const
void close() override
\reimp
static bool supportsSsl()
Returns true if this platform supports SSL; otherwise, returns false.
void setSslConfiguration(const QSslConfiguration &config)
void connectToHost(const QString &hostName, quint16 port, OpenMode openMode=ReadWrite, NetworkLayerProtocol protocol=AnyIPProtocol) override
~QSslSocket()
Destroys the QSslSocket.
bool waitForDisconnected(int msecs=30000) override
Waits until the socket has disconnected or msecs milliseconds, whichever comes first.
static long sslLibraryBuildVersionNumber()
virtual QVariant socketOption(QAbstractSocket::SocketOption option) override
static QString sslLibraryVersionString()
void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode mode=ReadWrite, NetworkLayerProtocol protocol=AnyIPProtocol)
Starts an encrypted connection to the device hostName on port, using mode as the \l OpenMode.
void setPeerVerifyName(const QString &hostName)
QSslCertificate localCertificate() const
Returns the socket's local \l {QSslCertificate} {certificate}, or an empty certificate if no local ce...
qint64 encryptedBytesToWrite() const
void continueInterruptedHandshake()
static bool isClassImplemented(QSsl::ImplementedClass cl, const QString &backendName={})
void setReadBufferSize(qint64 size) override
QSsl::SslProtocol sessionProtocol() const
Returns the socket's SSL/TLS protocol or UnknownProtocol if the connection isn't encrypted.
static bool isProtocolSupported(QSsl::SslProtocol protocol, const QString &backendName={})
static QList< QString > availableBackends()
void setPeerVerifyDepth(int depth)
static bool isFeatureSupported(QSsl::SupportedFeature feat, const QString &backendName={})
QSslKey privateKey() const
Returns this socket's private key.
void setProtocol(QSsl::SslProtocol protocol)
Sets the socket's SSL protocol to protocol.
QList< QSslCertificate > localCertificateChain() const
Returns the socket's local \l {QSslCertificate} {certificate} chain, or an empty list if no local cer...
void modeChanged(QSslSocket::SslMode newMode)
This signal is emitted when QSslSocket changes from \l QSslSocket::UnencryptedMode to either \l QSslS...
bool waitForConnected(int msecs=30000) override
Waits until the socket is connected, or msecs milliseconds, whichever happens first.
qint64 bytesAvailable() const override
\reimp
static QString activeBackend()
void startClientEncryption()
Starts a delayed SSL handshake for a client connection.
bool atEnd() const override
\reimp
QSslCertificate peerCertificate() const
Returns the peer's digital certificate (i.e., the immediate certificate of the host you are connected...
void setLocalCertificate(const QSslCertificate &certificate)
Sets the socket's local certificate to certificate.
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
constexpr QStringView left(qsizetype n) const noexcept
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
The QTcpSocket class provides a TCP socket.
Definition qtcpsocket.h:18
QTlsBackend is a factory class, providing implementations for the QSsl classes.
virtual QList< QSsl::SupportedFeature > supportedFeatures() const =0
virtual QList< QSsl::SslProtocol > supportedProtocols() const =0
static QList< QString > availableBackendNames()
virtual QList< QSsl::ImplementedClass > implementedClasses() const =0
static QString defaultBackendName()
static QTlsBackend * findBackend(const QString &backendName)
static QByteArray toAce(const QString &domain, AceProcessingOptions options={})
Definition qurl.cpp:3064
\inmodule QtCore
Definition qvariant.h:65
QSet< QString >::iterator it
else opt state
[0]
SupportedFeature
Enumerates possible features that a TLS backend supports.
Definition qssl.h:144
@ PrivateKey
Definition qssl.h:23
ImplementedClass
Enumerates classes that a TLS backend implements.
Definition qssl.h:132
KeyAlgorithm
Describes the different key algorithms supported by QSslKey.
Definition qssl.h:34
EncodingFormat
Describes supported encoding formats for certificates and keys.
Definition qssl.h:28
@ IpAddressEntry
Definition qssl.h:46
@ DnsEntry
Definition qssl.h:45
SslProtocol
Describes the protocol of the cipher.
Definition qssl.h:50
@ DtlsV1_2
Definition qssl.h:63
@ DtlsV1_2OrLater
Definition qssl.h:64
@ UnknownProtocol
Definition qssl.h:69
Combined button and popup list for selecting options.
@ CaseInsensitive
@ QueuedConnection
@ DirectConnection
static jboolean copy(JNIEnv *, jobject)
#define Q_FALLTHROUGH()
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_DEPRECATED
#define QT_WARNING_PUSH
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLConfig config
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputPortEXT port
static QString backendName
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
int qt_subtract_from_timeout(int timeout, int elapsed)
#define qCWarning(category,...)
#define qCDebug(category,...)
return ret
static ControlElement< T > * ptr(QWidget *widget)
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLenum GLsizei GLuint GLint * bytesWritten
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum mode
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLenum GLenum GLsizei const GLuint * ids
GLenum GLuint id
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum format
GLuint writeBuffer
GLenum const void * addr
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
GLenum GLsizei len
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
constexpr auto isVxworks
#define tr(X)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define emit
#define Q_UNUSED(x)
static int compare(quint64 a, quint64 b)
unsigned short quint16
Definition qtypes.h:48
ptrdiff_t qsizetype
Definition qtypes.h:165
long long qint64
Definition qtypes.h:60
#define Q_INT64_C(c)
Definition qtypes.h:57
ptrdiff_t qintptr
Definition qtypes.h:166
QByteArray ba
[0]
QFile file
[0]
QObject::connect nullptr
QTcpSocket * socket
[1]
QMutex mutex
[2]
QRect r2(QPoint(100, 200), QSize(11, 16))
QList< QSslCertificate > cert
[0]
const auto certs
[1]
QJSValue global
bool contains(const AT &t) const noexcept
Definition qlist.h:45
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...