예제 #1
0
    def load_cert_chain(self, certfile, keyfile=None, password=None):
        """
        Load a private key and the corresponding certificate. The certfile
        string must be the path to a single file in PEM format containing
        the certificate as well as any number of CA certificates needed to
        establish the certificate's authenticity.

        The keyfile string, if present, must point to a file containing the
        private key in.

        The password parameter is not supported yet.
        """

        if password is not None:
            raise NotImplementedError("password callback support not "
                                      "implemented yet")

        if certfile is not None:
            ret = _lib.wolfSSL_CTX_use_certificate_chain_file(
                self.native_object, t2b(certfile))
            if ret != _SSL_SUCCESS:
                raise SSLError("Unnable to load certificate chain. Err %d"% ret)
        else:
            raise TypeError("certfile should be a valid filesystem path")

        if keyfile is not None:
            ret = _lib.wolfSSL_CTX_use_PrivateKey_file(
                self.native_object, t2b(keyfile), _SSL_FILETYPE_PEM)
            if ret != _SSL_SUCCESS:
                raise SSLError("Unnable to load private key. Err %d" % ret)
예제 #2
0
    def load_verify_locations(self, cafile=None, capath=None, cadata=None):
        """
        Load a set of "certification authority" (CA) certificates used to
        validate other peers' certificates when verify_mode is other than
        CERT_NONE. At least one of cafile or capath must be specified.

        The cafile string, if present, is the path to a file of concatenated
        CA certificates in PEM format.

        The capath string, if present, is the path to a directory containing
        several CA certificates in PEM format.
        """

        if cafile is None and capath is None and cadata is None:
            raise TypeError("cafile, capath and cadata cannot be all omitted")

        if cafile is not None or capath is not None:
            ret = _lib.wolfSSL_CTX_load_verify_locations(
                self.native_object,
                t2b(cafile) if cafile else _ffi.NULL,
                t2b(capath) if capath else _ffi.NULL)

            if ret != _SSL_SUCCESS:
                raise SSLError("Unnable to load verify locations. Err %d" % ret)

        if cadata is not None:
            ret = _lib.wolfSSL_CTX_load_verify_buffer(
                self.native_object, t2b(cadata), len(cadata), _SSL_FILETYPE_PEM)

            if ret != _SSL_SUCCESS:
                raise SSLError("Unnable to load verify locations. Err %d" % ret)
예제 #3
0
    def load_cert_chain(self, certfile, keyfile=None, password=None):
        """
        Load a private key and the corresponding certificate. The certfile
        string must be the path to a single file in PEM format containing
        the certificate as well as any number of CA certificates needed to
        establish the certificate's authenticity.

        The keyfile string, if present, must point to a file containing the
        private key in.

        If you are using a key protected cert or key file, you must call
        set_passwd_cb before calling load_cert_chain because wolfSSL
        validates the provided file the first time it is loaded.


        wolfSSL does not support loading a certificate file that contains
        both the certificate AND private key. In this case, users should
        split them into two separate files and load using the certfile
        and keyfile parameters, respectively.
        """
        if certfile is not None:
            ret = _lib.wolfSSL_CTX_use_certificate_chain_file(
                self.native_object, t2b(certfile))
            if ret != _SSL_SUCCESS:
                raise SSLError("Unable to load certificate chain. E(%d)" % ret)
        else:
            raise TypeError("certfile should be a valid filesystem path")

        if keyfile is not None:
            ret = _lib.wolfSSL_CTX_use_PrivateKey_file(self.native_object,
                                                       t2b(keyfile),
                                                       _SSL_FILETYPE_PEM)
            if ret != _SSL_SUCCESS:
                raise SSLError("Unable to load private key. E(%d)" % ret)
예제 #4
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))
예제 #5
0
    def __init__(self, protocol, server_side=False):
        method = _WolfSSLMethod(protocol, server_side)

        self.protocol = protocol
        self._side = server_side
        self._verify_mode = None
        self.native_object = _lib.wolfSSL_CTX_new(method.native_object)

        # wolfSSL_CTX_new() takes ownership of the method.
        # the method is freed later inside wolfSSL_CTX_free()
        # or if wolfSSL_CTX_new() failed to allocate the context object.
        method.native_object = _ffi.NULL

        if self.native_object == _ffi.NULL:
            raise MemoryError("Unnable to allocate context object")

        # verify_mode initialization needs a valid native_object.
        self.verify_mode = CERT_NONE

        if not server_side:
            for curve in _SUPPORTED_CURVES:
                ret = _lib.wolfSSL_CTX_UseSupportedCurve(self.native_object,
                                                         curve)
                if ret != _SSL_SUCCESS:
                    raise SSLError("unnable to set curve (%d)" % curve)
예제 #6
0
    def recv_into(self, buffer, nbytes=None, flags=0):
        """
        Read nbytes bytes and place into buffer. If nbytes is 0, read up
        to full size of buffer.
        """
        self._check_closed("read")
        self._check_connected()

        if buffer is None:
            raise ValueError("buffer cannot be None")

        if nbytes is None:
            nbytes = len(buffer)
        else:
            nbytes = min(len(buffer), nbytes)

        if nbytes == 0:
            return 0

        data = _ffi.from_buffer(buffer)
        length = _lib.wolfSSL_read(self.native_object, data, nbytes)

        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 length
예제 #7
0
    def do_handshake(self, block=False):
        """
        Perform a TLS/SSL handshake.
        """
        self._check_closed("do_handshake")
        self._check_connected()

        ret = _lib.wolfSSL_negotiate(self.native_object)
        if ret != _SSL_SUCCESS:
            raise SSLError("do_handshake failed with error %d" % ret)
예제 #8
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.
        """
        ret = _lib.wolfSSL_CTX_set_cipher_list(self.native_object, t2b(ciphers))

        if ret != _SSL_SUCCESS:
            raise SSLError("Unnable to set cipher list")
예제 #9
0
    def use_sni(self, server_hostname):
        """
        Sets the SNI hostname, wraps native wolfSSL_UseSNI()
        """

        sni = t2b(server_hostname)

        ret = _lib.wolfSSL_UseSNI(self.native_object, 0, sni, len(sni))

        if ret != _SSL_SUCCESS:
            raise SSLError("Unable to set wolfSSL SNI")
예제 #10
0
    def sendall(self, data, flags=0):
        if flags != 0:
            raise NotImplementedError("non-zero flags not allowed in calls to "
                                      "sendall() on %s" % self.__class__)

        length = len(data)
        sent = 0

        while sent < length:
            ret = self.write(data[sent:])
            if (ret < 0):
                err = _lib.wolfSSL_get_error(self.native_object, 0)
                if err == _SSL_ERROR_WANT_WRITE:
                    raise SSLWantWriteError()
                else:
                    raise SSLError("wolfSSL_write error (%d)" % err)

            sent += ret

        return None
예제 #11
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''
예제 #12
0
    def __init__(self, session):
        self.native_object = _lib.wolfSSL_get_peer_certificate(session)

        if self.native_object == _ffi.NULL:
            raise SSLError("Unable to get internal WOLFSSL_X509 from wolfSSL")