From 09b3748086df564cb1faacd5e81da00378e29d1c Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Thu, 13 Apr 2023 15:16:59 -0400 Subject: [PATCH 1/3] Fix example closing server too soon --- examples/authenticated_relayer/server.py | 7 ++----- examples/basic/server.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/authenticated_relayer/server.py b/examples/authenticated_relayer/server.py index f00b6020..5f3aa11b 100644 --- a/examples/authenticated_relayer/server.py +++ b/examples/authenticated_relayer/server.py @@ -83,10 +83,7 @@ async def amain(): port=8025, authenticator=Authenticator(DB_AUTH) ) - try: - cont.start() - finally: - cont.stop() + cont.start() if __name__ == '__main__': @@ -96,7 +93,7 @@ async def amain(): logging.basicConfig(level=logging.DEBUG) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - loop.create_task(amain()) + loop.run_until_complete(loop.create_task(amain())) try: loop.run_forever() except KeyboardInterrupt: diff --git a/examples/basic/server.py b/examples/basic/server.py index fcb572a6..42c1685c 100644 --- a/examples/basic/server.py +++ b/examples/basic/server.py @@ -17,7 +17,7 @@ async def amain(loop): logging.basicConfig(level=logging.DEBUG) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - loop.create_task(amain(loop=loop)) + loop.run_until_complete(loop.create_task(amain(loop=loop))) try: loop.run_forever() except KeyboardInterrupt: From c1516bc8ca5bb7d62cd84515ef3bf29bb2138171 Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Thu, 13 Apr 2023 15:18:05 -0400 Subject: [PATCH 2/3] Set auth_required=True with authenticator callback --- aiosmtpd/docs/auth.rst | 6 ++++++ examples/authenticated_relayer/server.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/aiosmtpd/docs/auth.rst b/aiosmtpd/docs/auth.rst index 21c419fa..b0622e05 100644 --- a/aiosmtpd/docs/auth.rst +++ b/aiosmtpd/docs/auth.rst @@ -14,6 +14,7 @@ Activating Authentication but attempts to authenticate will always be rejected unless the :attr:`authenticator` parameter of :class:`~aiosmtpd.smtp.SMTP` is set to a valid & working :ref:`authcallback`. +The :attr:`auth_required` parameter can be set to ``True`` to reject clients that don't authenticate. AUTH API @@ -146,6 +147,11 @@ Authenticator Callback .. versionadded:: 1.3 +.. important:: + + Setting an authenticator on your server or controller is not sufficient to require authentication. + In addition to rejecting incorrect credentials in your authenticator, you should set :attr:`auth_required` to ``True`` to reject clients that don't authenticate at all. + AuthResult API -------------- diff --git a/examples/authenticated_relayer/server.py b/examples/authenticated_relayer/server.py index 5f3aa11b..896b9af6 100644 --- a/examples/authenticated_relayer/server.py +++ b/examples/authenticated_relayer/server.py @@ -81,7 +81,8 @@ async def amain(): handler, hostname='', port=8025, - authenticator=Authenticator(DB_AUTH) + authenticator=Authenticator(DB_AUTH), + auth_required=True, ) cont.start() From dab9abeae7be2dfd104c9eb76dfb1babd8ecb594 Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Thu, 13 Apr 2023 15:35:12 -0400 Subject: [PATCH 3/3] Fix authentication --- examples/authenticated_relayer/server.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/authenticated_relayer/server.py b/examples/authenticated_relayer/server.py index 896b9af6..36580dfc 100644 --- a/examples/authenticated_relayer/server.py +++ b/examples/authenticated_relayer/server.py @@ -30,9 +30,11 @@ def __call__(self, server, session, envelope, mechanism, auth_data): return fail_nothandled if not isinstance(auth_data, LoginPassword): return fail_nothandled - username = auth_data.login + try: + username = auth_data.login.decode('utf-8') + except UnicodeDecodeError: + return fail_nothandled password = auth_data.password - hashpass = self.ph.hash(password) conn = sqlite3.connect(self.auth_db) curs = conn.execute( "SELECT hashpass FROM userauth WHERE username=?", (username,) @@ -41,7 +43,7 @@ def __call__(self, server, session, envelope, mechanism, auth_data): conn.close() if not hash_db: return fail_nothandled - if hashpass != hash_db[0]: + if not self.ph.verify(hash_db[0], password): return fail_nothandled return AuthResult(success=True) @@ -83,6 +85,7 @@ async def amain(): port=8025, authenticator=Authenticator(DB_AUTH), auth_required=True, + auth_require_tls=False, ) cont.start()