Skip to content

Commit

Permalink
Add method to automatically determine EncryptionMethod to use (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
iMicknl authored Jun 8, 2024
1 parent c477a99 commit 3424404
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 5 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ asyncio.run(main())

### Determine the EncryptionMethod

(not supported yet)
If you are not sure which encryption method to use, you can leave it empty or pass `None` and use `get_encryption_method` to determine the encryption method.

`get_encryption_method` will return an `EncryptionMethod` when a match is found. Best would be to use this function only during your initial investigation.

This function will throw a `LoginTimeoutException` when no match is found, since this is still a HTTP Time Out. This could caused by the wrong encryption method, but also by trying to connect to an inaccessible host.

### Handle exceptions

Expand Down
39 changes: 35 additions & 4 deletions sagemcom_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
DEFAULT_USER_AGENT,
XMO_ACCESS_RESTRICTION_ERR,
XMO_AUTHENTICATION_ERR,
XMO_LOGIN_RETRY_ERR,
XMO_MAX_SESSION_COUNT_ERR,
XMO_NO_ERR,
XMO_NON_WRITABLE_PARAMETER_ERR,
Expand All @@ -39,6 +40,7 @@
AccessRestrictionException,
AuthenticationException,
BadRequestException,
LoginRetryErrorException,
LoginTimeoutException,
MaximumSessionCountException,
NonWritableParameterException,
Expand All @@ -61,7 +63,7 @@ def __init__(
host: str,
username: str,
password: str,
authentication_method: EncryptionMethod,
authentication_method: EncryptionMethod | None = None,
session: ClientSession | None = None,
ssl: bool | None = False,
verify_ssl: bool | None = True,
Expand All @@ -78,8 +80,8 @@ def __init__(
self.host = host
self.username = username
self.authentication_method = authentication_method
self.password = password
self._password_hash = self.__generate_hash(password)

self.protocol = "https" if ssl else "http"

self._current_nonce = None
Expand Down Expand Up @@ -232,6 +234,9 @@ async def __post(self, url, data):
if action_error_desc == XMO_MAX_SESSION_COUNT_ERR:
raise MaximumSessionCountException(action_error)

if action_error_desc == XMO_LOGIN_RETRY_ERR:
raise LoginRetryErrorException(action_error)

raise UnknownException(action_error)

return result
Expand Down Expand Up @@ -267,7 +272,8 @@ async def __api_request_async(self, actions, priority=False):
raise ConnectionError(str(exception)) from exception

async def login(self):
"""TODO."""
"""Login to the SagemCom F@st router using a username and password."""

actions = {
"id": 0,
"method": "logIn",
Expand Down Expand Up @@ -296,7 +302,7 @@ async def login(self):
response = await self.__api_request_async([actions], True)
except asyncio.TimeoutError as exception:
raise LoginTimeoutException(
"Request timed-out. This is mainly due to using the wrong encryption method."
"Login request timed-out. This could be caused by using the wrong encryption method, or using a (non) SSL connection."
) from exception

data = self.__get_response(response)
Expand All @@ -318,6 +324,31 @@ async def logout(self):
self._server_nonce = ""
self._request_id = -1

async def get_encryption_method(self):
"""Determine which encryption method to use for authentication and set it directly."""
for encryption_method in EncryptionMethod:
try:
self.authentication_method = encryption_method
self._password_hash = self.__generate_hash(
self.password, encryption_method
)

await self.login()

self._server_nonce = ""
self._session_id = 0
self._request_id = -1

return encryption_method
except (
LoginTimeoutException,
AuthenticationException,
LoginRetryErrorException,
):
pass

return None

async def get_value_by_xpath(self, xpath: str, options: dict | None = None) -> dict:
"""
Retrieve raw value from router using XPath.
Expand Down
1 change: 1 addition & 0 deletions sagemcom_api/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
XMO_REQUEST_NO_ERR = "XMO_REQUEST_NO_ERR"
XMO_UNKNOWN_PATH_ERR = "XMO_UNKNOWN_PATH_ERR"
XMO_MAX_SESSION_COUNT_ERR = "XMO_MAX_SESSION_COUNT_ERR"
XMO_LOGIN_RETRY_ERR = "XMO_LOGIN_RETRY_ERR"
4 changes: 4 additions & 0 deletions sagemcom_api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class AuthenticationException(Exception):
"""Raised when authentication is not correct."""


class LoginRetryErrorException(Exception):
"""Raised when too many login retries are attempted."""


class LoginTimeoutException(Exception):
"""Raised when a timeout is encountered during login."""

Expand Down

0 comments on commit 3424404

Please sign in to comment.