c++ - s_client - openssl softpedia
Manejando SSL_shutdown correctamente (1)
openssl
es un poco de arte oscuro.
En primer lugar, la página a la que hizo referencia tiene HTML-ified los valores de retorno mal. Esto es lo que dice la página de manual:
RETURN VALUES
The following return values can occur:
0 The shutdown is not yet finished. Call SSL_shutdown() for a second
time, if a bidirectional shutdown shall be performed. The output
of SSL_get_error(3) may be misleading, as an erroneous
SSL_ERROR_SYSCALL may be flagged even though no error occurred.
1 The shutdown was successfully completed. The "close notify" alert
was sent and the peer''s "close notify" alert was received.
-1 The shutdown was not successful because a fatal error occurred
either at the protocol level or a connection failure occurred. It
can also occur if action is need to continue the operation for non-
blocking BIOs. Call SSL_get_error(3) with the return value ret to
find out the reason.
Si tiene bloqueo de BIO, las cosas son relativamente simples. Un 0 en la primera llamada significa que debe volver a llamar a SSL_shutdown
si desea un apagado bidireccional. A 1 significa que has terminado. A -1 significa un error. En la segunda llamada (que solo haces si tienes un 0 de vuelta), se inicia un cierre bidireccional. La lógica dicta que no puede volver a obtener un 0 (porque es un BIO de bloqueo y habrá completado el primer paso). A -1 indica un error, y un 1 indica que se ha completado.
Si tiene BIO sin bloqueo, aplica lo mismo, excepto por el hecho de que necesita pasar por todo el SSL_ERROR_WANT_READ
y SSL_ERROR_WANT_WRITE
, es decir:
If the underlying BIO is non-blocking, SSL_shutdown() will also return
when the underlying BIO could not satisfy the needs of SSL_shutdown()
to continue the handshake. In this case a call to SSL_get_error() with
the return value of SSL_shutdown() will yield SSL_ERROR_WANT_READ or
SSL_ERROR_WANT_WRITE. The calling process then must repeat the call
after taking appropriate action to satisfy the needs of SSL_shutdown().
The action depends on the underlying BIO. When using a non-blocking
socket, nothing is to be done, but select() can be used to check for
the required condition. When using a buffering BIO, like a BIO pair,
data must be written into or retrieved out of the BIO before being able
to continue.
Entonces tienes dos niveles de repetición. Llama a SSL_shutdown
la ''primera'' vez, pero repita si obtiene SSL_ERROR_WANT_READ
o SSL_ERROR_WANT_WRITE
después de recorrer el ciclo select()
de la manera normal, y solo cuente el ''primer'' SSL_shutdown
como hecho si obtiene un código de error SSL_ERROR_WANT_
(en el cual caso de que fallara), o usted obtiene un retorno de 0
o 1
. Si obtienes 1
devolución, lo has hecho. Si obtiene un retorno de 0
, y desea un cierre bidireccional, entonces tiene que hacer la segunda llamada, en la que nuevamente deberá verificar SSL_ERROR_WANT_READ
o SSL_ERROR_WANT_WRITE
y volver a intentar seleccionar; eso no debería devolver 1
, pero puede devolver 0 o un error.
No es simple.
La documentación de openssl en SSL_shutdown establece que: Por lo tanto, se recomienda verificar el valor de retorno de SSL_shutdown () y volver a llamar a SSL_shutdown (), si el cierre bidireccional aún no se ha completado (el valor de retorno de la primera llamada es 0).
https://www.openssl.org/docs/ssl/SSL_shutdown.html
Tengo un fragmento de código a continuación donde compruebo el valor de retorno 0 de SSL_shutdown y llamo de nuevo, que he estado usando. Mi pregunta es, ¿está bien ignorar el valor de retorno de SSL_shutdown en la segunda llamada o deberíamos seguir intentando de nuevo SSL_shutdown hasta que se devuelva 1 (cierre bidireccional completo).
int r = SSL_shutdown(ssl);
//error handling here if r < 0
if(!r)
{
shutdown(fd,1);
SSL_shutdown(ssl); //how should I handle return value and error handling here is it required??
}
SSL_free(ssl);
SSLMap.erase(fd);
shutdown(fd,2);
close(fd);