Beispiel #1
0
    def do_handshake(self, block=False):  # pylint: disable=unused-argument
        """
        Perform a TLS/SSL handshake.
        """
        self._check_closed("do_handshake")
        self._check_connected()

        if self._server_side:
            ret = _lib.wolfSSL_accept(self.native_object)
        else:
            ret = _lib.wolfSSL_connect(self.native_object)

        if ret != _SSL_SUCCESS:
            err = _lib.wolfSSL_get_error(self.native_object, 0)
            if err == _SSL_ERROR_WANT_READ:
                raise SSLWantReadError()
            elif err == _SSL_ERROR_WANT_WRITE:
                raise SSLWantWriteError()
            else:
                eBuf = _ffi.new("char[80]")
                eStr = _ffi.string(_lib.wolfSSL_ERR_error_string(
                    err, eBuf)).decode("ascii")

                if 'ASN no signer error to confirm' in eStr or err is -188:
                    # Some Python ssl consumers explicitly check error message
                    # for 'certificate verify failed'
                    raise SSLError("do_handshake failed with error %d, "
                                   "certificate verify failed" % err)

                # get alert code and string to put in exception msg
                alertHistoryPtr = _ffi.new("WOLFSSL_ALERT_HISTORY*")
                alertRet = _lib.wolfSSL_get_alert_history(
                    self.native_object, alertHistoryPtr)
                if alertRet == _SSL_SUCCESS:
                    alertHistory = alertHistoryPtr[0]
                    code = alertHistory.last_rx.code
                    alertDesc = _lib.wolfSSL_alert_type_string_long(code)
                    if alertDesc != _ffi.NULL:
                        alertStr = _ffi.string(alertDesc).decode("ascii")
                    else:
                        alertStr = ''

                    raise SSLError("do_handshake failed with error %d: %s. "
                                   "alert (%d): %s" %
                                   (err, eStr, code, alertStr))
                else:
                    raise SSLError("do_handshake failed with error %d: %s" %
                                   (err, eStr))
Beispiel #2
0
    def get_der(self):
        outSz = _ffi.new("int *")
        derPtr = _lib.wolfSSL_X509_get_der(self.native_object, outSz)

        if derPtr == _ffi.NULL:
            return None

        derBytes = _ffi.buffer(derPtr, outSz[0])

        return derBytes
Beispiel #3
0
    def set_ciphers(self, ciphers):
        """
        Set the available ciphers for sockets created with this context. It
        should be a string in the wolfSSL cipher list format. If no cipher can
        be selected (because compile-time options or other configuration
        forbids use of all the specified ciphers), an SSLError will be raised.
        """
        cipherBytes = t2b(ciphers)
        ret = _lib.wolfSSL_CTX_set_cipher_list(self.native_object,
                                               _ffi.new("char[]", cipherBytes))

        if ret != _SSL_SUCCESS:
            raise SSLError("Unable to set cipher list")
Beispiel #4
0
    def read(self, length=1024, buffer=None):
        """
        Read up to LENGTH bytes and return them.
        Return zero-length string on EOF.
        """
        self._check_closed("read")
        self._check_connected()

        if buffer is not None:
            raise ValueError("buffer not allowed in calls to "
                             "read() on %s" % self.__class__)

        data = _ffi.new('byte[%d]' % length)
        length = _lib.wolfSSL_read(self.native_object, data, length)

        if length < 0:
            err = _lib.wolfSSL_get_error(self.native_object, 0)
            if err == _SSL_ERROR_WANT_READ:
                raise SSLWantReadError()
            else:
                raise SSLError("wolfSSL_read error (%d)" % err)

        return _ffi.buffer(data, length)[:] if length > 0 else b''
    def read(self, length=1024, buffer=None):
        """
        Read up to LENGTH bytes and return them.
        Return zero-length string on EOF.
        """
        self._check_closed("read")
        self._check_connected()

        if buffer is not None:
            raise ValueError("buffer not allowed in calls to "
                             "read() on %s" % self.__class__)

        data = _ffi.new('byte[%d]' % length)
        length = _lib.wolfSSL_read(self.native_object, data, length)

        if length < 0:
            err = _lib.wolfSSL_get_error(self.native_object, 0)
            if err == _SSL_ERROR_WANT_READ:
                raise SSLWantReadError()
            else:
                raise SSLError("wolfSSL_read error (%d)" % err)

        return _ffi.buffer(data, length)[:] if length > 0 else b''
Beispiel #6
0
    def __init__(self,
                 sock=None,
                 keyfile=None,
                 certfile=None,
                 server_side=False,
                 cert_reqs=CERT_NONE,
                 ssl_version=PROTOCOL_TLS,
                 ca_certs=None,
                 do_handshake_on_connect=True,
                 family=AF_INET,
                 sock_type=SOCK_STREAM,
                 proto=0,
                 fileno=None,
                 suppress_ragged_eofs=True,
                 ciphers=None,
                 _context=None,
                 server_hostname=None):

        # set options
        self.do_handshake_on_connect = do_handshake_on_connect
        self.suppress_ragged_eofs = suppress_ragged_eofs
        self._server_side = server_side

        # save socket
        self._sock = sock

        # set context
        if _context:
            self._context = _context
        else:
            if server_side and not certfile:
                raise ValueError("certfile must be specified for server-side "
                                 "operations")

            if keyfile and not certfile:
                raise ValueError("certfile must be specified")

            if certfile and not keyfile:
                keyfile = certfile

            self._context = SSLContext(ssl_version, server_side)
            self._context.verify_mode = cert_reqs
            if ca_certs:
                self._context.load_verify_locations(ca_certs)
            if certfile:
                self._context.load_cert_chain(certfile, keyfile)
            if ciphers:
                self._context.set_ciphers(ciphers)

            self.keyfile = keyfile
            self.certfile = certfile
            self.cert_reqs = cert_reqs
            self.ssl_version = ssl_version
            self.ca_certs = ca_certs
            self.ciphers = ciphers
            self.server_hostname = server_hostname

        # set SNI if passed in
        if server_hostname is not None:
            self._context.use_sni(server_hostname)

        # see if we are connected
        try:
            self._sock.getpeername()
        except socket_error as exception:
            if exception.errno != errno.ENOTCONN:
                raise
            connected = False
        else:
            connected = True

        self._closed = False
        self._connected = connected

        # create the SSL object
        self.native_object = _lib.wolfSSL_new(self.context.native_object)
        if self.native_object == _ffi.NULL:
            raise MemoryError("Unnable to allocate ssl object")

        ret = _lib.wolfSSL_set_fd(self.native_object, self._sock.fileno())
        if ret != _SSL_SUCCESS:
            self._release_native_object()
            raise ValueError("Unnable to set fd to ssl object")

        # match domain name / host name if set in context
        if server_hostname is not None:
            if self._context.check_hostname:

                sni = _ffi.new("char[]", server_hostname.encode("utf-8"))
                _lib.wolfSSL_check_domain_name(self.native_object, sni)

        if connected:
            try:
                if do_handshake_on_connect:
                    self.do_handshake()
            except SSLError:
                self._release_native_object()
                self._sock.close()
                raise