Solución:
¿Y cuál es la diferencia entre SSL_get_error y ERR_get_error?
Hay dos partes lógicas en OpenSSL. Primero está la biblioteca SSL, libssl.a
(y libssl.so
), e incluye el material relacionado con la comunicación. En segundo lugar está la biblioteca de criptografía, libcrypto.a
(y libcrypto.so
), e incluye números grandes, configuración, entrada / salida, etc.
libssl.a
depende de libcrypto.a
, y es por eso que el comando de enlace se ordena como -lssl -lcrypto
.
Tu usas SSL_get_error
para recuperar la mayoría de los errores de la biblioteca de porciones SSL, y usa ERR_get_error
para recuperar errores que no están en la parte SSL de la biblioteca.
¿Es esta la forma correcta de manejar errores en OpenSSL?
El código que mostró está más cerca de “cómo se apaga un socket SSL”. En última instancia, los giros controlan dos casos. Primero es una conexión semiabierta, cuando el cliente se apaga sin enviar el mensaje de notificación de cierre. El segundo es el comportamiento de su programa al enviar el mensaje de notificación de cierre.
Es difícil responder “¿es correcto?” Porque no conocemos el comportamiento que desea. Si no le importa si se envía la notificación de cierre, creo que solo necesita llamar SSL_shutdown
una vez, independientemente de lo que haga el cliente.
SSL_get_error:
SSL_get_error () devuelve un código de resultado (adecuado para la instrucción “switch” de C) para una llamada anterior a SSL_connect (), SSL_accept (), SSL_do_handshake (), SSL_read (), SSL_peek () o SSL_write () en ssl. El valor devuelto por esa función de E / S TLS / SSL debe pasarse a SSL_get_error () en el parámetro ret.
ERR_get_error:
ERR_get_error () devuelve el código de error más antiguo de la cola de errores del hilo y elimina la entrada. Esta función se puede llamar repetidamente hasta que no haya más códigos de error para devolver.
Entonces, este último es para un uso más general y no deben usarse juntos, porque:
La cola de errores del hilo actual debe estar vacía antes de que se intente la operación de E / S TLS / SSL, o SSL_get_error () no funcionará de manera confiable.
Por lo tanto, debe leer todos los errores usando ERR_get_error y manejarlos (o ignorarlos eliminándolos como lo hizo en su ejemplo de código con ERR_clear_error
) y luego realice la operación IO. Su enfoque parece ser correcto, aunque no puedo verificar todos los aspectos por mí mismo en este momento.
Consulte esta respuesta y esta publicación para obtener más información.
EDITAR: de acuerdo con este tutorial, las rutinas BIO_ pueden generar un error y afectar la cola de errores:
El tercer campo es el nombre del paquete que generó el error, como “Rutinas BIO” o “rutinas bignum”.