Issue 8047 - TIMEOUT and NETWORK_TIMEOUT don't work properly with SSL
Summary: TIMEOUT and NETWORK_TIMEOUT don't work properly with SSL
Status: UNCONFIRMED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: 2.4.40
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
: 8581 9320 9607 (view as issue list)
Depends on:
Blocks:
 
Reported: 2015-02-03 08:38 UTC by jsynacek@redhat.com
Modified: 2023-11-02 17:01 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description jsynacek@redhat.com 2015-02-03 08:38:36 UTC
Full_Name: Jan Synacek
Version: 2.4.40
OS: GNU/Linux
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (213.175.37.10)


TIMEOUT and NETWORK_TIMEOUT are not applied when trying to connect to a stalled
server using SSL. The same scenario works when using an unencrypted connection.

Reproducer:
1) set up a server for use with SSL (localhost connection is enough)
2) set NETWORK_TIMEOUT and TIMEOUT in ldap.conf
3) slapd -u ldap -g ldap -h "ldapi:/// ldaps://localhost" -d1
4) verify that connection works
   ldapsearch -x -H ldaps://localhost
5) kill -STOP <server pid>
6) ldapsearch -x -H ldaps://localhost
   At this point, the client hangs and doesn't properly time out.

For more information including a packet capture, see the original bug report:
https://bugzilla.redhat.com/show_bug.cgi?id=1186562#c4

This bug doesn't seem to be crypto library specific. I reproduced it with both
moznss and openssl. 
Comment 1 Howard Chu 2015-02-03 08:50:47 UTC
jsynacek@redhat.com wrote:
> Full_Name: Jan Synacek
> Version: 2.4.40
> OS: GNU/Linux
> URL: ftp://ftp.openldap.org/incoming/
> Submission from: (NULL) (213.175.37.10)
>
>
> TIMEOUT and NETWORK_TIMEOUT are not applied when trying to connect to a stalled
> server using SSL. The same scenario works when using an unencrypted connection.

This is a known issue - we don't have async connect/handshake APIs for 
these crypto libraries.
>
> Reproducer:
> 1) set up a server for use with SSL (localhost connection is enough)
> 2) set NETWORK_TIMEOUT and TIMEOUT in ldap.conf
> 3) slapd -u ldap -g ldap -h "ldapi:/// ldaps://localhost" -d1
> 4) verify that connection works
>     ldapsearch -x -H ldaps://localhost
> 5) kill -STOP <server pid>
> 6) ldapsearch -x -H ldaps://localhost
>     At this point, the client hangs and doesn't properly time out.
>
> For more information including a packet capture, see the original bug report:
> https://bugzilla.redhat.com/show_bug.cgi?id=1186562#c4
>
> This bug doesn't seem to be crypto library specific. I reproduced it with both
> moznss and openssl.
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 2 OpenLDAP project 2017-04-14 19:45:42 UTC
Fix in 2.5?
Comment 3 Quanah Gibson-Mount 2017-04-14 19:45:42 UTC
changed notes
moved from Incoming to Software Bugs
Comment 4 Quanah Gibson-Mount 2020-08-31 23:36:57 UTC
*** Issue 9320 has been marked as a duplicate of this issue. ***
Comment 5 Quanah Gibson-Mount 2020-08-31 23:38:14 UTC
Not possible until all SSL engines support async in the underlying SSL library, which is currently not the case
Comment 6 Allen Zhang 2020-09-01 08:04:32 UTC
HI
what we see is, we get stuck at connect() below 120 seconds.
if opt_tv is set, the connect will work in non-block mode and return immediately.
later in ldap_int_poll(), the network timeout will take effect.

what do you think?

static int
ldap_pvt_connect(LDAP *ld, ber_socket_t s,
                struct sockaddr *sin, ber_socklen_t addrlen,
                int async)
{
                int rc, err;
                struct timeval    tv, *opt_tv = NULL;

#ifdef LDAP_CONNECTIONLESS
                /* We could do a connect() but that would interfere with
                * attempts to poll a broadcast address
                */
                if (LDAP_IS_UDP(ld)) {
                                if (ld->ld_options.ldo_peer)
                                                ldap_memfree(ld->ld_options.ldo_peer);
                                ld->ld_options.ldo_peer=ldap_memcalloc(1, sizeof(struct sockaddr_storage));
                                AC_MEMCPY(ld->ld_options.ldo_peer,sin,addrlen);
                                return ( 0 );
                }
#endif
                if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
                                tv = ld->ld_options.ldo_tm_net;
                                opt_tv = &tv;
                }

                osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n",
                                                s, opt_tv ? tv.tv_sec : -1L, async);

                if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 )
                                return ( -1 );

                do{
                                osip_debug(ld, "attempting to connect: \n", 0, 0, 0);
                                if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
                                                osip_debug(ld, "connect success\n", 0, 0, 0);

                                                if ( !async && opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
                                                                return ( -1 );
                                                return ( 0 );
                                }
                                err = sock_errno();
                                osip_debug(ld, "connect errno: %d\n", err, 0, 0);

                } while(err == EINTR &&
                                LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ));

                if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
                                return ( -1 );
                }
                
                if ( async ) {
                                /* caller will call ldap_int_poll() as appropriate? */
                                return ( -2 );
                }

                rc = ldap_int_poll( ld, s, opt_tv, 1 );

                osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0);

                return rc;
}
Comment 7 Allen Zhang 2020-09-03 03:26:13 UTC
we will try to reproduce the SSL engine problem.
but we do see there is another problem in the TCP connecting phase -- before the connecting SSL. no timeout if the server IP is not reachable.
Comment 8 Allen Zhang 2020-09-04 00:36:10 UTC
We have some new findings as below.
We tested two scenarios:

The first test has a setup as below:
1. the server's IP is accessible.
2. server listens on the port but no response to any incoming data (so no ssl)

Test result:
ldapsearch will not timeout whatever timeout value we set.

The second test has a setup below:
1. the server's IP is NOT accessible.

Test result:

ldapsearch will timeout only after TCP timeout (about 120 seconds) but not timeout at the timeout value we set.

With our "fix version", ldapsearch will timeout according to our timeout value.

So we believe there are two issues in the implementation.
1. No timeout for TCP connection(when startTLS is used) -- this is a bug.
2. No timeout for ssl connection. this is an openssl lib limitation.
Comment 9 Quanah Gibson-Mount 2021-07-16 17:52:43 UTC
*** Issue 9607 has been marked as a duplicate of this issue. ***
Comment 10 Quanah Gibson-Mount 2023-11-02 17:01:13 UTC
*** Issue 8581 has been marked as a duplicate of this issue. ***