Source code for xmpp.sasl

# -*- coding: utf-8 -*-
#
# Copyright (C) <2016-2017> Gabriel Falcao <gabriel@nacaolivre.org>
# (C) Copyright 2003-2011 Jacek Konieczny <jajcus@jajcus.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License Version
# 2.1 as published by the Free Software Foundation.
#
# 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
"""SASL authentication implementaion for PyXMPP.

Normative reference:
  - `RFC 4422 <http://www.ietf.org/rfc/rfc4422.txt>`__
"""

from __future__ import division


import logging

from xmpp.sasl.core import Reply, Response, Challenge, Success, Failure
from xmpp.sasl.core import PasswordDatabase
from xmpp.sasl.core import CLIENT_MECHANISMS, SECURE_CLIENT_MECHANISMS
from xmpp.sasl.core import SERVER_MECHANISMS, SECURE_SERVER_MECHANISMS
from xmpp.sasl.core import CLIENT_MECHANISMS_D, SERVER_MECHANISMS_D

from xmpp.sasl import plain
from xmpp.sasl import external
from xmpp.sasl import scram


__all__ = [
    'filter_mechanism_list',
    'server_authenticator_factory',
    'client_authenticator_factory',
    'scram',
    'external',
    'plain',
    'Success',
    'Failure',
    'Challenge',
    'Response',
    'Reply',
    'PasswordDatabase',
    'CLIENT_MECHANISMS',
    'CLIENT_MECHANISMS_D',
    'SECURE_CLIENT_MECHANISMS',
    'SERVER_MECHANISMS',
    'SERVER_MECHANISMS_D',
    'SECURE_SERVER_MECHANISMS',
]


logger = logging.getLogger("xmpp.sasl")


def get_client_mechanisms():
    return CLIENT_MECHANISMS_D.keys()


def get_server_mechanisms():
    return SERVER_MECHANISMS_D.keys()


[docs]def client_authenticator_factory(mechanism): """Create a client authenticator object for given SASL mechanism. :Parameters: - `mechanism`: name of the SASL mechanism ("PLAIN", "DIGEST-MD5" or "GSSAPI"). :Types: - `mechanism`: `unicode` :raises `KeyError`: if no client authenticator is available for this mechanism :return: new authenticator. :returntype: `sasl.core.ClientAuthenticator`""" authenticator = CLIENT_MECHANISMS_D[mechanism] return authenticator()
[docs]def server_authenticator_factory(mechanism, password_database): """Create a server authenticator object for given SASL mechanism and password databaser. :Parameters: - `mechanism`: name of the SASL mechanism ("PLAIN", "DIGEST-MD5" or "GSSAPI"). - `password_database`: name of the password database object to be used for authentication credentials verification. :Types: - `mechanism`: `str` - `password_database`: `PasswordDatabase` :raises `KeyError`: if no server authenticator is available for this mechanism :return: new authenticator. :returntype: `sasl.core.ServerAuthenticator`""" authenticator = SERVER_MECHANISMS_D[mechanism] return authenticator(password_database)
[docs]def filter_mechanism_list(mechanisms, properties, allow_insecure=False, server_side=False): """Filter a mechanisms list only to include those mechanisms that cans succeed with the provided properties and are secure enough. :Parameters: - `mechanisms`: list of the mechanisms names - `properties`: available authentication properties - `allow_insecure`: allow insecure mechanisms :Types: - `mechanisms`: sequence of `unicode` - `properties`: mapping - `allow_insecure`: `bool` :returntype: `list` of `unicode` """ result = [] for mechanism in mechanisms: mechanism = mechanism.upper() try: if server_side: klass = SERVER_MECHANISMS_D[mechanism] else: klass = CLIENT_MECHANISMS_D[mechanism] except KeyError: continue secure = properties.get("security-layer") if not allow_insecure and not klass._pyxmpp_sasl_secure and not secure: continue if not klass.are_properties_sufficient(properties): continue result.append(mechanism) return result