mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-25 09:09:54 -05:00
ITS#6432 updated MozNSS context and PEM support
This commit is contained in:
parent
32048a5128
commit
1dbefa75be
1 changed files with 162 additions and 46 deletions
|
|
@ -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 );
|
||||
|
|
|
|||
Loading…
Reference in a new issue