tstellar / rpms / openldap

Forked from rpms/openldap 3 years ago
Clone
Jan Vcelak ce2de96
Enhancement, support multiple cert/key databases in tha same directory with another prefix.
Jan Vcelak ce2de96
Jan Vcelak ce2de96
Upstream ITS: #6689
Jan Vcelak ce2de96
Jan Vcelak ce2de96
--- openldap.old/libraries/libldap/tls_m.c	21 Jul 2010 20:57:01 -0000	1.18
Jan Vcelak ce2de96
+++ openldap.new/libraries/libldap/tls_m.c	28 Oct 2010 19:55:51 -0000
Jan Vcelak ce2de96
@@ -1202,16 +1202,55 @@
Jan Vcelak ce2de96
 			return -1;
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 	}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	return 0;
Jan Vcelak ce2de96
 }
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 /*
Jan Vcelak ce2de96
+ * NSS supports having multiple cert/key databases in the same
Jan Vcelak ce2de96
+ * directory, each one having a unique string prefix e.g.
Jan Vcelak ce2de96
+ * slapd-01-cert8.db - the prefix here is "slapd-01-"
Jan Vcelak ce2de96
+ * this function examines the given certdir - if it looks like
Jan Vcelak ce2de96
+ * /path/to/directory/prefix it will return the
Jan Vcelak ce2de96
+ * /path/to/directory part in realcertdir, and the prefix in prefix
Jan Vcelak ce2de96
+ */
Jan Vcelak ce2de96
+static void
Jan Vcelak ce2de96
+tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix )
Jan Vcelak ce2de96
+{
Jan Vcelak ce2de96
+	char sep = PR_GetDirectorySeparator();
Jan Vcelak ce2de96
+	char *ptr = NULL;
Jan Vcelak ce2de96
+	struct PRFileInfo prfi;
Jan Vcelak ce2de96
+	PRStatus prc;
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+	*realcertdir = (char *)certdir; /* default is the one passed in */
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+	/* if certdir is not given, just return */
Jan Vcelak ce2de96
+	if ( !certdir ) {
Jan Vcelak ce2de96
+		return;
Jan Vcelak ce2de96
+	}
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+	prc = PR_GetFileInfo( certdir, &prfi );
Jan Vcelak ce2de96
+	/* if certdir exists (file or directory) then it cannot specify a prefix */
Jan Vcelak ce2de96
+	if ( prc == PR_SUCCESS ) {
Jan Vcelak ce2de96
+		return;
Jan Vcelak ce2de96
+	}
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+	/* if certdir was given, and there is a '/' in certdir, see if there
Jan Vcelak ce2de96
+	   is anything after the last '/' - if so, assume it is the prefix */
Jan Vcelak ce2de96
+	if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) {
Jan Vcelak ce2de96
+		*realcertdir = PL_strndup( certdir, ptr-certdir );
Jan Vcelak ce2de96
+		*prefix = PL_strdup( ptr+1 );
Jan Vcelak ce2de96
+	}
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+	return;
Jan Vcelak ce2de96
+}
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+/*
Jan Vcelak ce2de96
  * This is the part of the init we defer until we get the
Jan Vcelak ce2de96
  * actual security configuration information.  This is
Jan Vcelak ce2de96
  * only called once, protected by a PRCallOnce
Jan Vcelak ce2de96
  * NOTE: This must be done before the first call to SSL_ImportFD,
Jan Vcelak ce2de96
  * especially the setting of the policy
Jan Vcelak ce2de96
  * NOTE: This must be called after fork()
Jan Vcelak ce2de96
  */
Jan Vcelak ce2de96
 static int
Jan Vcelak ce2de96
@@ -1223,16 +1262,17 @@
Jan Vcelak ce2de96
 	int ii;
Jan Vcelak ce2de96
 	int nn;
Jan Vcelak ce2de96
 	PRErrorCode errcode = 1;
Jan Vcelak ce2de96
 #ifdef HAVE_NSS_INITCONTEXT
Jan Vcelak ce2de96
 	NSSInitParameters initParams;
Jan Vcelak ce2de96
 	NSSInitContext *initctx = NULL;
Jan Vcelak ce2de96
 #endif
Jan Vcelak ce2de96
 	SECStatus rc;
Jan Vcelak ce2de96
+	int done = 0;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 #ifdef HAVE_NSS_INITCONTEXT
Jan Vcelak ce2de96
 	memset( &initParams, 0, sizeof( initParams ) );
Jan Vcelak ce2de96
 	initParams.length = sizeof( initParams );
Jan Vcelak ce2de96
 #endif /* HAVE_NSS_INITCONTEXT */
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 #ifndef HAVE_NSS_INITCONTEXT
Jan Vcelak ce2de96
 	if ( !NSS_IsInitialized() ) {
Jan Vcelak ce2de96
@@ -1246,50 +1286,61 @@
Jan Vcelak ce2de96
 		  DEFAULT_MOZNSS_DIR will only be used if the code cannot
Jan Vcelak ce2de96
 		  find a security dir to use based on the current
Jan Vcelak ce2de96
 		  settings
Jan Vcelak ce2de96
 		*/
Jan Vcelak ce2de96
 		nn = 0;
Jan Vcelak ce2de96
 		securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
Jan Vcelak ce2de96
 		securitydirs[nn++] = lt->lt_cacertdir;
Jan Vcelak ce2de96
 		securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
Jan Vcelak ce2de96
-		for ( ii = 0; ii < nn; ++ii ) {
Jan Vcelak ce2de96
+		for ( ii = 0; !done && ( ii < nn ); ++ii ) {
Jan Vcelak ce2de96
+			char *realcertdir = NULL;
Jan Vcelak ce2de96
+			const char *defprefix = "";
Jan Vcelak ce2de96
+			char *prefix = (char *)defprefix;
Jan Vcelak ce2de96
 			const char *securitydir = securitydirs[ii];
Jan Vcelak ce2de96
 			if ( NULL == securitydir ) {
Jan Vcelak ce2de96
 				continue;
Jan Vcelak ce2de96
 			}
Jan Vcelak ce2de96
+
Jan Vcelak ce2de96
+			tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
Jan Vcelak ce2de96
 #ifdef HAVE_NSS_INITCONTEXT
Jan Vcelak ce2de96
 #ifdef INITCONTEXT_HACK
Jan Vcelak ce2de96
 			if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
Jan Vcelak ce2de96
-				rc = NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY );
Jan Vcelak ce2de96
+				rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
Jan Vcelak ce2de96
 			} else {
Jan Vcelak ce2de96
-				initctx = NSS_InitContext( securitydir, "", "", SECMOD_DB,
Jan Vcelak ce2de96
+				initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
Jan Vcelak ce2de96
 										   &initParams, NSS_INIT_READONLY );
Jan Vcelak ce2de96
 				rc = (initctx == NULL) ? SECFailure : SECSuccess;
Jan Vcelak ce2de96
 			}
Jan Vcelak ce2de96
 #else
Jan Vcelak ce2de96
-			initctx = NSS_InitContext( securitydir, "", "", SECMOD_DB,
Jan Vcelak ce2de96
+			initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
Jan Vcelak ce2de96
 									   &initParams, NSS_INIT_READONLY );
Jan Vcelak ce2de96
 			rc = (initctx == NULL) ? SECFailure : SECSuccess;
Jan Vcelak ce2de96
 #endif
Jan Vcelak ce2de96
 #else
Jan Vcelak ce2de96
-			rc = NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY );
Jan Vcelak ce2de96
+			rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
Jan Vcelak ce2de96
 #endif
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 			if ( rc != SECSuccess ) {
Jan Vcelak ce2de96
 				errcode = PORT_GetError();
Jan Vcelak ce2de96
 				Debug( LDAP_DEBUG_TRACE,
Jan Vcelak ce2de96
-					   "TLS: could not initialize moznss using security dir %s - error %d:%s.\n",
Jan Vcelak ce2de96
-					   securitydir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
Jan Vcelak ce2de96
+					   "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
Jan Vcelak ce2de96
+					   realcertdir, prefix, errcode );
Jan Vcelak ce2de96
 			} else {
Jan Vcelak ce2de96
 				/* success */
Jan Vcelak ce2de96
-				Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s.\n",
Jan Vcelak ce2de96
-					   securitydir, 0, 0 );
Jan Vcelak ce2de96
+				Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n",
Jan Vcelak ce2de96
+					   realcertdir, prefix, 0 );
Jan Vcelak ce2de96
 				errcode = 0;
Jan Vcelak ce2de96
-				break;
Jan Vcelak ce2de96
+				done = 1;
Jan Vcelak ce2de96
+			}
Jan Vcelak ce2de96
+			if ( realcertdir != securitydir ) {
Jan Vcelak ce2de96
+				PL_strfree( realcertdir );
Jan Vcelak ce2de96
+			}
Jan Vcelak ce2de96
+			if ( prefix != defprefix ) {
Jan Vcelak ce2de96
+				PL_strfree( prefix );
Jan Vcelak ce2de96
 			}
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 		if ( errcode ) { /* no moznss db found, or not using moznss db */
Jan Vcelak ce2de96
 #ifdef HAVE_NSS_INITCONTEXT
Jan Vcelak ce2de96
 			int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
Jan Vcelak ce2de96
 #ifdef INITCONTEXT_HACK
Jan Vcelak ce2de96
 			if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
Jan Vcelak ce2de96
@@ -2038,19 +2089,16 @@
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 		errno = 0;
Jan Vcelak ce2de96
 		rc = SSL_ForceHandshake( s );
Jan Vcelak ce2de96
 		if (rc == SECSuccess) {
Jan Vcelak ce2de96
 			rc = 0;
Jan Vcelak ce2de96
 			break; /* done */
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 		err = PR_GetError();
Jan Vcelak ce2de96
-		Debug( LDAP_DEBUG_TRACE, 
Jan Vcelak ce2de96
-			   "TLS: error: accept - force handshake failure %d - error %d waitcounter %d\n",
Jan Vcelak ce2de96
-			   errno, err, waitcounter );
Jan Vcelak ce2de96
 		if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
Jan Vcelak ce2de96
 			waitcounter++;
Jan Vcelak ce2de96
 			in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
Jan Vcelak ce2de96
 			out_flags = 0;
Jan Vcelak ce2de96
 			errno = 0;
Jan Vcelak ce2de96
 			filesReady = tlsm_is_io_ready( s, in_flags, &out_flags );
Jan Vcelak ce2de96
 			if ( filesReady < 0 ) {
Jan Vcelak ce2de96
 				err = PR_GetError();
Jan Vcelak ce2de96
@@ -2155,49 +2203,49 @@
Jan Vcelak ce2de96
 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
Jan Vcelak ce2de96
 {
Jan Vcelak ce2de96
 	tlsm_session *s = (tlsm_session *)session;
Jan Vcelak ce2de96
 	CERTCertificate *cert;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	cert = SSL_LocalCertificate( s );
Jan Vcelak ce2de96
 	if (!cert) return LDAP_INVALID_CREDENTIALS;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
-	der_dn->bv_val = cert->derSubject.data;
Jan Vcelak ce2de96
+	der_dn->bv_val = (char *)cert->derSubject.data;
Jan Vcelak ce2de96
 	der_dn->bv_len = cert->derSubject.len;
Jan Vcelak ce2de96
 	CERT_DestroyCertificate( cert );
Jan Vcelak ce2de96
 	return 0;
Jan Vcelak ce2de96
 }
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 static int
Jan Vcelak ce2de96
 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
Jan Vcelak ce2de96
 {
Jan Vcelak ce2de96
 	tlsm_session *s = (tlsm_session *)session;
Jan Vcelak ce2de96
 	CERTCertificate *cert;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	cert = SSL_PeerCertificate( s );
Jan Vcelak ce2de96
 	if (!cert) return LDAP_INVALID_CREDENTIALS;
Jan Vcelak ce2de96
 	
Jan Vcelak ce2de96
-	der_dn->bv_val = cert->derSubject.data;
Jan Vcelak ce2de96
+	der_dn->bv_val = (char *)cert->derSubject.data;
Jan Vcelak ce2de96
 	der_dn->bv_len = cert->derSubject.len;
Jan Vcelak ce2de96
 	CERT_DestroyCertificate( cert );
Jan Vcelak ce2de96
 	return 0;
Jan Vcelak ce2de96
 }
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 /* what kind of hostname were we given? */
Jan Vcelak ce2de96
 #define	IS_DNS	0
Jan Vcelak ce2de96
 #define	IS_IP4	1
Jan Vcelak ce2de96
 #define	IS_IP6	2
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 static int
Jan Vcelak ce2de96
 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
Jan Vcelak ce2de96
 {
Jan Vcelak ce2de96
 	tlsm_session *s = (tlsm_session *)session;
Jan Vcelak ce2de96
 	CERTCertificate *cert;
Jan Vcelak ce2de96
 	const char *name, *domain = NULL, *ptr;
Jan Vcelak ce2de96
-	int i, ret, ntype = IS_DNS, nlen, dlen;
Jan Vcelak ce2de96
+	int ret, ntype = IS_DNS, nlen, dlen;
Jan Vcelak ce2de96
 #ifdef LDAP_PF_INET6
Jan Vcelak ce2de96
 	struct in6_addr addr;
Jan Vcelak ce2de96
 #else
Jan Vcelak ce2de96
 	struct in_addr addr;
Jan Vcelak ce2de96
 #endif
Jan Vcelak ce2de96
 	SECItem altname;
Jan Vcelak ce2de96
 	SECStatus rv;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
@@ -2259,17 +2307,17 @@
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 		do {
Jan Vcelak ce2de96
 			char *host;
Jan Vcelak ce2de96
 			int hlen;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 			/* ignore empty */
Jan Vcelak ce2de96
 			if ( !cur->name.other.len ) continue;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
-			host = cur->name.other.data;
Jan Vcelak ce2de96
+			host = (char *)cur->name.other.data;
Jan Vcelak ce2de96
 			hlen = cur->name.other.len;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 			if ( cur->type == certDNSName ) {
Jan Vcelak ce2de96
 				if ( ntype != IS_DNS )	continue;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 				/* is this an exact match? */
Jan Vcelak ce2de96
 				if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
Jan Vcelak ce2de96
 					ret = LDAP_SUCCESS;
Jan Vcelak ce2de96
@@ -2317,21 +2365,21 @@
Jan Vcelak ce2de96
 			while ( avas && ( ava = *avas++ )) {
Jan Vcelak ce2de96
 				if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
Jan Vcelak ce2de96
 					lastava = ava;
Jan Vcelak ce2de96
 			}
Jan Vcelak ce2de96
 		}
Jan Vcelak ce2de96
 		if ( lastava ) {
Jan Vcelak ce2de96
 			SECItem *av = CERT_DecodeAVAValue( &lastava->value );
Jan Vcelak ce2de96
 			if ( av ) {
Jan Vcelak ce2de96
-				if ( av->len == nlen && !strncasecmp( name, av->data, nlen )) {
Jan Vcelak ce2de96
+				if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
Jan Vcelak ce2de96
 					ret = LDAP_SUCCESS;
Jan Vcelak ce2de96
 				} else if ( av->data[0] == '*' && av->data[1] == '.' &&
Jan Vcelak ce2de96
 					domain && dlen == av->len - 1 && !strncasecmp( name,
Jan Vcelak ce2de96
-						av->data+1, dlen )) {
Jan Vcelak ce2de96
+						(char *)(av->data+1), dlen )) {
Jan Vcelak ce2de96
 					ret = LDAP_SUCCESS;
Jan Vcelak ce2de96
 				} else {
Jan Vcelak ce2de96
 					int len = av->len;
Jan Vcelak ce2de96
 					if ( len >= sizeof(buf) )
Jan Vcelak ce2de96
 						len = sizeof(buf)-1;
Jan Vcelak ce2de96
 					memcpy( buf, av->data, len );
Jan Vcelak ce2de96
 					buf[len] = '\0';
Jan Vcelak ce2de96
 				}
Jan Vcelak ce2de96
@@ -2479,17 +2527,16 @@
Jan Vcelak ce2de96
 {
Jan Vcelak ce2de96
 	return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
Jan Vcelak ce2de96
 }
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 static PRStatus PR_CALLBACK
Jan Vcelak ce2de96
 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
Jan Vcelak ce2de96
 {
Jan Vcelak ce2de96
 	struct tls_data		*p;
Jan Vcelak ce2de96
-	int rc;
Jan Vcelak ce2de96
 	ber_socklen_t len;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	p = (struct tls_data *)fd->secret;
Jan Vcelak ce2de96
 
Jan Vcelak ce2de96
 	if ( p == NULL || p->sbiod == NULL ) {
Jan Vcelak ce2de96
 		return PR_FAILURE;
Jan Vcelak ce2de96
 	}
Jan Vcelak ce2de96
 	len = sizeof(PRNetAddr);