[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
reverse lookups in singlethreaded code (ITS#332)
Full_Name: Christophe Colle
Version: 1.2.3
OS: solaris
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (195.130.132.49)
The reverse lookup-code for a new connection is in a single-threaded part of
code.
This means that whenever you connect to an ldap-server with a misconfigured
ip-adres (the reverse takes forever to resolve), then other connections will not
be
serviced properly anymore.
/* new connection */
ldap_pvt_thread_mutex_lock( &new_conn_mutex );
if ( FD_ISSET( tcps, &readfds ) ) {
len = sizeof(from);
if ( (ns = accept( tcps, (struct sockaddr *) &from,
&len )) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"accept() failed errno %d (%s)", errno,
errno > -1 && errno < sys_nerr ?
sys_errlist[errno] : "unknown", 0 );
ldap_pvt_thread_mutex_unlock( &new_conn_mutex
);
continue;
}
if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"FIONBIO ioctl on %d failed\n", ns, 0, 0 );
}
Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
0, 0 );
len = sizeof(from);
if ( getpeername( ns, (struct sockaddr *) &from, &len )
== 0 ) {
char *s;
client_addr = inet_ntoa( from.sin_addr );
#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
hp = gethostbyaddr( (char *)
&(from.sin_addr.s_addr),
sizeof(from.sin_addr.s_addr), AF_INET );
if(hp) {
....
This code extract clearly demonstrates that a lock is created on
new_conn_mutex, while accepting the socket and trying to reverse lookup the
remote side of the socket. This means that whenever your name-services fail,
noone can connect to the directory server (you can, but you will be put in a
backlog queue for a while). Sun's DS clearly makes availibility dependent on
'nameservices' which you don't have under control. I check the man-page to
switch of this behavior, but I couldn't find out how I should do this.
How can you experience/reproduce this DOS-attack:
1) /etc/nsswitch.conf: make sure you use dns
hosts: files dns
2) /etc/resolv.conf: use a non existent nameserver
nameserver 192.168.252.10
3) (re)start the ds with these reolver settings:
/etc/init.d/dsserv start
make sure no one conects to your DS and perform:
# time ./ldapsearch uid=colle
Search error: No such object
real 0m0.024s
user 0m0.000s
sys 0m0.030s
Less than a tenth of a seconds...Still looking good
Now from another machine (or a machine which has no ip-addres in your
/etc/hosts) issue:
./ldapsearch -h the_server uid=colle
And in the same time perform on the previous server:
# time ./ldapsearch uid=colle
Search error: No such object
real 0m57.081s
user 0m0.000s
sys 0m0.020s
Just because the reverse lookup cannot be done, a simple search on an
idle server takes up to 1 minute before you get an answer, whereas the
same request can be resolved in less than 1 second when no other
ip-address is connecting. This clearly demonstrates how a DOS-attack
can be setup, because the code is single-threaded in the
'accept'-part.