MozNSS: better file name matching for hashed CA certificate directory 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: #852786 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