diff --git a/servers/slapd/add.c b/servers/slapd/add.c
index 6e9541b4ee38e4e1811c7e754f563f1415a4fc74..823389b76b82aa3c3bd018d5fd4df6ff6298d8d2 100644
--- a/servers/slapd/add.c
+++ b/servers/slapd/add.c
@@ -58,8 +58,10 @@ do_add( Connection *conn, Operation *op )
 	entry_rdwr_init(e);
 
 	e->e_dn = dn;
-	dn = dn_normalize( ch_strdup( dn ) );
-	Debug( LDAP_DEBUG_ARGS, "    do_add: dn (%s)\n", dn, 0, 0 );
+	e->e_ndn = dn_normalize( ch_strdup( dn ) );
+	dn = NULL;
+
+	Debug( LDAP_DEBUG_ARGS, "    do_add: ndn (%s)\n", e->e_ndn, 0, 0 );
 
 	/* get the attrs */
 	e->e_attrs = NULL;
@@ -71,7 +73,6 @@ do_add( Connection *conn, Operation *op )
 		if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
 			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
 			    NULL, "decoding error" );
-			free( dn );
 			entry_free( e );
 			return;
 		}
@@ -82,7 +83,6 @@ do_add( Connection *conn, Operation *op )
 			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
 			    NULL );
 			free( type );
-			free( dn );
 			entry_free( e );
 			return;
 		}
@@ -94,15 +94,14 @@ do_add( Connection *conn, Operation *op )
 	}
 
 	Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d ADD dn=\"%s\"\n",
-	    conn->c_connid, op->o_opid, dn, 0, 0 );
+	    conn->c_connid, op->o_opid, e->e_ndn, 0, 0 );
 
 	/*
 	 * We could be serving multiple database backends.  Select the
 	 * appropriate one, or send a referral to our "referral server"
 	 * if we don't hold it.
 	 */
-	be = select_backend( dn );
-	free( dn );
+	be = select_backend( e->e_ndn );
 	if ( be == NULL ) {
 		entry_free( e );
 		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
diff --git a/servers/slapd/back-ldbm/cache.c b/servers/slapd/back-ldbm/cache.c
index 01a92295df87d35dbafa2f37994085d77804c814..f8664f5ebe2b0c133601ed25314d6f838ca4380d 100644
--- a/servers/slapd/back-ldbm/cache.c
+++ b/servers/slapd/back-ldbm/cache.c
@@ -35,7 +35,8 @@ cache_entry_cmp( Entry *e1, Entry *e2 )
 static int
 cache_entrydn_cmp( Entry *e1, Entry *e2 )
 {
-	return( strcasecmp( e1->e_dn, e2->e_dn ) );
+	/* compare their normalized dn's */
+	return( strcasecmp( e1->e_ndn, e2->e_ndn ) );
 }
 
 static int
@@ -234,10 +235,13 @@ cache_find_entry_dn2id(
 	pthread_mutex_lock( &cache->c_mutex );
 
 	e.e_dn = dn;
+	e.e_ndn = dn_normalize( ch_strdup( dn ) );
 
 	if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
 		cache_entrydn_cmp )) != NULL )
 	{
+		free(e.e_ndn);
+
 		Debug(LDAP_DEBUG_TRACE, "====> cache_find_entry_dn2id: found dn: %s\n",
 			dn, 0, 0);
 
@@ -291,6 +295,8 @@ cache_find_entry_dn2id(
 		return( id );
 	}
 
+	free(e.e_ndn);
+
 	/* free cache mutex */
 	pthread_mutex_unlock( &cache->c_mutex );
 
diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c
index 93b69fb1c2034681806c8b266878853dce9da806..a97206fe313f10de1a4bb1c765e0389c698b6795 100644
--- a/servers/slapd/back-passwd/search.c
+++ b/servers/slapd/back-passwd/search.c
@@ -136,6 +136,7 @@ pw2entry( Backend *be, struct passwd *pw )
 
 	sprintf( buf, "%s@%s", pw->pw_name, be->be_suffix[0] );
 	e->e_dn = ch_strdup( buf );
+	e->e_ndn = ch_strdup( buf );
 
 	val.bv_val = pw->pw_name;
 	val.bv_len = strlen( pw->pw_name );
diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c
index 5de991f4c45991f321e2fb2ca5f180007ddb13bc..3977211ce7fb851efb87eda06701f4668c7a3271 100644
--- a/servers/slapd/entry.c
+++ b/servers/slapd/entry.c
@@ -17,7 +17,7 @@ static int		emaxsize;/* max size of ebuf	     		 */
 Entry *
 str2entry( char	*s )
 {
-	int		i;
+	int			id = 0;
 	Entry		*e;
 	Attribute	**a;
 	char		*type;
@@ -46,22 +46,29 @@ str2entry( char	*s )
 	Debug( LDAP_DEBUG_TRACE, "=> str2entry\n",
 		s ? s : "NULL", 0, 0 );
 
-	e = (Entry *) ch_calloc( 1, sizeof(Entry) );
-
 	/* check to see if there's an id included */
 	next = s;
 	if ( isdigit( *s ) ) {
-		e->e_id = atoi( s );
+		id = atoi( s );
 		if ( (s = str_getline( &next )) == NULL ) {
 			Debug( LDAP_DEBUG_TRACE,
 			    "<= str2entry NULL (missing newline after id)\n",
 			    0, 0, 0 );
-			free( e );
 			return( NULL );
 		}
 	}
 
 	/* initialize reader/writer lock */
+	e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
+	if( e == NULL ) {
+		Debug( LDAP_DEBUG_TRACE,
+		    "<= str2entry NULL (entry allocation failed)\n",
+		    0, 0, 0 );
+		return( NULL );
+	}
+	e->e_id = id;
+
 	entry_rdwr_init(e);
 
 	/* dn + attributes */
@@ -86,6 +93,7 @@ str2entry( char	*s )
 			maxvals = 0;
 			a = NULL;
 		}
+
 		if ( strcasecmp( type, "dn" ) == 0 ) {
 			if ( e->e_dn != NULL ) {
 				Debug( LDAP_DEBUG_ANY,
@@ -94,6 +102,14 @@ str2entry( char	*s )
 				continue;
 			}
 			e->e_dn = ch_strdup( value );
+
+			if ( e->e_ndn != NULL ) {
+				Debug( LDAP_DEBUG_ANY,
+ "str2entry: entry %lu already has a normalized dn \"%s\" for \"%s\" (first ignored)\n",
+				    e->e_id, e->e_ndn, value );
+				free( e->e_ndn );
+			}
+			e->e_ndn = dn_normalize( ch_strdup( value ) );
 			continue;
 		}
 
@@ -117,6 +133,14 @@ str2entry( char	*s )
 		return( NULL );
 	}
 
+	if ( e->e_ndn == NULL ) {
+		Debug( LDAP_DEBUG_ANY,
+			"str2entry: entry %lu (\"%s\") has no normalized dn\n",
+		    e->e_id, e->e_dn, 0 );
+		entry_free( e );
+		return( NULL );
+	}
+
 	Debug(LDAP_DEBUG_TRACE, "<= str2entry 0x%lx\n", (unsigned long)e, 0,0);
 
 	return( e );
@@ -203,6 +227,9 @@ entry_free( Entry *e )
 	if ( e->e_dn != NULL ) {
 		free( e->e_dn );
 	}
+	if ( e->e_ndn != NULL ) {
+		free( e->e_ndn );
+	}
 	for ( a = e->e_attrs; a != NULL; a = next ) {
 		next = a->a_next;
 		attr_free( a );
diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c
index 698ac953a432d3f12c1068617eb7f06efb17f2a2..9efffc788e8c14a743b425b5ef86e92f3f204cd8 100644
--- a/servers/slapd/monitor.c
+++ b/servers/slapd/monitor.c
@@ -49,6 +49,7 @@ monitor_info( Connection *conn, Operation *op )
 	entry_rdwr_init(e);
 	e->e_attrs = NULL;
 	e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
+	e->e_ndn = NULL;
 
 	val.bv_val = Versionstr;
 	if (( p = strchr( Versionstr, '\n' )) == NULL ) {
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 4a311bac64452da45bcd4dd3ecac620e29c11474..7f132663a5c9a7ae08dba0180c48255a7339475f 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -120,6 +120,7 @@ typedef unsigned long	ID;
  */
 typedef struct entry {
 	char		*e_dn;		/* DN of this entry 		  */
+	char		*e_ndn;		/* normalized DN of this entry	  */
 	Attribute	*e_attrs;	/* list of attributes + values    */
 
 	ID		e_id;		/* id of this entry - this should */