[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#4940) libldap doesn't wait for server's TLS close_notify



Full_Name: Philip Guenther
Version: 2.3.27
OS: Linux and Solaris
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (64.58.1.252)


[I vaguely recall seeing a report of this issue in the archives of one of the
mailing lists, but I can no longer find the original.]

If you trace the packets sent when you use, for example, ldapsearch against a
server on a different host, using either the -Z option to do TLS or using an
ldaps URI, you'll discover that the TCP connection is actually reset instead of
being closed cleanly: the client sends TCP RSTs in response to the server's
final packets.

This is because libldap uses the following sequence when unbind a TLS or SSL
connection:
1) send the unbind request (over the TLS or SSL layer)
2) call SSL_shutdown(), sending the TLS close_notify alert
3) call close()

After receiving the close_notify alert from step (2), the server sends back its
own close_notify alert and then calls close().  However, because the client
didn't wait for the server's response before calling close() on its end, the
client's TCP stack considers the TCP connection to already be gone and responds
with the RST packets.  This occurs with Linux and Solaris clients and probably
most other unices: the response to packets after a close() doesn't vary in my
experience.

There are a number of ways this can be handled:
1) change the client to wait until it sees the server's close_notify alert by
   replacing "SSL_shutdown( p->ssl );" in tls.c with the two lines:
        if (SSL_shutdown( p->ssl ) == 0)
            SSL_shutdown( p->ssl );
   (I have confirmed that this works.  As documented, the first call will return
1
   if the server's close_notify has already been received, if not, the second
call
   will block until it is received.)

2) change the client to not bother to send a close_notify alert when it's just
   going to close() the connection; change the server to not send a
close_notify
   if it didn't get one.  This probably violates the TLS spec, but the fact
that
   TLS/1.1 permits resumption of sessions without close_notify having been sent
   indicates that the violation is not a major issue, particularly given that
LDAP's
   unbind request prevents truncation attacks.  Close_notifies are, of course,
   required if the client just wants to terminate the TLS layer and resume
   unprotected LDAP operations.

3) ignore the issue: it only causes one or two extra packets to be sent.  While
it
   also eliminates the TIME_WAIT state, LDAP's application-level close (the
unbind
   request) means it doesn't need reliable full-duplex closure, so the only
concern
   would be random connection issues from reincarnations of the TCP tuple,
which
   is unlikely for an LDAP connection.


Personally, I like the simplicity and cleanliness of solution (1).