# Path: src/net/tls/common.py
# class TLSError(Exception):
#     """
#     Base class for all TLS/SSL exceptions.
# 
#     Exception args is a message string.
#     """
#     pass
# 
# class TLSProtocolError(TLSError):
#     """
#     Raised when a protocol-related problem occurs, such as the remote end does
#     not speak TLS, or when no shared cipher could be established.
#     """
#     pass
# 
# class TLSVerificationError(TLSError):
#     """
#     Raised when the remote end's certificate did not verify correctly.
#     """
#     pass
# 
# class TLSSocketBase(kaa.Socket):
#     # list of suuported TLS authentication mechanisms (subclass must override)
#     supported_methods = []
#     
#     # Cached system-wide CA cert file (as detected), or None if none was found.
#     _cafile = False
# 
#     __kaasignals__ = {
#         'tls':
#             '''
#             Emitted when a TLS handshake has been successfully completed.
#             '''
#     }
# 
#     def __init__(self, cafile=None):
#         super(TLSSocketBase, self).__init__()
#         self._handshake = False
#         self._pre_handshake_write_queue = []
# 
#         if cafile:
#             self._cafile = cafile
#         elif TLSSocketBase._cafile is False:
#             self._cafile = None
#             for path in CA_SEARCH_PATH:
#                 if os.path.exists(path):
#                     cafile = path
#                     break
#             else:
#                 # Maybe locate(1) can help.
#                 # XXX: assumes this is fast.  Maybe this should be done async.
#                 path = os.popen('locate -l 1 ca-certificates.crt ca-bundle.crt 2>/dev/null').readline().strip()
#                 if os.path.exists(path):
#                     cafile = path
# 
#             TLSSocketBase._cafile = self._cafile = cafile


import logging
import os
import M2Crypto
import kaa
from M2Crypto import m2, X509
from .common import TLSError, TLSProtocolError, TLSVerificationError, TLSSocketBase
        if 'cert' in kwargs:
            try:
                ctx.load_cert(kwargs['cert'], keyfile=kwargs.get('key'))
            except M2Crypto.SSL.SSLError, e:
                # Reraise wrapped as TLSSocketError
                raise TLSError('Invalid certificate and/or key: %s' % e.message)

        if kwargs.get('verify'):
            # TODO: apply appropriate verify options.
            #ctx.set_verify(M2Crypto.SSL.verify_none, 10)
            if not self._cafile:
                # Verification was requested but on CA bundle found, therefore
                # impossible to verify.
                raise TLSError('CA bundle not found but verification requested.')
            else:
                # Load CA bundle.
                ctx.load_verify_locations(self._cafile)
                # M2Crypto does no error checking on this function, and at
                # least on my system it yields the delightfully inscrutable
                # "cert already in hash table" error (perhaps my distro's
                # CA bundle has duplicate certs?).  It doesn't seem there's
                # anything that can be done about it, so just eat it.
                # (There may be multiple such errors, so clear them all.)
                while True:
                    err = m2.err_get_error()
                    if not err:
                        break
                    # The magic number is X509_R_CERT_ALREADY_IN_HASH_TABLE, which
                    # is a constant that m2crypto doesn't export. :/
                    if err != 185057381:

# Path: src/net/tls/common.py
# class TLSError(Exception):
#     """
#     Base class for all TLS/SSL exceptions.
# 
#     Exception args is a message string.
#     """
#     pass
# 
# class TLSProtocolError(TLSError):
#     """
#     Raised when a protocol-related problem occurs, such as the remote end does
#     not speak TLS, or when no shared cipher could be established.
#     """
#     pass
# 
# class TLSVerificationError(TLSError):
#     """
#     Raised when the remote end's certificate did not verify correctly.
#     """
#     pass
# 
# class TLSSocketBase(kaa.Socket):
#     # list of suuported TLS authentication mechanisms (subclass must override)
#     supported_methods = []
#     
#     # Cached system-wide CA cert file (as detected), or None if none was found.
#     _cafile = False
# 
#     __kaasignals__ = {
#         'tls':
#             '''
#             Emitted when a TLS handshake has been successfully completed.
#             '''
#     }
# 
#     def __init__(self, cafile=None):
#         super(TLSSocketBase, self).__init__()
#         self._handshake = False
#         self._pre_handshake_write_queue = []
# 
#         if cafile:
#             self._cafile = cafile
#         elif TLSSocketBase._cafile is False:
#             self._cafile = None
#             for path in CA_SEARCH_PATH:
#                 if os.path.exists(path):
#                     cafile = path
#                     break
#             else:
#                 # Maybe locate(1) can help.
#                 # XXX: assumes this is fast.  Maybe this should be done async.
#                 path = os.popen('locate -l 1 ca-certificates.crt ca-bundle.crt 2>/dev/null').readline().strip()
#                 if os.path.exists(path):
#                     cafile = path
# 
#             TLSSocketBase._cafile = self._cafile = cafile


# Path: src/net/tls/m2.py
import logging
import os
import M2Crypto
import kaa
from M2Crypto import m2, X509
from .common import TLSError, TLSProtocolError, TLSVerificationError, TLSSocketBase

        if 'cert' in kwargs:
            try:
                ctx.load_cert(kwargs['cert'], keyfile=kwargs.get('key'))
            except M2Crypto.SSL.SSLError, e:
                # Reraise wrapped as TLSSocketError
                raise TLSError('Invalid certificate and/or key: %s' % e.message)

        if kwargs.get('verify'):
            # TODO: apply appropriate verify options.
            #ctx.set_verify(M2Crypto.SSL.verify_none, 10)
            if not self._cafile:
                # Verification was requested but on CA bundle found, therefore
                # impossible to verify.
                raise TLSError('CA bundle not found but verification requested.')
            else:
                # Load CA bundle.
                ctx.load_verify_locations(self._cafile)
                # M2Crypto does no error checking on this function, and at
                # least on my system it yields the delightfully inscrutable
                # "cert already in hash table" error (perhaps my distro's
                # CA bundle has duplicate certs?).  It doesn't seem there's
                # anything that can be done about it, so just eat it.
                # (There may be multiple such errors, so clear them all.)
                while True:
                    err = m2.err_get_error()
                    if not err:
                        break
                    # The magic number is X509_R_CERT_ALREADY_IN_HASH_TABLE, which
                    # is a constant that m2crypto doesn't export. :/
                    if err != 185057381:

                        raise TLSError(m2.err_reason_error_string(err))