2012-03-07 14 views
5

El problema:¿El módulo ssl de python valida correctamente los certificados? (Tengo un ejemplo raro, que me molesta)

módulo SSL de Python no se queja de un certificado, aunque la entidad emisora ​​no se proporciona en el archivo cacert.pem (caso de prueba 2. abajo). Yo uso CA extraídas de Mozilla. Firefox se queja correctamente sobre la CA desconocida (en este caso, el Departamento de Defensa).

Parece que solo el certificado en sí está validado, no es que se conozca la CA. Estoy ejecutando Python 2.7.1 y usando la versión de ssl OpenSSL 0.9.8r.

los casos de prueba:

Consulte los sitios siguientes en Firefox y con el ejemplo de abajo cliente Python.

  1. https://www.verisign.com - debería funcionar, CA se sabe
  2. https://www.us.army.mil - no debe trabajar, como CA no se conoce
  3. https://www.pcwebshop.co.uk - no debe trabajar, sólo el certificado de Parallels Panel

Caso 2. es validado por el cliente de python aunque no debería.

Caso 3. lanza una excepción como se esperaba:

routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed 

El Cliente Ejemplo de Python:

archivo de CA: http://curl.haxx.se/ca/cacert.pem (por defecto de Mozilla CA por mantenedores de rizo).

versión ligeramente modificada del http://docs.python.org/library/ssl.html#client-side-operation:

# test_ssl.py 
import socket, ssl, pprint, sys 
host = sys.argv[1] 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

# require a certificate from the server 
ssl_sock = ssl.wrap_socket(s, 
          # http://curl.haxx.se/ca/cacert.pem 
          ca_certs="cacert.pem", 
          cert_reqs=ssl.CERT_REQUIRED) 

ssl_sock.connect((host, 443)) 

print repr(ssl_sock.getpeername()) 
print ssl_sock.cipher() 
print pprint.pformat(ssl_sock.getpeercert()) 

# Set a simple HTTP request -- use httplib in actual code. 
ssl_sock.write("""GET/HTTP/1.0\r 
Host: """ + host + """\r\n\r\n""") 

# Read a chunk of data. Will not necessarily 
# read all the data returned by the server. 
data = ssl_sock.read() 
print data 

# note that closing the SSLSocket will also close the underlying socket 
ssl_sock.close() 

Uso:

python test_ssl.py www.verisign.com 
python test_ssl.py www.us.army.mil 
python test_ssl.py www.pcwebshop.co.uk 

ACTUALIZACIÓN:

Con la ayuda de strcat y otros que podría confirmar este comportamiento es específico para:

  • OSX Lion 10.7.1
  • Python 2.7.1 Python 2.6.7 &
  • OpenSSL 0.9.8r 8 Feb 2011

he probado en dos Macs y varias otras cajas. Tengo la sospecha de que OpenSSL en mac usa una segunda fuente de certificados de CA junto al archivo que le paso. Tal vez esto hace de www.us.army.mil un caso de prueba especial, ya que safari parece confiar en él también de manera automática. ¿Alguien conoce otros sitios grandes autofirmados o cómo funciona openssl en mac?

+0

¿qué versión de python estás probando? – strcat

+0

Python 2.7.1 (r271: 86832, 16 de junio de 2011, 16:59:05) – snies

+0

ssl.OPENSSL_VERSION == 'OpenSSL 0.9.8r 8 feb 2011' – snies

Respuesta

0

La solución es:

A través de pruebas que pude confirmar, que en OSX openssl hace utilizar el almacén de certificados sistema de CA, incluso si no se especifica como se ve en el ejemplo anterior pitón.

Utilicé www.us.army.mil como un caso de prueba, ya que se sabe que es un sitio autofirmado (http://royal.pingdom.com/2008/08/19/new-ssl-policy-in -firefox-hurting-decenas-de-miles-de-sitios /). Como resultado, los certificados de CA del sistema en OSX contienen dos certificados de DoD y, por lo tanto, Safari no se queja, y también mi cliente de prueba de Python.

Si i UNTRUST estos certificados en Keychan de acceso -> Las raíces del sistema -> Certificados el cliente Python muestra el comportamiento esperado, lo que confirma que ssl pitón/OpenSSL utiliza los certificados raíz en el sistema OSX 10.7.1 si se especifica o no . No sé si este es el comportamiento esperado, pero seguro que me sorprendió.

Cuestiones relacionadas