Jan Vcelak 3314657
MozNSS: load certificates from certdb, fallback to PEM
Jan Vcelak 3314657
Jan Vcelak 587944c
If TLS_CACERT pointed to a PEM file and TLS_CACERTDIR was set to NSS
Jan Vcelak 587944c
certificate database, the backend assumed that the certificate is always
Jan Vcelak 587944c
located in the certificate database. This assumption might be wrong.
Jan Vcelak 587944c
Jan Vcelak 587944c
This patch makes the library to try to load the certificate from NSS
Jan Vcelak 587944c
database and fallback to PEM file if unsuccessfull.
Jan Vcelak 3314657
Jan Vcelak 3314657
Author: Jan Vcelak <jvcelak@redhat.com>
Jan Vcelak 3314657
Upstream ITS: #7389
Jan Vcelak 3314657
Resolves: #857455
Jan Vcelak 3314657
Jan Vcelak 3314657
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
705b2a5
index 6847bea..8339391 100644
Jan Vcelak 3314657
--- a/libraries/libldap/tls_m.c
Jan Vcelak 3314657
+++ b/libraries/libldap/tls_m.c
Jan Vcelak 587944c
@@ -1412,7 +1412,7 @@ tlsm_ctx_load_private_key( tlsm_ctx *ctx )
Jan Vcelak 3314657
 	/* prefer unlocked key, then key from opened certdb, then any other */
Jan Vcelak 587944c
 	if ( unlocked_key )
Jan Vcelak 3314657
 		ctx->tc_private_key = unlocked_key;
Jan Vcelak 587944c
-	else if ( ctx->tc_certdb_slot )
Jan Vcelak 3314657
+	else if ( ctx->tc_certdb_slot && !ctx->tc_using_pem )
Jan Vcelak 587944c
 		ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg );
Jan Vcelak 3314657
 	else
Jan Vcelak 587944c
 		ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg );
705b2a5
@@ -1909,8 +1909,6 @@ tlsm_deferred_init( void *arg )
Jan Vcelak 3314657
 				}
Jan Vcelak 3314657
 				return -1;
Jan Vcelak 3314657
 			}
Jan Vcelak 3314657
-
Jan Vcelak 3314657
-			ctx->tc_using_pem = PR_TRUE;
Jan Vcelak 3314657
 		}
Jan Vcelak 3314657
 
Jan Vcelak 3314657
 		NSS_SetDomesticPolicy();
705b2a5
@@ -2363,15 +2361,9 @@ tlsm_deferred_ctx_init( void *arg )
Jan Vcelak 3314657
 
Jan Vcelak 3314657
 	/* set up our cert and key, if any */
Jan Vcelak 3314657
 	if ( lt->lt_certfile ) {
Jan Vcelak 3314657
-		/* if using the PEM module, load the PEM file specified by lt_certfile */
Jan Vcelak 3314657
-		/* otherwise, assume this is the name of a cert already in the db */
Jan Vcelak 3314657
-		if ( ctx->tc_using_pem ) {
Jan Vcelak 3314657
-			/* this sets ctx->tc_certificate to the correct value */
Jan Vcelak 3314657
-			int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE );
Jan Vcelak 3314657
-			if ( rc ) {
Jan Vcelak 3314657
-				return rc;
Jan Vcelak 3314657
-			}
Jan Vcelak 3314657
-		} else {
Jan Vcelak 3314657
+
Jan Vcelak 3314657
+		/* first search in certdb (lt_certfile is nickname) */
Jan Vcelak 3314657
+		if ( ctx->tc_certdb ) {
Jan Vcelak 3314657
 			char *tmp_certname;
Jan Vcelak 3314657
 
Jan Vcelak 587944c
 			if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) {
705b2a5
@@ -2391,8 +2383,31 @@ tlsm_deferred_ctx_init( void *arg )
Jan Vcelak 3314657
 				Debug( LDAP_DEBUG_ANY,
Jan Vcelak 3314657
 					   "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
Jan Vcelak 3314657
 					   lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak 4b460cc
+			}
Jan Vcelak 4b460cc
+		}
Jan Vcelak 3314657
+
Jan Vcelak 3314657
+		/* fallback to PEM module (lt_certfile is filename) */
Jan Vcelak 4b460cc
+		if ( !ctx->tc_certificate ) {
Jan Vcelak 4b460cc
+			if ( !pem_module && tlsm_init_pem_module() ) {
Jan Vcelak 4b460cc
+				int pem_errcode = PORT_GetError();
Jan Vcelak 4b460cc
+				Debug( LDAP_DEBUG_ANY,
Jan Vcelak 4b460cc
+					   "TLS: fallback to PEM impossible, module cannot be loaded - error %d:%s.\n",
Jan Vcelak 4b460cc
+					   pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
Jan Vcelak 4b460cc
 				return -1;
Jan Vcelak 4b460cc
 			}
Jan Vcelak 4b460cc
+
Jan Vcelak 3314657
+			/* this sets ctx->tc_certificate to the correct value */
Jan Vcelak 3314657
+			if ( !tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ) ) {
Jan Vcelak 3314657
+				ctx->tc_using_pem = PR_TRUE;
Jan Vcelak 3314657
+			}
Jan Vcelak 3314657
+		}
Jan Vcelak 3314657
+
Jan Vcelak 3314657
+		if ( ctx->tc_certificate ) {
Jan Vcelak 3314657
+			Debug( LDAP_DEBUG_ANY,
Jan Vcelak 3314657
+				   "TLS: certificate '%s' successfully loaded from %s.\n", lt->lt_certfile,
Jan Vcelak 3314657
+				   ctx->tc_using_pem ? "PEM file" : "moznss database", 0);
Jan Vcelak 3314657
+		} else {
Jan Vcelak 3314657
+			return -1;
Jan Vcelak 4b460cc
 		}
Jan Vcelak 3314657
 	}
Jan Vcelak 3314657