[Python-es] Ejecutar cliente/servidor SSL en la misma maquina

Leandro Demarco Vedelago leandrodemarco en gmail.com
Sab Oct 6 19:31:40 CEST 2012


Hola gente: estoy trabajando en una aplicacion que requiere un
cliente/servidor. Como va a haber logueo y/o registro involucrado me
decidi por usar SSL para encriptar la comunicacion y passlib para
hacer hashing de las contrasenhas del lado del servidor.
En fin, ayer lo termine y estuve testeandolo, ejecutando el servidor y
el cliente en maquinas separadas y anduvo a la perfeccion. Pero hoy
intente hacer algo de testeo ejecutando ambos en la misma maquina y me
tira un error extranho.

A continuacion el codigo relevante del servidor y del cliente, respectivamente:

class Server(DirectObject):
    def __init__(self):
        # Socket where the server will be polling for incoming connections
        self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.listener.bind(('127.0.0.1', 9099))
        self.activeSSLSockets = []

   def updateConnections(self, task):
        r,w,e = select.select([self.listener], [], [], 0.01)
        if r != []:
            # We have a new connection!
            clientSock, addr = self.listener.accept()
            print "New connection from " + str(addr)
            # Wrap it under SSL so that all communication is encrypted
            encryptedSock = ssl.wrap_socket(clientSock, server_side=True, \
                            keyfile="privkey.pem", certfile="cacert.pem", \
                            do_handshake_on_connect=False,\
                            ssl_version=ssl.PROTOCOL_SSLv3)
            self.activeSSLSockets.append(encryptedSock)
        return task.cont

    def updateDatagrams(self, task):
        r = []
        if self.activeSSLSockets != []:
            # Windows raises error if 3 arguments of select.select are empty
            r,w,e = select.select(self.activeSSLSockets, [], [], 0.01)
        for sslSock in r:
            data = sslSock.read(1024)
            self.process(data, sslSock)

        return task.cont

El socket del cliente se crea en la siguiente funcion, connectAndThen:

    def connectAndThen(self, user, password, nTries=1, nextStep=None):
        """
            Attempts to establish a connection through self.sckt with the
            server. It tries at most nTries, if in those nTries
connection wasn't
            established, self.sckt remains None.
            @nextStep is the action to perform once connection is established
            It can be login(user, password) or register(user,password)
        """
        i = 0
        timeOut = 3000

        while (not self.sckt and i<nTries):
            try:
                self.sckt = socket.create_connection((self.serverHost,
self.serverPort),\
                                                timeout=timeOut)
                i += 1
            except socket.error as detail:
                print "Attempt " + str(i) + " of " + str(nTries) + " failed!"
                i += 1

        if self.sckt:
            # Add ssl layer to the socket
            self.sslSock = ssl.wrap_socket(self.sckt, server_side=False, \
                            do_handshake_on_connect=True,\
                            ssl_version=ssl.PROTOCOL_SSLv3)
            # Connection established!
            self.connected = True
            # Start polling for incoming datagrams from the server
            taskMgr.add(self.updateDatagrams, "updateDatagrams")
            if nextStep == "login":
                self.login(user, password)
            else:
                self.register(user, password)
        else:
            messenger.send("serverNotFound")

    def updateDatagrams(self, task):
        """ Task in charge of polling the reader for incoming datagrams from
            the server
        """
        r, w, e = select([self.sslSock], [], [], 0.008)
        if r != []:
            # We have a message!
            data = self.sslSock.read(1024)
            self.process(data)

        return task.cont

Como mencione, si el codigo se ejectua en maquinas diferentes no hay
problemas. Pero al modificarlo para que se ejecuten en la misma
maquina la siguiente linea de la funcion updateDatagrams del servidor:

data = sslSock.read(1024)

genera la siguiente excepcion/error:

  File "SecureServer.py", line 73, in updateDatagrams
    data = sslSock.read(1024)
  File "/usr/lib/python2.7/ssl.py", line 151, in read
    return self._sslobj.read(len)
ssl.SSLError: [Errno 1] _ssl.c:1354: error:1408F044:SSL
routines:SSL3_GET_RECORD:internal error

Hay que configurar o setear alguna variable en algun lado para poder
ejecutar tanto el cliente como el servidor SSL (con cliente/servidor
sin SSL no tuve drama en la misma maquina?

Desde ya, muchas gracias.


Más información sobre la lista de distribución Python-es