Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Encryption for Archer C1200 Router Authentication #50

Merged
merged 3 commits into from
Oct 31, 2024

Conversation

swwgames
Copy link
Contributor

This pull request introduces an enhancement for the Archer C1200 router to allow users to authenticate with their plain password, rather than requiring the web encrypted password.

I added the encryption code to the EncryptionWrapper class in the encryption.py file.

If you like me to change anything please let me know.

Added encryption method for archer C1200
Added encryption method for the archer C1200
@swwgames
Copy link
Contributor Author

Hi! I just realized that the current code isn’t backwards compatible with users who are still using the web encrypted password. Would you prefer that I make it backwards compatible, or would you rather we display a warning message if someone uses the web encrypted password?

At the moment, if the web encrypted password is passed in, users will see a message indicating that the password is too long to encrypt.

Password too long for the RSA key size.

Please let me know which option you’d prefer, and I’ll make the changes accordingly!

@AlexandrErohin
Copy link
Owner

@swwgames Thank you for this addition!
Give me please a couple days to think and test what to do with compatibility

@AlexandrErohin AlexandrErohin merged commit ccf0ebb into AlexandrErohin:main Oct 31, 2024
4 checks passed
@AlexandrErohin
Copy link
Owner

@swwgames Hi
I have merged your additions. Thank you!. Could you test the latest version 5.0.0 of this client?

@swwgames swwgames deleted the c1200_encryption branch October 31, 2024 10:48
@swwgames
Copy link
Contributor Author

Hi @AlexandrErohin , I tested the Update and it works great!
Thank you for merging the pull request.

@AlexandrErohin
Copy link
Owner

@swwgames Hi
It looks like AC5400X router uses C1200 API, but with different password encryption. The new version breaks AC5400X support AlexandrErohin/home-assistant-tplink-router#113

@swwgames
Copy link
Contributor Author

swwgames commented Nov 5, 2024

Hi @AlexandrErohin,
That's unfortunate.
I think the best approach for now would be to make a copy of the Archer c1200 class from v4.2.3 and rename it to AC5400X.

@AlexandrErohin
Copy link
Owner

I think it will not work. As it uses this provider https://github.com/AlexandrErohin/TP-Link-Archer-C6U/blob/main/tplinkrouterc6u/client.py#L1398 - so it will always get wrong password from TplinkC1200Router and will never get to AC5400X client.

@swwgames
Copy link
Contributor Author

swwgames commented Nov 5, 2024

We can change the provider for the TplinkC1200Router, it uses /cgi-bin/luci/;stok=/locale?form=lang to get the language but it also communicates the router model.
The response is:

{
    "success": true,
    "data": {
        "locale": "en_US",
        "force": false,
        "region_select_permission": "yes",
        "model": "Wireless Router Archer C1200"
    }
}

When I have the time I can add this functionality.

@swwgames
Copy link
Contributor Author

swwgames commented Nov 5, 2024

I tested the following code to check if it is the Archer C1200 model:

    def _check_model(self) -> bool:
        url = '{}/cgi-bin/luci/;stok=/locale?form=lang'.format(self.host)
        response = post(
            url, params={'operation': 'read'},
            timeout=self.timeout,
            verify=self._verify_ssl,
        )

        try:
            data = response.json()

            model = data[self._data_block]['model']
            if 'Archer C1200' in model:
                return True

        except Exception as e:
            error = ('TplinkRouter - C1200 - {} - Unknown error for model! Error - {}; Response - {}'
                     .format(self.__class__.__name__, e, response.text))
            if self._logger:
                self._logger.error(error)
            raise ClientException(error)
        return False

This works, but maybe other models use the same encryption as the Archer C1200, this way they won't work with the encryption of the C1200. For those routers we could use a separate class that uses the web encrypted password.
Let me know what you think of this, or if you want me to try something else.

@AlexandrErohin
Copy link
Owner

@swwgames That would be great, but unfortunately there are some other routers which use your encryption.
I made some changes. Could you test please v5.0.1 of this client?
Please run this code 3 times and post the output here

from tplinkrouterc6u import TplinkRouterProvider

router = TplinkRouterProvider.get_client('http://192.168.0.1', 'password')

router.authorize()
firmware = router.get_firmware()
print(firmware.firmware_version)

status = router.get_status()
print(status.wired_total)

First time - you pass your plain password
Second time - you pass wrong password
Third time - you pass web encrypted password

@swwgames
Copy link
Contributor Author

swwgames commented Nov 6, 2024

I tested your code, these are the results:

  1. plain password:
Traceback (most recent call last):
  File "C:\Users\me\Documents\Code\Tp-link ArcherC1200\main.py", line 3, in <module>
    router = TplinkRouterProvider.get_client('http://192.168.1.100', 'TheCorrectPassword_masked')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 1449, in get_client
    raise ClientException('You need to use web encrypted password instead. Check the documentation!')
tplinkrouterc6u.exception.ClientException: You need to use web encrypted password instead. Check the documentation!
  1. plain password wrong:
Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 829, in authorize
    self._stok = data[self._data_block]['stok']
                 ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
KeyError: 'stok'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 1442, in get_client
    router.authorize()
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 840, in authorize
    raise AuthorizeError(error)
tplinkrouterc6u.exception.AuthorizeError: TplinkRouter - C1200 - Cannot authorize! Error - 'stok'; Response - {'errorcode': 'login failed', 'success': False, 'data': {'failureCount': 1, 'errorcode': '-5002', 'attemptsAllowed': 9}}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\me\Documents\Code\Tp-link ArcherC1200\main.py", line 3, in <module>
    router = TplinkRouterProvider.get_client('http://192.168.1.100', 'password')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 1444, in get_client
    logger.error(e.__str__())
    ^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'error'
  1. web encrypted password:
2.0.3 Build 20211219 Rel. 67401 (EU)
2

As you can see, the encryption does not work anymore.
I hope this helps, if you want me to test or try anything else let me know.

@AlexandrErohin
Copy link
Owner

@swwgames Thank you! From your test I have found the error
I have pushed to the main branch the fix. Could you pull the updates from https://github.com/AlexandrErohin/TP-Link-Archer-C6U/tree/main and test again?

@swwgames
Copy link
Contributor Author

swwgames commented Nov 6, 2024

Yes it works now!

  1. plain password:
2.0.3 Build 20211219 Rel. 67401 (EU)
2
  1. Wrong plain password:
Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 829, in authorize
    self._stok = data[self._data_block]['stok']
                 ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
KeyError: 'stok'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 1442, in get_client
    router.authorize()
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 840, in authorize
    raise AuthorizeError(error)
tplinkrouterc6u.exception.AuthorizeError: TplinkRouter - C1200 - Cannot authorize! Error - 'stok'; Response - {'errorcode': 'login failed', 'success': False, 'data': {'failureCount': 1, 'errorcode': '-5002', 'attemptsAllowed': 9}}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\me\Documents\Code\Tp-link ArcherC1200\main.py", line 3, in <module>
    router = TplinkRouterProvider.get_client('http://192.168.1.100', 'password')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\me\AppData\Local\Programs\Python\Python312\Lib\site-packages\tplinkrouterc6u\client.py", line 1447, in get_client
    raise ClientException(('Login failed! Please check if your router local password is correct or '
tplinkrouterc6u.exception.ClientException: Login failed! Please check if your router local password is correct or try to use web encrypted password instead. Check the documentation!
  1. web encrypted password:
2.0.3 Build 20211219 Rel. 67401 (EU)
2

@AlexandrErohin
Copy link
Owner

@swwgames Thank you for the help!

@swwgames
Copy link
Contributor Author

Hi @AlexandrErohin,
Yes I can do that.
Just to clarify you want me to add get_vpn_status and set_vpn to the C1200 client.

@AlexandrErohin
Copy link
Owner

@swwgames Yes. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants