diff --git a/examples/md5_auth.py b/examples/md5_auth.py new file mode 100644 index 0000000..2da177e --- /dev/null +++ b/examples/md5_auth.py @@ -0,0 +1,27 @@ +import logging +import os + +from panoramisk import Manager, Message + + +manager = Manager( + host=os.getenv('AMI_HOST', '127.0.0.1'), + port=os.getenv('AMI_PORT', 5038), + username=os.getenv('AMI_USERNAME', 'username'), + secret=os.getenv('AMI_SECRET', 'mysecret'), + auth_type='md5', # MD5 auth, no case sensitive + ping_delay=10, # Delay after start + ping_interval=10, # Periodically ping AMI (dead or alive) + reconnect_timeout=2, # Timeout reconnect if connection lost +) + + +@manager.register_event('*') # Register all events +async def ami_callback(mngr: Manager, msg: Message): + if msg.Event == 'FullyBooted': + print(msg) + + +if __name__ == '__main__': + logging.basicConfig(level=logging.INFO) + manager.connect(run_forever=True) diff --git a/panoramisk/manager.py b/panoramisk/manager.py index 5dacb86..15c4402 100644 --- a/panoramisk/manager.py +++ b/panoramisk/manager.py @@ -1,4 +1,5 @@ import asyncio +import hashlib import logging from collections import defaultdict from collections import deque @@ -53,6 +54,8 @@ def __init__(self, **config): self.ping_interval = int(self.config['ping_interval']) self.reconnect_timeout = int(self.config['reconnect_timeout']) self._connected = False + self.auth_type = self.config.get('auth_type') + self.auth_challenge_future = None self.register_event('FullyBooted', self.send_awaiting_actions) self.on_login = config.get('on_login', on_login) self.on_connect = config.get('on_connect', on_connect) @@ -82,6 +85,13 @@ def connection_made(self, f): self.protocol.encoding = self.encoding = self.config['encoding'] self.responses = self.protocol.responses = {} if 'username' in self.config: + if self.auth_type is not None: + if self.auth_type.lower() == 'md5': + self.auth_challenge_future = self.send_action({ + 'Action': 'Challenge', + 'AuthType': self.auth_type.upper()}) + self.auth_challenge_future.add_done_callback(self.secure_login) + return self.authenticated = False self.authenticated_future = self.send_action({ 'Action': 'Login', @@ -93,6 +103,20 @@ def connection_made(self, f): self.log.debug('username not in config file') self.pinger = self.loop.call_later(self.ping_delay, self.ping) + def secure_login(self, future): + resp = future.result() + if bool(resp.success): + auth_challenge = resp.Challenge + self.config['secret'] + key = hashlib.md5(auth_challenge.encode('utf-8')).hexdigest() + self.authenticated = False + self.authenticated_future = self.send_action({ + 'Action': 'Login', + 'Username': self.config['username'], + 'AuthType': self.auth_type.upper(), + 'Key': key, + 'Events': self.config['events']}) + self.authenticated_future.add_done_callback(self.login) + def login(self, future): self.authenticated_future = None resp = future.result()