Skip to content

Commit

Permalink
Merge pull request #2 from mvdwetering/fix_server_name_check
Browse files Browse the repository at this point in the history
Fix server name check
  • Loading branch information
mvdwetering authored Aug 1, 2024
2 parents 0ab942c + 5783792 commit 0a631b1
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
Expand Down
56 changes: 2 additions & 54 deletions aiohuesyncbox/huesyncbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,6 @@

logger = logging.getLogger(__name__)


class CommonNameInserterResolver(aiohttp.DefaultResolver): # type: ignore
def __init__(self, common_name, loop=None, *args, **kwargs):
super().__init__(loop=loop, *args, **kwargs)
self._common_name = common_name

async def resolve(self, host, port=0, family=socket.AF_INET):
hosts = []
if host.startswith("_"):
# Host was an IP address that was mangled to force a DNS lookup (_ are not valid)
# and with that forced lookup end up in this call.
# This is needed as IP addresses don't need lookup,
# but I need to set the hostname to the common_name for certificate validation
# and this seems to be the only place I could hook into

# Generate a suitable entry in the hosts list
hosts.append(
{
"host": host[1:],
"port": port,
"family": family,
"proto": 6, # TCP I think
"flags": socket.AI_NUMERICHOST,
}
)
else:
hosts.append(await super().resolve(host, port=port, family=family))

for host in hosts:
host["hostname"] = self._common_name

logger.debug("Resolved hosts: %s", hosts)

return hosts


class HueSyncBox:
"""Control a Philips Hue Play HDMI Sync Box."""

Expand Down Expand Up @@ -100,9 +64,6 @@ def _get_clientsession(self) -> aiohttp.ClientSession:
enable_cleanup_closed=True, # Home Assistant sets it so lets do it also
ssl=context,
limit_per_host=1, # Syncbox can handle a limited amount of connections, only take what we need
resolver=CommonNameInserterResolver(
self._id
), # Use custom resolver to get certificate validation on common_name working
)

return aiohttp.ClientSession(connector=connector, timeout=aiohttp.ClientTimeout(total=10))
Expand Down Expand Up @@ -183,19 +144,6 @@ async def update(self):
self.hue = Hue(response["hue"], self.request)
self.hdmi = Hdmi(response["hdmi"], self.request)

def _mangled_host(self) -> str:
"""
Returns the hostname or a modified hostname in case the host is an IP address
to make sure DNS lookups are required as that allows to use the common_name
instead of servername for certificate validation.
"""
try:
ipaddress.ip_address(self._host)
return f"_{self._host}"
except ValueError:
pass
return self._host

async def request(
self, method: str, path: str, data: Optional[Dict] = None, auth: bool = True
):
Expand All @@ -206,7 +154,7 @@ async def request(
# This solves an issue when Updates were scheduled and HA was shutdown
return None

url = f"https://{self._mangled_host()}:{self._port}{self._path}/v1{path}"
url = f"https://{self._host}:{self._port}{self._path}/v1{path}"

try:
logger.debug("%s, %s, %s" % (method, url, data))
Expand All @@ -216,7 +164,7 @@ async def request(
headers["Authorization"] = f"Bearer {self._access_token}"

async with self._clientsession.request(
method, url, json=data, headers=headers
method, url, json=data, headers=headers, server_hostname=self._id
) as resp:
logger.debug("%s, %s" % (resp.status, await resp.text("utf-8")))

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
aiohttp<4
aiohttp>=3.9.0,<4

0 comments on commit 0a631b1

Please sign in to comment.