Skip to content

Commit

Permalink
Merge pull request #41 from vanbalken/url-encode-password
Browse files Browse the repository at this point in the history
Fixes issue with encoding of credentials
  • Loading branch information
vanbalken authored Jan 12, 2024
2 parents 84dc5c2 + 6d24df3 commit 4de9307
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/ambv/black
rev: 21.7b0
rev: 22.3.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
Expand Down
6 changes: 3 additions & 3 deletions arris_tg2492lg/connect_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from dataclasses import dataclass
from datetime import datetime
from typing import Any, List, Optional
from urllib.parse import quote
from yarl import URL

from .const import (
Expand All @@ -35,11 +36,10 @@ def __init__(self, websession: ClientSession, hostname: str, password: str):
self._credential: Optional[Credential] = None

async def async_login(self) -> str:
arg_string = f"{USERNAME}:{self._password}"
arg_string = f"{quote(USERNAME)}:{quote(self._password)}"
arg = base64.b64encode(arg_string.encode("utf-8")).decode("ascii")

params = {"arg": arg, "_n": self._nonce}
async with self._websession.get(f"{self._hostname}/login", params=params) as response:
async with self._websession.get(f"{self._hostname}/login?arg={arg}&_n={self._nonce}") as response:
response.raise_for_status()

token = await response.text()
Expand Down
45 changes: 45 additions & 0 deletions tests/test_connect_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,51 @@ async def get_html_response(request):
await connect_box.async_login()


async def test_login_url_replaces_special_characters_in_password(aiohttp_client):
"""Validates that special characters in the password are replaced.
The webpage of the router replaces special characters in both the username and password using the '%xx' escape.
"""

async def login_result(request):
login_result.url = str(request.url)
return await _get_credential(request)

login_result.url = ""

app = web.Application()
app.router.add_get("/login", login_result)
client = await aiohttp_client(app)

connect_box = ConnectBox(client.session, f"http://{client.host}:{client.port}", "&=")

token = await connect_box.async_login()

assert token == "eyJuYW1lIjogImFkbWluIn0=" # base64 representation of: {"name": "admin"}
assert login_result.url.startswith(f"http://{client.host}:{client.port}/login?arg=YWRtaW46JTI2JTNE&_n=")


async def test_login_does_not_url_encode_base64(aiohttp_client):
"""Validate that the characters in the base64 arg parameter are not replaced.
The portal of the router does not replace special characters (=) in the base64 encoded parameter.
"""

async def login_result(request):
login_result.url = str(request.url)
return await _get_credential(request)

login_result.url = ""

app = web.Application()
app.router.add_get("/login", login_result)
client = await aiohttp_client(app)

connect_box = ConnectBox(client.session, f"http://{client.host}:{client.port}", "secret2")

await connect_box.async_login()

assert login_result.url.startswith(f"http://{client.host}:{client.port}/login?arg=YWRtaW46c2VjcmV0Mg==&_n=")


async def test_get_connected_devices(aiohttp_client):
app = web.Application()
app.router.add_get("/login", _get_credential)
Expand Down

0 comments on commit 4de9307

Please sign in to comment.