X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Ftls_m.c;h=95bcd3cad62e2c73de56b47e84aa7025b3b7d0fd;hb=59e9ff6243465640956b58ad1756a3ede53eca7c;hp=c1d0c2eefe4384aa03cf437ecdead3e3ed235cf9;hpb=5c878c1bf24e0f2b558cbbe59ffebe53819e49ed;p=openldap
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
index c1d0c2eefe..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-2014 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
@@ -1641,6 +1659,8 @@ tlsm_deferred_init( void *arg )
NSSInitContext *initctx = NULL;
PK11SlotInfo *certdb_slot = NULL;
#endif
+ SSLVersionRange range;
+ SSLProtocolVariant variant;
SECStatus rc;
int done = 0;
@@ -1821,10 +1841,18 @@ tlsm_deferred_init( void *arg )
}
return -1;
}
-
- ctx->tc_using_pem = PR_TRUE;
}
+ /*
+ * Set the SSL version range. MozNSS SSL versions are the same as openldap's:
+ *
+ * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_*
+ */
+ SSL_VersionRangeGetSupported(ssl_variant_stream, &range); /* this sets the max */
+ range.min = lt->lt_protocol_min ? lt->lt_protocol_min : range.min;
+ variant = ssl_variant_stream;
+ SSL_VersionRangeSetDefault(variant, &range);
+
NSS_SetDomesticPolicy();
PK11_SetPasswordFunc( tlsm_pin_prompt );
@@ -2277,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 )) {
@@ -2305,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;
}
}
@@ -2850,7 +2895,11 @@ tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
return 0;
}
-/* Yet again, we're pasting in glue that MozNSS ought to provide itself. */
+/*
+ * Yet again, we're pasting in glue that MozNSS ought to provide itself.
+ *
+ * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_*
+ */
static struct {
const char *name;
int num;
@@ -2859,6 +2908,8 @@ static struct {
{ "SSLv3", SSL_LIBRARY_VERSION_3_0 },
{ "TLSv1", SSL_LIBRARY_VERSION_TLS_1_0 },
{ "TLSv1.1", SSL_LIBRARY_VERSION_TLS_1_1 },
+ { "TLSv1.2", SSL_LIBRARY_VERSION_TLS_1_2 },
+ { "TLSv1.3", SSL_LIBRARY_VERSION_TLS_1_3 },
{ NULL, 0 }
};
@@ -3342,6 +3393,7 @@ tls_impl ldap_int_tls_impl = {
tlsm_session_version,
tlsm_session_cipher,
tlsm_session_peercert,
+ NULL,
&tlsm_sbio,