X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Ftls_m.c;h=95bcd3cad62e2c73de56b47e84aa7025b3b7d0fd;hb=59e9ff6243465640956b58ad1756a3ede53eca7c;hp=9dfa2f00bd268372c32299fe224e4f9b7b9863dc;hpb=994923dbc5b80d89a3f036e934b3da4d8d2b6569;p=openldap diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c index 9dfa2f00bd..95bcd3cad6 100644 --- a/libraries/libldap/tls_m.c +++ b/libraries/libldap/tls_m.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2008-2015 The OpenLDAP Foundation. + * Copyright 2008-2018 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,7 @@ #include #include #include +#include #include "ldap-int.h" #include "ldap-tls.h" @@ -118,9 +119,7 @@ static const PRIOMethods tlsm_PR_methods; #define PEM_LIBRARY "nsspem" #define PEM_MODULE "PEM" -/* hash files for use with cacertdir have this file name suffix */ -#define PEM_CA_HASH_FILE_SUFFIX ".0" -#define PEM_CA_HASH_FILE_SUFFIX_LEN 2 +#define PEM_CA_HASH_FILE_REGEX "^[0-9a-f]{8}\\.[0-9]+$" static SECMODModule *pem_module; @@ -625,7 +624,7 @@ nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum]) (ciphers_def[i].strength & strength) || (ciphers_def[i].version & protocol)) && (cipher_list[i] != -1)) { - /* Enable the NULL ciphers only if explicity + /* Enable the NULL ciphers only if explicitly * requested */ if (ciphers_def[i].attr & SSL_eNULL) { if (mask & SSL_eNULL) @@ -1145,6 +1144,8 @@ tlsm_auth_cert_handler(void *arg, PRFileDesc *fd, return ret; } +static PRCallOnceType tlsm_register_shutdown_callonce = {0,0}; + static SECStatus tlsm_nss_shutdown_cb( void *appData, void *nssData ) { @@ -1157,10 +1158,15 @@ tlsm_nss_shutdown_cb( void *appData, void *nssData ) SECMOD_DestroyModule( pem_module ); pem_module = NULL; } + + /* init callonce so it can be armed again for cases like persistent daemon with LDAP_OPT_X_TLS_NEWCTX */ + tlsm_register_shutdown_callonce.initialized = 0; + tlsm_register_shutdown_callonce.inProgress = 0; + tlsm_register_shutdown_callonce.status = 0; + return rc; } -static PRCallOnceType tlsm_register_shutdown_callonce = {0,0}; static PRStatus PR_CALLBACK tlsm_register_nss_shutdown_cb( void ) { @@ -1345,7 +1351,7 @@ tlsm_ctx_load_private_key( tlsm_ctx *ctx ) /* prefer unlocked key, then key from opened certdb, then any other */ if ( unlocked_key ) ctx->tc_private_key = unlocked_key; - else if ( ctx->tc_certdb_slot ) + else if ( ctx->tc_certdb_slot && !ctx->tc_using_pem ) ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg ); else ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg ); @@ -1473,6 +1479,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir PRDir *dir; PRDirEntry *entry; PRStatus fistatus = PR_FAILURE; + regex_t hashfile_re; memset( &fi, 0, sizeof(fi) ); fistatus = PR_GetFileInfo( cacertdir, &fi ); @@ -1502,20 +1509,30 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir goto done; } + if ( regcomp( &hashfile_re, PEM_CA_HASH_FILE_REGEX, REG_NOSUB|REG_EXTENDED ) != 0 ) { + Debug( LDAP_DEBUG_ANY, "TLS: cannot compile regex for CA hash files matching\n", 0, 0, 0 ); + goto done; + } + do { entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN ); if ( ( NULL != entry ) && ( NULL != entry->name ) ) { char *fullpath = NULL; - char *ptr; + int match; - ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX ); - if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) { + match = regexec( &hashfile_re, entry->name, 0, NULL, 0 ); + if ( match == REG_NOMATCH ) { Debug( LDAP_DEBUG_TRACE, - "TLS: file %s does not end in [%s] - does not appear to be a CA certificate " - "directory file with a properly hashed file name - skipping.\n", - entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 ); + "TLS: skipping '%s' - filename does not have expected format " + "(certificate hash with numeric suffix)\n", entry->name, 0, 0 ); + continue; + } else if ( match != 0 ) { + Debug( LDAP_DEBUG_ANY, + "TLS: cannot execute regex for CA hash file matching (%d).\n", + match, 0, 0 ); continue; } + fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name ); if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) { Debug( LDAP_DEBUG_TRACE, @@ -1531,6 +1548,7 @@ tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir PR_smprintf_free( fullpath ); } } while ( NULL != entry ); + regfree ( &hashfile_re ); PR_CloseDir( dir ); } done: @@ -1581,7 +1599,7 @@ tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) } /* - * Currently mutiple MozNSS contexts share one certificate storage. When the + * Currently multiple MozNSS contexts share one certificate storage. When the * certdb is being opened, only new certificates are added to the storage. * When different databases are used, conflicting nicknames make the * certificate lookup by the nickname impossible. In addition a token @@ -1823,8 +1841,6 @@ tlsm_deferred_init( void *arg ) } return -1; } - - ctx->tc_using_pem = PR_TRUE; } /* @@ -2289,15 +2305,9 @@ tlsm_deferred_ctx_init( void *arg ) /* set up our cert and key, if any */ if ( lt->lt_certfile ) { - /* if using the PEM module, load the PEM file specified by lt_certfile */ - /* otherwise, assume this is the name of a cert already in the db */ - if ( ctx->tc_using_pem ) { - /* this sets ctx->tc_certificate to the correct value */ - int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ); - if ( rc ) { - return rc; - } - } else { + + /* first search in certdb (lt_certfile is nickname) */ + if ( ctx->tc_certdb ) { char *tmp_certname; if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) { @@ -2317,8 +2327,31 @@ tlsm_deferred_ctx_init( void *arg ) Debug( LDAP_DEBUG_ANY, "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n", lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); + } + } + + /* fallback to PEM module (lt_certfile is filename) */ + if ( !ctx->tc_certificate ) { + if ( !pem_module && tlsm_init_pem_module() ) { + int pem_errcode = PORT_GetError(); + Debug( LDAP_DEBUG_ANY, + "TLS: fallback to PEM impossible, module cannot be loaded - error %d:%s.\n", + pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); return -1; } + + /* this sets ctx->tc_certificate to the correct value */ + if ( !tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ) ) { + ctx->tc_using_pem = PR_TRUE; + } + } + + if ( ctx->tc_certificate ) { + Debug( LDAP_DEBUG_ANY, + "TLS: certificate '%s' successfully loaded from %s.\n", lt->lt_certfile, + ctx->tc_using_pem ? "PEM file" : "moznss database", 0); + } else { + return -1; } } @@ -3360,6 +3393,7 @@ tls_impl ldap_int_tls_impl = { tlsm_session_version, tlsm_session_cipher, tlsm_session_peercert, + NULL, &tlsm_sbio,