Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dns/asyncquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ async def _http3(
if url_parts.port is not None:
port = url_parts.port

q.id = 0
q.set_id(0)
wire = q.to_wire()
the_connection: dns.quic.AsyncQuicConnection
if connection:
Expand Down Expand Up @@ -804,7 +804,7 @@ async def quic(
if server_hostname is not None and hostname is None:
hostname = server_hostname

q.id = 0
q.set_id(0)
wire = q.to_wire()
the_connection: dns.quic.AsyncQuicConnection
if connection:
Expand Down
1 change: 1 addition & 0 deletions dns/asyncresolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ async def resolve(
nameserver, tcp, backoff = resolution.next_nameserver()
if backoff:
await backend.sleep(backoff)
request.set_random_id()
timeout = self._compute_timeout(start, lifetime, resolution.errors)
try:
response = await nameserver.async_query(
Expand Down
19 changes: 19 additions & 0 deletions dns/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,25 @@ def had_tsig(self) -> bool:
def _make_opt(flags=0, payload=DEFAULT_EDNS_PAYLOAD, options=None):
return dns.renderer._make_opt(flags, payload, options)

def set_id(self, id: int):
"""Set the message id to the specified value, and if TSIG is going to be used
to sign this message later, update it accordingly.

:param id: The message id
:type id: int
"""
self.id = id
if self.want_tsig_sign:
assert self.tsig is not None
assert self.tsig.rdtype == dns.rdatatype.TSIG
tsig_rdata = cast(dns.rdtypes.ANY.TSIG.TSIG, self.tsig[0])
self.use_tsig(self.keyring, None, tsig_rdata.fudge, id, tsig_rdata.error, tsig_rdata.other,
tsig_rdata.algorithm)

def set_random_id(self):
"""Assign a newly-generated random query id to the message."""
self.set_id(dns.entropy.random_16())

def use_edns(
self,
edns: int | bool | None = 0,
Expand Down
4 changes: 2 additions & 2 deletions dns/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ def _http3(
if url_parts.port is not None:
port = url_parts.port

q.id = 0
q.set_id(0)
wire = q.to_wire()
the_connection: dns.quic.SyncQuicConnection
the_manager: dns.quic.SyncQuicManager
Expand Down Expand Up @@ -1444,7 +1444,7 @@ def quic(
if server_hostname is not None and hostname is None:
hostname = server_hostname

q.id = 0
q.set_id(0)
wire = q.to_wire()
the_connection: dns.quic.SyncQuicConnection
the_manager: dns.quic.SyncQuicManager
Expand Down
4 changes: 1 addition & 3 deletions dns/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import dns._file_util
import dns.edns
import dns.exception
import dns.flags
import dns.inet
import dns.ipv4
import dns.ipv6
Expand All @@ -41,11 +40,9 @@
import dns.nameserver
import dns.query
import dns.rcode
import dns.rdata
import dns.rdataclass
import dns.rdatatype
import dns.rdtypes.ANY.PTR
import dns.rdtypes.svcbbase
import dns.reversename
import dns.tsig

Expand Down Expand Up @@ -1317,6 +1314,7 @@ def resolve(
nameserver, tcp, backoff = resolution.next_nameserver()
if backoff:
time.sleep(backoff)
request.set_random_id()
timeout = self._compute_timeout(start, lifetime, resolution.errors)
try:
response = nameserver.query(
Expand Down
9 changes: 7 additions & 2 deletions doc/whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
What's New in dnspython
=======================

2.9.10 (in development)
2.10.0 (in development)

* The type annotation of ``public_key()`` on the ``dns.dnssecalgs`` private
key classes is now ``dns.dnssecalgs.base.GenericPublicKey``, as declared by
Expand All @@ -18,6 +18,11 @@ What's New in dnspython
2.9.1 (in development)
----------------------

* The resolver now assigns a new random query id to every query.

* For transports that require a 0 query id, set it in a way that does not break
TSIG.

* ``dns.message.QueryMessage.resolve_chaining()`` now caps the minimum TTL of
a negative response with no SOA record at 300 seconds
(``dns.message.NEGATIVE_TTL_WITHOUT_SOA``). Previously the TTL was left at
Expand Down Expand Up @@ -147,7 +152,7 @@ What's New in dnspython
signed response failed with ``BadSignature`` and a response with no TSIG at
all was accepted, as the RFC 8945 section 5.4 check for a missing TSIG was
skipped.

* ``dns.query.inbound_xfr()``, ``dns.asyncquery.inbound_xfr()``, and
``dns.query.xfr()`` now check every response message with
``dns.message.Message.is_response()`` and raise ``dns.query.BadResponse`` if
Expand Down
Loading