Source code for pysasl.mechanism.plain


import re
from typing import Union, Tuple, Sequence

from . import (ServerMechanism, ClientMechanism, ServerChallenge,
               ChallengeResponse)
from ..creds.client import ClientCredentials
from ..creds.plain import PlainCredentials
from ..exception import InvalidResponse, UnexpectedChallenge

__all__ = ['PlainMechanism']


[docs]class PlainMechanism(ServerMechanism, ClientMechanism): """Implements the PLAIN authentication mechanism.""" _pattern = re.compile(br'^([^\x00]*)\x00([^\x00]+)\x00([^\x00]*)$') __slots__: Sequence[str] = [] def __init__(self, name: Union[str, bytes] = b'PLAIN') -> None: super().__init__(name)
[docs] def server_attempt(self, responses: Sequence[ChallengeResponse]) \ -> Tuple[PlainCredentials, None]: try: first = responses[0] except IndexError as exc: raise ServerChallenge(b'') from exc match = re.match(self._pattern, first.response) if not match: raise InvalidResponse() zid, cid, secret = match.groups() cid_str = cid.decode('utf-8') secret_str = secret.decode('utf-8') zid_str = zid.decode('utf-8') or cid_str return PlainCredentials(cid_str, secret_str, zid_str), None
[docs] def client_attempt(self, creds: ClientCredentials, challenges: Sequence[ServerChallenge]) \ -> ChallengeResponse: if len(challenges) == 0: challenge = b'' elif len(challenges) == 1: challenge = challenges[0].data else: raise UnexpectedChallenge() authzid = creds.authzid.encode('utf-8') authcid = creds.authcid.encode('utf-8') secret = creds.secret.encode('utf-8') response = b'\0'.join((authzid, authcid, secret)) return ChallengeResponse(challenge, response)