diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2024-04-19 09:41:40 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2024-05-08 21:13:45 -0700 |
commit | 503fd609881fb220ac5abe7da2fe367efd90ed4b (patch) | |
tree | 0a4efedaf0508a308166d861d689572c6f9b569c /src/network/kernel/qdnslookup.cpp | |
parent | f2f00b2a4632aaeb58e6cdae7faef9e0bafaff49 (diff) |
QDnsLookup: add the ability to tell if the reply was authenticated
This is implemented for DNS-over-TLS and for the native Unix resolver,
because I can find no way to get the state of the reply on Windows with
the WinDNS.h API.
Change-Id: I455fe22ef4ad4b2f9b01fffd17c7bc022ded2363
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/network/kernel/qdnslookup.cpp')
-rw-r--r-- | src/network/kernel/qdnslookup.cpp | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index 9a35bd3365..a3ebbe04db 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -168,7 +168,7 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records) name, or the host name associated with an IP address you should use QHostInfo instead. - \section1 DNS-over-TLS + \section1 DNS-over-TLS and Authentic Data QDnsLookup supports DNS-over-TLS (DoT, as specified by \l{RFC 7858}) on some platforms. That currently includes all Unix platforms where regular @@ -182,6 +182,27 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records) server being connected to. Clients may use setSslConfiguration() to impose additional restrictions and sslConfiguration() to obtain information after the query is complete. + + QDnsLookup will request DNS servers queried over TLS to perform + authentication on the data they return. If they confirm the data is valid, + the \l authenticData property will be set to true. QDnsLookup does not + verify the integrity of the data by itself, so applications should only + trust this property on servers they have confirmed through other means to + be trustworthy. + + \section2 Authentic Data without TLS + + QDnsLookup request Authentic Data for any server set with setNameserver(), + even if TLS encryption is not required. This is useful when querying a + caching nameserver on the same host as the application or on a trusted + network. Though similar to the TLS case, the application is responsible for + determining if the server it chose to use is trustworthy, and if the + unencrypted connection cannot be tampered with. + + QDnsLookup obeys the system configuration to request Authentic Data on the + default nameserver (that is, if setNameserver() is not called). This is + currently only supported on Linux systems using glibc 2.31 or later. On any + other systems, QDnsLookup will ignore the AD bit in the query header. */ /*! @@ -419,6 +440,28 @@ QDnsLookup::~QDnsLookup() } /*! + \since 6.8 + \property QDnsLookup::authenticData + \brief whether the reply was authenticated by the resolver. + + QDnsLookup does not perform the authentication itself. Instead, it trusts + the name server that was queried to perform the authentication and report + it. The application is responsible for determining if any servers it + configured with setNameserver() are trustworthy; if no server was set, + QDnsLookup obeys system configuration on whether responses should be + trusted. + + This property may be set even if error() indicates a resolver error + occurred. + + \sa setNameserver(), nameserverProtocol() +*/ +bool QDnsLookup::isAuthenticData() const +{ + return d_func()->reply.authenticData; +} + +/*! \property QDnsLookup::error \brief the type of error that occurred if the DNS lookup failed, or NoError. */ @@ -1308,6 +1351,7 @@ inline QDebug operator<<(QDebug &d, QDnsLookupRunnable *r) #if QT_CONFIG(ssl) static constexpr std::chrono::milliseconds DnsOverTlsConnectTimeout(15'000); static constexpr std::chrono::milliseconds DnsOverTlsTimeout(120'000); +static constexpr quint8 DnsAuthenticDataBit = 0x20; static int makeReplyErrorFromSocket(QDnsLookupReply *reply, const QAbstractSocket *socket) { @@ -1334,6 +1378,9 @@ bool QDnsLookupRunnable::sendDnsOverTls(QDnsLookupReply *reply, QSpan<unsigned c socket.setProtocolTag("domain-s"_L1); # endif + // Request the name server attempt to authenticate the reply. + query[3] |= DnsAuthenticDataBit; + do { quint16 size = qToBigEndian<quint16>(query.size()); QDeadlineTimer timeout(DnsOverTlsTimeout); @@ -1363,8 +1410,12 @@ bool QDnsLookupRunnable::sendDnsOverTls(QDnsLookupReply *reply, QSpan<unsigned c // the maximum allocation is small. size = qFromBigEndian(size); response.resize(size); - if (waitForBytes(response.data(), size)) + if (waitForBytes(response.data(), size)) { + // check if the AD bit is set; we'll trust it over TLS requests + if (size >= 4) + reply->authenticData = response[3] & DnsAuthenticDataBit; return true; + } } while (false); // handle errors |