Commit 1561304f authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#6432

parent 09f88136
......@@ -6,6 +6,7 @@ OpenLDAP 2.4.22 Engineering
Added slapo-ldap idassert-passthru (ITS#6456)
Added slapo-pbind
Fixed libldap GnuTLS serial length (ITS#6460)
Fixed libldap MozNSS context and PEM support (ITS#6432)
Fixed slapd acl non-entry internal searches (ITS#6481)
Fixed slapd certificateListValidate (ITS#6466)
Fixed slapd empty URI parsing (ITS#6465)
......
......@@ -64,6 +64,16 @@
#include <nss/keyhi.h>
#include <nss/secmod.h>
/* NSS 3.12.5 and later have NSS_InitContext */
#if NSS_VMAJOR <= 3 && NSS_VMINOR <= 12 && NSS_VPATCH < 5
/* do nothing */
#else
#define HAVE_NSS_INITCONTEXT 1
#endif
/* InitContext does not currently work in server mode */
/* #define INITCONTEXT_HACK 1 */
typedef struct tlsm_ctx {
PRFileDesc *tc_model;
int tc_refcnt;
......@@ -77,6 +87,11 @@ typedef struct tlsm_ctx {
PRCallOnceType tc_callonce;
PRBool tc_using_pem;
char *tc_slotname; /* if using pem */
#ifdef HAVE_NSS_INITCONTEXT
NSSInitContext *tc_initctx; /* the NSS context */
#endif
PK11GenericObject **tc_pem_objs; /* array of objects to free */
int tc_n_pem_objs; /* number of objects */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_t tc_refmutex;
#endif
......@@ -88,10 +103,9 @@ static PRDescIdentity tlsm_layer_id;
static const PRIOMethods tlsm_PR_methods;
static int tlsm_did_init;
static const char* pem_library = "nsspem";
static SECMODModule* pemMod = NULL;
static const char *pem_mod_name = "PEM";
static SECMODModule* pem_module;
#define DEFAULT_TOKEN_NAME "default"
/* sprintf format used to create token name */
......@@ -925,12 +939,29 @@ tlsm_init_tokens( tlsm_ctx *ctx )
slotList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL );
for ( listEntry = PK11_GetFirstSafe( slotList ); !rc && listEntry;
listEntry = listEntry->next) {
listEntry = PK11_GetNextSafe( slotList, listEntry, PR_FALSE ) ) {
PK11SlotInfo *slot = listEntry->slot;
rc = tlsm_authenticate_to_slot( ctx, slot );
PK11_FreeSlot(slot);
}
PK11_FreeSlotList( slotList );
return rc;
}
static SECStatus
tlsm_nss_shutdown_cb( void *appData, void *nssData )
{
SECStatus rc = SECSuccess;
SSL_ShutdownServerSessionIDCache();
SSL_ClearSessionCache();
if ( pem_module ) {
SECMOD_UnloadUserModule( pem_module );
SECMOD_DestroyModule( pem_module );
pem_module = NULL;
}
return rc;
}
......@@ -941,19 +972,24 @@ tlsm_init_pem_module( void )
char *fullname = NULL;
char *configstring = NULL;
if ( pem_module ) {
return rc;
}
/* not loaded - load it */
/* get the system dependent library name */
fullname = PR_GetLibraryName( NULL, pem_library );
/* Load our PKCS#11 module */
configstring = PR_smprintf( "library=%s name=PEM parameters=\"\"", fullname );
PR_smprintf_free( fullname );
configstring = PR_smprintf( "library=%s name=%s parameters=\"\"", fullname, pem_mod_name );
PL_strfree( fullname );
pemMod = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
PR_smprintf_free( configstring );
if ( !pemMod || !pemMod->loaded ) {
if ( pemMod ) {
SECMOD_DestroyModule( pemMod );
pemMod = NULL;
if ( !pem_module || !pem_module->loaded ) {
if ( pem_module ) {
SECMOD_DestroyModule( pem_module );
pem_module = NULL;
}
rc = -1;
}
......@@ -961,6 +997,29 @@ tlsm_init_pem_module( void )
return rc;
}
static void
tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj )
{
int idx = ctx->tc_n_pem_objs;
ctx->tc_n_pem_objs++;
ctx->tc_pem_objs = (PK11GenericObject **)
PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) );
ctx->tc_pem_objs[idx] = obj;
}
static void
tlsm_free_pem_objs( tlsm_ctx *ctx )
{
/* free in reverse order of allocation */
while ( ctx->tc_n_pem_objs-- ) {
PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] );
ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL;
}
PORT_Free(ctx->tc_pem_objs);
ctx->tc_pem_objs = NULL;
ctx->tc_n_pem_objs = 0;
}
static int
tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca )
{
......@@ -1032,6 +1091,8 @@ tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca )
return -1;
}
tlsm_add_pem_obj( ctx, rv );
return 0;
}
......@@ -1079,13 +1140,16 @@ tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename )
} else {
/* When adding an encrypted key the PKCS#11 will be set as removed */
/* This will force the token to be seen as re-inserted */
SECMOD_WaitForAnyTokenEvent( pemMod, 0, 0 );
SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 );
PK11_IsPresent( slot );
retcode = 0;
}
PK11_FreeSlot( slot );
if ( !retcode ) {
tlsm_add_pem_obj( ctx, rv );
}
return retcode;
}
......@@ -1178,11 +1242,20 @@ tlsm_deferred_init( void *arg )
int ii;
int nn;
PRErrorCode errcode = 1;
#ifdef HAVE_NSS_INITCONTEXT
NSSInitParameters initParams;
NSSInitContext *initctx = NULL;
#endif
SECStatus rc;
/* NSS support for multi-init is coming */
#ifndef NSS_MULTI_INIT
#ifdef HAVE_NSS_INITCONTEXT
memset( &initParams, 0, sizeof( initParams ) );
initParams.length = sizeof( initParams );
#endif /* HAVE_NSS_INITCONTEXT */
#ifndef HAVE_NSS_INITCONTEXT
if ( !NSS_IsInitialized() ) {
#endif /* NSS_MULTI_INIT */
#endif /* HAVE_NSS_INITCONTEXT */
/*
MOZNSS_DIR will override everything else - you can
always set MOZNSS_DIR to force the use of this
......@@ -1197,12 +1270,30 @@ tlsm_deferred_init( void *arg )
securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
securitydirs[nn++] = lt->lt_cacertdir;
securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
for (ii = 0; ii < nn; ++ii) {
for ( ii = 0; ii < nn; ++ii ) {
const char *securitydir = securitydirs[ii];
if ( NULL == securitydir ) {
continue;
}
if ( NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY ) ) {
#ifdef HAVE_NSS_INITCONTEXT
#ifdef INITCONTEXT_HACK
if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
rc = NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY );
} else {
initctx = NSS_InitContext( securitydir, "", "", SECMOD_DB,
&initParams, NSS_INIT_READONLY );
rc = (initctx == NULL) ? SECFailure : SECSuccess;
}
#else
initctx = NSS_InitContext( securitydir, "", "", SECMOD_DB,
&initParams, NSS_INIT_READONLY );
rc = (initctx == NULL) ? SECFailure : SECSuccess;
#endif
#else
rc = NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY );
#endif
if ( rc != SECSuccess ) {
errcode = PORT_GetError();
Debug( LDAP_DEBUG_TRACE,
"TLS: could not initialize moznss using security dir %s - error %d:%s.\n",
......@@ -1217,7 +1308,25 @@ tlsm_deferred_init( void *arg )
}
if ( errcode ) { /* no moznss db found, or not using moznss db */
if ( NSS_NoDB_Init( NULL ) ) {
#ifdef HAVE_NSS_INITCONTEXT
int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
#ifdef INITCONTEXT_HACK
if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
rc = NSS_NoDB_Init( NULL );
} else {
initctx = NSS_InitContext( "", "", "", SECMOD_DB,
&initParams, flags );
rc = (initctx == NULL) ? SECFailure : SECSuccess;
}
#else
initctx = NSS_InitContext( "", "", "", SECMOD_DB,
&initParams, flags );
rc = (initctx == NULL) ? SECFailure : SECSuccess;
#endif
#else
rc = NSS_NoDB_Init( NULL );
#endif
if ( rc != SECSuccess ) {
errcode = PORT_GetError();
Debug( LDAP_DEBUG_ANY,
"TLS: could not initialize moznss - error %d:%s.\n",
......@@ -1225,6 +1334,10 @@ tlsm_deferred_init( void *arg )
return -1;
}
#ifdef HAVE_NSS_INITCONTEXT
ctx->tc_initctx = initctx;
#endif
/* initialize the PEM module */
if ( tlsm_init_pem_module() ) {
errcode = PORT_GetError();
......@@ -1241,6 +1354,12 @@ tlsm_deferred_init( void *arg )
ctx->tc_using_pem = PR_TRUE;
}
#ifdef HAVE_NSS_INITCONTEXT
if ( !ctx->tc_initctx ) {
ctx->tc_initctx = initctx;
}
#endif
NSS_SetDomesticPolicy();
PK11_SetPasswordFunc( tlsm_pin_prompt );
......@@ -1249,10 +1368,14 @@ tlsm_deferred_init( void *arg )
return -1;
}
tlsm_did_init = 1; /* we did the init - we should also clean up */
#ifndef NSS_MULTI_INIT
/* register cleanup function */
/* delete the old one, if any */
NSS_UnregisterShutdown( tlsm_nss_shutdown_cb, NULL );
NSS_RegisterShutdown( tlsm_nss_shutdown_cb, NULL );
#ifndef HAVE_NSS_INITCONTEXT
}
#endif /* NSS_MULTI_INIT */
#endif /* HAVE_NSS_INITCONTEXT */
return 0;
}
......@@ -1420,22 +1543,19 @@ tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
* the database
*/
static int
tlsm_clientauth_init( tlsm_ctx *ctx, const char *certname )
tlsm_clientauth_init( tlsm_ctx *ctx )
{
SECStatus status = SECFailure;
int rc;
PL_strfree( ctx->tc_certname );
rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, certname, 0, NULL, NULL );
rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"TLS: error: unable to set up client certificate authentication for "
"certificate named %s\n", certname, 0, 0 );
"certificate named %s\n", ctx->tc_certname, 0, 0 );
return -1;
}
ctx->tc_certname = PL_strdup( certname );
status = SSL_GetClientAuthDataHook( ctx->tc_model,
tlsm_get_client_auth_data,
(void *)ctx );
......@@ -1449,21 +1569,6 @@ tlsm_clientauth_init( tlsm_ctx *ctx, const char *certname )
static void
tlsm_destroy( void )
{
if (pemMod) {
SECMOD_DestroyModule(pemMod);
pemMod = NULL;
}
/* Only if we did the actual initialization */
if ( tlsm_did_init ) {
tlsm_did_init = 0;
SSL_ShutdownServerSessionIDCache();
SSL_ClearSessionCache();
NSS_Shutdown();
}
PR_Cleanup();
}
static tls_ctx *
......@@ -1487,6 +1592,11 @@ tlsm_ctx_new ( struct ldapoptions *lo )
ctx->tc_verify_cert = PR_FALSE;
ctx->tc_using_pem = PR_FALSE;
ctx->tc_slotname = NULL;
#ifdef HAVE_NSS_INITCONTEXT
ctx->tc_initctx = NULL;
#endif /* HAVE_NSS_INITCONTEXT */
ctx->tc_pem_objs = NULL;
ctx->tc_n_pem_objs = 0;
}
return (tls_ctx *)ctx;
}
......@@ -1528,7 +1638,13 @@ tlsm_ctx_free ( tls_ctx *ctx )
c->tc_certname = NULL;
PL_strfree( c->tc_pin_file );
c->tc_pin_file = NULL;
PL_strfree( c->tc_slotname );
PL_strfree( c->tc_slotname );
tlsm_free_pem_objs( c );
#ifdef HAVE_NSS_INITCONTEXT
if (c->tc_initctx)
NSS_ShutdownContext( c->tc_initctx );
c->tc_initctx = NULL;
#endif /* HAVE_NSS_INITCONTEXT */
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
#endif
......@@ -1566,7 +1682,7 @@ tlsm_deferred_ctx_init( void *arg )
return -1;
}
ctx->tc_certdb = CERT_GetDefaultCertDB(); /* replace with multi-init db call */
ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
if ( fd ) {
......@@ -1731,7 +1847,7 @@ tlsm_deferred_ctx_init( void *arg )
ctx->tc_certname, 0, 0 );
return -1;
}
if ( tlsm_clientauth_init( ctx, ctx->tc_certname ) ) {
if ( tlsm_clientauth_init( ctx ) ) {
Debug( LDAP_DEBUG_ANY,
"TLS: error: unable to set up client certificate authentication using %s\n",
ctx->tc_certname, 0, 0 );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment