From 8e593f0a0dbcb3193548ced3c2e78fbbd201b2db Mon Sep 17 00:00:00 2001 From: Kurt Roeckx Date: Tue, 11 Sep 2018 23:39:25 +0200 Subject: [PATCH] Improve SSL_shutdown() documentation Reviewed-by: Ben Kaduk GH: #7188 --- doc/man3/SSL_CTX_set_quiet_shutdown.pod | 4 +- doc/man3/SSL_get_error.pod | 2 +- doc/man3/SSL_set_shutdown.pod | 8 +-- doc/man3/SSL_shutdown.pod | 78 ++++++++++++++----------- 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/doc/man3/SSL_CTX_set_quiet_shutdown.pod b/doc/man3/SSL_CTX_set_quiet_shutdown.pod index 99922eb5bf..d3e6d9ff0e 100644 --- a/doc/man3/SSL_CTX_set_quiet_shutdown.pod +++ b/doc/man3/SSL_CTX_set_quiet_shutdown.pod @@ -33,7 +33,7 @@ SSL_get_quiet_shutdown() returns the "quiet shutdown" setting of B. =head1 NOTES Normally when a SSL connection is finished, the parties must send out -"close notify" alert messages using L +close_notify alert messages using L for a clean shutdown. When setting the "quiet shutdown" flag to 1, L @@ -41,7 +41,7 @@ will set the internal flags to SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN. (L then behaves like L called with SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN.) -The session is thus considered to be shutdown, but no "close notify" alert +The session is thus considered to be shutdown, but no close_notify alert is sent to the peer. This behaviour violates the TLS standard. The default is normal shutdown behaviour as described by the TLS standard. diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod index 01446a24a1..b3ab505687 100644 --- a/doc/man3/SSL_get_error.pod +++ b/doc/man3/SSL_get_error.pod @@ -39,7 +39,7 @@ if and only if B 0>. =item SSL_ERROR_ZERO_RETURN The TLS/SSL peer has closed the connection for writing by sending the -"close notify" alert. +close_notify alert. No more data can be read. Note that B does not necessarily indicate that the underlying transport has been closed. diff --git a/doc/man3/SSL_set_shutdown.pod b/doc/man3/SSL_set_shutdown.pod index 04bcc47814..7010807952 100644 --- a/doc/man3/SSL_set_shutdown.pod +++ b/doc/man3/SSL_set_shutdown.pod @@ -30,12 +30,12 @@ No shutdown setting, yet. =item SSL_SENT_SHUTDOWN -A "close notify" shutdown alert was sent to the peer, the connection is being +A close_notify shutdown alert was sent to the peer, the connection is being considered closed and the session is closed and correct. =item SSL_RECEIVED_SHUTDOWN -A shutdown alert was received form the peer, either a normal "close notify" +A shutdown alert was received form the peer, either a normal close_notify or a fatal error. =back @@ -47,13 +47,13 @@ the ssl session. If the session is still open, when L or L is called, it is considered bad and removed according to RFC2246. The actual condition for a correctly closed session is SSL_SENT_SHUTDOWN -(according to the TLS RFC, it is acceptable to only send the "close notify" +(according to the TLS RFC, it is acceptable to only send the close_notify alert but to not wait for the peer's answer, when the underlying connection is closed). SSL_set_shutdown() can be used to set this state without sending a close alert to the peer (see L). -If a "close notify" was received, SSL_RECEIVED_SHUTDOWN will be set, +If a close_notify was received, SSL_RECEIVED_SHUTDOWN will be set, for setting SSL_SENT_SHUTDOWN the application must however still call L or SSL_set_shutdown() itself. diff --git a/doc/man3/SSL_shutdown.pod b/doc/man3/SSL_shutdown.pod index 453853d672..0a3d6d370d 100644 --- a/doc/man3/SSL_shutdown.pod +++ b/doc/man3/SSL_shutdown.pod @@ -13,27 +13,36 @@ SSL_shutdown - shut down a TLS/SSL connection =head1 DESCRIPTION SSL_shutdown() shuts down an active TLS/SSL connection. It sends the -"close notify" shutdown alert to the peer. +close_notify shutdown alert to the peer. =head1 NOTES -SSL_shutdown() tries to send the "close notify" shutdown alert to the peer. +SSL_shutdown() tries to send the close_notify shutdown alert to the peer. Whether the operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set and a currently open session is considered closed and good and will be kept in the session cache for further reuse. -The shutdown procedure consists of 2 steps: the sending of the "close notify" -shutdown alert and the reception of the peer's "close notify" shutdown -alert. According to the TLS standard, it is acceptable for an application -to only send its shutdown alert and then close the underlying connection -without waiting for the peer's response (this way resources can be saved, -as the process can already terminate or serve another connection). -When the underlying connection shall be used for more communications, the -complete shutdown procedure (bidirectional "close notify" alerts) must be -performed, so that the peers stay synchronized. +The shutdown procedure consists of two steps: sending of the close_notify +shutdown alert, and reception of the peer's close_notify shutdown alert. +The order of those two steps depends on the application. + +It is acceptable for an application to only send its shutdown alert and +then close the underlying connection without waiting for the peer's response. +This way resources can be saved, as the process can already terminate or +serve another connection. +This should only be done when it is known that the other side will not send more +data, otherwise there is a risk of a truncation attack. -SSL_shutdown() supports both uni- and bidirectional shutdown by its 2 step -behaviour. +When a client only writes and never reads from the connection, and the server +has sent a session ticket to establish a session, the client might not be able +to resume the session because it did not received and process the session ticket +from the server. +In case the application wants to be able to resume the session, it is recommended to +do a complete shutdown procedure (bidirectional close_notify alerts). + +When the underlying connection shall be used for more communications, the +complete shutdown procedure must be performed, so that the peers stay +synchronized. SSL_shutdown() only closes the write direction. It is not possible to call SSL_write() after calling SSL_shutdown(). @@ -41,45 +50,43 @@ The read direction is closed by the peer. =head2 First to close the connection -When the application is the first party to send the "close notify" +When the application is the first party to send the close_notify alert, SSL_shutdown() will only send the alert and then set the SSL_SENT_SHUTDOWN flag (so that the session is considered good and will be kept in the cache). -SSL_shutdown() will then return with 0. +If successful, SSL_shutdown() will return 0. + If a unidirectional shutdown is enough (the underlying connection shall be -closed anyway), this first call to SSL_shutdown() is sufficient. +closed anyway), this first successful call to SSL_shutdown() is sufficient. In order to complete the bidirectional shutdown handshake, the peer needs -to send back a "close notify" alert. +to send back a close_notify alert. The SSL_RECEIVED_SHUTDOWN flag will be set after receiving and processing it. -SSL_shutdown() will return 1 when it has been received. -The peer is still allowed to send data after receiving the "close notify" +The peer is still allowed to send data after receiving the close_notify event. -If the peer did send data it needs to be processed by calling SSL_read() -before calling SSL_shutdown() a second time. +When it is done sending data, it will send the close_notify alert. +SSL_read() should be called until all data is received. SSL_read() will indicate the end of the peer data by returning <= 0 and SSL_get_error() returning SSL_ERROR_ZERO_RETURN. -It is recommended to call SSL_read() between SSL_shutdown() calls. =head2 Peer closes the connection -If the peer already sent the "close notify" alert B it was +If the peer already sent the close_notify alert B it was already processed implicitly inside another function (L), the SSL_RECEIVED_SHUTDOWN flag is set. SSL_read() will return <= 0 in that case, and SSL_get_error() will return SSL_ERROR_ZERO_RETURN. -SSL_shutdown() will send the "close notify" alert, set the SSL_SENT_SHUTDOWN -flag and will immediately return with 1. +SSL_shutdown() will send the close_notify alert, set the SSL_SENT_SHUTDOWN +flag. +If successful, SSL_shutdown() will return 1. + Whether SSL_RECEIVED_SHUTDOWN is already set can be checked using the SSL_get_shutdown() (see also L call. =head1 NOTES -It is recommended to do a bidirectional shutdown by checking the return value -of SSL_shutdown() and call it again until it returns 1 or a fatal error. - The behaviour of SSL_shutdown() additionally depends on the underlying BIO. If the underlying BIO is B, SSL_shutdown() will only return once the handshake step has been finished or an error occurred. @@ -95,8 +102,13 @@ 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. +After SSL_shutdown() returned 0, it is possible to call SSL_shutdown() again +to wait for the peer's close_notify alert. +SSL_shutdown() will return 1 in that case. +However, it is recommended to wait for it using SSL_read() instead. + SSL_shutdown() can be modified to only set the connection to "shutdown" -state but not actually send the "close notify" alert messages, +state but not actually send the close_notify alert messages, see L. When "quiet shutdown" is enabled, SSL_shutdown() will always succeed and return 1. @@ -109,16 +121,16 @@ The following return values can occur: =item Z<>0 -The shutdown is not yet finished: the "close notify" was send but the peer +The shutdown is not yet finished: the close_notify was sent but the peer did not send it back yet. -Call SSL_shutdown() again to do a bidirectional shutdown. +Call SSL_read() to do a bidirectional shutdown. The output of L may be misleading, as an erroneous SSL_ERROR_SYSCALL may be flagged even though no error occurred. =item Z<>1 -The shutdown was successfully completed. The "close notify" alert was sent -and the peer's "close notify" alert was received. +The shutdown was successfully completed. The close_notify alert was sent +and the peer's close_notify alert was received. =item E0 -- 2.25.1