Jan Vcelak ce2de96
TLS_CACERTDIR takes precedence over TLS_CACERTFILE
Jan Vcelak ce2de96
Jan Vcelak ce2de96
Resolves: #652304
Jan Vcelak ce2de96
Upstream ITS: #6704
Jan Vcelak ce2de96
Author: Rich Megginson (rmeggins@redhat.com)
Jan Vcelak ce2de96
Jan Vcelak ce2de96
diff -uNPrp openldap-2.4.23.old/libraries/libldap/tls_m.c openldap-2.4.23.new/libraries/libldap/tls_m.c
Jan Vcelak ce2de96
--- openldap-2.4.23.old/libraries/libldap/tls_m.c	2010-11-18 11:01:36.129392116 +0100
Jan Vcelak ce2de96
+++ openldap-2.4.23.new/libraries/libldap/tls_m.c	2010-11-18 11:02:19.466387205 +0100
Jan Vcelak ce2de96
@@ -1031,6 +1031,7 @@ tlsm_add_cert_from_file( tlsm_ctx *ctx, 
Jan Vcelak ce2de96
 	}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	if ( fi.type != PR_FILE_FILE ) {
Jan Vcelak ce2de96
+		PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
Jan Vcelak ce2de96
 		Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
 			   "TLS: error: the certificate file %s is not a file.\n",
Jan Vcelak ce2de96
 			   filename, 0 ,0 );
Jan Vcelak ce2de96
@@ -1123,6 +1124,7 @@ tlsm_add_key_from_file( tlsm_ctx *ctx, c
Jan Vcelak ce2de96
 	}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	if ( fi.type != PR_FILE_FILE ) {
Jan Vcelak ce2de96
+		PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
Jan Vcelak ce2de96
 		Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
 			   "TLS: error: the key file %s is not a file.\n",
Jan Vcelak ce2de96
 			   filename, 0 ,0 );
Jan Vcelak ce2de96
@@ -1178,69 +1180,91 @@ static int
Jan Vcelak ce2de96
 tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir )
Jan Vcelak ce2de96
 {
Jan Vcelak ce2de96
 	PRBool isca = PR_TRUE;
Jan Vcelak ce2de96
+	PRStatus status = PR_FAILURE;
Jan Vcelak ce2de96
+	PRErrorCode errcode = PR_SUCCESS;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	if ( cacertfile ) {
Jan Vcelak ce2de96
 		int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca );
Jan Vcelak ce2de96
 		if ( rc ) {
Jan Vcelak ce2de96
-			return rc;
Jan Vcelak ce2de96
+			errcode = PR_GetError();
Jan Vcelak ce2de96
+			Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
+				   "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
Jan Vcelak ce2de96
+				   cacertfile, errcode,
Jan Vcelak ce2de96
+				   PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak ce2de96
+		} else {
Jan Vcelak ce2de96
+			Debug( LDAP_DEBUG_TRACE,
Jan Vcelak ce2de96
+				   "TLS: loaded CA certificate file %s.\n",
Jan Vcelak ce2de96
+				   cacertfile, 0, 0 );
Jan Vcelak ce2de96
+			status = PR_SUCCESS; /* have at least one good CA - we can proceed */
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 	}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	if ( cacertdir ) {
Jan Vcelak ce2de96
 		PRFileInfo fi;
Jan Vcelak ce2de96
-		PRStatus status;
Jan Vcelak ce2de96
 		PRDir *dir;
Jan Vcelak ce2de96
 		PRDirEntry *entry;
Jan Vcelak ce2de96
+		PRStatus fistatus = PR_FAILURE;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 		memset( &fi, 0, sizeof(fi) );
Jan Vcelak ce2de96
-		status = PR_GetFileInfo( cacertdir, &fi );
Jan Vcelak ce2de96
-		if ( PR_SUCCESS != status) {
Jan Vcelak ce2de96
-			PRErrorCode errcode = PR_GetError();
Jan Vcelak ce2de96
+		fistatus = PR_GetFileInfo( cacertdir, &fi );
Jan Vcelak ce2de96
+		if ( PR_SUCCESS != fistatus) {
Jan Vcelak ce2de96
+			errcode = PR_GetError();
Jan Vcelak ce2de96
 			Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
 				   "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n",
Jan Vcelak ce2de96
 				   cacertdir, errcode,
Jan Vcelak ce2de96
 				   PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak ce2de96
-			return -1;
Jan Vcelak ce2de96
+			goto done;
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 		if ( fi.type != PR_FILE_DIRECTORY ) {
Jan Vcelak ce2de96
 			Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
 				   "TLS: error: the CA certificate directory %s is not a directory.\n",
Jan Vcelak ce2de96
 				   cacertdir, 0 ,0 );
Jan Vcelak ce2de96
-			return -1;
Jan Vcelak ce2de96
+			goto done;
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 		dir = PR_OpenDir( cacertdir );
Jan Vcelak ce2de96
 		if ( NULL == dir ) {
Jan Vcelak ce2de96
-			PRErrorCode errcode = PR_GetError();
Jan Vcelak ce2de96
+			errcode = PR_GetError();
Jan Vcelak ce2de96
 			Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
 				   "TLS: could not open the CA certificate directory %s - error %d:%s.\n",
Jan Vcelak ce2de96
 				   cacertdir, errcode,
Jan Vcelak ce2de96
 				   PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak ce2de96
-			return -1;
Jan Vcelak ce2de96
+			goto done;
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
-		status = -1;
Jan Vcelak ce2de96
 		do {
Jan Vcelak ce2de96
 			entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN );
Jan Vcelak ce2de96
 			if ( NULL != entry ) {
Jan Vcelak ce2de96
 				char *fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name );
Jan Vcelak ce2de96
 				if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) {
Jan Vcelak ce2de96
-					status = 0; /* found at least 1 valid CA file in the dir */
Jan Vcelak ce2de96
+					Debug( LDAP_DEBUG_TRACE,
Jan Vcelak ce2de96
+						   "TLS: loaded CA certificate file %s from CA certificate directory %s.\n",
Jan Vcelak ce2de96
+						   fullpath, cacertdir, 0 );
Jan Vcelak ce2de96
+					status = PR_SUCCESS; /* found at least 1 valid CA file in the dir */
Jan Vcelak ce2de96
+				} else {
Jan Vcelak ce2de96
+					errcode = PR_GetError();
Jan Vcelak ce2de96
+					Debug( LDAP_DEBUG_TRACE,
Jan Vcelak ce2de96
+						   "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
Jan Vcelak ce2de96
+						   fullpath, errcode,
Jan Vcelak ce2de96
+						   PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak ce2de96
 				}
Jan Vcelak ce2de96
 				PR_smprintf_free( fullpath );
Jan Vcelak ce2de96
 			}
Jan Vcelak ce2de96
 		} while ( NULL != entry );
Jan Vcelak ce2de96
 		PR_CloseDir( dir );
Jan Vcelak ce2de96
-
Jan Vcelak ce2de96
-		if ( status ) {
Jan Vcelak ce2de96
-			PRErrorCode errcode = PR_GetError();
Jan Vcelak ce2de96
-			Debug( LDAP_DEBUG_ANY,
Jan Vcelak ce2de96
-				   "TLS: did not find any valid CA certificate files in the CA certificate directory %s - error %d:%s.\n",
Jan Vcelak ce2de96
-				   cacertdir, errcode,
Jan Vcelak ce2de96
-				   PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak ce2de96
-			return -1;
Jan Vcelak ce2de96
+	}
Jan Vcelak ce2de96
+done:
Jan Vcelak ce2de96
+	if ( status != PR_SUCCESS ) {
Jan Vcelak ce2de96
+		const char *fmtstr = NULL;
Jan Vcelak ce2de96
+		if ( cacertfile && cacertdir ) {
Jan Vcelak ce2de96
+			fmtstr = "TLS: did not find any valid CA certificates in %s or %s\n";
Jan Vcelak ce2de96
+		} else {
Jan Vcelak ce2de96
+			fmtstr = "TLS: did not find any valid CA certificates in %s%s\n";
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
+		Debug( LDAP_DEBUG_ANY, fmtstr, cacertdir ? cacertdir : "",
Jan Vcelak ce2de96
+			   cacertfile ? cacertfile : "", 0 );
Jan Vcelak ce2de96
+		return -1;
Jan Vcelak ce2de96
 	}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	return 0;