fix: not all certificates in OpenSSL compatible CA certificate directory format are loaded CA certificate files in OpenSSL compatible CACERTDIR were loaded if the file extension was '.0'. However the file name should be 8 letters long certificate hash of the certificate subject name, followed by a numeric suffix which is used to differentiate between two certificates with the same subject name. Wit this patch, certificate file names are matched correctly (using regular expressions). Author: Jan Vcelak Upstream ITS: #7374 Resolves: #811468 diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c index 5e49fc5..61d71d4 100644 --- a/libraries/libldap/tls_m.c +++ b/libraries/libldap/tls_m.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "ldap-int.h" #include "ldap-tls.h" @@ -118,9 +119,7 @@ static const PRIOMethods tlsm_PR_methods; #define PEM_LIBRARY "nsspem" #define PEM_MODULE "PEM" -/* hash files for use with cacertdir have this file name suffix */ -#define PEM_CA_HASH_FILE_SUFFIX ".0" -#define PEM_CA_HASH_FILE_SUFFIX_LEN 2 +#define PEM_CA_HASH_FILE_REGEX "^[0-9a-f]{8}\\.[0-9]+$" static SECMODModule *pem_module; @@ -1541,6 +1540,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir PRDir *dir; PRDirEntry *entry; PRStatus fistatus = PR_FAILURE; + regex_t hashfile_re; memset( &fi, 0, sizeof(fi) ); fistatus = PR_GetFileInfo( cacertdir, &fi ); @@ -1570,20 +1570,30 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir goto done; } + if ( regcomp( &hashfile_re, PEM_CA_HASH_FILE_REGEX, REG_NOSUB|REG_EXTENDED ) != 0 ) { + Debug( LDAP_DEBUG_ANY, "TLS: cannot compile regex for CA hash files matching\n", 0, 0, 0 ); + goto done; + } + do { entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN ); if ( ( NULL != entry ) && ( NULL != entry->name ) ) { char *fullpath = NULL; - char *ptr; + int match; - ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX ); - if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) { + match = regexec( &hashfile_re, entry->name, 0, NULL, 0 ); + if ( match == REG_NOMATCH ) { Debug( LDAP_DEBUG_TRACE, - "TLS: file %s does not end in [%s] - does not appear to be a CA certificate " - "directory file with a properly hashed file name - skipping.\n", - entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 ); + "TLS: skipping '%s' - filename does not have expected format " + "(certificate hash with numeric suffix)\n", entry->name, 0, 0 ); + continue; + } else if ( match != 0 ) { + Debug( LDAP_DEBUG_ANY, + "TLS: cannot execute regex for CA hash file matching (%d).\n", + match, 0, 0 ); continue; } + fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name ); if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) { Debug( LDAP_DEBUG_TRACE, @@ -1599,6 +1609,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir PR_smprintf_free( fullpath ); } } while ( NULL != entry ); + regfree ( &hashfile_re ); PR_CloseDir( dir ); } done: -- 1.7.11.4