From f42b9bf97f1470f37b09abe94ecc06f81c482ae7 Mon Sep 17 00:00:00 2001 From: balki <3070606-balki@users.noreply.gitlab.com> Date: Wed, 19 Dec 2018 02:33:04 -0500 Subject: [PATCH] add password support --- mail4one/pop3.py | 14 +++++++++----- mail4one/server.py | 4 +++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/mail4one/pop3.py b/mail4one/pop3.py index 60d0a4c..0686d7b 100644 --- a/mail4one/pop3.py +++ b/mail4one/pop3.py @@ -5,6 +5,8 @@ from _contextvars import ContextVar from dataclasses import dataclass from pathlib import Path from typing import ClassVar, List, Set +from hashlib import sha256 +from secrets import compare_digest from .poputils import InvalidCommand, parse_command, err, Command, ClientQuit, ClientError, AuthError, ok, msg, end, \ Request, MailEntry, get_mail, get_mails_list, MailList @@ -20,6 +22,7 @@ class Session: all_sessions: ClassVar[Set] = set() mails_path: ClassVar[Path] = Path("") current_session: ClassVar = ContextVar("session") + password_hash: ClassVar[str] = "" @classmethod def get(cls): @@ -65,8 +68,8 @@ def write(data): Session.writer().write(data) -def validate_user_and_pass(username, password): - if username != password: +def validate_password(password): + if not compare_digest(Session.password_hash, sha256(password).hexdigest()): raise AuthError("Invalid user pass") @@ -77,7 +80,7 @@ async def handle_user_pass_auth(user_cmd): write(ok("Welcome")) cmd = await expect_cmd(Command.PASS) password = cmd.arg1 - validate_user_and_pass(username, password) + validate_password(password) logging.info(f"User: {username} has logged in successfully") return username @@ -252,8 +255,9 @@ async def new_session(stream_reader: asyncio.StreamReader, stream_writer: asynci stream_writer.close() -async def create_pop_server(dirpath: Path, port: int, host="", context: ssl.SSLContext = None): +async def create_pop_server(dirpath: Path, port: int, password_hash: str, host="", context: ssl.SSLContext = None): Session.mails_path = dirpath + Session.password_hash = password_hash logging.info( f"Starting POP3 server Maildir={dirpath}, host={host}, port={port}, context={context}") return await asyncio.start_server(new_session, host=host, port=port, ssl=context) @@ -265,4 +269,4 @@ async def a_main(*args, **kwargs): if __name__ == "__main__": - asyncio.run(a_main(Path("/tmp/mails"), 9995)) + asyncio.run(a_main(Path("/tmp/mails"), 9995, password_hash=sha256("dummy").hexdigest())) diff --git a/mail4one/server.py b/mail4one/server.py index 000f363..4c639b1 100644 --- a/mail4one/server.py +++ b/mail4one/server.py @@ -24,6 +24,7 @@ def parse_args(): parser = ArgumentParser() parser.add_argument('--certfile') parser.add_argument('--keyfile') + parser.add_argument('--password') parser.add_argument("mail_dir_path") args = parser.parse_args() @@ -63,7 +64,8 @@ def drop_privileges(): async def a_main(args, tls_context): - pop_server = await create_pop_server(args.mail_dir_path, port=args.pop_port, host=args.host, context=tls_context) + pop_server = await create_pop_server( + args.mail_dir_path, port=args.pop_port, host=args.host, context=tls_context, password=args.password) smtp_server = await create_smtp_server(args.mail_dir_path, port=args.smtp_port, host=args.host, context=tls_context) drop_privileges() await asyncio.gather(pop_server.serve_forever(), smtp_server.serve_forever())