SSL_read empty -> close?
Michael Wojcik
Michael.Wojcik at microfocus.com
Wed Oct 26 17:34:07 UTC 2022
> From: openssl-users <openssl-users-bounces at openssl.org> On Behalf Of Felipe
> Gasper
> Sent: Wednesday, 26 October, 2022 11:15
>
> I’m seeing that OpenSSL 3, when it reads empty on a socket, sends some
> sort of response, e.g.:
>
> ----- before read
> [pid 42417] read(7<UNIX:[276782->276781]>, "", 5) = 0
> [pid 42417] sendmsg(7<UNIX:[276782->276781]>, {msg_name=NULL, msg_namelen=0,
> msg_iov=[{iov_base="\0022", iov_len=2}], msg_iovlen=1,
> msg_control=[{cmsg_len=17, cmsg_level=SOL_TLS, cmsg_type=0x1}],
> msg_controllen=17, msg_flags=0}, 0) = -1 EPIPE (Broken pipe)
> ----- after read
>
> What is that being sent after the read()? Is there a way to disable
> it?
I'd guess it's a TLS Alert Close_notify.
When read/recv on a TCP stream socket returns 0, it means a TCP FIN has been received from the peer (or possibly some interfering middleman, such as a firewall). This indicates the peer will no longer be sending any application data, only at most ACKs and perhaps a RST if conversation does not go quietly into that good night. Since TLS requires bidirectional communications, that means the TLS conversation is effectively open, and the local end needs to be closed; and TLS requires sending a close_notify so the peer knows the conversation has not been truncated.
Now, the most common cause of a FIN is the peer calling close(), which means it can't receive that close_notify. But TCP supports half-close, and the peer *could have* called shutdown(, SD_SEND), indicating that it was done sending but still wanted to be able to receive data. So the local side has no way of knowing, at the point where it gets a 0 from read(), that the peer definitely can't see the close_notify; and thus it's still obligated by the TLS specification (I believe) to send it.
At any rate, that's my understanding of the requirement for sending close_notify - I haven't confirmed that in the RFC - and what I suspect OpenSSL is doing there. I could well be wrong.
If the peer *has* called close, then EPIPE is what you'd expect. Note that on UNIXy systems this means you should have set the disposition of SIGPIPE to SIG_IGN to avoid being signaled, but all well-written UNIX programs should do that anyway. (SIGPIPE, as Dennis Ritchie noted many years ago, was always intended as a failsafe for poorly-written programs that fail to check for errors when writing.)
--
Michael Wojcik
More information about the openssl-users
mailing list