Source code for aiosasl.channel_binding_methods

########################################################################
# File name: channel_binding_methods.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
# <http://www.gnu.org/licenses/>.
#
########################################################################
"""
Channel binding methods
=======================

The module :mod:`aiosasl.channel_binding_methods` provides
implementations of the :class:`~aiosasl.ChannelBindingProvider`
interface for use with :mod:`ssl` respective :mod:`OpenSSL`.

.. autoclass:: StdlibTLS

.. autoclass:: TLSUnique

.. autoclass:: TLSServerEndPoint
"""
import functools

from . import ChannelBindingProvider


[docs]class StdlibTLS(ChannelBindingProvider): """ Provider for channel binding for :mod:`ssl`. :param connection: the SSL connection :type connection: :class:`ssl.SSLSocket` :param type_: the channel binding type :type type_: :class:`str` """ def __init__(self, connection, type_): super().__init__() self._connection = connection self._type = type_ @property def cb_name(self): return self._type.encode("us-ascii") def extract_cb_data(self): return self._connection.get_channel_binding(self._type)
[docs]class TLSUnique(ChannelBindingProvider): """ Provider for the channel binding ``tls-unique`` as specified by :rfc:`5929` for :mod:`OpenSSL`. .. warning:: This only supports connections that were not created by session resumption. :param connection: the SSL connection :type connection: :class:`OpenSSL.SSL.Connection` """ def __init__(self, connection): super().__init__() self._connection = connection @property def cb_name(self): return b"tls-unique" def extract_cb_data(self): return self._connection.get_finished()
def parse_openssl_digest(digest): return bytes(map(functools.partial(int, base=16), digest.split(b":")))
[docs]class TLSServerEndPoint(ChannelBindingProvider): """ Provider for the channel binding ``tls-server-end-point`` as specified by :rfc:`5929` for :mod:`OpenSSL`. :param connection: the SSL connection :type connection: :class:`OpenSSL.SSL.Connection` """ def __init__(self, connection): super().__init__() self._connection = connection @property def cb_name(self): return b"tls-server-end-point" def extract_cb_data(self): cert = self._connection.get_peer_certificate() algo, part, _ = cert.get_signature_algorithm().lower().partition( b"with") if not part: raise NotImplementedError if algo in (b"sha1", b"md5"): algo = b"sha256" return parse_openssl_digest(cert.digest(algo.decode("us-ascii")))