Edgar Fuß ef@math.uni-bonn.de writes:
I already have problems with /etc/ssl/certs directory, when I use CACertDirs with a lot of certificates in the directory, it was awfully long to get the result, so I switch to CaCertFile instead ... And the problem is only with pam_ldap and not with ldapsearch (or the contrary, I don't remember), and the pam_ldap was linked against gnutls and ldapsearch linked against openssl ...
We experienced the same problem. The culprit turned out to be libldap2 (opposed to libldap-2.3-0), which has GNUTLS support patched in by Debian. To the contrary, ldapsearch is linked against libldap-2.3-0, which uses OpenSSL.
More precisely, the problem is get_ca_list() in libraries/libldap/tls.c. If you profile a test program like
#include <stdlib.h> #include <dirent.h> #include <stdio.h> #include <sys/param.h> #include <sys/stat.h> #include <gnutls/gnutls.h> gnutls_certificate_credentials_t ca_list;
int main(int argc, char *argv[]) { DIR *d; struct dirent *dent; char ca_file[MAXPATHLEN]; struct stat s; char *dir;
if (argc != 2) exit(1); dir = argv[1]; d = opendir(dir); if (d == NULL) exit(1); gnutls_global_init(); gnutls_certificate_allocate_credentials(&ca_list); while ((dent = readdir(d)) != NULL) { snprintf(ca_file, sizeof ca_file, "%s/%s", dir, dent->d_name); stat(ca_file, &s); if (!S_ISREG(s.st_mode)) continue; gnutls_certificate_set_x509_trust_file(ca_list, ca_file, GNUTLS_X509_FMT_PEM); } closedir(d); }
you see unreasonable amounts of time being spent in memory and string manipulation routines.
Edgar, thanks for providing test code. I profiled and improved GnuTLS to execute your code faster, on my system the time was reduced from 40 seconds to 0.3 seconds. I found debugging and fixing this problem interesting so I blogged about it:
http://blog.josefsson.org/2008/02/27/real-world-performance-tuning-with-call...
Not being an TLS/SSL expert, I'm wondering why you need to add all those certificates in the first place. I thought the whole point of all those <subject hash>.<serial> links in /etc/openssl/certs (or whatever) was that a client could find a CA certificate simply by hashing the subject.
GnuTLS doesn't support hashed certificate directories. Further, TLS servers need to send a list of names of trusted certificates to clients, so the server has to open and parse all local trust roots anyway. Right now, this is done for clients too, since the relevant code in GnuTLS doesn't know whether it will be used as a client or server. I hope the new code will be fast enough so that it isn't a bottle-neck. I suppose that it could be optimized further, so that it isn't done for clients at all, but let's not optimize prematurely.
Thanks, /Simon