Hi, initial report at: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=185080
Imho it's more a OpenSSL than a OpenLDAP client problem. Regards, Peter Description of problem: During tracking down, why a LDAP enabled postfix cannot lookup via TLS enabled LDAP client I found that openssl function SSL_add_dir_cert_subjects_to_stack is very optimistic relating to the files found in a specified directory. Version-Release number of selected component (if applicable): openssl-0.9.7a-43.4 also openssl-0.9.7.i (latest 0.9.7 release) also openssl-0.9.8.a (latest 0.9.8 release) in conjunction with openldap-2.2.13-4 also openldap-2.2.30 (latest 2.2 release) also openldap-2.3.20 (latest 2.3 release) How reproducible: Always Steps to Reproduce: 1. Create a directory for local PKI storage, e.g. /etc/pki 2. Store local CA, local server certificates and local keys into this directory 3. Set proper permissions to keys, e.g. chmod o-rwx *.key.pem # ll /etc/pki/ total 120 lrwxrwxrwx 1 root root 23 Sep 14 15:42 592fcc04.0 -> ca.crt -r--r--r-- 1 root root 1834 Sep 14 15:39 ca.crt -r--r--r-- 1 root root 2529 Sep 14 15:39 AE-CA-Class4-2005-A.crt -r-------- 1 root root 5875 Sep 14 15:45 ca+cert+key.pem -r--r--r-- 1 root root 4196 Sep 14 16:07 ca+cert.pem -r--r--r-- 1 root root 2362 Sep 14 15:37 cert.crt -r--r----- 1 root root 4041 Sep 14 15:50 cert+key.pem -r--r----- 1 root ldap 1679 Sep 14 15:37 key.pem (note: group=ldap for LDAP server, which reads key file for server TLS after changing the user to "ldap") 4. Configure /etc/openldap/slapd.conf for TLS like TLSCACertificateFile /etc/pki/ca.crt TLSCACertificatePath /etc/pki TLSCertificateFile /etc/pki/crt.crt TLSCertificateKeyFile /etc/pki/key.pem 5. Configure /etc/openldap/ldap.conf related URI ldaps://ldapserver/ #URI ldap://ldapserver/ BASE dc=example,dc=com TLS_CACERTDIR /etc/pki # <- important! 6. Try ldapsearch usig TLS as root: ldapsearch -x -H ldaps://ldapserver/ Result: working 7. Try ldapsearch using TLS as normal user: $ ldapsearch -x -v -H ldaps://ldapserver Result: not working, message: ldap_initialize( ldaps://ldapserver ) ldap_bind: Can't contact LDAP server (-1) Using strace shows me: open("/etc/pki/key.pem", O_RDONLY) = -1 EACCES (Permission denied) close(4) = 0 write(2, "ldap_bind: Can\'t contact LDAP server (-1)\n", 42ldap_bind: Can't contact LDAP server (-1) ) = 42 exit_group(1) = ? Process 15652 detached Ooops, why will ldapsearch open this key file??? Ok, thanks to opensource we are now now digging through the code: A) openldap: openldap-2.2.13/libraries/libldap/tls.c (same code in newer/latest versions) static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir ) { STACK_OF(X509_NAME) *ca_list = NULL; if ( bundle ) { ca_list = SSL_load_client_CA_file( bundle ); } #if defined(HAVE_DIRENT_H) || defined(dirent) if ( dir ) { int freeit = 0; if ( !ca_list ) { ca_list = sk_X509_NAME_new_null(); freeit = 1; } if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) && freeit ) { sk_X509_NAME_free( ca_list ); ca_list = NULL; } } #endif return ca_list; } Ok, openldap calls an openssl functions to read all certificates in "dir" and add to "ca_list". Note that here is also an opportunity for improvements to be more graceful, if SSL_load_client_CA_file works but SSL_add_dir_cert_subjects_to_stack fails. Currently, the whole ca_list ist dropped. B) openssl: openssl-0.9.7a/ssl/ssl_cert.c (same code in newer/latest versions) /*! * Add a directory of certs to a stack. * \param stack the stack to append to. * \param dir the directory to append from. All files in this directory will be * examined as potential certs. Any that are acceptable to * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be * included. * \return 1 for success, 0 for failure. Note that in the case of failure some * certs may have been added to \c stack. */ #ifndef OPENSSL_SYS_WIN32 #ifndef OPENSSL_SYS_VMS /* XXXX This may be fixed in the future */ #ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! */ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir) { DIR *d; struct dirent *dstruct; int ret = 0; CRYPTO_w_lock(CRYPTO_LOCK_READDIR); d = opendir(dir); /* Note that a side effect is that the CAs will be sorted by name */ if(!d) { SYSerr(SYS_F_OPENDIR, get_last_sys_error()); ERR_add_error_data(3, "opendir('", dir, "')"); SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); goto err; } while((dstruct=readdir(d))) { char buf[1024]; int r; if(strlen(dir)+strlen(dstruct->d_name)+2 > sizeof buf) { SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); goto err; } r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,dstruct->d_name); if (r <= 0 || r >= sizeof buf) goto err; if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) goto err; } ret = 1; err: if (d) closedir(d); CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); return ret; } #endif #endif Oooppppssss!!!! Looks like developers were very optimistic that after reading the directory into "d", all files are readable by the user which executes the program. Only a test whether path is too long was made. Afterwards, file is given to BIO_snprintf for reading, which fails on non-readable files. There is an additional check missing! Additional info: It looks like that a simple # touch /path/to/my/pki/certs/dummy # chmod go-rwx /path/to/my/pki/certs/dummy would stop the use of TLS enabled clients executed by non-root users (e.g. here: postfix) at all - that's bad! BTW: If I temporary change permissions to 444 to all files in this directory, ldapsearch works for non-root users TLS enabled. -- Dr. Peter Bieringer http://www.bieringer.de/pb/ GPG/PGP Key 0x958F422D mailto: pb at bieringer dot de Deep Space 6 Co-Founder and Core Member http://www.deepspace6.net/ ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager [EMAIL PROTECTED]