# 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
    def __init__(self, bio, ssl):
        # Hold reference to SSL object to ensure _BIOWrapper.__del__ gets
        # called before _SSLWrapper.__del__.  Otherwise, if the SSL obj
        # gets freed before the BIO object, we will segfault.
        self.obj = bio
        self.ssl = ssl

    def __del__(self):
        if self.obj is not None:
            self.m2_bio_free_all(self.obj)


class M2TLSSocket(TLSSocketBase):
    """
    TLSSocket implementation that uses M2Crypto.  This class uses OpenSSL's BIO
    pairs for guaranteed async IO; all socket communication is handled by us
    (via the IOChannel).  See:

        http://www.openssl.org/docs/crypto/BIO_new_bio_pair.html

    Inspired heavily by TwistedProtocolWrapper.py from M2Crypto.
    """
    # list of suuported TLS authentication mechanisms
    supported_methods = [ 'X.509' ]

    def __init__(self):
        super(M2TLSSocket, self).__init__()
        self._reset()



# 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

    def __init__(self, bio, ssl):
        # Hold reference to SSL object to ensure _BIOWrapper.__del__ gets
        # called before _SSLWrapper.__del__.  Otherwise, if the SSL obj
        # gets freed before the BIO object, we will segfault.
        self.obj = bio
        self.ssl = ssl

    def __del__(self):
        if self.obj is not None:
            self.m2_bio_free_all(self.obj)


class M2TLSSocket(TLSSocketBase):
    """
    TLSSocket implementation that uses M2Crypto.  This class uses OpenSSL's BIO
    pairs for guaranteed async IO; all socket communication is handled by us
    (via the IOChannel).  See:

        http://www.openssl.org/docs/crypto/BIO_new_bio_pair.html

    Inspired heavily by TwistedProtocolWrapper.py from M2Crypto.
    """
    # list of suuported TLS authentication mechanisms
    supported_methods = [ 'X.509' ]

    def __init__(self):
        super(M2TLSSocket, self).__init__()
        self._reset()



    def _m2_check_err(self, r=None, cls=TLSError):