Skip to content

Commit

Permalink
Check SAN for IP if using an address URL in https() [#1125].
Browse files Browse the repository at this point in the history
Httpx needs us to set the "sni_hostname" extension if the
server in the URL is an IP address, as otherwise it will not
check the certificate.  With this change, it will look for a
SAN with the IP address.
  • Loading branch information
rthalley committed Sep 14, 2024
1 parent 406079a commit b0be655
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
20 changes: 17 additions & 3 deletions dns/asyncquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
from dns._asyncbackend import NullContext
from dns.query import (
BadResponse,
HTTPVersion,
NoDOH,
NoDOQ,
HTTPVersion,
UDPMode,
_check_status,
_compute_times,
Expand Down Expand Up @@ -560,12 +560,14 @@ async def https(
else:
url = where

extensions = {}
if bootstrap_address is None:
parsed = urllib.parse.urlparse(url)
if parsed.hostname is None:
raise ValueError("no hostname in URL")
if dns.inet.is_address(parsed.hostname):
bootstrap_address = parsed.hostname
extensions["sni_hostname"] = parsed.hostname
if parsed.port is not None:
port = parsed.port

Expand Down Expand Up @@ -638,13 +640,25 @@ async def https(
}
)
response = await backend.wait_for(
the_client.post(url, headers=headers, content=wire), timeout
the_client.post(
url,
headers=headers,
content=wire,
extensions=extensions,
),
timeout,
)
else:
wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
twire = wire.decode() # httpx does a repr() if we give it bytes
response = await backend.wait_for(
the_client.get(url, headers=headers, params={"dns": twire}), timeout
the_client.get(
url,
headers=headers,
params={"dns": twire},
extensions=extensions,
),
timeout,
)

# see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
Expand Down
16 changes: 14 additions & 2 deletions dns/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,12 +449,14 @@ def https(
else:
url = where

extensions = {}
if bootstrap_address is None:
parsed = urllib.parse.urlparse(url)
if parsed.hostname is None:
raise ValueError("no hostname in URL")
if dns.inet.is_address(parsed.hostname):
bootstrap_address = parsed.hostname
extensions["sni_hostname"] = parsed.hostname
if parsed.port is not None:
port = parsed.port

Expand Down Expand Up @@ -525,12 +527,22 @@ def https(
"content-length": str(len(wire)),
}
)
response = session.post(url, headers=headers, content=wire, timeout=timeout)
response = session.post(
url,
headers=headers,
content=wire,
timeout=timeout,
extensions=extensions,
)
else:
wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
twire = wire.decode() # httpx does a repr() if we give it bytes
response = session.get(
url, headers=headers, timeout=timeout, params={"dns": twire}
url,
headers=headers,
timeout=timeout,
params={"dns": twire},
extensions=extensions,
)

# see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
Expand Down

0 comments on commit b0be655

Please sign in to comment.