summaryrefslogtreecommitdiffstats
path: root/src/network/kernel/qdnslookup.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2024-04-19 20:45:00 -0700
committerThiago Macieira <thiago.macieira@intel.com>2024-05-08 21:13:43 -0700
commit9724b039cac2cc309575ce5a030841939eeb1acd (patch)
tree235d2a2d574214742b2d3c1b18662c5050443df7 /src/network/kernel/qdnslookup.cpp
parentfd6cfd22831c6ff7078bb97e62439375cfc849f6 (diff)
QDnsLookup: add initial support for DNS-over-TLS (DoT)
This is just an empty shell for now. The implementation will come in the next commit. [ChangeLog][QtNetwork][QDnsLookup] The class now supports DNS-over-TLS and some other DNSSEC experimental features, on some platforms. Use QDnsLookup::isProtocolSupported to know if the protocol is supported on a given platform. Change-Id: I455fe22ef4ad4b2f9b01fffd17c7e034dee75533 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/network/kernel/qdnslookup.cpp')
-rw-r--r--src/network/kernel/qdnslookup.cpp179
1 files changed, 172 insertions, 7 deletions
diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp
index c310c7e28e..fedefe1e3b 100644
--- a/src/network/kernel/qdnslookup.cpp
+++ b/src/network/kernel/qdnslookup.cpp
@@ -159,6 +159,21 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
\note If you simply want to find the IP address(es) associated with a host
name, or the host name associated with an IP address you should use
QHostInfo instead.
+
+ \section1 DNS-over-TLS
+
+ QDnsLookup supports DNS-over-TLS (DoT, as specified by \l{RFC 7858}) on
+ some platforms. That currently includes all Unix platforms where regular
+ queries are supported, if \l QSslSocket support is present in Qt. To query
+ if support is present at runtime, use isProtocolSupported().
+
+ When using DNS-over-TLS, QDnsLookup only implements the "Opportunistic
+ Privacy Profile" method of authentication, as described in \l{RFC 7858}
+ section 4.1. In this mode, QDnsLookup (through \l QSslSocket) only
+ validates that the server presents a certificate that is valid for the
+ server being connected to. Clients may use setSslConfiguration() to impose
+ additional restrictions and sslConfiguration() to obtain information after
+ the query is complete.
*/
/*!
@@ -217,6 +232,62 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
*/
/*!
+ \enum QDnsLookup::Protocol
+
+ Indicates the type of DNS server that is being queried.
+
+ \value Standard
+ Regular, unencrypted DNS, using UDP and falling back to TCP as necessary
+ (default port: 53)
+
+ \value DnsOverTls
+ Encrypted DNS over TLS (DoT, as specified by \l{RFC 7858}), over TCP
+ (default port: 853)
+
+ \sa isProtocolSupported(), nameserverProtocol, setNameserver()
+*/
+
+/*!
+ \since 6.8
+
+ Returns true if DNS queries using \a protocol are supported with QDnsLookup.
+
+ \sa nameserverProtocol
+*/
+bool QDnsLookup::isProtocolSupported(Protocol protocol)
+{
+#if QT_CONFIG(libresolv) || defined(Q_OS_WIN)
+ switch (protocol) {
+ case QDnsLookup::Standard:
+ return true;
+ case QDnsLookup::DnsOverTls:
+ return false;
+ }
+#else
+ Q_UNUSED(protocol)
+#endif
+ return false;
+}
+
+/*!
+ \since 6.8
+
+ Returns the standard (default) port number for the protocol \a protocol.
+
+ \sa isProtocolSupported()
+*/
+quint16 QDnsLookup::defaultPortForProtocol(Protocol protocol) noexcept
+{
+ switch (protocol) {
+ case QDnsLookup::Standard:
+ return DnsPort;
+ case QDnsLookup::DnsOverTls:
+ return DnsOverTlsPort;
+ }
+ return 0; // will probably fail somewhere
+}
+
+/*!
\fn void QDnsLookup::finished()
This signal is emitted when the reply has finished processing.
@@ -270,7 +341,7 @@ QDnsLookup::QDnsLookup(Type type, const QString &name, QObject *parent)
*/
QDnsLookup::QDnsLookup(Type type, const QString &name, const QHostAddress &nameserver, QObject *parent)
- : QDnsLookup(type, name, nameserver, DnsPort, parent)
+ : QDnsLookup(type, name, nameserver, 0, parent)
{
}
@@ -285,8 +356,9 @@ QDnsLookup::QDnsLookup(Type type, const QString &name, const QHostAddress &names
//! [nameserver-port]
\note Setting the port number to any value other than the default (53) can
cause the name resolution to fail, depending on the operating system
- limitations and firewalls. Notably, the Windows API used by QDnsLookup is
- unable to handle alternate port numbers.
+ limitations and firewalls, if the nameserverProtocol() to be used
+ QDnsLookup::Standard. Notably, the Windows API used by QDnsLookup is unable
+ to handle alternate port numbers.
//! [nameserver-port]
*/
QDnsLookup::QDnsLookup(Type type, const QString &name, const QHostAddress &nameserver, quint16 port, QObject *parent)
@@ -300,6 +372,30 @@ QDnsLookup::QDnsLookup(Type type, const QString &name, const QHostAddress &names
}
/*!
+ \since 6.8
+
+ Constructs a QDnsLookup object to issue a query for \a name of record type
+ \a type, using the DNS server \a nameserver running on port \a port, and
+ sets \a parent as the parent object.
+
+ The query will be sent using \a protocol, if supported. Use
+ isProtocolSupported() to check if it is supported.
+
+ \include qdnslookup.cpp nameserver-port
+*/
+QDnsLookup::QDnsLookup(Type type, const QString &name, Protocol protocol,
+ const QHostAddress &nameserver, quint16 port, QObject *parent)
+ : QObject(*new QDnsLookupPrivate, parent)
+{
+ Q_D(QDnsLookup);
+ d->name = name;
+ d->type = type;
+ d->nameserver = nameserver;
+ d->port = port;
+ d->protocol = protocol;
+}
+
+/*!
Destroys the QDnsLookup object.
It is safe to delete a QDnsLookup object even if it is not finished, you
@@ -416,6 +512,10 @@ QBindable<QHostAddress> QDnsLookup::bindableNameserver()
\property QDnsLookup::nameserverPort
\since 6.6
\brief the port number of nameserver to use for DNS lookup.
+
+ The value of 0 indicates that QDnsLookup should use the default port for
+ the nameserverProtocol().
+
\include qdnslookup.cpp nameserver-port
*/
@@ -437,18 +537,44 @@ QBindable<quint16> QDnsLookup::bindableNameserverPort()
}
/*!
+ \property QDnsLookup::nameserverProtocol
+ \since 6.8
+ \brief the protocol to use when sending the DNS query
+
+ \sa isProtocolSupported()
+*/
+QDnsLookup::Protocol QDnsLookup::nameserverProtocol() const
+{
+ return d_func()->protocol;
+}
+
+void QDnsLookup::setNameserverProtocol(Protocol protocol)
+{
+ d_func()->protocol = protocol;
+}
+
+QBindable<QDnsLookup::Protocol> QDnsLookup::bindableNameserverProtocol()
+{
+ return &d_func()->protocol;
+}
+
+/*!
+ \fn void QDnsLookup::setNameserver(const QHostAddress &nameserver, quint16 port)
\since 6.6
+
Sets the nameserver to \a nameserver and the port to \a port.
\include qdnslookup.cpp nameserver-port
\sa QDnsLookup::nameserver, QDnsLookup::nameserverPort
*/
-void QDnsLookup::setNameserver(const QHostAddress &nameserver, quint16 port)
+
+void QDnsLookup::setNameserver(Protocol protocol, const QHostAddress &nameserver, quint16 port)
{
Qt::beginPropertyUpdateGroup();
setNameserver(nameserver);
setNameserverPort(port);
+ setNameserverProtocol(protocol);
Qt::endPropertyUpdateGroup();
}
@@ -523,6 +649,29 @@ QList<QDnsTextRecord> QDnsLookup::textRecords() const
return d_func()->reply.textRecords;
}
+#if QT_CONFIG(ssl)
+/*!
+ \since 6.8
+ Sets the \a sslConfiguration to use for outgoing DNS-over-TLS connections.
+
+ \sa sslConfiguration(), QSslSocket::setSslConfiguration()
+*/
+void QDnsLookup::setSslConfiguration(const QSslConfiguration &sslConfiguration)
+{
+ Q_UNUSED(sslConfiguration)
+}
+
+/*!
+ Returns the current SSL configuration.
+
+ \sa setSslConfiguration()
+*/
+QSslConfiguration QDnsLookup::sslConfiguration() const
+{
+ return {};
+}
+#endif
+
/*!
Aborts the DNS lookup operation.
@@ -565,6 +714,9 @@ void QDnsLookup::lookup()
#ifdef QDNSLOOKUP_DEBUG
qDebug("DNS reply for %s: %i (%s)", qPrintable(d->name), reply.error, qPrintable(reply.errorString));
#endif
+#if QT_CONFIG(ssl)
+ d->sslConfiguration = std::move(reply.sslConfiguration);
+#endif
d->reply = reply;
d->runnable = nullptr;
d->isFinished = true;
@@ -1070,8 +1222,14 @@ inline QDnsLookupRunnable::QDnsLookupRunnable(const QDnsLookupPrivate *d)
: requestName(encodeLabel(d->name)),
nameserver(d->nameserver),
requestType(d->type),
- port(d->port)
+ port(d->port),
+ protocol(d->protocol)
{
+ if (port == 0)
+ port = QDnsLookup::defaultPortForProtocol(protocol);
+#if QT_CONFIG(ssl)
+ sslConfiguration = d->sslConfiguration;
+#endif
}
void QDnsLookupRunnable::run()
@@ -1120,9 +1278,16 @@ inline QDebug operator<<(QDebug &d, QDnsLookupRunnable *r)
if (r->requestName.size() > MaxDomainNameLength)
d << "... (truncated)";
d << " type " << r->requestType;
- if (!r->nameserver.isNull())
+ if (!r->nameserver.isNull()) {
d << " to nameserver " << qUtf16Printable(r->nameserver.toString())
- << " port " << (r->port ? r->port : DnsPort);
+ << " port " << (r->port ? r->port : QDnsLookup::defaultPortForProtocol(r->protocol));
+ switch (r->protocol) {
+ case QDnsLookup::Standard:
+ break;
+ case QDnsLookup::DnsOverTls:
+ d << " (TLS)";
+ }
+ }
return d;
}