diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2024-05-06 14:17:26 -0700 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2024-05-09 04:13:44 +0000 |
commit | f2f00b2a4632aaeb58e6cdae7faef9e0bafaff49 (patch) | |
tree | 1072ed17a0b43eb0b4dab8b6a31673459f839a4e /tests/auto | |
parent | 9724b039cac2cc309575ce5a030841939eeb1acd (diff) |
QDnsLookup: implement DNS-over-TLS
For the libresolv (Unix) implementation, we already had the packet
prepared by res_nmkquery(). This commit moves the res_nsend() to a
separate function so QDnsLookupRunnable::query() can be more concise.
On the Windows side, this commit creates a separate function for the DoT
case, because we now need to use two other functions from WinDNS so we
can create a query and parse the reply.
The rest is just QSslSocket.
Change-Id: I455fe22ef4ad4b2f9b01fffd17c805a3cb0466eb
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp | 87 |
1 files changed, 71 insertions, 16 deletions
diff --git a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp index 2723caa3b8..058bfb341e 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 @@ -135,9 +142,57 @@ static QList<QHostAddress> globalPublicNameservers(QDnsLookup::Protocol proto) //"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; - if (proto != QDnsLookup::Standard) - return result; QRandomGenerator &rng = *QRandomGenerator::system(); for (auto name : candidates) { // check the candidates for reachability @@ -147,23 +202,18 @@ static QList<QHostAddress> globalPublicNameservers(QDnsLookup::Protocol proto) 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"; @@ -190,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) |