Proper SSL_shutdown handling

The openssl documentation on SSL_shutdown states that: Therefore, it is recommended that you check the return value of SSL_shutdown () and call SSL_shutdown () again if bidirectional shutdown has not yet completed (the return value of the first call is 0).

https://www.openssl.org/docs/ssl/SSL_shutdown.html

I have a code snippet below where I check for the return value 0 from SSL_shutdown and call it again, which I used. My question is whether it is correct to ignore the return value of SSL_shutdown in the second call, or should we continue to retry SSL_shutdown until 1 is returned (bidirectional termination).

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); 
+9
c ++ c openssl
source share
1 answer

openssl bit of dark art.

First, the page you linked to did not return HTML return values โ€‹โ€‹well. This is what the manual page actually says:

  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 "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. 

If you have blocking BIOs, everything is relatively simple. "0" on the first call means you need to re-call SSL_shutdown if you want to completely disable two-way communication. In essence, this means that you sent a close_notify warning, but you have not received it yet). 1 means that you previously received a close_notify warning from another partner, and you are completely done. -1 means fatal error. The second call (which you only make if you returned 0) then triggers a bi-directional disconnect (that is, now wait on the other side for them to send you their warning "close_notify"). Logic tells you that you cannot return 0 again (because it is a blocking BIO and the first step will be performed). -1 indicates an error, and 1 indicates success.

If you have non-blocking BIOs, the same return values โ€‹โ€‹are applied, โ€œpossibly 0 and then 1โ€, except for the fact that you also need to go through the entire SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE , i.e.

  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. 

So you have two levels of repetition. You call SSL_shutdown "first" time, but repeat if you get SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE after SSL_ERROR_WANT_WRITE around the select() loop in the usual way, and consider the "first" SSL_shutdown to complete if you get an error code other than SSL_ERROR_WANT_ (in this case, a failure ), or you will receive a refund of 0 or 1 . If you received a refund of 1 , you are done. If you get a return of 0 and want a bi-directional disconnect, then you need to make a second call, after which you will again need to check SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE and repeat the selection; this should not return 1 , but may return 0 or an error.

Not easy.

A couple of additional notes from the documents : after calling SSL_Shutdown and getting "0" back for the first time, you can additionally call SSL_Read instead of SSL_Shutdown (in case the host still sends you any data on this SSL socket) and, I suppose, I โ€œhopeโ€ that they will eventually send you a message on their part to clear the pipes.

Also, if you plan to close the socket after completion of the operation "anyway", you can completely skip the second SSL_Shutdown call ("1" from "0, then 1") and just go ahead and close the socket, the kernel should take care to cancel "now ignored "close_notify alerts that they should be sent ...

+12
source share

All Articles