示例#1
0
    def _read(fdptr, data, dataLength):
        """
        The SecureTransport SSL read callback.

        @param fdptr: reference value added via SSLSetConnection
        @type fdptr: ffi(int *)
        @param data: buffer to read data into
        @type data: ffi(void *)
        @param dataLength: length of the buffer to read into, and on return
            the actual length of data read
        @type dataLength: ffi(size_t *)
        """

        # Get the associated L{Connection} object
        engine_id = ffi.cast("int *", fdptr)[0]
        engine = Connection.engines[engine_id]

        # If there are bytes pending in the L{Connection}s buffer, read as much
        # of those as possible, or return errSSLWouldBlock
        dlen = dataLength[0]
        rdata = ffi.buffer(data, dlen)
        if engine.getBytes(rdata, dlen) is None:
            dataLength[0] = 0
            return security.errSSLWouldBlock

        return 0
示例#2
0
    def connect(self):
        """
        Create the SecureTransport SSLContextRef object and initialize it.
        """

        self.ctx = security.SSLCreateContext(ffi.NULL, security.kSSLClientSide if self.is_client else security.kSSLServerSide, security.kSSLStreamType)

        minVersion = None
        for option, minValue in (
            (OP_NO_SSLv2, security.kSSLProtocol3),
            (OP_NO_SSLv3, security.kTLSProtocol1),
            (OP_NO_TLSv1, security.kTLSProtocol11),
            (OP_NO_TLSv1_1, security.kTLSProtocol12),
            (OP_NO_TLSv1_2, security.kTLSProtocol12),   # TLS1.2 is the highest supported right now
        ):
            if option in self.context.options:
                minVersion = minValue
        if minVersion is not None:
            security.SSLSetProtocolVersionMin(self.ctx, minVersion)

        # Make sure we have a reference back to this L{Connection} in the SecureTransport callbacks
        self.connref = ffi.new("int *", self.engine_id)
        err = security.SSLSetConnection(self.ctx, ffi.cast("SSLConnectionRef", self.connref))
        if err:
            self.shutdown()
            raise Error(err)

        # Setup the actual SecureTransport callbacks
        err = security.SSLSetIOFuncs(self.ctx, self._read, self._write)
        if err:
            self.shutdown()
            raise Error(err)

        # Must have a certificate identity if we are a server
        if not self.is_client and self.context.identity is None:
            self.shutdown()
            raise Error("No certificate")

        # Must have a peer name if we are a client
        if self.is_client and not self.context.peerName:
            self.shutdown()
            raise Error("No peer name set with client connection.")
        elif self.is_client:
            # Always set the client peer name for proper certificate validation
            err = security.SSLSetPeerDomainName(self.ctx, self.context.peerName, len(self.context.peerName))
            if err:
                self.shutdown()
                raise Error(err)

        # Add the certificate
        if self.context.identity is not None:
            certs = CFArrayRef.fromList([self.context.identity])
            err = security.SSLSetCertificate(self.ctx, certs.ref())
            if err:
                self.shutdown()
                raise Error(err)
示例#3
0
    def _write(fdptr, data, dataLength):
        """
        The SecureTransport SSL write callback.

        @param fdptr: reference value added via SSLSetConnection
        @type fdptr: ffi(int *)
        @param data: buffer to write
        @type data: ffi(const void *)
        @param dataLength: length of the data to write, and on return
            the actual length of data written
        @type dataLength: ffi(size_t *)
        """

        # Get the associated L{Connection} object
        engine_id = ffi.cast("int *", fdptr)[0]
        engine = Connection.engines[engine_id]

        # We always write everything in one go
        dlen = dataLength[0]
        wdata = ffi.buffer(data, dlen)
        engine.protocol.transport.write(wdata[:])

        return 0