[pyar] Auth entre servidor / cliente usando https y evitar robo de info en el medio ...

Marcelo Fernandez marcelo.fidel.fernandez en gmail.com
Mar Ene 18 13:35:30 ART 2011


Buenas,

2011/1/17 Claudio Freire <klaussfreire en gmail.com>:
>
> 2011/1/17 Emiliano Dalla Verde Marcozzi <edvm en airtrack.com.ar>
>>
>> 2011/1/17 Daniel Moisset <dmoisset en machinalis.com>
>>>
>>> https esta bastante bien hecho, y no se te pueden meter transparentemente
>>> al medio si haces las cosas bien. Es decir, armar un certificado de una CA,
>>> firmar con ese el certificado que usas en el server, y poner la clave
>>> publica de la CA en los clientes. Si no sabes quienes vas a ser los
>>> clientes, podes pedir una firma de una CA conocida, pero te la van a cobrar.
>>
>> Antes que nada, gracias por tu respuesta Daniel ... estoy leyendo sobre el
>> protocolo https y voy a ver como es este maneje de que los clientes utilicen
>> la cllave publica ...
>
> En general, lo que tenés que hacer es que el server verifique el certificado
> que se utilizó en la conexión https (que verifique que es un cliente
> autorizado) y, asimismo, que el cliente verifique a su vez el certificado
> del servidor, que es el servidor al que quiere realmente enviar el
> user/pass.
>
> Eso se hace con API de openssl o lo que uses, no de https. httplib no provee
> ninguna verificación automática de la cadena de certificados otra que "acá
> tenés el certificado que me mandaron del otro lado, verificalo si querés".

Es cierto, httplib no fuerza el chequeo del certificado del cliente
contra el del servidor (y hay que tener cuidado porque te deja pasarle
client keys, ¡pero sólo para que el server valide!); pero eso no
quiere decir que no se pueda hacer.

Yo me armé esta clase:

http://pastebin.com/7hxHT2tE

Claro que la validación "fuerte" pero del lado del servidor la hace
Apache (y ejemplos de esto creo que hay de sobra en la web). Cualquier
cosa si le hace falta a Emiliano y en cuanto tenga un rato subo un
ejemplito de una configuración de VirtualHost con esto.

El script se puede correr desde consola, este es un ejemplo donde la
validación fue OK:
marcelo en jupiter:~/src/py_https$ python https_auth_handler.py
miservidor.ssl 443 key_file.pkey cert_file.cert CA_file.cert
200 OK
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="es">
  <head>
    <meta name="ROBOTS" content="NOINDEX, NOFOLLOW"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Pagina SSL</title>
    <link rel="stylesheet" title="Default" type="text/css"
href="css/default.css">
    <link rel="alternate stylesheet" title="Debug" type="text/css"
href="css/debug.css">
  </head>
  <body>
  <h1>Pagina SSL</h1>
  </body>
</html>

Y este es un caso de Error:
marcelo en jupiter:~/src/py_https$ python https_auth_handler.py
miservidor.ssl 443 key_file.pkey cert_file.cert CA_file.cert
Traceback (most recent call last):
  File "https_auth.py", line 8, in <module>
    conn.request('GET', '/')
  File "/usr/lib/python2.6/httplib.py", line 914, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python2.6/httplib.py", line 951, in _send_request
    self.endheaders()
  File "/usr/lib/python2.6/httplib.py", line 908, in endheaders
    self._send_output()
  File "/usr/lib/python2.6/httplib.py", line 780, in _send_output
    self.send(msg)
  File "/usr/lib/python2.6/httplib.py", line 739, in send
    self.connect()
  File "/home/marcelo/src/py_https/https_auth_handler.py", line 31, in connect
    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
ca_certs=self.ca_file, cert_reqs=ssl.CERT_REQUIRED)
  File "/usr/lib/python2.6/ssl.py", line 338, in wrap_socket
    suppress_ragged_eofs=suppress_ragged_eofs)
  File "/usr/lib/python2.6/ssl.py", line 120, in __init__
    self.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 279, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:490: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Otro cantar es usar esto con urllib2, que tiene ventajas como el uso
automágico de cookies. Yo creé un bug al respecto [1], y postié ahí un
ejemplo de cómo "saltear" esa limitación (con una clase parecida pero
más básica que la del script anterior, que no valida desde el
cliente).

[1] http://bugs.python.org/issue3466

Por suerte en 3.2 esto parece que cambia y se soluciona, según
comentaron en el bug.

Espero que sirva,

Saludos
-- 
Marcelo F. Fernández
Buenos Aires, Argentina
Licenciado en Sistemas - CCNA

E-Mail: marcelo.fidel.fernandez en gmail.com
Blog: http://blog.marcelofernandez.info
Twitter: http://twitter.com/fidelfernandez



More information about the pyar mailing list