2012-09-09 20 views
20

En Python, ssl.wrap_socket puede leer certificados de archivos, ssl.wrap_socket requiere el certificado como ruta de archivo.Cómo abrir un socket ssl usando un certificado almacenado en variables de cadena en python

¿Cómo puedo iniciar una conexión SSL usando un certificado leído de variables de cadena?

Mi entorno host no permite escribir en archivos, y el módulo tempfile no funciona
Estoy usando Python 2.7.
Guardo el certificado dentro de MySQL y lo leo como una cadena.

Edit: Me di por vencido, esto es básicamente requiere implementar ssl por código python puro, esto está más allá de mi conocimiento actual.

+1

Seguramente su entorno host le permite almacenar certificados SSL, de alguna manera? incluso si ellos quieren suplirlos ellos mismos. – EJP

+0

Guardé los datos del certificado en mysql. mi código necesita un socket ssl para otro host para recuperar datos. Leí el certificado de la base de datos, pero no sé cómo crear el ssl wrap. – kaala

+0

Al buscar en la fuente, ssl.wrap_socket llama directamente a la función de código nativo (openssl) SSL_CTX_use_cert_chain_file que requiere una ruta a un archivo, por lo que lo que está intentando hacer no es posible. Necesita escribir el certificado en un archivo para que esto funcione. – cnelson

Respuesta

23

Al buscar en la fuente, ssl.wrap_socket llama directamente a la función de código nativo (openssl) SSL_CTX_use_cert_chain_file que requiere una ruta a un archivo, por lo que lo que está intentando hacer no es posible.

Como referencia:

en ssl/init .py que vemos:

def wrap_socket(sock, keyfile=None, certfile=None, 
       server_side=False, cert_reqs=CERT_NONE, 
       ssl_version=PROTOCOL_SSLv23, ca_certs=None, 
       do_handshake_on_connect=True): 

    return SSLSocket(sock, keyfile=keyfile, certfile=certfile, 
        server_side=server_side, cert_reqs=cert_reqs, 
        ssl_version=ssl_version, ca_certs=ca_certs, 
        do_handshake_on_connect=do_handshake_on_connect) 

Puntos de Estados Unidos para el constructor SSLSocket (que está en el mismo archivo) y vemos las siguientes situaciones:

self._sslobj = _ssl2.sslwrap(self._sock, server_side, 
            keyfile, certfile, 
            cert_reqs, ssl_version, ca_certs) 

_ssl2 se implementa en C (_ssl2.c)

En cuanto a la función sslwrap, vemos que está creando un nuevo objeto:

return (PyObject *) newPySSLObject(Sock, key_file, cert_file, 
             server_side, verification_mode, 
             protocol, cacerts_file); 

Mirando el constructor para ese objeto, al final vemos:

  ret = SSL_CTX_use_certificate_chain_file(self->ctx, 
                cert_file); 

Esa función se define en OpenSSL, por lo ahora tenemos que cambiar a esa base de código.

en ssl/ssl_rsa.c nos encontramos finalmente en la función:

BIO_read_filename(in,file) 

Si se mira lo suficientemente lejos en el código BIO (parte de OpenSSL) que finalmente va a llegar a un fopen() normal:

fp=fopen(ptr,p); 

Parece que está escrito. Debe estar en un archivo que pueda abrir el fopen() de C.

Además, como la biblioteca ssl de python tan rápidamente salta en C, tampoco veo un lugar inmediatamente obvio para monkeypatch en una solución alternativa.

+1

Casi esperaba un hack sucio ... – domenukk

-1

Puede tratar cadenas como archivos con StringIO.

+1

StringIO es no funciona en ssl.wrap_socket, que requiere una cadena como ruta de archivo. Excepción: TypeError ('debe ser de cadena o ninguno, no instancia',) Rastreo: Rastreo (llamada más reciente pasado): Archivo "/data1/www/htdocs/705/pty/1/pty.py ", línea 23, en connect self.push.connect (self.gateway) Archivo" /usr/local/sae/python/lib/python2.7/ssl.py ", línea 331, en connect self._real_connect (addr, False) Archivo "/usr/local/sae/python/lib/python2.7/ssl.py", línea 314, en _real_connect self.ca_certs, self.ciphers) TypeError: debe ser una cadena o None , no instancia – kaala

+1

Entonces toma una ruta de archivo y no un objeto de archivo –

5

mirada rápida a pesar de la fuente del módulo SSL confirma lo que quiere no es compatible con la API: http://code.google.com/codesearch#2T6lfGELm_A/trunk/Modules/_ssl.c&q=sslwrap&type=cs

cual no quiere decir que es imposible, se podría crear una tubería con nombre, alimentar a un extremo de Python y dar el nombre de archivo al módulo ssl.

Para un uso más sencillo y menos seguro, descargue cert de la memoria al archivo mkstemp() 'd.

Incluso podría montar el volumen FUSE e interceptar la devolución de llamada de archivos.

Finalmente, utilice los tipos para hackear en el contexto ssl en tiempo de ejecución y cargue cert/ket desde un búfer siguiendo la receta C Read certificate files from memory instead of a file using OpenSSL Cosas como estas se han hecho antes, pero no es para nada quisquilloso.

Parece que estás tratando de salir de, por ejemplo, aplicación de motor "cárcel", tal vez simplemente no es posible?

Si no es quisquilloso con la implementación de ssl, puede usar M2Crypto, TLS Lite, pyOpenSSL u otra cosa. Cuanto antes sea python puro, definitivamente puede hackearlo para usar certificados/claves en memoria.

+0

La tubería nombrada es básicamente un archivo temporal, ¿no? Muy buenas ideas sin embargo. Creo que usar M2Crypto o algo similar será el mejor enfoque entonces. – domenukk

+0

sí crear named pipes requiere permiso de escritura en el sistema de archivos –

+0

Incluso después de haber conectado en 'load_verify_locations' of' ssl._ssl._SSLContext' usando ctypes hackery, toda esa función se obtiene como un objeto 'ssl.SSLContext' y es un misterio para mí cómo usar eso para acceder a la ubicación correcta de la memoria que se asignó para la clase principal 'PySSLContext' subyacente, de modo que pueda recuperar el puntero a su miembro' ctx' de tipo 'SL_CTX *'. ¿Alguien tiene punteros (literales)? – josch

Cuestiones relacionadas