diff options
Diffstat (limited to 'tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp')
-rw-r--r-- | tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp | 159 |
1 files changed, 134 insertions, 25 deletions
diff --git a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp index f71e94862c..af3a74a498 100644 --- a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp +++ b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp @@ -13,6 +13,13 @@ #include <QtNetwork/QNetworkDatagram> #include <QtNetwork/QUdpSocket> +#if QT_CONFIG(networkproxy) +# include <QtNetwork/QNetworkProxyFactory> +#endif +#if QT_CONFIG(ssl) +# include <QtNetwork/QSslSocket> +#endif + #ifdef Q_OS_UNIX # include <QtCore/QFile> #else @@ -37,8 +44,11 @@ class tst_QDnsLookup: public QObject QStringList domainNameListAlternatives(const QString &input); std::unique_ptr<QDnsLookup> lookupCommon(QDnsLookup::Type type, const QString &domain, - const QHostAddress &server = {}, quint16 port = 53); + const QHostAddress &server = {}, quint16 port = 0, + QDnsLookup::Protocol protocol = QDnsLookup::Standard); QStringList formatReply(const QDnsLookup *lookup) const; + + void setNameserver_helper(QDnsLookup::Protocol protocol); public slots: void initTestCase(); @@ -57,6 +67,8 @@ private slots: void setNameserverLoopback(); void setNameserver_data(); void setNameserver(); + void dnsOverTls_data(); + void dnsOverTls(); void bindingsAndProperties(); void automatedBindings(); }; @@ -74,9 +86,11 @@ static const char preparedDnsQuery[] = "\x00\x00\x06\x00\x01" // <root domain> IN SOA ; -static QList<QHostAddress> systemNameservers() +static QList<QHostAddress> systemNameservers(QDnsLookup::Protocol protocol) { QList<QHostAddress> result; + if (protocol != QDnsLookup::Standard) + return result; #ifdef Q_OS_WIN ULONG infosize = 0; @@ -113,7 +127,7 @@ static QList<QHostAddress> systemNameservers() return result; } -static QList<QHostAddress> globalPublicNameservers() +static QList<QHostAddress> globalPublicNameservers(QDnsLookup::Protocol proto) { const char *const candidates[] = { // Google's dns.google @@ -128,6 +142,56 @@ static QList<QHostAddress> globalPublicNameservers() //"9.9.9.9", "2620:fe::9", }; + auto udpSendAndReceive = [](const QHostAddress &addr, QByteArray &data) { + QUdpSocket socket; + socket.connectToHost(addr, 53); + if (socket.waitForConnected(1)) + socket.write(data); + + if (!socket.waitForReadyRead(1000)) + return socket.errorString(); + + QNetworkDatagram dgram = socket.receiveDatagram(); + if (!dgram.isValid()) + return socket.errorString(); + + data = dgram.data(); + return QString(); + }; + + auto tlsSendAndReceive = [](const QHostAddress &addr, QByteArray &data) { +#if QT_CONFIG(ssl) + QSslSocket socket; + QDeadlineTimer timeout(2000); + socket.connectToHostEncrypted(addr.toString(), 853); + if (!socket.waitForEncrypted(2000)) + return socket.errorString(); + + quint16 size = qToBigEndian<quint16>(data.size()); + socket.write(reinterpret_cast<char *>(&size), sizeof(size)); + socket.write(data); + + if (!socket.waitForReadyRead(timeout.remainingTime())) + return socket.errorString(); + if (socket.bytesAvailable() < 2) + return u"protocol error"_s; + + socket.read(reinterpret_cast<char *>(&size), sizeof(size)); + size = qFromBigEndian(size); + + while (socket.bytesAvailable() < size) { + int remaining = timeout.remainingTime(); + if (remaining < 0 || !socket.waitForReadyRead(remaining)) + return socket.errorString(); + } + + data = socket.readAll(); + return QString(); +#else + return u"SSL/TLS support not compiled in"_s; +#endif + }; + QList<QHostAddress> result; QRandomGenerator &rng = *QRandomGenerator::system(); for (auto name : candidates) { @@ -138,23 +202,18 @@ static QList<QHostAddress> globalPublicNameservers() char *ptr = data.data(); qToBigEndian(id, ptr); - QUdpSocket socket; - socket.connectToHost(addr, 53); - if (socket.waitForConnected(1)) - socket.write(data); - - if (!socket.waitForReadyRead(1000)) { - qDebug() << addr << "discarded:" << socket.errorString(); - continue; - } - - QNetworkDatagram dgram = socket.receiveDatagram(); - if (!dgram.isValid()) { - qDebug() << addr << "discarded:" << socket.errorString(); + QString errorString = [&] { + switch (proto) { + case QDnsLookup::Standard: return udpSendAndReceive(addr, data); + case QDnsLookup::DnsOverTls: return tlsSendAndReceive(addr, data); + } + Q_UNREACHABLE(); + }(); + if (!errorString.isEmpty()) { + qDebug() << addr << "discarded:" << errorString; continue; } - data = dgram.data(); ptr = data.data(); if (data.size() < HeaderSize) { qDebug() << addr << "discarded: reply too small"; @@ -181,6 +240,11 @@ void tst_QDnsLookup::initTestCase() { if (qgetenv("QTEST_ENVIRONMENT") == "ci") dnsServersMustWork = true; + +#if QT_CONFIG(networkproxy) + // for DNS-over-TLS + QNetworkProxyFactory::setUseSystemConfiguration(true); +#endif } QString tst_QDnsLookup::domainName(const QString &input) @@ -221,9 +285,10 @@ QStringList tst_QDnsLookup::domainNameListAlternatives(const QString &input) std::unique_ptr<QDnsLookup> tst_QDnsLookup::lookupCommon(QDnsLookup::Type type, const QString &domain, - const QHostAddress &server, quint16 port) + const QHostAddress &server, quint16 port, + QDnsLookup::Protocol protocol) { - auto lookup = std::make_unique<QDnsLookup>(type, domainName(domain), server, port); + auto lookup = std::make_unique<QDnsLookup>(type, domainName(domain), protocol, server, port); QObject::connect(lookup.get(), &QDnsLookup::finished, &QTestEventLoop::instance(), &QTestEventLoop::exitLoop); lookup->lookup(); @@ -309,6 +374,14 @@ QStringList tst_QDnsLookup::formatReply(const QDnsLookup *lookup) const result.append(std::move(entry)); } + for (const QDnsTlsAssociationRecord &rr : lookup->tlsAssociationRecords()) { + QString entry = u"TLSA %1 %2 %3 %4"_s.arg(int(rr.usage())).arg(int(rr.selector())) + .arg(int(rr.matchType())).arg(rr.value().toHex().toUpper()); + if (rr.name() != domain) + entry = "TLSA unexpected label to "_L1 + rr.name(); + result.append(std::move(entry)); + } + result.sort(); return result; } @@ -439,6 +512,10 @@ void tst_QDnsLookup::lookup_data() "SRV 2 50 7 aaaa-single;" "SRV 3 50 7 a-multi"; + QTest::newRow("tlsa") << QDnsLookup::Type::TLSA << "_25._tcp.multi" + << "TLSA 3 1 1 0123456789ABCDEFFEDCBA9876543210" + "0123456789ABCDEFFEDCBA9876543210"; + QTest::newRow("txt-single") << QDnsLookup::TXT << "txt-single" << "TXT \"Hello\""; QTest::newRow("txt-multi-onerr") << QDnsLookup::TXT << "txt-multi-onerr" @@ -457,8 +534,12 @@ void tst_QDnsLookup::lookup() if (!lookup) return; - QCOMPARE(lookup->error(), QDnsLookup::NoError); +#ifdef Q_OS_WIN + if (QTest::currentDataTag() == "tlsa"_L1) + QSKIP("WinDNS doesn't work properly with TLSA records and we don't know why"); +#endif QCOMPARE(lookup->errorString(), QString()); + QCOMPARE(lookup->error(), QDnsLookup::NoError); QCOMPARE(lookup->type(), type); QCOMPARE(lookup->name(), domainName(domain)); @@ -591,31 +672,59 @@ void tst_QDnsLookup::setNameserverLoopback() QCOMPARE(lookup.error(), QDnsLookup::NotFoundError); } -void tst_QDnsLookup::setNameserver_data() +template <QDnsLookup::Protocol Protocol> +static void setNameserver_data_helper(const QByteArray &protoName) { - static QList<QHostAddress> servers = systemNameservers() + globalPublicNameservers(); + if (!QDnsLookup::isProtocolSupported(Protocol)) + QSKIP(protoName + " not supported"); + + static QList<QHostAddress> servers = systemNameservers(Protocol) + + globalPublicNameservers(Protocol); QTest::addColumn<QHostAddress>("server"); if (servers.isEmpty()) { - QSKIP("No reachable DNS servers were found"); + QSKIP("No reachable " + protoName + " servers were found"); } else { for (const QHostAddress &h : std::as_const(servers)) QTest::addRow("%s", qUtf8Printable(h.toString())) << h; } } -void tst_QDnsLookup::setNameserver() +void tst_QDnsLookup::setNameserver_data() +{ + setNameserver_data_helper<QDnsLookup::Standard>("DNS"); +} + +void tst_QDnsLookup::setNameserver_helper(QDnsLookup::Protocol protocol) { QFETCH(QHostAddress, server); + QElapsedTimer timer; + timer.start(); std::unique_ptr<QDnsLookup> lookup = - lookupCommon(QDnsLookup::Type::A, "a-single", server); + lookupCommon(QDnsLookup::Type::A, "a-single", server, 0, protocol); if (!lookup) return; + qDebug() << "Lookup took" << timer.elapsed() << "ms"; QCOMPARE(lookup->error(), QDnsLookup::NoError); QString result = formatReply(lookup.get()).join(';'); QCOMPARE(result, "A 192.0.2.1"); } +void tst_QDnsLookup::setNameserver() +{ + setNameserver_helper(QDnsLookup::Standard); +} + +void tst_QDnsLookup::dnsOverTls_data() +{ + setNameserver_data_helper<QDnsLookup::DnsOverTls>("DNS-over-TLS"); +} + +void tst_QDnsLookup::dnsOverTls() +{ + setNameserver_helper(QDnsLookup::DnsOverTls); +} + void tst_QDnsLookup::bindingsAndProperties() { QDnsLookup lookup; |