add password support
This commit is contained in:
parent
5ef67e6dc9
commit
f42b9bf97f
@ -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()))
|
||||||
|
@ -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())
|
||||||
|
Loading…
Reference in New Issue
Block a user