Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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
348#include "qssl_p.h"
349#include "qsslsocket.h"
350#include "qsslcipher.h"
351#include "qocspresponse.h"
352#include "qtlsbackend_p.h"
353#include "qsslconfiguration_p.h"
354#include "qsslsocket_p.h"
355
356#include <QtCore/qdebug.h>
357#include <QtCore/qdir.h>
358#include <QtCore/qmutex.h>
359#include <QtCore/qurl.h>
360#include <QtCore/qelapsedtimer.h>
361#include <QtNetwork/qhostaddress.h>
362#include <QtNetwork/qhostinfo.h>
363
365
366using namespace Qt::StringLiterals;
367
369{
370public:
374 {
375#if QT_CONFIG(dtls)
377#endif // dtls
378 }
379
385};
387
388
395{
396 Q_D(QSslSocket);
397#ifdef QSSLSOCKET_DEBUG
398 qCDebug(lcSsl) << "QSslSocket::QSslSocket(" << parent << "), this =" << (void *)this;
399#endif
400 d->q_ptr = this;
401 d->init();
402}
403
408{
409 Q_D(QSslSocket);
410#ifdef QSSLSOCKET_DEBUG
411 qCDebug(lcSsl) << "QSslSocket::~QSslSocket(), this =" << (void *)this;
412#endif
413 delete d->plainSocket;
414 d->plainSocket = nullptr;
415}
416
430{
431 Q_D(QSslSocket);
432 if (!d->paused)
433 return;
434 // continuing might emit signals, rather do this through the event loop
435 QMetaObject::invokeMethod(this, "_q_resumeImplementation", Qt::QueuedConnection);
436}
437
480{
481 Q_D(QSslSocket);
482 if (d->state == ConnectedState || d->state == ConnectingState) {
483 qCWarning(lcSsl,
484 "QSslSocket::connectToHostEncrypted() called when already connecting/connected");
485 return;
486 }
487
488 if (!supportsSsl()) {
489 qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
490 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
491 return;
492 }
493
494 if (!d->verifyProtocolSupported("QSslSocket::connectToHostEncrypted:"))
495 return;
496
497 d->init();
498 d->autoStartHandshake = true;
499 d->initialized = true;
500
501 // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
502 // establish the connection immediately (i.e., first attempt).
503 connectToHost(hostName, port, mode, protocol);
504}
505
518 const QString &sslPeerName, OpenMode mode,
519 NetworkLayerProtocol protocol)
520{
521 Q_D(QSslSocket);
522 if (d->state == ConnectedState || d->state == ConnectingState) {
523 qCWarning(lcSsl,
524 "QSslSocket::connectToHostEncrypted() called when already connecting/connected");
525 return;
526 }
527
528 if (!supportsSsl()) {
529 qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
530 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
531 return;
532 }
533
534 d->init();
535 d->autoStartHandshake = true;
536 d->initialized = true;
537 d->verificationPeerName = sslPeerName;
538
539 // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
540 // establish the connection immediately (i.e., first attempt).
541 connectToHost(hostName, port, mode, protocol);
542}
543
556bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state, OpenMode openMode)
557{
558 Q_D(QSslSocket);
559#ifdef QSSLSOCKET_DEBUG
560 qCDebug(lcSsl) << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ','
561 << state << ',' << openMode << ')';
562#endif
563 if (!d->plainSocket)
564 d->createPlainSocket(openMode);
565 bool retVal = d->plainSocket->setSocketDescriptor(socketDescriptor, state, openMode);
566 d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
567 d->setError(d->plainSocket->error(), d->plainSocket->errorString());
570 setLocalPort(d->plainSocket->localPort());
571 setLocalAddress(d->plainSocket->localAddress());
572 setPeerPort(d->plainSocket->peerPort());
573 setPeerAddress(d->plainSocket->peerAddress());
574 setPeerName(d->plainSocket->peerName());
575 d->readChannelCount = d->plainSocket->readChannelCount();
576 d->writeChannelCount = d->plainSocket->writeChannelCount();
577 return retVal;
578}
579
587{
588 Q_D(QSslSocket);
589 if (d->plainSocket)
590 d->plainSocket->setSocketOption(option, value);
591}
592
600{
601 Q_D(QSslSocket);
602 if (d->plainSocket)
603 return d->plainSocket->socketOption(option);
604 else
605 return QVariant();
606}
607
619{
620 Q_D(const QSslSocket);
621 return d->mode;
622}
623
640{
641 Q_D(const QSslSocket);
642 return d->connectionEncrypted;
643}
644
651{
652 Q_D(const QSslSocket);
653 return d->configuration.protocol;
654}
655
662{
663 Q_D(QSslSocket);
664 d->configuration.protocol = protocol;
665}
666
682{
683 Q_D(const QSslSocket);
684 return d->configuration.peerVerifyMode;
685}
686
705{
706 Q_D(QSslSocket);
707 d->configuration.peerVerifyMode = mode;
708}
709
724{
725 Q_D(const QSslSocket);
726 return d->configuration.peerVerifyDepth;
727}
728
743{
744 Q_D(QSslSocket);
745 if (depth < 0) {
746 qCWarning(lcSsl, "QSslSocket::setPeerVerifyDepth: cannot set negative depth of %d", depth);
747 return;
748 }
749 d->configuration.peerVerifyDepth = depth;
750}
751
761{
762 Q_D(const QSslSocket);
763 return d->verificationPeerName;
764}
765
775{
776 Q_D(QSslSocket);
777 d->verificationPeerName = hostName;
778}
779
787{
788 Q_D(const QSslSocket);
789 if (d->mode == UnencryptedMode)
790 return QAbstractSocket::bytesAvailable() + (d->plainSocket ? d->plainSocket->bytesAvailable() : 0);
792}
793
801{
802 Q_D(const QSslSocket);
803 if (d->mode == UnencryptedMode)
804 return d->plainSocket ? d->plainSocket->bytesToWrite() : 0;
805 return d->writeBuffer.size();
806}
807
816{
817 Q_D(const QSslSocket);
818 if (d->mode == UnencryptedMode)
819 return 0;
820 return d->plainSocket->bytesAvailable();
821}
822
830{
831 Q_D(const QSslSocket);
832 if (d->mode == UnencryptedMode)
833 return 0;
834 return d->plainSocket->bytesToWrite();
835}
836
844{
845 Q_D(const QSslSocket);
846 if (d->mode == UnencryptedMode)
847 return QAbstractSocket::canReadLine() || (d->plainSocket && d->plainSocket->canReadLine());
849}
850
855{
856#ifdef QSSLSOCKET_DEBUG
857 qCDebug(lcSsl) << "QSslSocket::close()";
858#endif
859 Q_D(QSslSocket);
860
861 // On Windows, CertGetCertificateChain is probably still doing its
862 // job, if the socket is re-used, we want to ignore its reported
863 // root CA.
864 if (auto *backend = d->backend.get())
865 backend->cancelCAFetch();
866
867 if (!d->abortCalled && (encryptedBytesToWrite() || !d->writeBuffer.isEmpty()))
868 flush();
869 if (d->plainSocket) {
870 if (d->abortCalled)
871 d->plainSocket->abort();
872 else
873 d->plainSocket->close();
874 }
876
877 // must be cleared, reading/writing not possible on closed socket:
878 d->buffer.clear();
879 d->writeBuffer.clear();
880}
881
886{
887 Q_D(const QSslSocket);
888 if (d->mode == UnencryptedMode)
889 return QAbstractSocket::atEnd() && (!d->plainSocket || d->plainSocket->atEnd());
890 return QAbstractSocket::atEnd();
891}
892
899{
900 Q_D(QSslSocket);
901 d->readBufferMaxSize = size;
902
903 if (d->plainSocket)
904 d->plainSocket->setReadBufferSize(size);
905}
906
922{
923 Q_D(const QSslSocket);
924
925 // create a deep copy of our configuration
927 copy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
928 copy->sessionCipher = d->sessionCipher();
929 copy->sessionProtocol = d->sessionProtocol();
930
931 return QSslConfiguration(copy);
932}
933
947{
948 Q_D(QSslSocket);
949 d->configuration.localCertificateChain = configuration.localCertificateChain();
950 d->configuration.privateKey = configuration.privateKey();
951 d->configuration.ciphers = configuration.ciphers();
952 d->configuration.ellipticCurves = configuration.ellipticCurves();
953 d->configuration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
954 d->configuration.dhParams = configuration.diffieHellmanParameters();
955 d->configuration.caCertificates = configuration.caCertificates();
956 d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
957 d->configuration.peerVerifyMode = configuration.peerVerifyMode();
958 d->configuration.protocol = configuration.protocol();
959 d->configuration.backendConfig = configuration.backendConfiguration();
960 d->configuration.sslOptions = configuration.d->sslOptions;
961 d->configuration.sslSession = configuration.sessionTicket();
962 d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
963 d->configuration.nextAllowedProtocols = configuration.allowedNextProtocols();
964 d->configuration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
965 d->configuration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
966#if QT_CONFIG(ocsp)
967 d->configuration.ocspStaplingEnabled = configuration.ocspStaplingEnabled();
968#endif
969#if QT_CONFIG(openssl)
970 d->configuration.reportFromCallback = configuration.handshakeMustInterruptOnError();
971 d->configuration.missingCertIsFatal = configuration.missingCertificateIsFatal();
972#endif // openssl
973 // if the CA certificates were set explicitly (either via
974 // QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
975 // we cannot load the certificates on demand
976 if (!configuration.d->allowRootCertOnDemandLoading) {
977 d->allowRootCertOnDemandLoading = false;
978 d->configuration.allowRootCertOnDemandLoading = false;
979 }
980}
981
990{
991 Q_D(QSslSocket);
992 d->configuration.localCertificateChain = localChain;
993}
994
1003{
1004 Q_D(const QSslSocket);
1005 return d->configuration.localCertificateChain;
1006}
1007
1028{
1029 Q_D(QSslSocket);
1030 d->configuration.localCertificateChain = QList<QSslCertificate>();
1031 d->configuration.localCertificateChain += certificate;
1032}
1033
1043{
1044 QFile file(path);
1047
1048}
1049
1057{
1058 Q_D(const QSslSocket);
1059 if (d->configuration.localCertificateChain.isEmpty())
1060 return QSslCertificate();
1061 return d->configuration.localCertificateChain[0];
1062}
1063
1090{
1091 Q_D(const QSslSocket);
1092 return d->configuration.peerCertificate;
1093}
1094
1119{
1120 Q_D(const QSslSocket);
1121 return d->configuration.peerCertificateChain;
1122}
1123
1141{
1142 Q_D(const QSslSocket);
1143 return d->sessionCipher();
1144}
1145
1155{
1156 Q_D(const QSslSocket);
1157 return d->sessionProtocol();
1158}
1159
1170{
1171 Q_D(const QSslSocket);
1172 if (const auto *backend = d->backend.get())
1173 return backend->ocsps();
1174 return {};
1175}
1176
1191{
1192 Q_D(QSslSocket);
1193 d->configuration.privateKey = key;
1194}
1195
1217 QSsl::EncodingFormat format, const QByteArray &passPhrase)
1218{
1221 qCWarning(lcSsl, "QSslSocket::setPrivateKey: Couldn't open file for reading");
1222 return;
1223 }
1224
1225 QSslKey key(file.readAll(), algorithm, format, QSsl::PrivateKey, passPhrase);
1226 if (key.isNull()) {
1227 qCWarning(lcSsl, "QSslSocket::setPrivateKey: "
1228 "The specified file does not contain a valid key");
1229 return;
1230 }
1231
1232 Q_D(QSslSocket);
1233 d->configuration.privateKey = key;
1234}
1235
1242{
1243 Q_D(const QSslSocket);
1244 return d->configuration.privateKey;
1245}
1246
1255{
1256 Q_D(QSslSocket);
1257 if (!d->plainSocket)
1258 return false;
1259 bool retVal = d->plainSocket->waitForConnected(msecs);
1260 if (!retVal) {
1261 setSocketState(d->plainSocket->state());
1262 d->setError(d->plainSocket->error(), d->plainSocket->errorString());
1263 }
1264 return retVal;
1265}
1266
1284{
1285 Q_D(QSslSocket);
1286 if (!d->plainSocket || d->connectionEncrypted)
1287 return false;
1288 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1289 return false;
1290 if (!d->verifyProtocolSupported("QSslSocket::waitForEncrypted:"))
1291 return false;
1292
1293 QElapsedTimer stopWatch;
1294 stopWatch.start();
1295
1296 if (d->plainSocket->state() != QAbstractSocket::ConnectedState) {
1297 // Wait until we've entered connected state.
1298 if (!d->plainSocket->waitForConnected(msecs))
1299 return false;
1300 }
1301
1302 while (!d->connectionEncrypted) {
1303 // Start the handshake, if this hasn't been started yet.
1304 if (d->mode == UnencryptedMode)
1306 // Loop, waiting until the connection has been encrypted or an error
1307 // occurs.
1308 if (!d->plainSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed())))
1309 return false;
1310 }
1311 return d->connectionEncrypted;
1312}
1313
1318{
1319 Q_D(QSslSocket);
1320 if (!d->plainSocket)
1321 return false;
1322 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1323 return d->plainSocket->waitForReadyRead(msecs);
1324
1325 // This function must return true if and only if readyRead() *was* emitted.
1326 // So we initialize "readyReadEmitted" to false and check if it was set to true.
1327 // waitForReadyRead() could be called recursively, so we can't use the same variable
1328 // (the inner waitForReadyRead() may fail, but the outer one still succeeded)
1329 bool readyReadEmitted = false;
1330 bool *previousReadyReadEmittedPointer = d->readyReadEmittedPointer;
1331 d->readyReadEmittedPointer = &readyReadEmitted;
1332
1333 QElapsedTimer stopWatch;
1334 stopWatch.start();
1335
1336 if (!d->connectionEncrypted) {
1337 // Wait until we've entered encrypted mode, or until a failure occurs.
1338 if (!waitForEncrypted(msecs)) {
1339 d->readyReadEmittedPointer = previousReadyReadEmittedPointer;
1340 return false;
1341 }
1342 }
1343
1344 if (!d->writeBuffer.isEmpty()) {
1345 // empty our cleartext write buffer first
1346 d->transmit();
1347 }
1348
1349 // test readyReadEmitted first because either operation above
1350 // (waitForEncrypted or transmit) may have set it
1351 while (!readyReadEmitted &&
1352 d->plainSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
1353 }
1354
1355 d->readyReadEmittedPointer = previousReadyReadEmittedPointer;
1356 return readyReadEmitted;
1357}
1358
1363{
1364 Q_D(QSslSocket);
1365 if (!d->plainSocket)
1366 return false;
1367 if (d->mode == UnencryptedMode)
1368 return d->plainSocket->waitForBytesWritten(msecs);
1369
1370 QElapsedTimer stopWatch;
1371 stopWatch.start();
1372
1373 if (!d->connectionEncrypted) {
1374 // Wait until we've entered encrypted mode, or until a failure occurs.
1375 if (!waitForEncrypted(msecs))
1376 return false;
1377 }
1378 if (!d->writeBuffer.isEmpty()) {
1379 // empty our cleartext write buffer first
1380 d->transmit();
1381 }
1382
1383 return d->plainSocket->waitForBytesWritten(qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
1384}
1385
1394{
1395 Q_D(QSslSocket);
1396
1397 // require calling connectToHost() before waitForDisconnected()
1398 if (state() == UnconnectedState) {
1399 qCWarning(lcSsl, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState");
1400 return false;
1401 }
1402
1403 if (!d->plainSocket)
1404 return false;
1405 // Forward to the plain socket unless the connection is secure.
1406 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1407 return d->plainSocket->waitForDisconnected(msecs);
1408
1409 QElapsedTimer stopWatch;
1410 stopWatch.start();
1411
1412 if (!d->connectionEncrypted) {
1413 // Wait until we've entered encrypted mode, or until a failure occurs.
1414 if (!waitForEncrypted(msecs))
1415 return false;
1416 }
1417 // We are delaying the disconnect, if the write buffer is not empty.
1418 // So, start the transmission.
1419 if (!d->writeBuffer.isEmpty())
1420 d->transmit();
1421
1422 // At this point, the socket might be disconnected, if disconnectFromHost()
1423 // was called just after the connectToHostEncrypted() call. Also, we can
1424 // lose the connection as a result of the transmit() call.
1425 if (state() == UnconnectedState)
1426 return true;
1427
1428 bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
1429 if (!retVal) {
1430 setSocketState(d->plainSocket->state());
1431 d->setError(d->plainSocket->error(), d->plainSocket->errorString());
1432 }
1433 return retVal;
1434}
1435
1447{
1448 Q_D(const QSslSocket);
1449 if (const auto *backend = d->backend.get())
1450 return backend->tlsErrors();
1451 return {};
1452}
1453
1460{
1462}
1463
1471{
1472 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1473 return tlsBackend->tlsLibraryVersionNumber();
1474
1475 return -1;
1476}
1477
1485{
1486 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1487 return tlsBackend->tlsLibraryVersionString();
1488 return {};
1489}
1490
1499{
1500 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1501 return tlsBackend->tlsLibraryBuildVersionNumber();
1502 return -1;
1503}
1504
1514{
1515 if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
1516 return tlsBackend->tlsLibraryBuildVersionString();
1517
1518 return {};
1519}
1520
1530{
1532}
1533
1547{
1549
1552
1554}
1555
1570{
1571 if (!backendName.size()) {
1572 qCWarning(lcSsl, "Invalid parameter (backend name cannot be an empty string)");
1573 return false;
1574 }
1575
1578 qCWarning(lcSsl) << "Cannot set backend named" << backendName
1579 << "as active, another backend is already in use";
1580 locker.unlock();
1581 return activeBackend() == backendName;
1582 }
1583
1585 qCWarning(lcSsl) << "Cannot set unavailable backend named" << backendName
1586 << "as active";
1587 return false;
1588 }
1589
1591
1592 return true;
1593}
1594
1605{
1607}
1608
1617{
1618 const auto versions = supportedProtocols(backendName);
1619 return versions.contains(protocol);
1620}
1621
1631{
1633}
1634
1644{
1645 return implementedClasses(backendName).contains(cl);
1646}
1647
1656{
1658}
1659
1668{
1669 return supportedFeatures(backendName).contains(ft);
1670}
1671
1686{
1687 Q_D(QSslSocket);
1688 if (d->mode != UnencryptedMode) {
1689 qCWarning(lcSsl,
1690 "QSslSocket::startClientEncryption: cannot start handshake on non-plain connection");
1691 return;
1692 }
1693 if (state() != ConnectedState) {
1694 qCWarning(lcSsl,
1695 "QSslSocket::startClientEncryption: cannot start handshake when not connected");
1696 return;
1697 }
1698
1699 if (!supportsSsl()) {
1700 qCWarning(lcSsl, "QSslSocket::startClientEncryption: TLS initialization failed");
1701 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
1702 return;
1703 }
1704
1705 if (!d->verifyProtocolSupported("QSslSocket::startClientEncryption:"))
1706 return;
1707
1708#ifdef QSSLSOCKET_DEBUG
1709 qCDebug(lcSsl) << "QSslSocket::startClientEncryption()";
1710#endif
1711 d->mode = SslClientMode;
1712 emit modeChanged(d->mode);
1713 d->startClientEncryption();
1714}
1715
1737{
1738 Q_D(QSslSocket);
1739 if (d->mode != UnencryptedMode) {
1740 qCWarning(lcSsl, "QSslSocket::startServerEncryption: cannot start handshake on non-plain connection");
1741 return;
1742 }
1743#ifdef QSSLSOCKET_DEBUG
1744 qCDebug(lcSsl) << "QSslSocket::startServerEncryption()";
1745#endif
1746 if (!supportsSsl()) {
1747 qCWarning(lcSsl, "QSslSocket::startServerEncryption: TLS initialization failed");
1748 d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
1749 return;
1750 }
1751 if (!d->verifyProtocolSupported("QSslSocket::startServerEncryption"))
1752 return;
1753
1754 d->mode = SslServerMode;
1755 emit modeChanged(d->mode);
1756 d->startServerEncryption();
1757}
1758
1785{
1786 Q_D(QSslSocket);
1787 d->ignoreAllSslErrors = true;
1788}
1789
1812{
1813 Q_D(QSslSocket);
1814 d->ignoreErrorsList = errors;
1815}
1816
1817
1829{
1830 Q_D(QSslSocket);
1831 if (auto *backend = d->backend.get())
1832 backend->enableHandshakeContinuation();
1833}
1834
1838void QSslSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode, NetworkLayerProtocol protocol)
1839{
1840 Q_D(QSslSocket);
1841 d->preferredNetworkLayerProtocol = protocol;
1842 if (!d->initialized)
1843 d->init();
1844 d->initialized = false;
1845
1846#ifdef QSSLSOCKET_DEBUG
1847 qCDebug(lcSsl) << "QSslSocket::connectToHost("
1848 << hostName << ',' << port << ',' << openMode << ')';
1849#endif
1850 if (!d->plainSocket) {
1851#ifdef QSSLSOCKET_DEBUG
1852 qCDebug(lcSsl) << "\tcreating internal plain socket";
1853#endif
1854 d->createPlainSocket(openMode);
1855 }
1856#ifndef QT_NO_NETWORKPROXY
1857 d->plainSocket->setProtocolTag(d->protocolTag);
1858 d->plainSocket->setProxy(proxy());
1859#endif
1861 d->readChannelCount = d->writeChannelCount = 0;
1862 d->plainSocket->connectToHost(hostName, port, openMode, d->preferredNetworkLayerProtocol);
1863 d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
1864}
1865
1870{
1871 Q_D(QSslSocket);
1872#ifdef QSSLSOCKET_DEBUG
1873 qCDebug(lcSsl) << "QSslSocket::disconnectFromHost()";
1874#endif
1875 if (!d->plainSocket)
1876 return;
1877 if (d->state == UnconnectedState)
1878 return;
1879 if (d->mode == UnencryptedMode && !d->autoStartHandshake) {
1880 d->plainSocket->disconnectFromHost();
1881 return;
1882 }
1883 if (d->state <= ConnectingState) {
1884 d->pendingClose = true;
1885 return;
1886 }
1887 // Make sure we don't process any signal from the CA fetcher
1888 // (Windows):
1889 if (auto *backend = d->backend.get())
1890 backend->cancelCAFetch();
1891
1892 // Perhaps emit closing()
1893 if (d->state != ClosingState) {
1894 d->state = ClosingState;
1895 emit stateChanged(d->state);
1896 }
1897
1898 if (!d->writeBuffer.isEmpty()) {
1899 d->pendingClose = true;
1900 return;
1901 }
1902
1903 if (d->mode == UnencryptedMode) {
1904 d->plainSocket->disconnectFromHost();
1905 } else {
1906 d->disconnectFromHost();
1907 }
1908}
1909
1914{
1915 Q_D(QSslSocket);
1916 qint64 readBytes = 0;
1917
1918 if (d->mode == UnencryptedMode && !d->autoStartHandshake) {
1919 readBytes = d->plainSocket->read(data, maxlen);
1920#ifdef QSSLSOCKET_DEBUG
1921 qCDebug(lcSsl) << "QSslSocket::readData(" << (void *)data << ',' << maxlen << ") =="
1922 << readBytes;
1923#endif
1924 } else {
1925 // possibly trigger another transmit() to decrypt more data from the socket
1926 if (d->plainSocket->bytesAvailable() || d->hasUndecryptedData())
1927 QMetaObject::invokeMethod(this, "_q_flushReadBuffer", Qt::QueuedConnection);
1928 else if (d->state != QAbstractSocket::ConnectedState)
1929 return maxlen ? qint64(-1) : qint64(0);
1930 }
1931
1932 return readBytes;
1933}
1934
1939{
1940 Q_D(QSslSocket);
1941#ifdef QSSLSOCKET_DEBUG
1942 qCDebug(lcSsl) << "QSslSocket::writeData(" << (void *)data << ',' << len << ')';
1943#endif
1944 if (d->mode == UnencryptedMode && !d->autoStartHandshake)
1945 return d->plainSocket->write(data, len);
1946
1947 d->write(data, len);
1948
1949 // make sure we flush to the plain socket's buffer
1950 if (!d->flushTriggered) {
1951 d->flushTriggered = true;
1952 QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
1953 }
1954
1955 return len;
1956}
1957
1959
1964 : initialized(false)
1965 , mode(QSslSocket::UnencryptedMode)
1966 , autoStartHandshake(false)
1967 , connectionEncrypted(false)
1968 , ignoreAllSslErrors(false)
1969 , readyReadEmittedPointer(nullptr)
1970 , allowRootCertOnDemandLoading(true)
1971 , plainSocket(nullptr)
1972 , paused(false)
1973 , flushTriggered(false)
1974{
1976 // If the global configuration doesn't allow root certificates to be loaded
1977 // on demand then we have to disable it for this socket as well.
1980
1981 const auto *tlsBackend = tlsBackendInUse();
1982 if (!tlsBackend) {
1983 qCWarning(lcSsl, "No TLS backend is available");
1984 return;
1985 }
1987 if (!backend.get()) {
1988 qCWarning(lcSsl) << "The backend named" << tlsBackend->backendName()
1989 << "does not support TLS";
1990 }
1991}
1992
1997{
1998}
1999
2004{
2005 if (const auto *tlsBackend = tlsBackendInUse())
2007 return false;
2008}
2009
2017{
2018 if (!supportsSsl())
2019 return;
2020
2021 const auto *tlsBackend = tlsBackendInUse();
2024}
2025
2030{
2031 // TLSTODO: delete those data members.
2033 autoStartHandshake = false;
2034 connectionEncrypted = false;
2035 ignoreAllSslErrors = false;
2036 abortCalled = false;
2037 pendingClose = false;
2038 flushTriggered = false;
2039 // We don't want to clear the ignoreErrorsList, so
2040 // that it is possible setting it before connecting.
2041
2042 buffer.clear();
2043 writeBuffer.clear();
2046
2047 if (backend.get()) {
2048 Q_ASSERT(q_ptr);
2049 backend->init(static_cast<QSslSocket *>(q_ptr), this);
2050 }
2051}
2052
2057{
2058 auto protocolName = "DTLS"_L1;
2059 switch (configuration.protocol) {
2061 // UnknownProtocol, according to our docs, is for cipher whose protocol is unknown.
2062 // Should not be used when configuring QSslSocket.
2063 protocolName = "UnknownProtocol"_L1;
2064 Q_FALLTHROUGH();
2067 case QSsl::DtlsV1_0:
2068 case QSsl::DtlsV1_2:
2069 case QSsl::DtlsV1_0OrLater:
2071 qCWarning(lcSsl) << where << "QSslConfiguration with unexpected protocol" << protocolName;
2073 QSslSocket::tr("Attempted to use an unsupported protocol."));
2074 return false;
2076 default:
2077 return true;
2078 }
2079}
2080
2085{
2087 QMutexLocker locker(&globalData()->mutex);
2088 return globalData()->config->ciphers;
2089}
2090
2095{
2097 QMutexLocker locker(&globalData()->mutex);
2098 return globalData()->supportedCiphers;
2099}
2100
2105{
2106 QMutexLocker locker(&globalData()->mutex);
2107 globalData()->config.detach();
2108 globalData()->config->ciphers = ciphers;
2109}
2110
2115{
2116 QMutexLocker locker(&globalData()->mutex);
2117 globalData()->config.detach();
2118 globalData()->supportedCiphers = ciphers;
2119}
2120
2125{
2126 const auto *tlsBackend = tlsBackendInUse();
2127 if (!tlsBackend)
2128 return;
2129
2131 if (!ids.size())
2132 return;
2133
2135 curves.reserve(ids.size());
2136 for (int id : ids) {
2137 QSslEllipticCurve curve;
2138 curve.id = id;
2139 curves.append(curve);
2140 }
2141
2142 // Set the list of supported ECs, but not the list
2143 // of *default* ECs. OpenSSL doesn't like forcing an EC for the wrong
2144 // ciphersuite, so don't try it -- leave the empty list to mean
2145 // "the implementation will choose the most suitable one".
2147}
2148
2153{
2154 QMutexLocker locker(&globalData()->mutex);
2155 globalData()->dtlsConfig.detach();
2156 globalData()->dtlsConfig->ciphers = ciphers;
2157}
2158
2163{
2165 QMutexLocker locker(&globalData()->mutex);
2166 return globalData()->dtlsConfig->ciphers;
2167}
2168
2173{
2175 const QMutexLocker locker(&globalData()->mutex);
2176 return globalData()->supportedEllipticCurves;
2177}
2178
2183{
2184 const QMutexLocker locker(&globalData()->mutex);
2185 globalData()->config.detach();
2186 globalData()->dtlsConfig.detach();
2187 globalData()->supportedEllipticCurves = curves;
2188}
2189
2194{
2196 QMutexLocker locker(&globalData()->mutex);
2197 return globalData()->config->caCertificates;
2198}
2199
2204{
2206 QMutexLocker locker(&globalData()->mutex);
2207 globalData()->config.detach();
2208 globalData()->config->caCertificates = certs;
2209 globalData()->dtlsConfig.detach();
2210 globalData()->dtlsConfig->caCertificates = certs;
2211 // when the certificates are set explicitly, we do not want to
2212 // load the system certificates on demand
2214}
2215
2220{
2222 QMutexLocker locker(&globalData()->mutex);
2223 if (globalData()->config->caCertificates.contains(cert))
2224 return;
2225 globalData()->config.detach();
2226 globalData()->config->caCertificates += cert;
2227 globalData()->dtlsConfig.detach();
2228 globalData()->dtlsConfig->caCertificates += cert;
2229}
2230
2235{
2237 QMutexLocker locker(&globalData()->mutex);
2238 globalData()->config.detach();
2239 globalData()->config->caCertificates += certs;
2240 globalData()->dtlsConfig.detach();
2241 globalData()->dtlsConfig->caCertificates += certs;
2242}
2243
2248{
2250 QMutexLocker locker(&globalData()->mutex);
2251 return QSslConfiguration(globalData()->config.data());
2252}
2253
2258{
2260 QMutexLocker locker(&globalData()->mutex);
2261 if (globalData()->config == configuration.d)
2262 return; // nothing to do
2263
2264 globalData()->config = const_cast<QSslConfigurationPrivate*>(configuration.d.constData());
2265}
2266
2271{
2273 QMutexLocker locker(&globalData()->mutex);
2274 const QSslConfigurationPrivate *global = globalData()->config.constData();
2275
2276 if (!global)
2277 return;
2278
2279 ptr->ref.storeRelaxed(1);
2280 ptr->peerCertificate = global->peerCertificate;
2281 ptr->peerCertificateChain = global->peerCertificateChain;
2282 ptr->localCertificateChain = global->localCertificateChain;
2283 ptr->privateKey = global->privateKey;
2284 ptr->sessionCipher = global->sessionCipher;
2285 ptr->sessionProtocol = global->sessionProtocol;
2286 ptr->ciphers = global->ciphers;
2287 ptr->caCertificates = global->caCertificates;
2288 ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
2289 ptr->protocol = global->protocol;
2290 ptr->peerVerifyMode = global->peerVerifyMode;
2291 ptr->peerVerifyDepth = global->peerVerifyDepth;
2292 ptr->sslOptions = global->sslOptions;
2293 ptr->ellipticCurves = global->ellipticCurves;
2294 ptr->backendConfig = global->backendConfig;
2295#if QT_CONFIG(dtls)
2296 ptr->dtlsCookieEnabled = global->dtlsCookieEnabled;
2297#endif
2298#if QT_CONFIG(ocsp)
2299 ptr->ocspStaplingEnabled = global->ocspStaplingEnabled;
2300#endif
2301#if QT_CONFIG(openssl)
2302 ptr->reportFromCallback = global->reportFromCallback;
2303 ptr->missingCertIsFatal = global->missingCertIsFatal;
2304#endif
2305}
2306
2311{
2313 QMutexLocker locker(&globalData()->mutex);
2314
2315 return QSslConfiguration(globalData()->dtlsConfig.data());
2316}
2317
2322{
2324 QMutexLocker locker(&globalData()->mutex);
2325 if (globalData()->dtlsConfig == configuration.d)
2326 return; // nothing to do
2327
2328 globalData()->dtlsConfig = const_cast<QSslConfigurationPrivate*>(configuration.d.constData());
2329}
2330
2334void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode)
2335{
2336 Q_Q(QSslSocket);
2337 q->setOpenMode(openMode); // <- from QIODevice
2338 q->setSocketState(QAbstractSocket::UnconnectedState);
2339 q->setSocketError(QAbstractSocket::UnknownSocketError);
2340 q->setLocalPort(0);
2341 q->setLocalAddress(QHostAddress());
2342 q->setPeerPort(0);
2343 q->setPeerAddress(QHostAddress());
2344 q->setPeerName(QString());
2345
2346 plainSocket = new QTcpSocket(q);
2347 q->connect(plainSocket, SIGNAL(connected()),
2350 q->connect(plainSocket, SIGNAL(hostFound()),
2353 q->connect(plainSocket, SIGNAL(disconnected()),
2356 q->connect(plainSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
2359 q->connect(plainSocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
2362 q->connect(plainSocket, SIGNAL(readyRead()),
2365 q->connect(plainSocket, SIGNAL(channelReadyRead(int)),
2371 q->connect(plainSocket, SIGNAL(channelBytesWritten(int,qint64)),
2374 q->connect(plainSocket, SIGNAL(readChannelFinished()),
2377#ifndef QT_NO_NETWORKPROXY
2380#endif
2381
2382 buffer.clear();
2383 writeBuffer.clear();
2384 connectionEncrypted = false;
2388 q->setReadBufferSize(readBufferMaxSize);
2389}
2390
2392{
2393 if (!socket->d_func()->plainSocket)
2394 return;
2396}
2397
2399{
2400 if (!socket->d_func()->plainSocket)
2401 return;
2403}
2404
2406{
2407 return paused;
2408}
2409
2411{
2412 paused = p;
2413}
2414
2415bool QSslSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
2416{
2417 // this function is called from QAbstractSocket::bind
2418 if (!initialized)
2419 init();
2420 initialized = false;
2421
2422#ifdef QSSLSOCKET_DEBUG
2423 qCDebug(lcSsl) << "QSslSocket::bind(" << address << ',' << port << ',' << mode << ')';
2424#endif
2425 if (!plainSocket) {
2426#ifdef QSSLSOCKET_DEBUG
2427 qCDebug(lcSsl) << "\tcreating internal plain socket";
2428#endif
2430 }
2431 bool ret = plainSocket->bind(address, port, mode);
2436 return ret;
2437}
2438
2443{
2444 Q_Q(QSslSocket);
2445 q->setLocalPort(plainSocket->localPort());
2446 q->setLocalAddress(plainSocket->localAddress());
2447 q->setPeerPort(plainSocket->peerPort());
2448 q->setPeerAddress(plainSocket->peerAddress());
2449 q->setPeerName(plainSocket->peerName());
2453
2454#ifdef QSSLSOCKET_DEBUG
2455 qCDebug(lcSsl) << "QSslSocket::_q_connectedSlot()";
2456 qCDebug(lcSsl) << "\tstate =" << q->state();
2457 qCDebug(lcSsl) << "\tpeer =" << q->peerName() << q->peerAddress() << q->peerPort();
2458 qCDebug(lcSsl) << "\tlocal =" << QHostInfo::fromName(q->localAddress().toString()).hostName()
2459 << q->localAddress() << q->localPort();
2460#endif
2461
2463 q->startClientEncryption();
2464
2465 emit q->connected();
2466
2468 pendingClose = false;
2469 q->disconnectFromHost();
2470 }
2471}
2472
2477{
2478 Q_Q(QSslSocket);
2479#ifdef QSSLSOCKET_DEBUG
2480 qCDebug(lcSsl) << "QSslSocket::_q_hostFoundSlot()";
2481 qCDebug(lcSsl) << "\tstate =" << q->state();
2482#endif
2483 emit q->hostFound();
2484}
2485
2490{
2491 Q_Q(QSslSocket);
2492#ifdef QSSLSOCKET_DEBUG
2493 qCDebug(lcSsl) << "QSslSocket::_q_disconnectedSlot()";
2494 qCDebug(lcSsl) << "\tstate =" << q->state();
2495#endif
2496 disconnected();
2497 emit q->disconnected();
2498
2499 q->setLocalPort(0);
2500 q->setLocalAddress(QHostAddress());
2501 q->setPeerPort(0);
2502 q->setPeerAddress(QHostAddress());
2503 q->setPeerName(QString());
2505}
2506
2511{
2512 Q_Q(QSslSocket);
2513#ifdef QSSLSOCKET_DEBUG
2514 qCDebug(lcSsl) << "QSslSocket::_q_stateChangedSlot(" << state << ')';
2515#endif
2516 q->setSocketState(state);
2517 emit q->stateChanged(state);
2518}
2519
2524{
2525 Q_UNUSED(error);
2526#ifdef QSSLSOCKET_DEBUG
2527 Q_Q(QSslSocket);
2528 qCDebug(lcSsl) << "QSslSocket::_q_errorSlot(" << error << ')';
2529 qCDebug(lcSsl) << "\tstate =" << q->state();
2530 qCDebug(lcSsl) << "\terrorString =" << q->errorString();
2531#endif
2532 // this moves encrypted bytes from plain socket into our buffer
2534 qint64 tmpReadBufferMaxSize = readBufferMaxSize;
2535 readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained
2536 transmit();
2537 readBufferMaxSize = tmpReadBufferMaxSize;
2538 }
2539
2541}
2542
2547{
2548 Q_Q(QSslSocket);
2549#ifdef QSSLSOCKET_DEBUG
2550 qCDebug(lcSsl) << "QSslSocket::_q_readyReadSlot() -" << plainSocket->bytesAvailable() << "bytes available";
2551#endif
2555 emit q->readyRead();
2556 return;
2557 }
2558
2559 transmit();
2560}
2561
2566{
2567 Q_Q(QSslSocket);
2569 emit q->channelReadyRead(channel);
2570}
2571
2576{
2577 Q_Q(QSslSocket);
2578#ifdef QSSLSOCKET_DEBUG
2579 qCDebug(lcSsl) << "QSslSocket::_q_bytesWrittenSlot(" << written << ')';
2580#endif
2581
2583 emit q->bytesWritten(written);
2584 else
2585 emit q->encryptedBytesWritten(written);
2587 q->disconnectFromHost();
2588}
2589
2594{
2595 Q_Q(QSslSocket);
2597 emit q->channelBytesWritten(channel, written);
2598}
2599
2604{
2605 Q_Q(QSslSocket);
2606 emit q->readChannelFinished();
2607}
2608
2613{
2614 Q_Q(QSslSocket);
2615
2616 // need to notice if knock-on effects of this flush (e.g. a readReady() via transmit())
2617 // make another necessary, so clear flag before calling:
2618 flushTriggered = false;
2619 if (!writeBuffer.isEmpty())
2620 q->flush();
2621}
2622
2627{
2628 // trigger a read from the plainSocket into SSL
2630 transmit();
2631}
2632
2637{
2638 if (plainSocket)
2640 paused = false;
2641 if (!connectionEncrypted) {
2644 } else {
2645 const auto sslErrors = backend->tlsErrors();
2646 Q_ASSERT(!sslErrors.isEmpty());
2647 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
2649 return;
2650 }
2651 }
2652 transmit();
2653}
2654
2659{
2660 Q_ASSERT(backend.get());
2661
2662 bool doEmitSslError;
2663 if (!ignoreErrorsList.empty()) {
2664 // check whether the errors we got are all in the list of expected errors
2665 // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
2666 // was called)
2667 const auto &sslErrors = backend->tlsErrors();
2668 doEmitSslError = false;
2669 for (int a = 0; a < sslErrors.size(); a++) {
2670 if (!ignoreErrorsList.contains(sslErrors.at(a))) {
2671 doEmitSslError = true;
2672 break;
2673 }
2674 }
2675 } else {
2676 // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and
2677 // we get an SSL error, emit a signal unless we ignored all errors (by calling
2678 // QSslSocket::ignoreSslErrors() )
2679 doEmitSslError = !ignoreAllSslErrors;
2680 }
2681 return !doEmitSslError;
2682}
2683
2688{
2689 return autoStartHandshake;
2690}
2691
2696{
2697 return pendingClose;
2698}
2699
2704{
2705 pendingClose = pc;
2706}
2707
2712{
2713 return readBufferMaxSize;
2714}
2715
2720{
2721 readBufferMaxSize = maxSize;
2722}
2723
2728{
2729 connectionEncrypted = enc;
2730}
2731
2736{
2737 return writeBuffer;
2738}
2739
2744{
2745 return buffer;
2746}
2747
2752{
2753 return emittedBytesWritten;
2754}
2755
2760{
2762}
2763
2765{
2766 return backend.get() && backend->hasUndecryptedData();
2767}
2768
2773{
2775 //unencrypted mode - do not use QIODevice::peek, as it reads ahead data from the plain socket
2776 //peek at data already in the QIODevice buffer (from a previous read)
2777 qint64 r = buffer.peek(data, maxSize, transactionPos);
2778 if (r == maxSize)
2779 return r;
2780 data += r;
2781 //peek at data in the plain socket
2782 if (plainSocket) {
2783 qint64 r2 = plainSocket->peek(data, maxSize - r);
2784 if (r2 < 0)
2785 return (r > 0 ? r : r2);
2786 return r + r2;
2787 }
2788
2789 return -1;
2790 } else {
2791 //encrypted mode - the socket engine will read and decrypt data into the QIODevice buffer
2792 return QTcpSocketPrivate::peek(data, maxSize);
2793 }
2794}
2795
2800{
2802 //unencrypted mode - do not use QIODevice::peek, as it reads ahead data from the plain socket
2803 //peek at data already in the QIODevice buffer (from a previous read)
2805 ret.reserve(maxSize);
2806 ret.resize(buffer.peek(ret.data(), maxSize, transactionPos));
2807 if (ret.size() == maxSize)
2808 return ret;
2809 //peek at data in the plain socket
2810 if (plainSocket)
2811 return ret + plainSocket->peek(maxSize - ret.size());
2812
2813 return QByteArray();
2814 } else {
2815 //encrypted mode - the socket engine will read and decrypt data into the QIODevice buffer
2816 return QTcpSocketPrivate::peek(maxSize);
2817 }
2818}
2819
2824{
2825 Q_D(QSslSocket);
2826
2827 if (d->mode == QSslSocket::UnencryptedMode && !d->autoStartHandshake)
2828 return d->plainSocket->skip(maxSize);
2829
2830 // In encrypted mode, the SSL backend writes decrypted data directly into the
2831 // QIODevice's read buffer. As this buffer is always emptied by the caller,
2832 // we need to wait for more incoming data.
2833 return (d->state == QAbstractSocket::ConnectedState) ? Q_INT64_C(0) : Q_INT64_C(-1);
2834}
2835
2840{
2841#ifdef QSSLSOCKET_DEBUG
2842 qCDebug(lcSsl) << "QSslSocketPrivate::flush()";
2843#endif
2845 // encrypt any unencrypted bytes in our buffer
2846 transmit();
2847 }
2848
2849 return plainSocket && plainSocket->flush();
2850}
2851
2856{
2857 if (backend.get())
2858 backend->startClientEncryption();
2859}
2860
2865{
2866 if (backend.get())
2867 backend->startServerEncryption();
2868}
2869
2874{
2875 if (backend.get())
2876 backend->transmit();
2877}
2878
2883{
2884 if (backend.get())
2885 backend->disconnectFromHost();
2886}
2887
2892{
2893 if (backend.get())
2894 backend->disconnected();
2895}
2896
2901{
2902 if (backend.get())
2903 return backend->sessionCipher();
2904
2905 return {};
2906}
2907
2912{
2913 if (backend.get())
2914 return backend->sessionProtocol();
2915
2916 return QSsl::UnknownProtocol;
2917}
2918
2923{
2924 if (backend.get())
2925 backend->continueHandshake();
2926}
2927
2932{
2934}
2935
2940{
2941 s_loadRootCertsOnDemand = supported;
2942}
2943
2948{
2949 const auto ba = [](const auto &cstr) constexpr {
2950 return QByteArray::fromRawData(std::begin(cstr), std::size(cstr) - 1);
2951 };
2952 static const QByteArray dirs[] = {
2953 ba("/etc/ssl/certs/"), // (K)ubuntu, OpenSUSE, Mandriva ...
2954 ba("/usr/lib/ssl/certs/"), // Gentoo, Mandrake
2955 ba("/usr/share/ssl/"), // Centos, Redhat, SuSE
2956 ba("/usr/local/ssl/"), // Normal OpenSSL Tarball
2957 ba("/var/ssl/certs/"), // AIX
2958 ba("/usr/local/ssl/certs/"), // Solaris
2959 ba("/etc/openssl/certs/"), // BlackBerry
2960 ba("/opt/openssl/certs/"), // HP-UX
2961 ba("/etc/ssl/"), // OpenBSD
2962 };
2964}
2965
2969void QSslSocketPrivate::checkSettingSslContext(QSslSocket* socket, std::shared_ptr<QSslContext> tlsContext)
2970{
2971 if (!socket)
2972 return;
2973
2974 if (auto *backend = socket->d_func()->backend.get())
2975 backend->checkSettingSslContext(tlsContext);
2976}
2977
2982{
2983 if (!socket)
2984 return {};
2985
2986 if (const auto *backend = socket->d_func()->backend.get())
2987 return backend->sslContext();
2988
2989 return {};
2990}
2991
2993{
2994 QHostAddress hostAddress(peerName);
2995 if (!hostAddress.isNull()) {
2996 const auto subjectAlternativeNames = cert.subjectAlternativeNames();
2997 const auto ipAddresses = subjectAlternativeNames.equal_range(QSsl::AlternativeNameEntryType::IpAddressEntry);
2998
2999 for (auto it = ipAddresses.first; it != ipAddresses.second; it++) {
3001 return true;
3002 }
3003 }
3004
3005 const QString lowerPeerName = QString::fromLatin1(QUrl::toAce(peerName));
3006 const QStringList commonNames = cert.subjectInfo(QSslCertificate::CommonName);
3007
3008 for (const QString &commonName : commonNames) {
3009 if (isMatchingHostname(commonName, lowerPeerName))
3010 return true;
3011 }
3012
3013 const auto subjectAlternativeNames = cert.subjectAlternativeNames();
3014 const auto altNames = subjectAlternativeNames.equal_range(QSsl::DnsEntry);
3015 for (auto it = altNames.first; it != altNames.second; ++it) {
3016 if (isMatchingHostname(*it, lowerPeerName))
3017 return true;
3018 }
3019
3020 return false;
3021}
3022
3028{
3029 qsizetype wildcard = cn.indexOf(u'*');
3030
3031 // Check this is a wildcard cert, if not then just compare the strings
3032 if (wildcard < 0)
3033 return QLatin1StringView(QUrl::toAce(cn)) == hostname;
3034
3035 qsizetype firstCnDot = cn.indexOf(u'.');
3036 qsizetype secondCnDot = cn.indexOf(u'.', firstCnDot+1);
3037
3038 // Check at least 3 components
3039 if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.size()))
3040 return false;
3041
3042 // Check * is last character of 1st component (ie. there's a following .)
3043 if (wildcard+1 != firstCnDot)
3044 return false;
3045
3046 // Check only one star
3047 if (cn.lastIndexOf(u'*') != wildcard)
3048 return false;
3049
3050 // Reject wildcard character embedded within the A-labels or U-labels of an internationalized
3051 // domain name (RFC6125 section 7.2)
3052 if (cn.startsWith("xn--"_L1, Qt::CaseInsensitive))
3053 return false;
3054
3055 // Check characters preceding * (if any) match
3056 if (wildcard && QStringView{hostname}.left(wildcard).compare(QStringView{cn}.left(wildcard), Qt::CaseInsensitive) != 0)
3057 return false;
3058
3059 // Check characters following first . match
3060 qsizetype hnDot = hostname.indexOf(u'.');
3061 if (QStringView{hostname}.mid(hnDot + 1) != QStringView{cn}.mid(firstCnDot + 1)
3062 && QStringView{hostname}.mid(hnDot + 1) != QLatin1StringView(QUrl::toAce(cn.mid(firstCnDot + 1)))) {
3063 return false;
3064 }
3065
3066 // Check if the hostname is an IP address, if so then wildcards are not allowed
3067 QHostAddress addr(hostname);
3068 if (!addr.isNull())
3069 return false;
3070
3071 // Ok, I guess this was a wildcard CN and the hostname matches.
3072 return true;
3073}
3074
3079{
3080 const QMutexLocker locker(&backendMutex);
3081 if (tlsBackend)
3082 return tlsBackend;
3083
3084 if (!activeBackendName.size())
3086
3087 if (!activeBackendName.size()) {
3088 qCWarning(lcSsl, "No functional TLS backend was found");
3089 return nullptr;
3090 }
3091
3093 if (tlsBackend) {
3095 const QMutexLocker locker(&backendMutex);
3096 tlsBackend = nullptr;
3097 },
3099 }
3100 return tlsBackend;
3101}
3102
3107{
3108 return mode;
3109}
3110
3115{
3117}
3118
3123{
3124 return verificationPeerName;
3125}
3126
3131{
3132 return hostName;
3133}
3134
3136{
3137 return plainSocket;
3138}
3139
3144{
3145 if (const auto *tlsBackend = tlsBackendInUse())
3147 return {};
3148}
3149
3151
3152#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
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
\inmodule QtCore
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
The QHostAddress class provides an IP address.
bool isNull() const
Returns true if this host address is not valid for any host or interface.
bool isEqual(const QHostAddress &address, ConversionMode mode=TolerantConversion) const
QString hostName() const
Returns the name of the host whose IP addresses were looked up.
static QHostInfo fromName(const QString &name)
Looks up the IP address(es) for the given host name.
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.
Definition qlist.h:74
bool empty() const noexcept
Definition qlist.h:682
static QList< T > fromReadOnlyData(const T(&t)[N]) noexcept
Definition qlist.h:722
void detach()
Definition qlist.h:409
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qmutex.h:317
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:323
\inmodule QtCore
Definition qmutex.h:285
The QNetworkProxy class provides a network layer proxy.
QObject * q_ptr
Definition qobject.h:60
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
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:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
The QTcpSocket class provides a TCP socket.
Definition qtcpsocket.h:18
QTlsBackend is a factory class, providing implementations for the QSsl classes.
virtual QList< QSslCertificate > systemCaCertificates() const
virtual QList< QSsl::SupportedFeature > supportedFeatures() const =0
virtual QString backendName() const =0
virtual QList< QSsl::SslProtocol > supportedProtocols() const =0
static QList< QString > availableBackendNames()
virtual QTlsPrivate::TlsCryptograph * createTlsCryptograph() const
virtual QList< QSsl::ImplementedClass > implementedClasses() const =0
virtual void ensureInitialized() const
virtual QList< int > ellipticCurvesIds() const
static QString defaultBackendName()
static QTlsBackend * findBackend(const QString &backendName)
static QByteArray toAce(const QString &domain, AceProcessingOptions options={})
Definition qurl.cpp:3061
\inmodule QtCore
Definition qvariant.h:64
QSet< QString >::iterator it
else opt state
[0]
SupportedFeature
Definition qssl.h:132
@ PrivateKey
Definition qssl.h:20
ImplementedClass
Definition qssl.h:121
KeyAlgorithm
Describes the different key algorithms supported by QSslKey.
Definition qssl.h:29
EncodingFormat
Describes supported encoding formats for certificates and keys.
Definition qssl.h:24
@ IpAddressEntry
Definition qssl.h:40
@ DnsEntry
Definition qssl.h:39
SslProtocol
Describes the protocol of the cipher.
Definition qssl.h:43
@ DtlsV1_2
Definition qssl.h:56
@ DtlsV1_2OrLater
Definition qssl.h:57
@ UnknownProtocol
Definition qssl.h:62
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
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:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
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]
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
GLenum GLsizei len
GLuint writeBuffer
GLenum const void * addr
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
GLuint GLenum option
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define tr(X)
#define emit
#define Q_UNUSED(x)
static int compare(quint64 a, quint64 b)
unsigned short quint16
Definition qtypes.h:43
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
#define Q_INT64_C(c)
Definition qtypes.h:52
ptrdiff_t qintptr
Definition qtypes.h:71
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:44
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...
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent