summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/ssl.c
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/slapd/ssl.c
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/slapd/ssl.c')
-rw-r--r--ldap/servers/slapd/ssl.c1499
1 files changed, 1499 insertions, 0 deletions
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
new file mode 100644
index 00000000..49eea76a
--- /dev/null
+++ b/ldap/servers/slapd/ssl.c
@@ -0,0 +1,1499 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/* SSL-related stuff for slapd */
+
+#if defined(NET_SSL)
+
+#if defined( _WINDOWS )
+#include <windows.h>
+#include <winsock.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "proto-ntutil.h"
+#include <string.h>
+#include <stdlib.h>
+#include <direct.h>
+#include <io.h>
+#endif
+
+#ifdef LINUX
+#include <sys/param.h>
+#endif
+
+#include <ssl.h>
+#include <nss.h>
+#include <key.h>
+#include <sslproto.h>
+#include "secmod.h"
+#include <string.h>
+#include <errno.h>
+
+#include "slap.h"
+
+#include "svrcore.h"
+#include "fe.h"
+#include <ldap_ssl.h> /* ldapssl_client_init */
+#include "certdb.h"
+
+/* For IRIX... */
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+extern char* slapd_SSL3ciphers;
+extern symbol_t supported_ciphers[];
+
+/* dongle_file_name is set in slapd_nss_init when we set the path for the
+ key, cert, and secmod files - the dongle file must be in the same directory
+ and use the same naming scheme
+*/
+static char* dongle_file_name = NULL;
+
+static int _security_library_initialized = 0;
+static int _ssl_listener_initialized = 0;
+
+/* Our name for the internal token, must match PKCS-11 config data below */
+static char *internalTokenName = "Internal (Software) Token";
+
+static int stimeout;
+static char *ciphers = NULL;
+static char * configDN = "cn=encryption,cn=config";
+
+/* Copied from libadmin/libadmin.h public/nsapi.h */
+#define SERVER_KEY_NAME "Server-Key"
+#define MAGNUS_ERROR_LEN 1024
+#define LOG_WARN 0
+#define LOG_FAILURE 3
+#define FILE_PATHSEP '/'
+
+/* ----------------------- Multiple cipher support ------------------------ */
+
+
+#ifdef NET_SSL
+
+static char **cipher_names = NULL;
+typedef struct {
+ char *version;
+ char *name;
+ int num;
+} cipherstruct;
+
+
+static cipherstruct _conf_ciphers[] = {
+ {"SSL3","rc4", SSL_EN_RC4_128_WITH_MD5},
+ {"SSL3","rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
+ {"SSL3","rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
+ {"SSL3","rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
+ /*{"idea", SSL_EN_IDEA_128_CBC_WITH_MD5}, */
+ {"SSL3","des", SSL_EN_DES_64_CBC_WITH_MD5},
+ {"SSL3","desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
+ {"SSL3","rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
+ {"SSL3","rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"SSL3","rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
+ {"SSL3","rsa_fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
+ {"SSL3","rsa_fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
+ {"SSL3","rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
+ {"SSL3","rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
+ {"SSL3","rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
+ {"TLS","tls_rsa_export1024_with_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
+ {"TLS","tls_rsa_export1024_with_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
+ {"SSL3","fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
+ {"SSL3","fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
+ {"SSL3","fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
+
+
+ /*{"SSL3","dhe_dss_40_sha", SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA}, */
+ {"SSL3","dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA},
+ {"SSL3","dhe_dss_3des_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA},
+ /*{"SSL3","dhe_rsa_40_sha", SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA}, */
+ {"SSL3","dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA},
+ {"SSL3","dhe_rsa_3des_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA},
+
+ {"TLS","tls_rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
+ {"TLS","tls_dhe_dss_aes_128_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
+ {"TLS","tls_dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+
+ {"TLS","tls_rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
+ {"TLS","tls_dhe_dss_aes_256_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
+ {"TLS","tls_dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+ /*{"TLS","tls_dhe_dss_1024_des_sha", TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA}, */
+ {"TLS","tls_dhe_dss_1024_rc4_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
+ {"TLS","tls_dhe_dss_rc4_128_sha", TLS_DHE_DSS_WITH_RC4_128_SHA},
+ {NULL, NULL, 0}
+};
+
+char ** getSupportedCiphers()
+{
+ SSLCipherSuiteInfo info;
+ char *sep = "::";
+ int number_of_ciphers = sizeof (_conf_ciphers) /sizeof(cipherstruct);
+ int i;
+ if (cipher_names == NULL ) {
+ cipher_names = (char **) slapi_ch_calloc ((number_of_ciphers +1 ) , sizeof(char *));
+ for (i = 0 ; _conf_ciphers[i].name != NULL; i++ ) {
+ SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[i].num,&info,sizeof(info));
+ cipher_names[i] = PR_smprintf("%s%s%s%s%s%s%s%s%d\0",_conf_ciphers[i].version,sep,_conf_ciphers[i].name,sep,info.symCipherName,sep,info.macAlgorithmName,sep,info.symKeyBits);
+ }
+ cipher_names[i] = NULL;
+ }
+ return cipher_names;
+}
+void
+_conf_setallciphers(int active)
+{
+ int x;
+
+ /* MLM - change: Because null_md5 is NOT encrypted at all, force
+ * them to activate it by name. */
+ for(x = 0; _conf_ciphers[x].name; x++) {
+ if(active && !strcmp(_conf_ciphers[x].name, "rsa_null_md5")) {
+ continue;
+ }
+#ifdef NET_SSL
+ SSL_CipherPrefSetDefault(_conf_ciphers[x].num, active ? PR_TRUE : PR_FALSE);
+#endif
+ }
+}
+
+char *
+_conf_setciphers(char *ciphers)
+{
+ char *t, err[MAGNUS_ERROR_LEN];
+ int x, active;
+ char *raw = ciphers;
+
+ /* Default is to activate all of them */
+ if(!ciphers || ciphers[0] == '\0') {
+ _conf_setallciphers(1);
+ return NULL;
+ }
+/* Enable all the ciphers by default and the following while loop would disable the user disabled ones This is needed becuase we added a new set of ciphers in the table . Right now there is no support for this from the console */
+ _conf_setallciphers(1);
+
+ t = ciphers;
+ while(t) {
+ while((*ciphers) && (isspace(*ciphers))) ++ciphers;
+
+ switch(*ciphers++) {
+ case '+':
+ active = 1; break;
+ case '-':
+ active = 0; break;
+ default:
+ sprintf(err, "invalid ciphers <%s>: format is "
+ "+cipher1,-cipher2...", raw);
+ return slapi_ch_strdup(err);
+ }
+ if( (t = strchr(ciphers, ',')) )
+ *t++ = '\0';
+
+ if(!strcasecmp(ciphers, "all"))
+ _conf_setallciphers(active);
+ else {
+ for(x = 0; _conf_ciphers[x].name; x++) {
+ if(!strcasecmp(ciphers, _conf_ciphers[x].name)) {
+ SSL_CipherPrefSetDefault(_conf_ciphers[x].num, active ? PR_TRUE : PR_FALSE);
+ break;
+ }
+ }
+ if(!_conf_ciphers[x].name) {
+ sprintf(err, "unknown cipher %s", ciphers);
+ return slapi_ch_strdup(err);
+ }
+ }
+ if(t)
+ ciphers = t;
+ }
+ return NULL;
+}
+
+/* SSL Policy stuff */
+
+/*
+ * Policy table
+ */
+static struct policy
+{
+ long ciphersuite;
+ int exportPolicy;
+} policy_table[] = {
+ { SSL_EN_RC4_128_WITH_MD5, SSL_NOT_ALLOWED },
+ { SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_ALLOWED },
+ { SSL_EN_RC2_128_CBC_WITH_MD5, SSL_NOT_ALLOWED },
+ { SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_ALLOWED },
+ { SSL_EN_IDEA_128_CBC_WITH_MD5, SSL_NOT_ALLOWED },
+ { SSL_EN_DES_64_CBC_WITH_MD5, SSL_NOT_ALLOWED },
+ { SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_NOT_ALLOWED },
+
+ /* SSL v3 Cipher Suites */
+ { SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED },
+#if 0
+ { SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED },
+#endif
+ { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED },
+ { SSL_RSA_WITH_RC4_128_MD5, SSL_RESTRICTED },
+#if 0
+ { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED },
+#endif
+ { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED },
+
+#if 0
+ { SSL_RSA_WITH_IDEA_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_ALLOWED },
+#endif
+
+ { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RESTRICTED },
+
+#if 0
+ { SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_ALLOWED },
+ { SSL_DH_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_ALLOWED },
+ { SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED },
+
+ { SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_ALLOWED },
+ { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_ALLOWED },
+ { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED },
+
+ { SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED },
+ { SSL_DH_ANON_WITH_RC4_128_MD5, SSL_NOT_ALLOWED },
+ { SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA, SSL_ALLOWED },
+ { SSL_DH_ANON_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_DH_ANON_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED },
+#endif
+
+ { SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL_NOT_ALLOWED },
+ { SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL_NOT_ALLOWED },
+ { SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED },
+
+ { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_RESTRICTED },
+ { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED },
+};
+
+
+/*
+ * SSLPLCY_Install
+ *
+ * Call the SSL_CipherPolicySet function for each ciphersuite.
+ */
+PRStatus
+SSLPLCY_Install(void)
+{
+
+ SECStatus s = 0;
+
+
+#ifdef NS_DOMESTIC
+
+ s = NSS_SetDomesticPolicy();
+
+#else
+ s = NSS_SetExportPolicy();
+
+#endif
+
+
+ return s?PR_FAILURE:PR_SUCCESS;
+
+}
+
+
+#endif /* NET_SSL */
+
+static void
+slapd_SSL_report(int degree, char *fmt, va_list args)
+{
+ char buf[2048];
+ vsprintf( buf, fmt, args );
+ LDAPDebug( LDAP_DEBUG_ANY, "SSL %s: %s\n",
+ (degree == LOG_FAILURE) ? "failure" : "alert",
+ buf, 0 );
+}
+
+void
+slapd_SSL_error(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ slapd_SSL_report(LOG_FAILURE, fmt, args);
+ exit(1);
+}
+
+void
+slapd_SSL_warn(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ slapd_SSL_report(LOG_WARN, fmt, args);
+ va_end(args);
+}
+
+
+static void
+server_free_alias_dir(char *s)
+{
+ void *mem = s;
+
+ slapi_ch_free(&mem);
+}
+
+
+/**
+ * Get a particular entry
+ */
+static Slapi_Entry *
+getConfigEntry( const char *dn, Slapi_Entry **e2 ) {
+ Slapi_DN sdn;
+
+ slapi_sdn_init_dn_byref( &sdn, dn );
+ slapi_search_internal_get_entry( &sdn, NULL, e2,
+ plugin_get_default_component_id());
+ slapi_sdn_done( &sdn );
+ return *e2;
+}
+
+/**
+ * Free an entry
+ */
+static void
+freeConfigEntry( Slapi_Entry ** e ) {
+ if ( (e != NULL) && (*e != NULL) ) {
+ slapi_entry_free( *e );
+ *e = NULL;
+ }
+}
+
+/**
+ * Get a list of child DNs
+ */
+static char **
+getChildren( char *dn ) {
+ Slapi_PBlock *new_pb = NULL;
+ Slapi_Entry **e;
+ int search_result = 1;
+ int nEntries = 0;
+ char **list = NULL;
+
+ new_pb = slapi_search_internal ( dn, LDAP_SCOPE_ONELEVEL,
+ "(objectclass=nsEncryptionModule)",
+ NULL, NULL, 0);
+
+ slapi_pblock_get( new_pb, SLAPI_NENTRIES, &nEntries);
+ if ( nEntries > 0 ) {
+ slapi_pblock_get( new_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
+ slapi_pblock_get( new_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &e);
+ if ( e != NULL ) {
+ int i;
+ list = (char **)slapi_ch_malloc( sizeof(*list) * (nEntries + 1));
+ for ( i = 0; e[i] != NULL; i++ ) {
+ list[i] = slapi_ch_strdup(slapi_entry_get_dn(e[i]));
+ }
+ list[nEntries] = NULL;
+ }
+ }
+ slapi_free_search_results_internal(new_pb);
+ slapi_pblock_destroy(new_pb );
+ return list;
+}
+
+/**
+ * Free a list of child DNs
+ */
+static void
+freeChildren( char **list ) {
+ if ( list != NULL ) {
+ int i;
+ for ( i = 0; list[i] != NULL; i++ ) {
+ slapi_ch_free( (void **)(&list[i]) );
+ }
+ slapi_ch_free( (void **)(&list) );
+ }
+}
+
+
+/*
+ * slapd_nss_init() is always called from main(), even if we do not
+ * plan to listen on a secure port. If config_available is 0, the
+ * config. entries from dse.ldif are NOT available (used only when
+ * running in referral mode).
+ * As of DS6.1, the init_ssl flag passed is ignored.
+ */
+int
+slapd_nss_init(int init_ssl, int config_available)
+{
+ SECStatus secStatus;
+ PRErrorCode errorCode;
+ char *keyfn = NULL;
+ char *certfn = NULL;
+ char *val = NULL;
+ char certPref[1024];
+ char keyPref[1024];
+ char path[1024];
+ int rv = 0;
+ int len = 0;
+ PRUint32 nssFlags = 0;
+ Slapi_Entry *ec = NULL;
+ char *instancedir;
+
+ if (config_available) {
+ getConfigEntry( configDN, &ec );
+ }
+
+ if ( ec != NULL ) {
+ certfn = slapi_entry_attr_get_charptr( ec, "nscertfile" );
+ keyfn = slapi_entry_attr_get_charptr( ec, "nskeyfile" );
+ slapi_entry_free (ec);
+ ec = NULL;
+ }
+
+ instancedir = config_get_instancedir();
+ strcpy(path, instancedir);
+ slapi_ch_free_string(&instancedir);
+
+ /* make sure path does not end in the path separator character */
+ len = strlen(path);
+ if (path[len-1] == '/' || path[len-1] == '\\') {
+ path[len-1] = '\0';
+ }
+
+ /* get the server root from the path */
+ val = strrchr(path, '/');
+ if (!val) {
+ val = strrchr(path, '\\');
+ }
+ val++;
+
+ if(keyfn && certfn) {
+ if (is_abspath(certfn)) {
+ /* first, initialize path from the certfn */
+ strcpy(path, certfn);
+ /* extract path from cert db filename */
+ val = strrchr(path, '/');
+ if (!val) {
+ val = strrchr(path, '\\');
+ }
+ *val = 0; /* path is initialized */
+ /* next, init the cert db prefix */
+ val++;
+ strcpy(certPref, val);
+ } else {
+ strcpy(val, certfn);
+ val = strrchr(path, '/');
+ if (!val) {
+ val = strrchr(path, '\\');
+ }
+ val++;
+ strcpy(certPref, val);
+ *val = '\0';
+ }
+ /* path represents now the base directory where cert, key, pin, and module db live */
+ /* richm - use strrstr to get the last occurance of -cert in the string, in case
+ the instance is named slapd-cert - the certdb name will be slapd-cert-cert7.db
+ */
+ val = PL_strrstr(certPref, "-cert");
+ val++;
+ *val = '\0';
+ /* certPref keeps the prefix added to the cert db, usually "slapd-myserver-" */
+
+ /* now find the key db prefix */
+ val = strrchr(keyfn, '/');
+ if (!val) {
+ val = strrchr(keyfn, '\\');
+ }
+ if (val != NULL) {
+ val++;
+ } else {
+ val = keyfn;
+ }
+ strcpy(keyPref, val);
+ /* richm - use strrstr to get the last occurance of -key in the string, in case
+ the instance is named slapd-key - the keydb name will be slapd-key-key3.db
+ */
+ val = PL_strrstr(keyPref, "-key");
+ val++;
+ *val = '\0';
+ /* keypref keeps the prefix added to the key db, usually "slapd-myserver-" */
+ } else {
+ if ( config_get_security() ) {
+ /* Have to have the key and cert file names to enable an SSL port */
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to retrieve SSL "
+ "configuration information ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s): "
+ "nskeyfile: %s, nscertfile: %s ",
+ errorCode, slapd_pr_strerror(errorCode),
+ (keyfn ? "found" : "not found"),
+ (certfn ? "found" : "not found"));
+ }
+ sprintf(certPref, "%s-", val);
+ strcpy(keyPref, certPref);
+ strcpy(val, "alias/");
+ }
+
+ slapi_ch_free((void **) &certfn);
+ slapi_ch_free((void **) &keyfn);
+
+ /******** Initialise NSS *********/
+
+ nssFlags &= (~NSS_INIT_READONLY);
+ slapd_pk11_configurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 );
+ secStatus = NSS_Initialize(path, certPref, keyPref, "secmod.db", nssFlags);
+
+ dongle_file_name = PR_smprintf("%s/%spin.txt", path, certPref);
+
+ if (secStatus != SECSuccess) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: NSS initialization failed ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s): "
+ "path: %s, certdb prefix: %s, keydb prefix: %s.",
+ errorCode, slapd_pr_strerror(errorCode), path, certPref, keyPref);
+ rv = -1;
+ }
+
+ /****** end of NSS Initialization ******/
+
+ return rv;
+}
+
+
+
+
+
+/*
+ * slapd_ssl_init() is called from main() if we plan to listen
+ * on a secure port.
+ */
+int
+slapd_ssl_init() {
+ PRErrorCode errorCode;
+ char ** family_list;
+ char *val = NULL;
+ char cipher_string[1024];
+ int rv = 0;
+ PK11SlotInfo *slot;
+#ifndef _WIN32
+ SVRCOREStdPinObj *StdPinObj;
+#else
+ SVRCOREFilePinObj *FilePinObj;
+ SVRCOREAltPinObj *AltPinObj;
+ SVRCORENTUserPinObj *NTUserPinObj;
+#endif
+ Slapi_Entry *entry = NULL;
+
+ /* Get general information */
+
+ getConfigEntry( configDN, &entry );
+
+ val = slapi_entry_attr_get_charptr( entry, "nssslSessionTimeout" );
+ ciphers = slapi_entry_attr_get_charptr( entry, "nsssl3ciphers" );
+
+ /* We are currently using the value of sslSessionTimeout
+ for ssl3SessionTimeout, see SSL_ConfigServerSessionIDCache() */
+ /* Note from Tom Weinstein on the meaning of the timeout:
+
+ Timeouts are in seconds. '0' means use the default, which is
+ 24hrs for SSL3 and 100 seconds for SSL2.
+ */
+
+ if(!val) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to retrieve SSL "
+ "configuration information ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s): "
+ "nssslSessionTimeout: %s ",
+ errorCode, slapd_pr_strerror(errorCode),
+ (val ? "found" : "not found"));
+ slapi_ch_free((void **) &val);
+ slapi_ch_free((void **) &ciphers);
+ return -1;
+ }
+
+ stimeout = atoi(val);
+ slapi_ch_free((void **) &val);
+
+#ifndef _WIN32
+ if ( SVRCORE_CreateStdPinObj(&StdPinObj, dongle_file_name, PR_TRUE) !=
+ SVRCORE_Success) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to create PinObj ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ SVRCORE_RegisterPinObj((SVRCOREPinObj *)StdPinObj);
+#else
+ if (SVRCORE_CreateFilePinObj(&FilePinObj, dongle_file_name) !=
+ SVRCORE_Success) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to create FilePinObj ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ if (SVRCORE_CreateNTUserPinObj(&NTUserPinObj) != SVRCORE_Success){
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to create NTUserPinObj ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ if (SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj,
+ (SVRCOREPinObj *)NTUserPinObj) != SVRCORE_Success) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to create AltPinObj ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ SVRCORE_RegisterPinObj((SVRCOREPinObj *)AltPinObj);
+
+#endif /* _WIN32 */
+
+ if((family_list = getChildren(configDN))) {
+ char **family;
+ char *token;
+ char *activation;
+
+ for (family = family_list; *family; family++) {
+
+ token = NULL;
+ activation = NULL;
+
+ freeConfigEntry( &entry );
+
+ getConfigEntry( *family, &entry );
+ if ( entry == NULL ) {
+ continue;
+ }
+
+ activation = slapi_entry_attr_get_charptr( entry, "nssslactivation" );
+ if((!activation) || (!strcasecmp(activation, "off"))) {
+ /* this family was turned off, goto next */
+ slapi_ch_free((void **) &activation);
+ continue;
+ }
+
+ slapi_ch_free((void **) &activation);
+
+ token = slapi_entry_attr_get_charptr( entry, "nsssltoken" );
+ if( token ) {
+ if( !strcasecmp(token, "internal") ||
+ !strcasecmp(token, "internal (software)"))
+ slot = slapd_pk11_getInternalKeySlot();
+ else
+ slot = slapd_pk11_findSlotByName(token);
+ } else {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to get token ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+
+ slapi_ch_free((void **) &token);
+
+ if (!slot) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to find slot ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ /* authenticate */
+ if(slapd_pk11_authenticate(slot, PR_TRUE, NULL) != SECSuccess)
+ {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to authenticate ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ }
+ freeChildren( family_list );
+ }
+ freeConfigEntry( &entry );
+
+ if(SSLPLCY_Install() != PR_SUCCESS) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to set SSL export policy ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+
+
+ /* ugaston- Cipher preferences must be set before any sslSocket is created
+ * for such sockets to take preferences into account.
+ */
+
+ /* Step Three.5: Set SSL cipher preferences */
+ *cipher_string = 0;
+ if(ciphers && (*ciphers) && strcmp(ciphers, "blank"))
+ strcpy(cipher_string, ciphers);
+ slapi_ch_free((void **) &ciphers);
+
+ if( NULL != (val = _conf_setciphers(cipher_string)) ) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to set SSL cipher "
+ "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ val, errorCode, slapd_pr_strerror(errorCode));
+ rv = 3;
+ slapi_ch_free((void **) &val);
+ }
+
+ freeConfigEntry( &entry );
+
+
+ /* Introduce a way of knowing whether slapd_ssl_init has
+ * already been executed. */
+ _security_library_initialized = 1;
+
+
+ if ( rv != 0 )
+ return rv;
+
+
+ return 0;
+
+}
+
+
+int slapd_ssl_init2(PRFileDesc **fd, int startTLS)
+{
+ PRFileDesc *pr_sock, *sock = (*fd);
+ PRErrorCode errorCode;
+ SECStatus rv = SECFailure;
+ char ** family_list;
+ CERTCertificate *cert = NULL;
+ SECKEYPrivateKey *key = NULL;
+ char errorbuf[BUFSIZ];
+ char *val = NULL;
+ int nFamilies = 0;
+ SECStatus sslStatus;
+ int slapd_SSLclientAuth;
+ char* tmpDir;
+ Slapi_Entry *e = NULL;
+
+ /* turn off the PKCS11 pin interactive mode */
+#ifndef _WIN32
+ SVRCOREStdPinObj *StdPinObj;
+
+ StdPinObj = (SVRCOREStdPinObj *)SVRCORE_GetRegisteredPinObj();
+ SVRCORE_SetStdPinInteractive(StdPinObj, PR_FALSE);
+#endif
+
+ errorbuf[0] = '\0';
+
+ /* Import pr fd into SSL */
+ pr_sock = SSL_ImportFD( NULL, sock );
+ if( pr_sock == (PRFileDesc *)NULL ) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to import NSPR "
+ "fd into SSL (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return 1;
+ }
+
+ (*fd) = pr_sock;
+
+ /* Step / Three.6 /
+ * - If in FIPS mode, authenticate to the token before
+ * doing anything else
+ */
+ {
+ PK11SlotInfo *slot = slapd_pk11_getInternalSlot();
+ if (!slot) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to get internal slot ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+
+ if(slapd_pk11_isFIPS()) {
+ if(slapd_pk11_authenticate(slot, PR_TRUE, NULL) != SECSuccess) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to authenticate ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+ }
+
+ slapd_pk11_setSlotPWValues(slot, 0, 0);
+ }
+
+
+
+ /*
+ * Now, get the complete list of cipher families. Each family
+ * has a token name and personality name which we'll use to find
+ * appropriate keys and certs, and call SSL_ConfigSecureServer
+ * with.
+ */
+
+ if((family_list = getChildren(configDN))) {
+ char **family;
+ char cert_name[1024];
+ char *token;
+ char *personality;
+ char *activation;
+
+ for (family = family_list; *family; family++) {
+ token = NULL;
+ personality = NULL;
+ activation = NULL;
+
+ getConfigEntry( *family, &e );
+ if ( e == NULL ) {
+ continue;
+ }
+
+ activation = slapi_entry_attr_get_charptr( e, "nssslactivation" );
+ if((!activation) || (!strcasecmp(activation, "off"))) {
+ /* this family was turned off, goto next */
+ slapi_ch_free((void **) &activation);
+ freeConfigEntry( &e );
+ continue;
+ }
+
+ slapi_ch_free((void **) &activation);
+
+ token = slapi_entry_attr_get_charptr( e, "nsssltoken" );
+ personality = slapi_entry_attr_get_charptr( e, "nssslpersonalityssl" );
+ if( token && personality ) {
+ if( !strcasecmp(token, "internal") ||
+ !strcasecmp(token, "internal (software)") )
+ strcpy(cert_name, personality);
+ else
+ /* external PKCS #11 token - attach token name */
+ sprintf(cert_name, "%s:%s", token, personality);
+ }
+ else {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to get cipher "
+ "family information. Missing nsssltoken or"
+ "nssslpersonalityssl in %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ *family, errorCode, slapd_pr_strerror(errorCode));
+ slapi_ch_free((void **) &token);
+ slapi_ch_free((void **) &personality);
+ freeConfigEntry( &e );
+ continue;
+ }
+
+ slapi_ch_free((void **) &token);
+
+ /* Step Four -- Locate the server certificate */
+ cert = slapd_pk11_findCertFromNickname(cert_name, NULL);
+
+ if (cert == NULL) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Can't find "
+ "certificate (%s) for family %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ cert_name, *family,
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+ /* Step Five -- Get the private key from cert */
+ if( cert != NULL )
+ key = slapd_pk11_findKeyByAnyCert(cert, NULL);
+
+ if (key == NULL) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Unable to retrieve "
+ "private key for cert %s of family %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ cert_name, *family,
+ errorCode, slapd_pr_strerror(errorCode));
+ slapi_ch_free((void **) &personality);
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ freeConfigEntry( &e );
+ continue;
+ }
+
+ /* Step Six -- Configure Secure Server Mode */
+ if(pr_sock) {
+ SECCertificateUsage returnedUsages;
+ rv = CERT_VerifyCertificateNow(
+ CERT_GetDefaultCertDB(), cert, PR_TRUE,
+ certificateUsageSSLServer,
+ SSL_RevealPinArg(pr_sock),
+ &returnedUsages);
+ if (SECSuccess == rv) {
+ if( slapd_pk11_fortezzaHasKEA(cert) == PR_TRUE ) {
+ rv = SSL_ConfigSecureServer(*fd, cert, key, kt_fortezza);
+ }
+ else {
+ rv = SSL_ConfigSecureServer(*fd, cert, key, kt_rsa);
+ }
+ if (SECSuccess != rv) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("ConfigSecureServer: "
+ "Server key/certificate is "
+ "bad for cert %s of family %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ cert_name, *family, errorCode,
+ slapd_pr_strerror(errorCode));
+ }
+ } else {
+ /* verify certificate failed */
+ /* If the common name in the subject DN for the certificate
+ * is not identical to the domain name passed in the
+ * hostname parameter, SECFailure. */
+ errorCode = PR_GetError();
+ slapd_SSL_warn("CERT_VerifyCertificateNow: "
+ "verify certificate failed "
+ "for cert %s of family %s ("
+ SLAPI_COMPONENT_NAME_NSPR
+ " error %d - %s)",
+ cert_name, *family, errorCode,
+ slapd_pr_strerror(errorCode));
+ }
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ if (SECSuccess != rv) {
+ slapi_ch_free((void **) &personality);
+ freeConfigEntry( &e );
+ continue;
+ }
+ nFamilies++;
+ freeConfigEntry( &e );
+ }
+ freeChildren( family_list );
+ }
+
+
+ if ( !nFamilies ) {
+ slapd_SSL_error("None of the cipher are valid");
+ return -1;
+ }
+
+ /* Step Seven -- Configure Server Session ID Cache */
+
+ tmpDir = slapd_get_tmp_dir();
+
+ slapi_log_error(
+ SLAPI_LOG_TRACE,
+ "slapd_ssl_init2",
+ "tmp dir = %s\n", tmpDir);
+
+ rv = SSL_ConfigServerSessionIDCache(0, stimeout, stimeout, tmpDir);
+ if (rv) {
+ errorCode = PR_GetError();
+ if (errorCode == ENOSPC) {
+ slapd_SSL_error("Config of server nonce cache failed, "
+ "out of disk space! Make more room in /tmp "
+ "and try again. (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+ else {
+ slapd_SSL_error("Config of server nonce cache failed (error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+ return rv;
+ }
+
+ sslStatus = SSL_OptionSet(pr_sock, SSL_SECURITY, PR_TRUE);
+ if (sslStatus != SECSuccess) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to enable security "
+ "on the imported socket (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ return -1;
+ }
+
+ sslStatus = SSL_OptionSet(pr_sock, SSL_ENABLE_SSL3, PR_TRUE);
+ if (sslStatus != SECSuccess) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to enable SSLv3 "
+ "on the imported socket (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+
+ sslStatus = SSL_OptionSet(pr_sock, SSL_ENABLE_TLS, PR_TRUE);
+ if (sslStatus != SECSuccess) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to enable TLS "
+ "on the imported socket (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+/* Explicitly disabling SSL2 - NGK */
+ sslStatus = SSL_OptionSet(pr_sock, SSL_ENABLE_SSL2, PR_FALSE);
+
+ /* Retrieve the SSL Client Authentication status from cn=config */
+ /* Set a default value if no value found */
+ getConfigEntry( configDN, &e );
+ val = NULL;
+ if ( e != NULL ) {
+ val = slapi_entry_attr_get_charptr( e, "nssslclientauth" );
+ }
+
+ if( !val ) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Cannot get SSL Client "
+ "Authentication status. No nsslclientauth in %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ configDN, errorCode, slapd_pr_strerror(errorCode));
+ switch( SLAPD_SSLCLIENTAUTH_DEFAULT ) {
+ case SLAPD_SSLCLIENTAUTH_OFF:
+ val = "off";
+ break;
+ case SLAPD_SSLCLIENTAUTH_ALLOWED:
+ val = "allowed";
+ break;
+ case SLAPD_SSLCLIENTAUTH_REQUIRED:
+ val = "required";
+ break;
+ default:
+ val = "allowed";
+ break;
+ }
+ }
+ if( config_set_SSLclientAuth( "nssslclientauth", val, errorbuf,
+ CONFIG_APPLY ) != LDAP_SUCCESS ) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Cannot set SSL Client "
+ "Authentication status to \"%s\", error (%s). "
+ "Supported values are \"off\", \"allowed\" "
+ "and \"required\". (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ val, errorbuf, errorCode, slapd_pr_strerror(errorCode));
+ }
+
+ freeConfigEntry( &e );
+
+ if(( slapd_SSLclientAuth = config_get_SSLclientAuth()) != SLAPD_SSLCLIENTAUTH_OFF ) {
+ int err;
+ switch (slapd_SSLclientAuth) {
+ case SLAPD_SSLCLIENTAUTH_ALLOWED:
+#ifdef SSL_REQUIRE_CERTIFICATE /* new feature */
+ if ((err = SSL_OptionSet (pr_sock, SSL_REQUIRE_CERTIFICATE, PR_FALSE)) < 0) {
+ PRErrorCode prerr = PR_GetError();
+ LDAPDebug (LDAP_DEBUG_ANY,
+ "SSL_OptionSet(SSL_REQUIRE_CERTIFICATE,PR_FALSE) %d "
+ SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ err, prerr, slapd_pr_strerror(prerr));
+ }
+#endif
+ /* Give the client a clear opportunity to send her certificate: */
+ case SLAPD_SSLCLIENTAUTH_REQUIRED:
+ if ((err = SSL_OptionSet (pr_sock, SSL_REQUEST_CERTIFICATE, PR_TRUE)) < 0) {
+ PRErrorCode prerr = PR_GetError();
+ LDAPDebug (LDAP_DEBUG_ANY,
+ "SSL_OptionSet(SSL_REQUEST_CERTIFICATE,PR_TRUE) %d "
+ SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ err, prerr, slapd_pr_strerror(prerr));
+ }
+ default: break;
+ }
+ }
+
+ /* Introduce a way of knowing whether slapd_ssl_init2 has
+ * already been executed.
+ * The cases in which slapd_ssl_init2 is executed during an
+ * Start TLS operation are not taken into account, for it is
+ * the fact of being executed by the server's SSL listener socket
+ * that matters. */
+
+ if (!startTLS)
+ _ssl_listener_initialized = 1; /* --ugaston */
+
+ return 0;
+}
+
+/* richm 20020227
+ To do LDAP client SSL init, we need to do
+
+ static void
+ ldapssl_basic_init( void )
+ {
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ PR_SetConcurrency( 4 );
+ }
+ NSS_Init(certdbpath);
+ SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE);
+ SSL_OptionSetDefault(SSL_ENABLE_SSLdirs
+3, PR_TRUE);
+#ifdef NS_DOMESTIC
+ s = NSS_SetDomesticPolicy();
+#elif NS_EXPORT
+ s = NSS_SetExportPolicy();
+
+We already do pr_init, we don't need pr_setconcurrency, we already do nss_init and the rest
+
+*/
+
+int
+slapd_SSL_client_init()
+{
+ return 0;
+}
+
+static int
+slapd_SSL_client_auth (LDAP* ld)
+{
+ int rc = 0;
+ PRErrorCode errorCode;
+ char* pw = NULL;
+ char ** family_list;
+ Slapi_Entry *entry = NULL;
+ char cert_name[1024];
+ char *token = NULL;
+#ifndef _WIN32
+ SVRCOREStdPinObj *StdPinObj;
+#else
+ SVRCOREAltPinObj *AltPinObj;
+#endif
+ SVRCOREError err = SVRCORE_Success;
+
+ if((family_list = getChildren(configDN))) {
+ char **family;
+ char *personality = NULL;
+ char *activation = NULL;
+ char *cipher = NULL;
+
+ for (family = family_list; *family; family++) {
+ getConfigEntry( *family, &entry );
+ if ( entry == NULL ) {
+ continue;
+ }
+
+ activation = slapi_entry_attr_get_charptr( entry, "nssslactivation" );
+ if((!activation) || (!strcasecmp(activation, "off"))) {
+ /* this family was turned off, goto next */
+ slapi_ch_free((void **) &activation);
+ freeConfigEntry( &entry );
+ continue;
+ }
+
+ slapi_ch_free((void **) &activation);
+
+ personality = slapi_entry_attr_get_charptr( entry, "nssslpersonalityssl" );
+ cipher = slapi_entry_attr_get_charptr( entry, "cn" );
+ if ( cipher && !strcasecmp(cipher, "RSA" )) {
+ char *ssltoken;
+
+ /* If there already is a token name, use it */
+ if (token) {
+ slapi_ch_free((void **) &personality);
+ slapi_ch_free((void **) &cipher);
+ freeConfigEntry( &entry );
+ continue;
+ }
+
+ ssltoken = slapi_entry_attr_get_charptr( entry, "nsssltoken" );
+ if( ssltoken && personality ) {
+ if( !strcasecmp(ssltoken, "internal") ||
+ !strcasecmp(ssltoken, "internal (software)") ) {
+
+ /* Translate config internal name to more
+ * readable form. Certificate name is just
+ * the personality for internal tokens.
+ */
+ token = slapi_ch_strdup(internalTokenName);
+ strcpy(cert_name, personality);
+ slapi_ch_free((void **) &ssltoken);
+ } else {
+ /* external PKCS #11 token - attach token name */
+ /*ssltoken was already dupped and we don't need it anymore*/
+ token = ssltoken;
+ sprintf(cert_name, "%s:%s", token, personality);
+ }
+ } else {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to get cipher "
+ "family information. Missing nsssltoken or"
+ "nssslpersonalityssl in %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ *family, errorCode, slapd_pr_strerror(errorCode));
+ slapi_ch_free((void **) &ssltoken);
+ slapi_ch_free((void **) &personality);
+ slapi_ch_free((void **) &cipher);
+ freeConfigEntry( &entry );
+ continue;
+ }
+ } else { /* external PKCS #11 cipher */
+ char *ssltoken;
+
+ ssltoken = slapi_entry_attr_get_charptr( entry, "nsssltoken" );
+ if( token && personality ) {
+
+ /* free the old token and remember the new one */
+ if (token) slapi_ch_free((void **)&token);
+ token = ssltoken; /*ssltoken was already dupped and we don't need it anymore*/
+
+ /* external PKCS #11 token - attach token name */
+ sprintf(cert_name, "%s:%s", token, personality);
+ } else {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("Security Initialization: Failed to get cipher "
+ "family information. Missing nsssltoken or"
+ "nssslpersonalityssl in %s ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ *family, errorCode, slapd_pr_strerror(errorCode));
+ slapi_ch_free((void **) &ssltoken);
+ slapi_ch_free((void **) &personality);
+ slapi_ch_free((void **) &cipher);
+ freeConfigEntry( &entry );
+ continue;
+ }
+
+ }
+ slapi_ch_free((void **) &personality);
+ slapi_ch_free((void **) &cipher);
+ freeConfigEntry( &entry );
+ } /* end of for */
+
+ freeChildren( family_list );
+ }
+
+ /* Free config data */
+
+ /* We cannot allow NSS to cache outgoing client auth connections -
+ each client auth connection must have it's own non-shared SSL
+ connection to the peer so that it will go through the
+ entire handshake protocol every time including the use of its
+ own unique client cert - see bug 605457
+ */
+
+ ldapssl_set_option(ld, SSL_NO_CACHE, PR_TRUE);
+
+#ifndef _WIN32
+ StdPinObj = (SVRCOREStdPinObj *)SVRCORE_GetRegisteredPinObj();
+ err = SVRCORE_StdPinGetPin( &pw, StdPinObj, token );
+#else
+ AltPinObj = (SVRCOREAltPinObj *)SVRCORE_GetRegisteredPinObj();
+ pw = SVRCORE_GetPin( (SVRCOREPinObj *)AltPinObj, token, PR_FALSE);
+#endif
+ if ( err != SVRCORE_Success || pw == NULL) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("SSL client authentication cannot be used "
+ "(no password). (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ errorCode, slapd_pr_strerror(errorCode));
+ } else {
+ rc = ldapssl_enable_clientauth (ld, SERVER_KEY_NAME, pw, cert_name);
+ if (rc != 0) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("ldapssl_enable_clientauth(%s, %s) %i ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ SERVER_KEY_NAME, cert_name, rc,
+ errorCode, slapd_pr_strerror(errorCode));
+ }
+ }
+
+ if (token) slapi_ch_free((void**)&token);
+ slapi_ch_free((void**)&pw);
+
+ LDAPDebug (LDAP_DEBUG_TRACE, "slapd_SSL_client_auth() %i\n", rc, 0, 0);
+ return rc;
+}
+
+int
+slapd_simple_client_bind_s(LDAP* ld, char* DN, char* pw, int LDAPv)
+{
+ int rc;
+ PRErrorCode errorCode;
+
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, (void *) &LDAPv);
+ rc = ldap_simple_bind_s (ld, DN, pw);
+ if (rc != 0) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("ldap_simple_bind_s(%s, %s) %i (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ DN, pw, rc, errorCode, slapd_pr_strerror(errorCode));
+ }
+ LDAPDebug (LDAP_DEBUG_TRACE, "slapd_simple_client_bind_s(%s, %i) %i\n", DN, LDAPv, rc);
+ return rc;
+}
+
+int
+slapd_SSL_client_bind_s (LDAP* ld, char* DN, char* pw, int use_SSL, int LDAPv)
+{
+ int rc;
+ struct berval noCred = {0, 0};
+
+ if (!use_SSL || LDAPv == LDAP_VERSION2) {
+ rc = slapd_simple_client_bind_s(ld, DN, pw, LDAPv);
+ } else {
+
+ LDAPDebug (
+ LDAP_DEBUG_TRACE,
+ "slapd_SSL_client_bind_s: Trying SSL Client Authentication\n",
+ 0, 0, 0);
+
+ rc = slapd_SSL_client_auth(ld);
+
+ if(rc != 0)
+ {
+ LDAPDebug (
+ LDAP_DEBUG_TRACE,
+ "slapd_SSL_client_bind_s: SSL Client Auth Failed during replication Bind\n",
+ 0, 0, 0);
+ return rc;
+ }
+
+ rc = ldap_sasl_bind_s (ld, "", LDAP_SASL_EXTERNAL, &noCred,
+ NULL /* LDAPControl **serverctrls */,
+ NULL /* LDAPControl **clientctrls */,
+ NULL /* struct berval **servercredp */);
+
+ }
+ LDAPDebug (
+ LDAP_DEBUG_TRACE,
+ "slapd_SSL_client_bind_s(%i,%i) %i\n", use_SSL, LDAPv, rc);
+ return rc;
+}
+
+int
+slapd_sasl_ext_client_bind (LDAP* ld, int **msgid)
+{
+ int rc;
+ PRErrorCode errorCode;
+ struct berval noCred = {0, 0};
+
+ LDAPDebug (
+ LDAP_DEBUG_TRACE,
+ "slapd_sasl_ext_client_bind: Trying SSL Client Authentication\n",
+ 0, 0, 0);
+
+ rc = slapd_SSL_client_auth(ld);
+ if(rc != 0)
+ {
+ LDAPDebug (
+ LDAP_DEBUG_TRACE,
+ "slapd_sasl_ext_client_bind: SSL Client Auth Failed during replication Bind\n",
+ 0, 0, 0);
+ return rc;
+ }
+
+ rc = ldap_sasl_bind (ld, "", LDAP_SASL_EXTERNAL, &noCred,
+ NULL,
+ NULL,
+ *msgid);
+ if (rc != 0) {
+ errorCode = PR_GetError();
+ slapd_SSL_warn("ldap_sasl_bind(\"\",LDAP_SASL_EXTERNAL) %i (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ rc, errorCode, slapd_pr_strerror(errorCode));
+ }
+
+ LDAPDebug (
+ LDAP_DEBUG_TRACE,
+ "slapd_sasl_ext_client_bind %i\n", rc, 0, 0);
+
+ return rc;
+}
+
+
+int slapd_Client_auth(LDAP* ld)
+{
+ int rc=0;
+
+ rc = slapd_SSL_client_auth (ld);
+
+ return rc;
+}
+
+
+/* Function for keeping track of the SSL initialization status:
+ * - returns 1: when slapd_ssl_init has been executed
+ */
+int
+slapd_security_library_is_initialized()
+{
+ return _security_library_initialized;
+}
+
+
+/* Function for keeping track of the SSL listener socket initialization status:
+ * - returns 1: when slapd_ssl_init2 has been executed
+ */
+int
+slapd_ssl_listener_is_initialized()
+{
+ return _ssl_listener_initialized;
+}
+
+
+char* slapd_get_tmp_dir()
+{
+ static char tmpdir[] = "/tmp";
+ static char tmp[256];
+ char* instanceDir;
+#if defined( XP_WIN32 )
+ unsigned ilen;
+ char pch;
+#endif
+ struct stat ffinfo;
+
+ tmp[0] = '\0';
+
+ if((instanceDir = config_get_instancedir()) == NULL)
+ {
+ slapi_log_error(
+ SLAPI_LOG_FATAL,
+ "slapd_get_tmp_dir",
+ "config_get_instancedir returns NULL Setting tmp dir to default\n");
+
+#if defined( XP_WIN32 )
+ ilen = strlen(tmp);
+ GetTempPath( ilen+1, tmp );
+ /* Remove trailing slash. */
+ pch = tmp[ilen-1];
+ if( pch == '\\' || pch == '/' )
+ tmp[ilen-1] = '\0';
+ return tmp;
+#else
+ return( tmpdir );
+#endif
+ }
+
+ sprintf(tmp,"%s/tmp",instanceDir);
+
+#if defined( XP_WIN32 )
+ for(ilen=0;ilen < strlen(tmp); ilen++)
+ {
+ if(tmp[ilen]=='/')
+ tmp[ilen]='\\';
+ }
+#endif
+
+ if(stat(tmp,&ffinfo) == -1)
+#if defined( XP_WIN32 )
+ if(CreateDirectory(tmp, NULL) == 0)
+ {
+ slapi_log_error(
+ SLAPI_LOG_FATAL,
+ "slapd_get_tmp_dir",
+ "CreateDirectory(%s, NULL) Error: %s\n",
+ tmp, strerror(errno));
+ return ( tmpdir );
+ }
+#else
+ if(mkdir(tmp, 00770) == -1)
+ {
+ slapi_log_error(
+ SLAPI_LOG_FATAL,
+ "slapd_get_tmp_dir",
+ "mkdir(%s, 00770) Error: %s\n",
+ tmp, strerror(errno));
+ return ( tmpdir );
+ }
+#endif
+
+ return ( tmp );
+
+}
+
+#endif /* NET_SSL */