add password support

This commit is contained in:
Balakrishnan Balasubramanian 2018-12-19 02:33:04 -05:00
parent 5ef67e6dc9
commit f42b9bf97f
2 changed files with 12 additions and 6 deletions

View File

@ -5,6 +5,8 @@ from _contextvars import ContextVar
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import ClassVar, List, Set 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, \ from .poputils import InvalidCommand, parse_command, err, Command, ClientQuit, ClientError, AuthError, ok, msg, end, \
Request, MailEntry, get_mail, get_mails_list, MailList Request, MailEntry, get_mail, get_mails_list, MailList
@ -20,6 +22,7 @@ class Session:
all_sessions: ClassVar[Set] = set() all_sessions: ClassVar[Set] = set()
mails_path: ClassVar[Path] = Path("") mails_path: ClassVar[Path] = Path("")
current_session: ClassVar = ContextVar("session") current_session: ClassVar = ContextVar("session")
password_hash: ClassVar[str] = ""
@classmethod @classmethod
def get(cls): def get(cls):
@ -65,8 +68,8 @@ def write(data):
Session.writer().write(data) Session.writer().write(data)
def validate_user_and_pass(username, password): def validate_password(password):
if username != password: if not compare_digest(Session.password_hash, sha256(password).hexdigest()):
raise AuthError("Invalid user pass") raise AuthError("Invalid user pass")
@ -77,7 +80,7 @@ async def handle_user_pass_auth(user_cmd):
write(ok("Welcome")) write(ok("Welcome"))
cmd = await expect_cmd(Command.PASS) cmd = await expect_cmd(Command.PASS)
password = cmd.arg1 password = cmd.arg1
validate_user_and_pass(username, password) validate_password(password)
logging.info(f"User: {username} has logged in successfully") logging.info(f"User: {username} has logged in successfully")
return username return username
@ -252,8 +255,9 @@ async def new_session(stream_reader: asyncio.StreamReader, stream_writer: asynci
stream_writer.close() 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.mails_path = dirpath
Session.password_hash = password_hash
logging.info( logging.info(
f"Starting POP3 server Maildir={dirpath}, host={host}, port={port}, context={context}") 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) 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__": if __name__ == "__main__":
asyncio.run(a_main(Path("/tmp/mails"), 9995)) asyncio.run(a_main(Path("/tmp/mails"), 9995, password_hash=sha256("dummy").hexdigest()))

View File

@ -24,6 +24,7 @@ def parse_args():
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('--certfile') parser.add_argument('--certfile')
parser.add_argument('--keyfile') parser.add_argument('--keyfile')
parser.add_argument('--password')
parser.add_argument("mail_dir_path") parser.add_argument("mail_dir_path")
args = parser.parse_args() args = parser.parse_args()
@ -63,7 +64,8 @@ def drop_privileges():
async def a_main(args, tls_context): 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) smtp_server = await create_smtp_server(args.mail_dir_path, port=args.smtp_port, host=args.host, context=tls_context)
drop_privileges() drop_privileges()
await asyncio.gather(pop_server.serve_forever(), smtp_server.serve_forever()) await asyncio.gather(pop_server.serve_forever(), smtp_server.serve_forever())