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