2010-02-13 22 views
9

Estoy escribiendo un pequeño programa con la biblioteca OpenSSL que se supone debe establecer una conexión con un servidor SSLv3. Este servidor dispensa un certificado autofirmado, lo que hace que el saludo de mano falle con este mensaje: "error de handshake de alerta de sslv3, certificado autofirmado en la cadena de certificados".OpenSSL Ignorar error de certificado autofirmado

¿Hay alguna manera de forzar la conexión para continuar? He intentado llamar SSL_CTX_set_verify así:

SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 

Pero no parece que cambiar nada.

¿Alguna sugerencia?

+0

'SSL_VERIFY_NONE' desactiva la verificación del certificado del todo. Probablemente no quieras hacer esto ya que esto te deja vulnerable a los ataques MITM. Lo correcto es agregar el certificado autofirmado a la lista de certificados de confianza. (Consulte SSL_CTX_load_verify_locations().) –

+0

Por cierto, el mensaje de error no significa que el certificado del servidor esté autofirmado. Significa que no confía en el certificado de CA raíz: ** X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ​​** _ Existe un certificado autofirmado en la cadena de certificados. La cadena de certificados se puede construir usando los certificados que no son de confianza, pero la CA raíz no se pudo encontrar localmente. Los certificados de CA raíz siempre están autofirmados. –

Respuesta

4

Por defecto OpenSSL camina la cadena de certificados y trata de verificar en cada paso, SSL_set_verify() no cambia eso, ver Tha hombre página. Citando que: se realiza

El procedimiento de verificación real, ya sea usando el incorporado procedimiento de comprobación o utilizando otro función de verificación de solicitud previsto establecer con SSL_CTX_set_cert_verify_callback (3).

Así que la solución es crear una devolución de llamada simple y establecer que uno, por lo que se anula toda la cadena de certificados a pie:

static int always_true_callback(X509_STORE_CTX *ctx, void *arg) 
{ 
    return 1; 
} 

SSL_CTX_set_cert_verify_callback(CTX, always_true_callback); 
+2

Apenas unos pocos párrafos debajo del texto citado: 'Si no se especifica verify_callback, se usará la devolución de llamada predeterminada. Su valor de retorno es idéntico a preverify_ok, por lo que cualquier falla de verificación dará lugar a la terminación del protocolo de enlace TLS/SSL con un mensaje de alerta, si SSL_VERIFY_PEER está configurado. Su respuesta es incorrecta, establecer el modo de verificación SSL_VERIFY_NONE debería ser suficiente . – Spidey

+1

@Spidey ¿Leyó la pregunta? Se da porque SSL_VERIFY_NONE es * no * suficiente. ¿Lo intentaste tú mismo? FYI el manual que citó es para 'SSL_CTX_set_verify()'. Pero la verificación puede fallar de muchas maneras más, incluso si la devolución de llamada * set_verify * siempre tiene éxito, es por eso que debe establecer la devolución de llamada más genérica con 'SSL_CTX_set_cert_verify_callback()'. – jimis

+0

Siempre devolviendo '1' deshabilita la verificación del certificado por completo. Esto es lo mismo que establecer 'SSL_VERIFY_NONE'. (es decir, @Spidey tiene razón.) Probablemente no quiera hacer esto ya que esto lo hace vulnerable a los ataques de MITM. Lo correcto es agregar el certificado autofirmado a la lista de certificados de confianza. (Ver SSL_CTX_load_verify_locations()) –

0

¿Ha intentado configurar SSL_set_verify?

SSL_set_verify(s, SSL_VERIFY_NONE, NULL); 
+0

Probado, sin cambios – Ramsey

+0

Más código estaría bien en este punto. – Xorlev

+0

Gracias por las respuestas. He intentado todas sus sugerencias y todavía no tuve suerte. He pegado partes clave del programa aquí: http://pastebin.com/m78497bf3 – Ramsey

2

¿Ha intentado dejar su aplicación certificado de CA del servidor para que su aplicación puede verificar la cadena de certificados?

+0

Correcto, aunque en este caso el servidor usa una autocomprobación. certificado firmado, en lo que el OP debe hacer que confíe su aplicación no es un certificado CA, sino el certificado del servidor. –

+0

Malo, el OP es incorrecto. El certificado del servidor no está autofirmado. El mensaje de error incluido en la pregunta muestra que el error es 'X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN', lo que significa que el certificado autofirmado mencionado no es el certificado del servidor, sino el certificado de una CA raíz. –

0

Puede probar pasando su propia devolución de llamada al SSL_set_verify() y luego hacer su propia verificación. No es ideal ya que creo que debes hacer toda la verificación y luego permitir que se ignore el error autofirmado, pero deberías ser capaz de determinar qué hace el código de verificación estándar desde la fuente OpenSSL y luego simplemente extraerlo en su propia verificación de devolución de llamada y permitir que el código de error específico ...

+0

Si va a aceptar certificados autofirmados, el resto de los pasos de verificación no tienen sentido de todos modos. – caf

+0

caf - potencialmente, sí ... –

2

comprobar estos ejemplos de OpenSSL: http://www.rtfm.com/openssl-examples/

el wclient.c conecta a cualquier página https, por ejemplo:

wclient -h www.yahoo.com -p 443 

Si ejecuta eso con la instalación predeterminada, obtendrá un error de certificado (aunque puede usar el distintivo -i para omitir la comprobación del certificado).

para verificar el certificado, tendrá que descargar los certificados CA (Verisign, Thawte, Equifax, etc), por lo que Google este archivo cacert.pem, descarga y cambie su nombre por root.pem y Podré conectarme a un servidor web y validar su certificado.

+0

Además, si desea imprimir el certificado, inserte esta línea (en wclient.c) después de check_cert (ssl, host): X509_print_fp (stdout, SSL_get_peer_certificate (ssl)); –

+0

Correcto, aunque en este caso el servidor usa un certificado autofirmado, lo que el OP debe hacer para que su aplicación no sea un certificado CA, sino un certificado del servidor. –

+0

Malo, el OP es incorrecto. El certificado del servidor no está autofirmado. El mensaje de error incluido en la pregunta muestra que el error es 'X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN', lo que significa que el certificado autofirmado mencionado no es el certificado del servidor, sino el certificado de una CA raíz. –

0

Mi código de cliente de muestra (link) funciona bien con el certificado de servidor autofirmado. Tengo el siguiente código después de SSL_CONNECT y tener un control total sobre la auto firmado los certificados de aceptación de mi cliente

SSL_CTX* ctx = SSL_CTX_new(SSLv3_method()); 

// TCP connection and SSL handshake ... 

/* Check the certificate */ 

rc = SSL_get_verify_result(ssl); 
if(rc != X509_V_OK) { 
    if (rc == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || rc == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) { 
    fprintf(stderr, "self signed certificate\n"); 
    } 
    else { 
    fprintf(stderr, "Certificate verification error: %ld\n", SSL_get_verify_result(ssl)); 
    SSL_CTX_free(ctx); 
    return 0; 
    } 
} 
+0

¡Esto lo deja vulnerable a los ataques de MITM! Cualquier certificado autofirmado se acepta si haces esto. Los errores que ignora no se generan si el certificado es de confianza. Lo correcto es agregar el certificado autofirmado a la lista de certificados de confianza. (Consulte SSL_CTX_load_verify_locations().) –

Cuestiones relacionadas