Fallos de protocolo de enlace SSL cuando no se enviaron datos a través de Twisted TLSConnection

Empiezo a buscar la implementación de FTP explícito extendiendo el FTP Twisted actual.

La mayor parte del código era sencillo e implementar AUTH, PBSZ, PROT fue fácil y obtuve un canal de control seguro que funciona.

Mi problema es con el canal de datos.

El error del lado del cliente es:SSL routines', 'SSL3_READ_BYTES', 'ssl handshake failure'

Parece que el apretón de manos y el apagado SSL se llaman solo cuando se enviaron algunos datos a través del canal de datos. Esto afecta el caso al enviar archivos vacíos o al enumerar carpetas vacías, ya que antes de cerrar la conexión, el cliente llamará al cierre SSL.

Estoy buscando alguna sugerencia sobre cómo y dónde debo buscar para solucionar el apretón de manos TLS de Twisted TLS cuando no se envían datos.

Este código funciona al enumerar carpetas que no están vacías ... pero fallará si la carpeta no contiene archivos o carpetas.

¡Muchas gracias!

def getDTPPort(self, factory):
    """
    Return a port for passive access, using C{self.passivePortRange}
    attribute.
    """
    for portn in self.passivePortRange:
        try:
            if self.protected_data:
                dtpPort = reactor.listenSSL(
                    port=portn, factory=factory,
                    contextFactory=self.ssl_context)
            else:
                dtpPort = self.listenFactory(portn, factory)

        except error.CannotListenError:
            continue
        else:
            return dtpPort
    raise error.CannotListenError('', portn,
        "No port available in range %s" %
        (self.passivePortRange,))
Actualización 1

Actualizaré este texto ya que los comentarios no están bien formateados:

Entonces terminé con:

def getDTPPort(self, factory):
    """
    Return a port for passive access, using C{self.passivePortRange}
    attribute.
    """
    for portn in self.passivePortRange:
        try:
            if self.protected_data:
                tls_factory = TLSMemoryBIOFactory(
                    contextFactory=self.ssl_context,
                    isClient=False,
                    wrappedFactory=factory)
                dtpPort = reactor.listenTCP(
                    port=portn, factory=tls_factory)
            else:
                dtpPort = self.listenFactory(portn, factory)

        except error.CannotListenError:
            continue
        else:
            return dtpPort
    raise error.CannotListenError('', portn,
        "No port available in range %s" %
        (self.passivePortRange,))
Actualización 2

El problema se debe al hecho de que la conexión está cerrada mientras el protocolo de enlace aún se está ejecutando. No sé cómo verificar en una conexión vacía que se realizó el protocolo de enlace SSL.

Así que terminé con este estúpido código

def loseConnection(self):
    """
    Send a TLS close alert and close the underlying connection.
    """
    self.disconnecting = True

    def close_connection():
        if not self._writeBlockedOnRead:
            self._tlsConnection.shutdown()
            self._flushSendBIO()
            self.transport.loseConnection()

    # If we don't know if the handshake was done, we wait for a bit
    # and the close the connection.
    # This is done to avoid closing the connection in the middle of a
    # handshake.
    if not self._handshakeDone:
        reactor.callLater(0.1, close_connection)
    else:
        close_connection()

Respuestas a la pregunta(1)

Su respuesta a la pregunta