########################################################################
# File name: __init__.py
# This file is part of: aiosasl
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# .
#
########################################################################
"""
Using SASL in a protocol
========================
To make use of SASL over an existing protocol, you first need to subclass and
implement :class:`SASLInterface`.
The usable mechanisms need to be detected by your application using the
protocol over which to implement SASL. This is generally protocol-specific. For
example, XMPP uses stream features to announce which SASL mechanisms are
supported by the server.
When a set of SASL mechanism strings has been obtained by the server (let us
call a set with the mechanism strings ``sasl_mechanisms``), the mechanisms
supported by your application (a list of :class:`SASLMechanism` subclass
instances, let us call it ``mechanism_impls``) can be queried for support::
# intf =
for impl in mechanism_impl:
token = impl.any_supported(sasl_mechanisms)
if token is not None:
sm = aiosasl.SASLStateMachine(intf)
try:
await impl.authenticate(sm, token)
except aiosasl.AuthenticationFailure:
# handle authentication failure
# it is generally not sensible to re-try with other mechanisms
except aiosasl.SASLFailure:
# this is a protocol problem, it is sensible to re-try other
# mechanisms
else:
# authentication was successful!
The instances for the mechanisms can be re-used; they do not save any state,
the state is held by :class:`SASLStateMachine` instead. The different
mechanisms require different arguments (the password-based mechanisms generally
require a callback which provides credentials).
The mechanisms which are currently supported by :mod:`aiosasl` are summarised
below:
.. autosummary::
ANONYMOUS
PLAIN
SCRAM
SCRAMPLUS
Interface for protocols using SASL
==================================
To implement SASL on an existing protocol, you need to subclass
:class:`SASLInterface` and implement the abstract methods:
.. autoclass:: SASLInterface
.. autoclass:: SASLState
SASL mechansims
===============
.. autoclass:: PLAIN
.. autoclass:: SCRAM(credential_provider, *[, after_scram_plus=False][, enforce_minimum_iteration_count=True])
.. autoclass:: SCRAMPLUS(credential_provider, cb_provider, *[, enforce_minimum_iteration_count=True])
.. autoclass:: ANONYMOUS
Base class
----------
.. autoclass:: SASLMechanism
A note for implementers
-----------------------
The :class:`SASLStateMachine` unwraps `(SASLState.SUCCESS, payload)` messages
passed in from a :class:`SASLInterface` to the equivalent sequence
`(SASLState.CHALLENGE, payload)` (requiring the empty string as response) and
`(SASLState.SUCCESS, None)`. The two forms are equivalent as per the SASL
specification and this unwrapping allows uniform treatment of both
forms by the :class:`SASLMechanism` implementations.
SASL state machine
==================
.. autoclass:: SASLStateMachine
Exception classes
=================
.. autoclass:: SASLError
.. autoclass:: SASLFailure
.. autoclass:: AuthenticationFailure
Version information
===================
.. autodata:: __version__
.. autodata:: version_info
""" # NOQA
from .common import ( # noqa:F401
AuthenticationFailure,
SASLError,
SASLFailure,
SASLState,
)
from .statemachine import ( # noqa:F401
SASLInterface,
SASLMechanism,
SASLStateMachine,
)
from .scram import ( # noqa:F401
SCRAM,
SCRAMPLUS,
)
from .plain import ( # noqa:F401
PLAIN,
)
from .anonymous import ( # noqa:F401
ANONYMOUS,
)
from .version import version, __version__, version_info # noqa:F401
#: The imported :mod:`aiosasl` version as a tuple.
#:
#: The components of the tuple are, in order: `major version`, `minor version`,
#: `patch level`, and `pre-release identifier`.
version_info = version_info
#: The imported :mod:`aiosasl` version as a string.
#:
#: The version number is dot-separated; in pre-release or development versions,
#: the version number is followed by a hypen-separated pre-release identifier.
__version__ = __version__