diff --git a/lib/nntp/tiny/session.py b/lib/nntp/tiny/session.py index 4c9b199..06e6bf2 100644 --- a/lib/nntp/tiny/session.py +++ b/lib/nntp/tiny/session.py @@ -13,6 +13,7 @@ from nntp.tiny.buffer import LineBuffer, OutputBuffer, BufferOverflow from nntp.tiny.db import Database from nntp.tiny.response import Response, ResponseCode from nntp.tiny.newsgroup import Newsgroup +from nntp.tiny.user import User, UserPermission from nntp.tiny.message import Message, MessageRange, MessagePart class SessionMode(enum.Enum): @@ -26,7 +27,8 @@ class Session(): 'HDR', 'NEWNEWS', 'LIST ACTIVE NEWSGROUP OVERVIEW.FMT SUBSCRIPTIONS', - 'OVER MSGID' + 'OVER MSGID', + 'AUTHINFO USER', ] RE_SPLIT = re.compile(r'\s+') @@ -40,8 +42,10 @@ class Session(): self.mode: SessionMode = SessionMode.READER self.active: bool = True - self.newsgroup: Optional[Newsgroup] = None - self.article_id: Optional[int] = None + self.newsgroup: Optional[Newsgroup] = None + self.user: Optional[User] = None + self.perms: Optional[UserPermission] = None + self.article_id: Optional[int] = None def readline(self): return self.buf.readline(self.sock) @@ -60,10 +64,45 @@ class Session(): return self.print(str(response)) + def _cmd_authinfo_user(self, username): + if self.user is not None: + return self.respond(ResponseCode.NNTP_AUTH_BAD_SEQUENCE) + + self.user = self.db.get(User, {'username': username}) + + return self.respond(ResponseCode.NNTP_INQUIRY_PASSPHRASE) + + def _cmd_authinfo_pass(self, password): + if self.user is None or not self.user.auth(password): + return self.respond(ResponseCode.NNTP_AUTH_FAILED) + + self.perms = self.user.permissions(self.db) + + return self.respond(ResponseCode.NNTP_AUTH_ACCEPTED) + + AUTHINFO_SUBCOMMANDS = { + 'USER': _cmd_authinfo_user, + 'PASS': _cmd_authinfo_pass + } + + def _cmd_authinfo(self, *args): + if len(args) == 0: + return self.respond(ResponseCode.NNTP_SYNTAX_ERROR, "No subcommand provided") + + subcmd, *subargs = args + + fn = self.AUTHINFO_SUBCOMMANDS.get(subcmd.upper()) + + if fn is None: + return self.respond(ResponseCode.NNTP_COMMAND_UNKNOWN) + + return fn(self, *subargs) + def _cmd_capabilities(self, *args): self.respond(ResponseCode.NNTP_CAPABILITIES_FOLLOW) - self.print('AUTHUSER INFO') + if self.perms and self.perms & UserPermission.POST: + self.print('POST') for item in self.NNTP_CAPABILITIES: self.print(item) @@ -653,6 +692,7 @@ class Session(): return self.respond(ResponseCode.NNTP_CONNECTION_CLOSING) COMMANDS = { + 'AUTHINFO': _cmd_authinfo, 'CAPABILITIES': _cmd_capabilities, 'MODE': _cmd_mode, 'GROUP': _cmd_group,