dnspython 2.9.0__tar.gz → 2.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. dnspython-2.9.1/LICENSE +35 -0
  2. {dnspython-2.9.0 → dnspython-2.9.1}/PKG-INFO +4 -2
  3. {dnspython-2.9.0 → dnspython-2.9.1}/README.md +1 -1
  4. {dnspython-2.9.0 → dnspython-2.9.1}/dns/asyncquery.py +10 -6
  5. {dnspython-2.9.0 → dnspython-2.9.1}/dns/asyncresolver.py +1 -0
  6. {dnspython-2.9.0 → dnspython-2.9.1}/dns/btreezone.py +53 -30
  7. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssec.py +11 -9
  8. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/cryptography.py +3 -3
  9. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/dsa.py +6 -0
  10. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/ecdsa.py +5 -0
  11. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/eddsa.py +1 -1
  12. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/mldsa.py +1 -1
  13. {dnspython-2.9.0 → dnspython-2.9.1}/dns/edns.py +21 -5
  14. {dnspython-2.9.0 → dnspython-2.9.1}/dns/entropy.py +19 -3
  15. {dnspython-2.9.0 → dnspython-2.9.1}/dns/message.py +72 -9
  16. {dnspython-2.9.0 → dnspython-2.9.1}/dns/name.py +59 -9
  17. {dnspython-2.9.0 → dnspython-2.9.1}/dns/namedict.py +2 -1
  18. {dnspython-2.9.0 → dnspython-2.9.1}/dns/query.py +9 -5
  19. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdata.py +6 -3
  20. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/AFSDB.py +2 -2
  21. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/CAA.py +1 -1
  22. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/CERT.py +1 -1
  23. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/HIP.py +1 -1
  24. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/KEY.py +1 -1
  25. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/LOC.py +7 -0
  26. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/NSEC3.py +23 -6
  27. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/OPENPGPKEY.py +1 -1
  28. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/RP.py +2 -2
  29. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/RT.py +1 -1
  30. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/SIG.py +7 -0
  31. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/SOA.py +2 -2
  32. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/SSHFP.py +10 -0
  33. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/TKEY.py +3 -3
  34. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/TSIG.py +4 -3
  35. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/APL.py +2 -1
  36. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/DHCID.py +1 -1
  37. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/IPSECKEY.py +1 -1
  38. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/NAPTR.py +1 -1
  39. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/PX.py +2 -2
  40. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/SRV.py +1 -1
  41. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/base64base.py +1 -1
  42. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/dnskeybase.py +1 -1
  43. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/mxbase.py +31 -2
  44. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/nsbase.py +8 -3
  45. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/rrsigbase.py +11 -5
  46. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/svcbbase.py +7 -7
  47. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/tlsabase.py +13 -0
  48. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/util.py +7 -4
  49. {dnspython-2.9.0 → dnspython-2.9.1}/dns/renderer.py +2 -2
  50. {dnspython-2.9.0 → dnspython-2.9.1}/dns/resolver.py +1 -3
  51. {dnspython-2.9.0 → dnspython-2.9.1}/dns/reversename.py +2 -0
  52. {dnspython-2.9.0 → dnspython-2.9.1}/dns/set.py +4 -0
  53. {dnspython-2.9.0 → dnspython-2.9.1}/dns/tokenizer.py +14 -1
  54. {dnspython-2.9.0 → dnspython-2.9.1}/dns/ttl.py +1 -1
  55. {dnspython-2.9.0 → dnspython-2.9.1}/dns/version.py +1 -1
  56. {dnspython-2.9.0 → dnspython-2.9.1}/dns/versioned.py +4 -3
  57. {dnspython-2.9.0 → dnspython-2.9.1}/dns/wire.py +4 -2
  58. {dnspython-2.9.0 → dnspython-2.9.1}/dns/wirebase.py +7 -0
  59. {dnspython-2.9.0 → dnspython-2.9.1}/dns/zone.py +16 -3
  60. {dnspython-2.9.0 → dnspython-2.9.1}/dns/zonefile.py +80 -74
  61. {dnspython-2.9.0 → dnspython-2.9.1}/pyproject.toml +4 -2
  62. {dnspython-2.9.0 → dnspython-2.9.1}/pyproject.toml.orig +4 -2
  63. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_btreezone.py +20 -0
  64. dnspython-2.9.1/tests/test_btreezone_delegations.py +217 -0
  65. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_bugs.py +46 -0
  66. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_dnssec.py +69 -0
  67. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_dnssecalgs.py +41 -0
  68. dnspython-2.9.1/tests/test_doq.py +142 -0
  69. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_edns.py +18 -0
  70. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_entropy.py +9 -4
  71. dnspython-2.9.1/tests/test_gateway_text.py +38 -0
  72. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_generate.py +63 -0
  73. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_message.py +75 -0
  74. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_name.py +47 -0
  75. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_namedict.py +20 -0
  76. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_nsec3.py +35 -0
  77. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_query.py +3 -3
  78. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdata.py +205 -1
  79. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_renderer.py +9 -0
  80. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_resolver.py +56 -0
  81. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_reversename.py +37 -0
  82. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_set.py +33 -0
  83. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_tokenizer.py +29 -0
  84. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_transaction.py +64 -0
  85. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_tsig.py +41 -0
  86. dnspython-2.9.1/tests/test_tsig_doh_doq.py +144 -0
  87. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_ttl.py +5 -0
  88. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_wire.py +61 -2
  89. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_xfr.py +195 -26
  90. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_zone.py +40 -0
  91. dnspython-2.9.0/tests/test_doq.py +0 -76
  92. {dnspython-2.9.0 → dnspython-2.9.1}/dns/__init__.py +0 -0
  93. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_asyncbackend.py +0 -0
  94. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_asyncio_backend.py +0 -0
  95. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_ddr.py +0 -0
  96. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_features.py +0 -0
  97. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_file_util.py +0 -0
  98. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_immutable_ctx.py +0 -0
  99. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_no_ssl.py +0 -0
  100. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_render_util.py +0 -0
  101. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_text_util.py +0 -0
  102. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_tls_util.py +0 -0
  103. {dnspython-2.9.0 → dnspython-2.9.1}/dns/_trio_backend.py +0 -0
  104. {dnspython-2.9.0 → dnspython-2.9.1}/dns/asyncbackend.py +0 -0
  105. {dnspython-2.9.0 → dnspython-2.9.1}/dns/btree.py +0 -0
  106. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/__init__.py +0 -0
  107. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/base.py +0 -0
  108. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssecalgs/rsa.py +0 -0
  109. {dnspython-2.9.0 → dnspython-2.9.1}/dns/dnssectypes.py +0 -0
  110. {dnspython-2.9.0 → dnspython-2.9.1}/dns/e164.py +0 -0
  111. {dnspython-2.9.0 → dnspython-2.9.1}/dns/enum.py +0 -0
  112. {dnspython-2.9.0 → dnspython-2.9.1}/dns/exception.py +0 -0
  113. {dnspython-2.9.0 → dnspython-2.9.1}/dns/flags.py +0 -0
  114. {dnspython-2.9.0 → dnspython-2.9.1}/dns/grange.py +0 -0
  115. {dnspython-2.9.0 → dnspython-2.9.1}/dns/immutable.py +0 -0
  116. {dnspython-2.9.0 → dnspython-2.9.1}/dns/inet.py +0 -0
  117. {dnspython-2.9.0 → dnspython-2.9.1}/dns/ipv4.py +0 -0
  118. {dnspython-2.9.0 → dnspython-2.9.1}/dns/ipv6.py +0 -0
  119. {dnspython-2.9.0 → dnspython-2.9.1}/dns/nameserver.py +0 -0
  120. {dnspython-2.9.0 → dnspython-2.9.1}/dns/node.py +0 -0
  121. {dnspython-2.9.0 → dnspython-2.9.1}/dns/opcode.py +0 -0
  122. {dnspython-2.9.0 → dnspython-2.9.1}/dns/py.typed +0 -0
  123. {dnspython-2.9.0 → dnspython-2.9.1}/dns/quic/__init__.py +0 -0
  124. {dnspython-2.9.0 → dnspython-2.9.1}/dns/quic/_asyncio.py +0 -0
  125. {dnspython-2.9.0 → dnspython-2.9.1}/dns/quic/_common.py +0 -0
  126. {dnspython-2.9.0 → dnspython-2.9.1}/dns/quic/_sync.py +0 -0
  127. {dnspython-2.9.0 → dnspython-2.9.1}/dns/quic/_trio.py +0 -0
  128. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rcode.py +0 -0
  129. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdataclass.py +0 -0
  130. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdataset.py +0 -0
  131. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdatatype.py +0 -0
  132. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/AMTRELAY.py +0 -0
  133. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/AVC.py +0 -0
  134. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/BRID.py +0 -0
  135. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/CDNSKEY.py +0 -0
  136. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/CDS.py +0 -0
  137. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/CNAME.py +0 -0
  138. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/CSYNC.py +0 -0
  139. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/DLV.py +0 -0
  140. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/DNAME.py +0 -0
  141. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/DNSKEY.py +0 -0
  142. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/DS.py +0 -0
  143. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/DSYNC.py +0 -0
  144. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/EUI48.py +0 -0
  145. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/EUI64.py +0 -0
  146. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/GPOS.py +0 -0
  147. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/HHIT.py +0 -0
  148. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/HINFO.py +0 -0
  149. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/ISDN.py +0 -0
  150. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/L32.py +0 -0
  151. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/L64.py +0 -0
  152. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/LP.py +0 -0
  153. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/MX.py +0 -0
  154. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/NID.py +0 -0
  155. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/NINFO.py +0 -0
  156. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/NS.py +0 -0
  157. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/NSEC.py +0 -0
  158. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/NSEC3PARAM.py +0 -0
  159. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/OPT.py +0 -0
  160. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/PTR.py +0 -0
  161. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/RESINFO.py +0 -0
  162. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/RRSIG.py +0 -0
  163. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/SMIMEA.py +0 -0
  164. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/SPF.py +0 -0
  165. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/TLSA.py +0 -0
  166. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/TXT.py +0 -0
  167. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/URI.py +0 -0
  168. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/WALLET.py +0 -0
  169. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/X25.py +0 -0
  170. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/ZONEMD.py +0 -0
  171. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/ANY/__init__.py +0 -0
  172. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/CH/A.py +0 -0
  173. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/CH/__init__.py +0 -0
  174. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/A.py +0 -0
  175. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/AAAA.py +0 -0
  176. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/HTTPS.py +0 -0
  177. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/KX.py +0 -0
  178. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/NSAP.py +0 -0
  179. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/NSAP_PTR.py +0 -0
  180. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/SVCB.py +0 -0
  181. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/WKS.py +0 -0
  182. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/IN/__init__.py +0 -0
  183. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/__init__.py +0 -0
  184. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/dsbase.py +0 -0
  185. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/euibase.py +0 -0
  186. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rdtypes/txtbase.py +0 -0
  187. {dnspython-2.9.0 → dnspython-2.9.1}/dns/rrset.py +0 -0
  188. {dnspython-2.9.0 → dnspython-2.9.1}/dns/serial.py +0 -0
  189. {dnspython-2.9.0 → dnspython-2.9.1}/dns/style.py +0 -0
  190. {dnspython-2.9.0 → dnspython-2.9.1}/dns/transaction.py +0 -0
  191. {dnspython-2.9.0 → dnspython-2.9.1}/dns/tsig.py +0 -0
  192. {dnspython-2.9.0 → dnspython-2.9.1}/dns/tsigkeyring.py +0 -0
  193. {dnspython-2.9.0 → dnspython-2.9.1}/dns/update.py +0 -0
  194. {dnspython-2.9.0 → dnspython-2.9.1}/dns/win32util.py +0 -0
  195. {dnspython-2.9.0 → dnspython-2.9.1}/dns/xfr.py +0 -0
  196. {dnspython-2.9.0 → dnspython-2.9.1}/dns/zonetypes.py +0 -0
  197. {dnspython-2.9.0 → dnspython-2.9.1}/examples/async_dns.py +0 -0
  198. {dnspython-2.9.0 → dnspython-2.9.1}/examples/ddns_client.py +0 -0
  199. {dnspython-2.9.0 → dnspython-2.9.1}/examples/ddns_server.py +0 -0
  200. {dnspython-2.9.0 → dnspython-2.9.1}/examples/ddr.py +0 -0
  201. {dnspython-2.9.0 → dnspython-2.9.1}/examples/doh-json.py +0 -0
  202. {dnspython-2.9.0 → dnspython-2.9.1}/examples/doh.py +0 -0
  203. {dnspython-2.9.0 → dnspython-2.9.1}/examples/doq.py +0 -0
  204. {dnspython-2.9.0 → dnspython-2.9.1}/examples/dot.py +0 -0
  205. {dnspython-2.9.0 → dnspython-2.9.1}/examples/e164.py +0 -0
  206. {dnspython-2.9.0 → dnspython-2.9.1}/examples/ecs.py +0 -0
  207. {dnspython-2.9.0 → dnspython-2.9.1}/examples/edns.py +0 -0
  208. {dnspython-2.9.0 → dnspython-2.9.1}/examples/edns_resolver.py +0 -0
  209. {dnspython-2.9.0 → dnspython-2.9.1}/examples/mx-typed.py +0 -0
  210. {dnspython-2.9.0 → dnspython-2.9.1}/examples/mx.py +0 -0
  211. {dnspython-2.9.0 → dnspython-2.9.1}/examples/name.py +0 -0
  212. {dnspython-2.9.0 → dnspython-2.9.1}/examples/query_specific.py +0 -0
  213. {dnspython-2.9.0 → dnspython-2.9.1}/examples/receive_notify.py +0 -0
  214. {dnspython-2.9.0 → dnspython-2.9.1}/examples/reverse.py +0 -0
  215. {dnspython-2.9.0 → dnspython-2.9.1}/examples/reverse_name.py +0 -0
  216. {dnspython-2.9.0 → dnspython-2.9.1}/examples/send_notify.py +0 -0
  217. {dnspython-2.9.0 → dnspython-2.9.1}/examples/server.py +0 -0
  218. {dnspython-2.9.0 → dnspython-2.9.1}/examples/tsig.py +0 -0
  219. {dnspython-2.9.0 → dnspython-2.9.1}/examples/wire_read_tcp.py +0 -0
  220. {dnspython-2.9.0 → dnspython-2.9.1}/examples/xfr.py +0 -0
  221. {dnspython-2.9.0 → dnspython-2.9.1}/examples/zonediff.py +0 -0
  222. {dnspython-2.9.0 → dnspython-2.9.1}/tests/__init__.py +0 -0
  223. {dnspython-2.9.0 → dnspython-2.9.1}/tests/doh.py +0 -0
  224. {dnspython-2.9.0 → dnspython-2.9.1}/tests/doq.py +0 -0
  225. {dnspython-2.9.0 → dnspython-2.9.1}/tests/example +0 -0
  226. {dnspython-2.9.0 → dnspython-2.9.1}/tests/example1.good +0 -0
  227. {dnspython-2.9.0 → dnspython-2.9.1}/tests/example2.good +0 -0
  228. {dnspython-2.9.0 → dnspython-2.9.1}/tests/example3.good +0 -0
  229. {dnspython-2.9.0 → dnspython-2.9.1}/tests/example4.good +0 -0
  230. {dnspython-2.9.0 → dnspython-2.9.1}/tests/keys.py +0 -0
  231. {dnspython-2.9.0 → dnspython-2.9.1}/tests/md_module.py +0 -0
  232. {dnspython-2.9.0 → dnspython-2.9.1}/tests/mx-2-0.pickle +0 -0
  233. {dnspython-2.9.0 → dnspython-2.9.1}/tests/nanonameserver.py +0 -0
  234. {dnspython-2.9.0 → dnspython-2.9.1}/tests/query +0 -0
  235. {dnspython-2.9.0 → dnspython-2.9.1}/tests/resolv.conf +0 -0
  236. {dnspython-2.9.0 → dnspython-2.9.1}/tests/stxt_module.py +0 -0
  237. {dnspython-2.9.0 → dnspython-2.9.1}/tests/svcb_test_vectors.generic +0 -0
  238. {dnspython-2.9.0 → dnspython-2.9.1}/tests/svcb_test_vectors.text +0 -0
  239. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_address.py +0 -0
  240. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_ascii_digits.py +0 -0
  241. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_async.py +0 -0
  242. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_btree.py +0 -0
  243. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_constants.py +0 -0
  244. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_ddr.py +0 -0
  245. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_doh.py +0 -0
  246. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_exceptions.py +0 -0
  247. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_features.py +0 -0
  248. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_flags.py +0 -0
  249. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_grange.py +0 -0
  250. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_immutable.py +0 -0
  251. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_nsec3_hash.py +0 -0
  252. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_ntoaaton.py +0 -0
  253. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_processing_order.py +0 -0
  254. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdataset.py +0 -0
  255. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdtypeandclass.py +0 -0
  256. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdtypeanydnskey.py +0 -0
  257. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdtypeanyeui.py +0 -0
  258. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdtypeanykey.py +0 -0
  259. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdtypeanyloc.py +0 -0
  260. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rdtypeanytkey.py +0 -0
  261. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_resolution.py +0 -0
  262. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_resolver_override.py +0 -0
  263. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rrset.py +0 -0
  264. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_rrset_reader.py +0 -0
  265. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_serial.py +0 -0
  266. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_svcb.py +0 -0
  267. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_tls_util.py +0 -0
  268. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_tsigkeyring.py +0 -0
  269. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_update.py +0 -0
  270. {dnspython-2.9.0 → dnspython-2.9.1}/tests/test_zonedigest.py +0 -0
  271. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tls/ca.crt +0 -0
  272. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tls/private.pem +0 -0
  273. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tls/public.crt +0 -0
  274. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tsigkeys/1.key +0 -0
  275. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tsigkeys/2.key +0 -0
  276. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tsigkeys/3.key +0 -0
  277. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tsigkeys/4.key +0 -0
  278. {dnspython-2.9.0 → dnspython-2.9.1}/tests/tsigkeys/5.key +0 -0
  279. {dnspython-2.9.0 → dnspython-2.9.1}/tests/ttl_include.text +0 -0
  280. {dnspython-2.9.0 → dnspython-2.9.1}/tests/ttxt_module.py +0 -0
  281. {dnspython-2.9.0 → dnspython-2.9.1}/tests/utest.py +0 -0
  282. {dnspython-2.9.0 → dnspython-2.9.1}/tests/util.py +0 -0
  283. {dnspython-2.9.0 → dnspython-2.9.1}/util/constants-tool +0 -0
  284. {dnspython-2.9.0 → dnspython-2.9.1}/util/generate-features +0 -0
  285. {dnspython-2.9.0 → dnspython-2.9.1}/util/generate-mx-pickle.py +0 -0
  286. {dnspython-2.9.0 → dnspython-2.9.1}/util/generate-rdatatype-doc.py +0 -0
  287. {dnspython-2.9.0 → dnspython-2.9.1}/util/make-test-project +0 -0
  288. {dnspython-2.9.0 → dnspython-2.9.1}/util/update-version +0 -0
  289. {dnspython-2.9.0 → dnspython-2.9.1}/util/uv-dev-setup +0 -0
@@ -0,0 +1,35 @@
1
+ ISC License
2
+
3
+ Copyright (C) Dnspython Contributors
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for
6
+ any purpose with or without fee is hereby granted, provided that the
7
+ above copyright notice and this permission notice appear in all
8
+ copies.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12
+ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13
+ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+
19
+
20
+
21
+ Copyright (C) 2001-2017 Nominum, Inc.
22
+ Copyright (C) Google Inc.
23
+
24
+ Permission to use, copy, modify, and distribute this software and its
25
+ documentation for any purpose with or without fee is hereby granted,
26
+ provided that the above copyright notice and this permission notice
27
+ appear in all copies.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
30
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
31
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
32
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
33
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
34
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
35
+ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dnspython
3
- Version: 2.9.0
3
+ Version: 2.9.1
4
4
  Summary: DNS toolkit
5
5
  Author: Bob Halley
6
6
  Author-email: Bob Halley <halley@dnspython.org>
7
7
  License-Expression: ISC
8
+ License-File: LICENSE
8
9
  Classifier: Development Status :: 5 - Production/Stable
9
10
  Classifier: Intended Audience :: Developers
10
11
  Classifier: Intended Audience :: System Administrators
@@ -18,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.11
18
19
  Classifier: Programming Language :: Python :: 3.12
19
20
  Classifier: Programming Language :: Python :: 3.13
20
21
  Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
21
23
  Requires-Dist: black>=26.5 ; extra == 'dev'
22
24
  Requires-Dist: coverage>=7.15 ; extra == 'dev'
23
25
  Requires-Dist: hypercorn>=0.18.0 ; extra == 'dev'
@@ -83,7 +85,7 @@ testing of DNS software.
83
85
 
84
86
  ## ABOUT THIS RELEASE
85
87
 
86
- This is `dnspython` 2.9.0.
88
+ This is `dnspython` 2.9.1.
87
89
  Please read
88
90
  [What's New](https://dnspython.readthedocs.io/en/stable/whatsnew.html) for
89
91
  information about the changes in this release.
@@ -29,7 +29,7 @@ testing of DNS software.
29
29
 
30
30
  ## ABOUT THIS RELEASE
31
31
 
32
- This is `dnspython` 2.9.0.
32
+ This is `dnspython` 2.9.1.
33
33
  Please read
34
34
  [What's New](https://dnspython.readthedocs.io/en/stable/whatsnew.html) for
35
35
  information about the changes in this release.
@@ -698,7 +698,7 @@ async def https(
698
698
  r = dns.message.from_wire(
699
699
  response.content,
700
700
  keyring=q.keyring,
701
- request_mac=q.request_mac,
701
+ request_mac=q.mac,
702
702
  one_rr_per_rrset=one_rr_per_rrset,
703
703
  ignore_trailing=ignore_trailing,
704
704
  )
@@ -732,7 +732,7 @@ async def _http3(
732
732
  if url_parts.port is not None:
733
733
  port = url_parts.port
734
734
 
735
- q.id = 0
735
+ q.set_id(0)
736
736
  wire = q.to_wire()
737
737
  the_connection: dns.quic.AsyncQuicConnection
738
738
  if connection:
@@ -762,7 +762,7 @@ async def _http3(
762
762
  r = dns.message.from_wire(
763
763
  wire,
764
764
  keyring=q.keyring,
765
- request_mac=q.request_mac,
765
+ request_mac=q.mac,
766
766
  one_rr_per_rrset=one_rr_per_rrset,
767
767
  ignore_trailing=ignore_trailing,
768
768
  )
@@ -804,7 +804,7 @@ async def quic(
804
804
  if server_hostname is not None and hostname is None:
805
805
  hostname = server_hostname
806
806
 
807
- q.id = 0
807
+ q.set_id(0)
808
808
  wire = q.to_wire()
809
809
  the_connection: dns.quic.AsyncQuicConnection
810
810
  if connection:
@@ -818,7 +818,7 @@ async def quic(
818
818
  async with mfactory(
819
819
  context,
820
820
  verify_mode=verify,
821
- server_name=server_hostname,
821
+ server_name=hostname,
822
822
  ) as the_manager:
823
823
  if not connection:
824
824
  the_connection = the_manager.connect( # pyright: ignore
@@ -833,7 +833,7 @@ async def quic(
833
833
  r = dns.message.from_wire(
834
834
  wire,
835
835
  keyring=q.keyring,
836
- request_mac=q.request_mac,
836
+ request_mac=q.mac,
837
837
  one_rr_per_rrset=one_rr_per_rrset,
838
838
  ignore_trailing=ignore_trailing,
839
839
  )
@@ -869,6 +869,7 @@ async def _inbound_xfr(
869
869
  txn_manager, rdtype, serial, is_udp, raise_on_serial_went_backwards
870
870
  ) as inbound:
871
871
  done = False
872
+ first = True
872
873
  tsig_ctx = None
873
874
  while not done:
874
875
  _, mexpiration = _compute_times(timeout)
@@ -893,6 +894,9 @@ async def _inbound_xfr(
893
894
  multi=(not is_udp),
894
895
  one_rr_per_rrset=is_ixfr,
895
896
  )
897
+ if not query.is_response(r, xfr_continuation=not first):
898
+ raise BadResponse
899
+ first = False
896
900
  done = inbound.process_message(r)
897
901
  yield r
898
902
  tsig_ctx = r.tsig_ctx
@@ -89,6 +89,7 @@ class Resolver(dns.resolver.BaseResolver):
89
89
  nameserver, tcp, backoff = resolution.next_nameserver()
90
90
  if backoff:
91
91
  await backend.sleep(backoff)
92
+ request.set_random_id()
92
93
  timeout = self._compute_timeout(start, lifetime, resolution.errors)
93
94
  try:
94
95
  response = await nameserver.async_query(
@@ -225,7 +225,7 @@ class WritableVersion(dns.zone.WritableVersion):
225
225
  if self.zone.relativize:
226
226
  return name == dns.name.empty
227
227
  else:
228
- return name == self.zone.origin
228
+ return name == self.origin
229
229
 
230
230
  def _maybe_cow_with_name(
231
231
  self, name: dns.name.Name
@@ -236,20 +236,25 @@ class WritableVersion(dns.zone.WritableVersion):
236
236
  node.flags |= NodeFlags.ORIGIN
237
237
  elif self.delegations.is_glue(name):
238
238
  node.flags |= NodeFlags.GLUE
239
+ elif name in self.delegations:
240
+ node.flags |= NodeFlags.DELEGATION
239
241
  return (node, name)
240
242
 
241
243
  def update_glue_flag(self, name: dns.name.Name, is_glue: bool) -> None:
242
- """Set or clear the ``NodeFlags.GLUE`` flag on all nodes that are
243
- subdomains of *name*.
244
+ """Update the delegation and glue flags on proper subdomains of *name*.
245
+
246
+ An added delegation obscures any descendant delegations. Removing
247
+ one exposes the first NS rdataset on each branch of its subtree.
244
248
 
245
249
  :param name: The delegation-point name whose subtree should be updated.
246
250
  :type name: :py:class:`dns.name.Name`
247
- :param is_glue: ``True`` to set the GLUE flag; ``False`` to clear it.
251
+ :param is_glue: ``True`` to obscure the subtree; ``False`` to expose it.
248
252
  :type is_glue: bool
249
253
  """
250
254
  cursor = self.nodes.cursor() # pyright: ignore
251
255
  cursor.seek(name, False)
252
256
  updates = []
257
+ cut = name if is_glue else None
253
258
  while True:
254
259
  elt = cursor.next()
255
260
  if elt is None:
@@ -257,18 +262,27 @@ class WritableVersion(dns.zone.WritableVersion):
257
262
  ename = elt.key()
258
263
  if not ename.is_subdomain(name):
259
264
  break
260
- node = cast(dns.node.Node, elt.value())
265
+ node = elt.value()
266
+ self.delegations.discard(ename)
267
+ if cut is not None and not ename.is_subdomain(cut):
268
+ cut = None
269
+ if cut is not None:
270
+ flags = NodeFlags.GLUE
271
+ elif node.get_rdataset(self.zone.rdclass, dns.rdatatype.NS) is not None:
272
+ flags = NodeFlags.DELEGATION
273
+ cut = ename
274
+ self.delegations.add(ename)
275
+ else:
276
+ flags = NodeFlags(0)
277
+ if node.flags == flags:
278
+ continue
261
279
  if ename not in self.changed:
262
- new_node = self.zone.node_factory()
263
- new_node.id = self.id # type: ignore
280
+ new_node = cast(Node, self.zone.node_factory())
281
+ new_node.id = self.id
264
282
  new_node.rdatasets.extend(node.rdatasets)
265
283
  self.changed.add(ename)
266
284
  node = new_node
267
- assert isinstance(node, Node)
268
- if is_glue:
269
- node.flags |= NodeFlags.GLUE
270
- else:
271
- node.flags &= ~NodeFlags.GLUE
285
+ node.flags = flags
272
286
  # We don't update node here as any insertion could disturb the
273
287
  # btree and invalidate our cursor. We could use the cursor in a
274
288
  # with block and avoid this, but it would do a lot of parking and
@@ -277,12 +291,28 @@ class WritableVersion(dns.zone.WritableVersion):
277
291
  for ename, node in updates:
278
292
  self.nodes[ename] = node
279
293
 
294
+ def _update_delegation(self, name: dns.name.Name, node: Node) -> None:
295
+ is_delegation = (
296
+ not node.is_origin_or_glue()
297
+ and node.get_rdataset(self.zone.rdclass, dns.rdatatype.NS) is not None
298
+ )
299
+ if is_delegation:
300
+ node.flags |= NodeFlags.DELEGATION
301
+ if name not in self.delegations:
302
+ self.delegations.add(name)
303
+ self.update_glue_flag(name, True)
304
+ elif name in self.delegations:
305
+ node.flags &= ~NodeFlags.DELEGATION
306
+ self.delegations.discard(name)
307
+ self.update_glue_flag(name, False)
308
+
280
309
  def delete_node(self, name: dns.name.Name) -> None:
281
310
  """Delete the node at *name*, updating delegation tracking as needed.
282
311
 
283
312
  If *name* is a delegation point, it is removed from the delegations
284
- index and the GLUE flag is cleared from its subtree. If *name* does
285
- not exist in the zone, this method is a no-op.
313
+ index and any exposed descendant NS nodes become delegation points.
314
+ Nodes beneath those delegations remain glue. If *name* does not
315
+ exist in the zone, this method is a no-op.
286
316
 
287
317
  :param name: The name of the node to delete.
288
318
  :type name: :py:class:`dns.name.Name`
@@ -290,7 +320,7 @@ class WritableVersion(dns.zone.WritableVersion):
290
320
  name = self._validate_name(name)
291
321
  node = self.nodes.get(name)
292
322
  if node is not None:
293
- if node.is_delegation(): # pyright: ignore
323
+ if name in self.delegations:
294
324
  self.delegations.discard(name)
295
325
  self.update_glue_flag(name, False)
296
326
  del self.nodes[name]
@@ -303,7 +333,9 @@ class WritableVersion(dns.zone.WritableVersion):
303
333
 
304
334
  If *rdataset* is an NS rdataset and *name* is not the origin or beneath
305
335
  an existing delegation, the ``DELEGATION`` flag is set on the node and
306
- the ``GLUE`` flag is set on all nodes in *name*'s subtree.
336
+ the ``GLUE`` flag is set on all nodes in *name*'s subtree, obscuring
337
+ any descendant delegations. Replacing an NS rdataset with a CNAME
338
+ removes the delegation and exposes descendant delegations.
307
339
 
308
340
  :param name: The owner name.
309
341
  :type name: :py:class:`dns.name.Name`
@@ -311,15 +343,8 @@ class WritableVersion(dns.zone.WritableVersion):
311
343
  :type rdataset: :py:class:`dns.rdataset.Rdataset`
312
344
  """
313
345
  node, name = self._maybe_cow_with_name(name)
314
- if (
315
- rdataset.rdtype == dns.rdatatype.NS
316
- and not node.is_origin_or_glue() # type: ignore
317
- ):
318
- node.flags |= NodeFlags.DELEGATION # type: ignore
319
- if name not in self.delegations:
320
- self.delegations.add(name)
321
- self.update_glue_flag(name, True)
322
346
  node.replace_rdataset(rdataset)
347
+ self._update_delegation(name, cast(Node, node))
323
348
 
324
349
  def delete_rdataset(
325
350
  self,
@@ -330,8 +355,9 @@ class WritableVersion(dns.zone.WritableVersion):
330
355
  """Delete the rdataset with *rdtype* and *covers* at *name*.
331
356
 
332
357
  If the deleted rdataset was the NS rdataset at a delegation point,
333
- the ``DELEGATION`` flag is cleared from that node and the ``GLUE``
334
- flag is cleared from all nodes in its subtree.
358
+ the ``DELEGATION`` flag is cleared from that node and any exposed
359
+ descendant NS nodes become delegation points. Nodes beneath those
360
+ delegations remain glue.
335
361
 
336
362
  :param name: The owner name.
337
363
  :type name: :py:class:`dns.name.Name`
@@ -341,11 +367,8 @@ class WritableVersion(dns.zone.WritableVersion):
341
367
  :type covers: :py:class:`dns.rdatatype.RdataType`
342
368
  """
343
369
  node, name = self._maybe_cow_with_name(name)
344
- if rdtype == dns.rdatatype.NS and name in self.delegations: # pyright: ignore
345
- node.flags &= ~NodeFlags.DELEGATION # type: ignore
346
- self.delegations.discard(name) # pyright: ignore
347
- self.update_glue_flag(name, False)
348
370
  node.delete_rdataset(self.zone.rdclass, rdtype, covers)
371
+ self._update_delegation(name, cast(Node, node))
349
372
  if len(node) == 0:
350
373
  del self.nodes[name]
351
374
 
@@ -296,6 +296,10 @@ def _find_candidate_keys(
296
296
  and key_id(rd) == rrsig.key_tag
297
297
  and (rd.flags & Flag.ZONE) == Flag.ZONE # RFC 4034 2.1.1
298
298
  and rd.protocol == 3 # RFC 4034 2.1.2
299
+ # A revoked key may only validate the DNSKEY RRset (RFC 5011 2.1)
300
+ and (
301
+ (rd.flags & Flag.REVOKE) == 0 or rrsig.type_covered == dns.rdatatype.DNSKEY
302
+ )
299
303
  ]
300
304
 
301
305
 
@@ -354,6 +358,11 @@ def _validate_rrsig(
354
358
  if policy is None:
355
359
  policy = default_policy
356
360
 
361
+ # RFC 4035 section 5.3.1: the RRSIG must cover the RRset's type and class.
362
+ _, rdataset = _get_rrname_rdataset(rrset)
363
+ if rrsig.type_covered != rdataset.rdtype or rrsig.rdclass != rdataset.rdclass:
364
+ raise ValidationFailure("RRSIG does not cover the RRset")
365
+
357
366
  candidate_keys = _find_candidate_keys(keys, rrsig)
358
367
  if candidate_keys is None:
359
368
  raise ValidationFailure("unknown key")
@@ -715,10 +724,6 @@ def nsec3_hash(
715
724
  :rtype: str
716
725
  """
717
726
 
718
- b32_conversion = str.maketrans(
719
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", "0123456789ABCDEFGHIJKLMNOPQRSTUV"
720
- )
721
-
722
727
  try:
723
728
  if isinstance(algorithm, str):
724
729
  algorithm = NSEC3Hash[algorithm.upper()]
@@ -747,10 +752,7 @@ def nsec3_hash(
747
752
  for _ in range(iterations):
748
753
  digest = hashlib.sha1(digest + salt_encoded).digest()
749
754
 
750
- output = base64.b32encode(digest).decode("utf-8")
751
- output = output.translate(b32_conversion)
752
-
753
- return output
755
+ return base64.b32hexencode(digest).decode("utf-8")
754
756
 
755
757
 
756
758
  def make_ds_rdataset(
@@ -1117,7 +1119,7 @@ def _sign_zone_nsec(
1117
1119
  _txn_add_nsec(txn, last_secure, name, zone.rdclass, rrsig_ttl, rrset_signer)
1118
1120
  last_secure = name
1119
1121
 
1120
- if last_secure:
1122
+ if last_secure is not None:
1121
1123
  _txn_add_nsec(
1122
1124
  txn, last_secure, zone.origin, zone.rdclass, rrsig_ttl, rrset_signer
1123
1125
  )
@@ -20,7 +20,7 @@ class CryptographyPublicKey(GenericPublicKey):
20
20
  self.key = key
21
21
 
22
22
  @classmethod
23
- def from_pem(cls, public_pem: bytes) -> "GenericPublicKey":
23
+ def from_pem(cls, public_pem: bytes) -> GenericPublicKey:
24
24
  key = serialization.load_pem_public_key(public_pem)
25
25
  return cls(key=key)
26
26
 
@@ -34,7 +34,7 @@ class CryptographyPublicKey(GenericPublicKey):
34
34
  class CryptographyPrivateKey(GenericPrivateKey):
35
35
  key: Any = None
36
36
  key_cls: Any = None
37
- public_cls: type[CryptographyPublicKey] # pyright: ignore
37
+ public_cls: type[CryptographyPublicKey] # type: ignore
38
38
 
39
39
  def __init__(self, key: Any) -> None: # pylint: disable=super-init-not-called
40
40
  if self.key_cls is None:
@@ -51,7 +51,7 @@ class CryptographyPrivateKey(GenericPrivateKey):
51
51
  @classmethod
52
52
  def from_pem(
53
53
  cls, private_pem: bytes, password: bytes | None = None
54
- ) -> "GenericPrivateKey":
54
+ ) -> GenericPrivateKey:
55
55
  key = serialization.load_pem_private_key(private_pem, password=password)
56
56
  return cls(key=key)
57
57
 
@@ -1,5 +1,6 @@
1
1
  import struct
2
2
 
3
+ from cryptography.exceptions import InvalidSignature
3
4
  from cryptography.hazmat.backends import default_backend
4
5
  from cryptography.hazmat.primitives import hashes
5
6
  from cryptography.hazmat.primitives.asymmetric import dsa, utils
@@ -16,6 +17,11 @@ class PublicDSA(CryptographyPublicKey):
16
17
  chosen_hash = hashes.SHA1()
17
18
 
18
19
  def verify(self, signature: bytes, data: bytes) -> None:
20
+ # RFC 2536 section 3: the signature is T, R, and S (41 octets), where T
21
+ # is the same as the key's T.
22
+ dsa_t = (self.key.key_size // 8 - 64) // 8
23
+ if len(signature) != 41 or signature[0] != dsa_t:
24
+ raise InvalidSignature
19
25
  sig_r = signature[1:21]
20
26
  sig_s = signature[21:]
21
27
  sig = utils.encode_dss_signature(
@@ -1,3 +1,4 @@
1
+ from cryptography.exceptions import InvalidSignature
1
2
  from cryptography.hazmat.backends import default_backend
2
3
  from cryptography.hazmat.primitives import hashes
3
4
  from cryptography.hazmat.primitives.asymmetric import ec, utils
@@ -16,6 +17,10 @@ class PublicECDSA(CryptographyPublicKey):
16
17
  octets: int
17
18
 
18
19
  def verify(self, signature: bytes, data: bytes) -> None:
20
+ # RFC 6605 section 4: the signature is r and s, each exactly
21
+ # self.octets long.
22
+ if len(signature) != self.octets * 2:
23
+ raise InvalidSignature
19
24
  sig_r = signature[0 : self.octets]
20
25
  sig_s = signature[self.octets :]
21
26
  sig = utils.encode_dss_signature(
@@ -25,7 +25,7 @@ class PublicEDDSA(CryptographyPublicKey):
25
25
 
26
26
 
27
27
  class PrivateEDDSA(CryptographyPrivateKey):
28
- public_cls: type[PublicEDDSA] # pyright: ignore
28
+ public_cls: type[PublicEDDSA] # type: ignore
29
29
 
30
30
  def sign(
31
31
  self,
@@ -27,7 +27,7 @@ class PublicMLDSA(CryptographyPublicKey):
27
27
 
28
28
 
29
29
  class PrivateMLDSA(CryptographyPrivateKey):
30
- public_cls: Type[PublicMLDSA] # pyright: ignore
30
+ public_cls: Type[PublicMLDSA] # type: ignore
31
31
 
32
32
  def sign(
33
33
  self,
@@ -73,6 +73,22 @@ class OptionType(dns.enum.IntEnum):
73
73
  return 65535
74
74
 
75
75
 
76
+ def _escapify_text(text: str) -> str:
77
+ """Escape backslash and control characters in option text so that text
78
+ taken from the wire cannot add lines to, or otherwise alter, the output
79
+ of ``to_text()``."""
80
+
81
+ escaped = ""
82
+ for c in text:
83
+ if c == "\\":
84
+ escaped += "\\\\"
85
+ elif ord(c) < 0x20 or 0x7F <= ord(c) <= 0x9F:
86
+ escaped += f"\\{ord(c):03d}"
87
+ else:
88
+ escaped += c
89
+ return escaped
90
+
91
+
76
92
  class Option:
77
93
  """Base class for all EDNS option types."""
78
94
 
@@ -432,7 +448,7 @@ class EDEOption(Option): # lgtm[py/missing-equals]
432
448
  )
433
449
  output += f" ({desc})"
434
450
  if self.text is not None:
435
- output += f": {self.text}"
451
+ output += f": {_escapify_text(self.text)}"
436
452
  return output
437
453
 
438
454
  def to_wire(self, file: Any | None = None) -> bytes | None:
@@ -564,7 +580,7 @@ class EDEExtraTextLanguageOption(Option):
564
580
  return self.language.encode()
565
581
 
566
582
  def to_text(self) -> str:
567
- return f"EDE-EXTRA-TEXT-LANGUAGE {self.language}"
583
+ return f"EDE-EXTRA-TEXT-LANGUAGE {_escapify_text(self.language)}"
568
584
 
569
585
  @classmethod
570
586
  def from_wire_parser(
@@ -594,7 +610,7 @@ class FilteringContactOption(Option):
594
610
  return self.contact.encode()
595
611
 
596
612
  def to_text(self) -> str:
597
- return f"FILTERING-CONTACT {self.contact}"
613
+ return f"FILTERING-CONTACT {_escapify_text(self.contact)}"
598
614
 
599
615
  @classmethod
600
616
  def from_wire_parser(
@@ -624,7 +640,7 @@ class FilteringOrganizationOption(Option):
624
640
  return self.organization.encode()
625
641
 
626
642
  def to_text(self) -> str:
627
- return f"FILTERING-ORGANIZATION {self.organization}"
643
+ return f"FILTERING-ORGANIZATION {_escapify_text(self.organization)}"
628
644
 
629
645
  @classmethod
630
646
  def from_wire_parser(
@@ -658,7 +674,7 @@ class FilteringDBOption(Option):
658
674
  return self.db.encode()
659
675
 
660
676
  def to_text(self) -> str:
661
- return f"FILTERING-DB {self.db}"
677
+ return f"FILTERING-DB {_escapify_text(self.db)}"
662
678
 
663
679
  @classmethod
664
680
  def from_wire_parser(
@@ -34,9 +34,9 @@ class EntropyPool:
34
34
  self.digest: bytearray | None = None
35
35
  self.next_byte = 0
36
36
  self.lock = threading.Lock()
37
- self.hash = hashlib.sha1()
38
- self.hash_len = 20
39
- self.pool = bytearray(b"\0" * self.hash_len)
37
+ self.hash = None
38
+ self.hash_len = 0
39
+ self.pool = bytearray()
40
40
  if seed is not None:
41
41
  self._stir(seed)
42
42
  self.seeded = True
@@ -45,7 +45,19 @@ class EntropyPool:
45
45
  self.seeded = False
46
46
  self.seed_pid = 0
47
47
 
48
+ def _new_hash(self):
49
+ try:
50
+ self.hash = hashlib.sha256()
51
+ self.hash_len = 32
52
+ except AttributeError:
53
+ self.hash = hashlib.sha1()
54
+ self.hash_len = 20
55
+ if len(self.pool) != self.hash_len:
56
+ self.pool = bytearray(b"\0" * self.hash_len)
57
+
48
58
  def _stir(self, entropy: bytes | bytearray) -> None:
59
+ if self.hash is None:
60
+ self._new_hash()
49
61
  for c in entropy:
50
62
  if self.pool_index == self.hash_len:
51
63
  self.pool_index = 0
@@ -77,8 +89,12 @@ class EntropyPool:
77
89
  with self.lock:
78
90
  self._maybe_seed()
79
91
  if self.digest is None or self.next_byte == self.hash_len:
92
+ assert self.hash is not None
80
93
  self.hash.update(bytes(self.pool))
81
94
  self.digest = bytearray(self.hash.digest())
95
+ # We make a new hash because on MicroPython you can't update
96
+ # and digest more than once.
97
+ self._new_hash()
82
98
  self._stir(self.digest)
83
99
  self.next_byte = 0
84
100
  value = self.digest[self.next_byte]