socialwifi / RouterOS-api

Python API to RouterBoard devices produced by MikroTik.
MIT License
251 stars 100 forks source link

API login exception #56

Open mh2019-av opened 4 years ago

mh2019-av commented 4 years ago

Found this exception on some mikrotik devices. I fixed it by removing .encode() from lines: 94 and 98 in api.py.

--- api.py.bad  2019-12-11 16:06:39.430995285 +0000
+++ api.py  2019-12-11 16:07:07.795300124 +0000
@@ -91,11 +91,11 @@
             token = binascii.unhexlify(response.done_message['ret'])
             hasher = hashlib.md5()
             hasher.update(b'\x00')
-            hasher.update(password.encode())
+            hasher.update(password)
             hasher.update(token)
             hashed = b'00' + hasher.hexdigest().encode('ascii')
             self.get_binary_resource('/').call(
-                'login', {'name': login.encode(), 'response': hashed})
+                'login', {'name': login, 'response': hashed})

     def get_resource(self, path, structure=None):
         structure = structure or api_structure.default_structure

Trace:

  File "/project/venv/lib/python3.5/site-packages/routeros_api/api.py", line 52, in get_api
    self.api.login(self.username, self.password, self.plaintext_login)
  File "/project/venv/lib/python3.5/site-packages/routeros_api/api.py", line 99, in login
    'login', {'name': login.encode(), 'response': hashed})
AttributeError: 'bytes' object has no attribute 'encode'
mms101 commented 4 years ago

the same problem, but removing .encode() didn't help.

mms101 commented 4 years ago

works, if you add plaintext_login=True connection = routeros_api.RouterOsApiPool(IP, username='admin', password='password', plaintext_login=True)

mh2019-av commented 4 years ago

Looks like this problem has something to do with the routeros version. In our network we have 24 different versions. The patch I included above is needed only for versions older than 6.43.1

Regardless, the code doesn't look right: the login and the password are encoded twice which is causing the error.

    def login(self, login, password, plaintext_login):
        response = None
        if plaintext_login:
            if isinstance(login, string_types):
                login = login.encode()
            if isinstance(password, string_types):
                password = password.encode()
            response = self.get_binary_resource('/').call('login',{ 'name': login, 'password': password })
        else:
            response = self.get_binary_resource('/').call('login')
        if 'ret' in response.done_message:
            token = binascii.unhexlify(response.done_message['ret'])
            hasher = hashlib.md5()
            hasher.update(b'\x00')
            hasher.update(password.encode())
            hasher.update(token)
            hashed = b'00' + hasher.hexdigest().encode('ascii')
            self.get_binary_resource('/').call(
                'login', {'name': login.encode(), 'response': hashed})