[Date Prev][Date Next] [Chronological] [Thread] [Top]

general aliasing



Well, here is the code to implement general aliasing in the openldap
distribution (and the suffix masquerading is there too).  There is a
diffs and two new files.

I ran the examples in
http://www.ietf.org/internet-drafts/draft-byrne-ldap-alias-00.txt  and
they all worked as expected.  Note that I think there is a typo in

             dn: o=myCorporation, c=myCountry
             ou: myCorporation
             objectclass:organization

Pretty sure that should be

             dn: o=myCorporation, c=myCountry
             o: myCorporation
             objectclass:organization

Please keep in mind I have not done much testing (no time, too many
other things to do). Comments on how to improve the code, bugs, etc.
appreciated.  Also, for loop detection I introduce a new back-end
parameter called be_maxDerefDepth rather than trying to search through
all past derefs to see if one recurs.

I would like to ensure that some of these capabilities make it into the
distribution at some point to avoid keeping different source trees and
worrying about continuous remerging later.   Please let me know if you
need anything else to put changes into the general source tree.

--
Will Ballantyne     GEMS Technical Architect
mailto:Will.Ballantyne@gems1.gov.bc.ca


Only in new.ldap: .make-platform
Only in new.ldap: .makefiles
Only in new.ldap: Make-common
diff -urx *.o -x CVS -x Makefile ldap/clients/ud/string_to_key.c new.ldap/clients/ud/string_to_key.c
--- ldap/clients/ud/string_to_key.c	Mon Aug 31 12:11:18 1998
+++ new.ldap/clients/ud/string_to_key.c	Mon Oct  5 23:05:51 1998
@@ -1,7 +1,7 @@
 #if defined(KERBEROS) && !defined(openbsd)
 /*
- * $Source: /repo/OpenLDAP/pkg/ldap/clients/ud/string_to_key.c,v $
- * $Author: kurt $
+ * $Source: /usr/local/cvsroot/ldap/clients/ud/string_to_key.c,v $
+ * $Author: wballant $
  *
  * Copyright 1985, 1986, 1987, 1988, 1989 by the Massachusetts Institute
  * of Technology.
Only in new.ldap/include: ldapconfig.h
Only in new.ldap/servers/slapd: .#Make-template.1.1.1.1
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/Make-template new.ldap/servers/slapd/Make-template
--- ldap/servers/slapd/Make-template	Fri Sep 11 19:44:46 1998
+++ new.ldap/servers/slapd/Make-template	Wed Oct 21 16:19:35 1998
@@ -23,14 +23,16 @@
 		value.c ava.c bind.c unbind.c abandon.c filterentry.c \
 		phonetic.c acl.c str2filter.c aclparse.c init.c \
 		detach.c strdup.c tempnam.c repl.c lock.c \
-		schema.c schemaparse.c monitor.c configinfo.c
+		schema.c schemaparse.c monitor.c configinfo.c \
+		suffixAlias.c alias.c
 OBJS	= main.o daemon.o connection.o search.o filter.o add.o charray.o \
 		attr.o entry.o config.o backend.o result.o operation.o \
 		dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
 		value.o ava.o bind.o unbind.o abandon.o filterentry.o \
 		phonetic.o acl.o str2filter.o aclparse.o init.o \
 		detach.o strdup.o tempnam.o repl.o lock.o \
-		schema.o schemaparse.o monitor.o configinfo.o
+		schema.o schemaparse.o monitor.o configinfo.o \
+		suffixAlias.o alias.o
 
 INCLUDES= -I. -I$(HDIR) $(KRBINCLUDEFLAG)
 DEFINES = $(DEFS) $(SERVERDEFS)
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/add.c new.ldap/servers/slapd/add.c
--- ldap/servers/slapd/add.c	Tue Aug 18 16:30:57 1998
+++ new.ldap/servers/slapd/add.c	Wed Oct 14 23:56:31 1998
@@ -19,6 +19,7 @@
 
 extern Backend	*select_backend();
 extern char	*dn_normalize();
+extern char 	*suffixAlias();
 
 extern char		*default_referral;
 extern time_t		currenttime;
@@ -32,6 +33,7 @@
     Connection	*conn;
     Operation	*op;
 {
+	int		j, dnLength;
 	BerElement	*ber = op->o_ber;
 	char		*dn, *last;
 	unsigned long	len, tag;
@@ -61,6 +63,9 @@
 		    "decoding error" );
 		return;
 	}
+
+
+
 	e->e_dn = dn;
 	dn = dn_normalize( strdup( dn ) );
 	Debug( LDAP_DEBUG_ARGS, "    do_add: dn (%s)\n", dn, 0, 0 );
@@ -108,6 +113,9 @@
 		    default_referral );
 		return;
 	}
+
+	/* translate the base if it matches an aliased part.  */
+	e->e_dn = suffixAlias ( e->e_dn, op, be );
 
 	/*
 	 * do the add if 1 && (2 || 3)
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/back-ldbm/Make-template new.ldap/servers/slapd/back-ldbm/Make-template
--- ldap/servers/slapd/back-ldbm/Make-template	Thu Aug 20 21:33:42 1998
+++ new.ldap/servers/slapd/back-ldbm/Make-template	Tue Oct 20 15:46:17 1998
@@ -20,11 +20,13 @@
 SRCS	= idl.c add.c search.c cache.c dbcache.c dn2id.c id2entry.c \
 		index.c id2children.c nextid.c abandon.c compare.c \
 		modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
-		filterindex.c unbind.c kerberos.c close.c group.c
+		filterindex.c unbind.c kerberos.c close.c group.c \
+		alias.c
 OBJS	= idl.o add.o search.o cache.o dbcache.o dn2id.o id2entry.o \
 		index.o id2children.o nextid.o abandon.o compare.o \
 		modify.o modrdn.o delete.o init.o config.o bind.o attr.o \
-		filterindex.o unbind.o kerberos.o close.o group.o
+		filterindex.o unbind.o kerberos.o close.o group.o \
+		alias.o
 
 INCLUDES= -I. -I.. -I$(HDIR) $(KRBINCLUDEFLAG)
 DEFINES = $(DEFS) $(SERVERDEFS) $(THREADS)
Only in new.ldap/servers/slapd/back-ldbm: alias.c
Only in new.ldap/servers/slapd/back-ldbm: alias.c~
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/back-ldbm/dn2id.c new.ldap/servers/slapd/back-ldbm/dn2id.c
--- ldap/servers/slapd/back-ldbm/dn2id.c	Tue Aug 18 15:10:02 1998
+++ new.ldap/servers/slapd/back-ldbm/dn2id.c	Tue Oct 20 21:14:31 1998
@@ -12,6 +12,9 @@
 extern Entry		*id2entry();
 extern char		*dn_parent();
 extern Datum		ldbm_cache_fetch();
+extern Attribute	*attr_find();
+extern void		attr_free();
+extern void		entry_free();
 
 int
 dn2id_add(
@@ -161,8 +164,8 @@
 	Entry		*e;
 	char		*pdn;
 
-	if ( (id = dn2id( be, dn )) != NOID && (e = id2entry( be, id ))
-	    != NULL ) {
+	if ( (id = dn2id( be, dn )) != NOID && 
+	     (e = id2entry( be, id )) != NULL ) {
 		return( e );
 	}
 	*matched = NULL;
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/back-ldbm/search.c new.ldap/servers/slapd/back-ldbm/search.c
--- ldap/servers/slapd/back-ldbm/search.c	Sat Aug  8 19:13:59 1998
+++ new.ldap/servers/slapd/back-ldbm/search.c	Wed Oct 21 15:41:23 1998
@@ -61,6 +61,7 @@
 	int		rmaxsize, nrefs;
 	char		*rbuf, *rcur, *r;
 	int		nentries = 0;
+	char            *realBase;
 
 	if ( tlimit == 0 && be_isroot( be, op->o_dn ) ) {
 		tlimit = -1;	/* allow root to set no limit */
@@ -76,20 +77,40 @@
 		    be->be_sizelimit : slimit;
 	}
 
+
+	realBase = strdup (base);
+	/* 
+         * check and apply aliasing where the dereferencing applies to 
+         * the subordinates of the base
+         */
+	switch ( deref ) {
+          case LDAP_DEREF_FINDING:
+          case LDAP_DEREF_ALWAYS: {
+	    realBase = derefDN ( be, conn, op, base ); 
+	    break;
+          }
+        }
+
+	(void) dn_normalize (realBase);
+
+	Debug( LDAP_DEBUG_TRACE, "using base %s\n", realBase,
+	       0, 0 );
+	
+
 	switch ( scope ) {
 	case LDAP_SCOPE_BASE:
-		candidates = base_candidates( be, conn, op, base, filter,
-		    attrs, attrsonly, &matched, &err );
+		candidates = base_candidates( be, conn, op, realBase, filter,
+		    attrs, attrsonly, &matched, &err, deref );
 		break;
 
 	case LDAP_SCOPE_ONELEVEL:
-		candidates = onelevel_candidates( be, conn, op, base, filter,
-		    attrs, attrsonly, &matched, &err );
+		candidates = onelevel_candidates( be, conn, op, realBase, filter,
+		    attrs, attrsonly, &matched, &err, deref );
 		break;
 
 	case LDAP_SCOPE_SUBTREE:
-		candidates = subtree_candidates( be, conn, op, base, filter,
-		    attrs, attrsonly, &matched, NULL, &err, 1 );
+		candidates = subtree_candidates( be, conn, op, realBase, filter,
+		    attrs, attrsonly, &matched, NULL, &err, 1, deref );
 		break;
 
 	default:
@@ -114,121 +135,134 @@
 	strcpy( rbuf, "Referral:" );
 	rcur = strchr( rbuf, '\0' );
 	for ( id = idl_firstid( candidates ); id != NOID;
-	    id = idl_nextid( candidates, id ) ) {
-		/* check for abandon */
-		pthread_mutex_lock( &op->o_abandonmutex );
-		if ( op->o_abandon ) {
-			pthread_mutex_unlock( &op->o_abandonmutex );
-			idl_free( candidates );
-			free( rbuf );
-			return( 0 );
+	      id = idl_nextid( candidates, id ) ) {
+	  /* check for abandon */
+	  pthread_mutex_lock( &op->o_abandonmutex );
+	  if ( op->o_abandon ) {
+	    pthread_mutex_unlock( &op->o_abandonmutex );
+	    idl_free( candidates );
+	    free( rbuf );
+	    return( 0 );
+	  }
+	  pthread_mutex_unlock( &op->o_abandonmutex );
+	  
+	  /* check time limit */
+	  pthread_mutex_lock( &currenttime_mutex );
+	  time( &currenttime );
+	  if ( tlimit != -1 && currenttime > stoptime ) {
+	    pthread_mutex_unlock( &currenttime_mutex );
+	    send_ldap_search_result( conn, op,
+				     LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
+				     NULL, nentries );
+	    idl_free( candidates );
+	    free( rbuf );
+	    return( 0 );
+	  }
+	  pthread_mutex_unlock( &currenttime_mutex );
+	  
+	  /* get the entry */
+	  if ( (e = id2entry( be, id )) == NULL ) {
+	    Debug( LDAP_DEBUG_ARGS, "candidate %d not found\n", id,
+		   0, 0 );
+	    continue;
+	  }
+	  
+	  /*
+	   * if it's a referral, add it to the list of referrals. only do
+	   * this for subtree searches, and don't check the filter explicitly
+	   * here since it's only a candidate anyway.
+	   */
+	  if ( e->e_dn != NULL && strncasecmp( e->e_dn, "ref=", 4 )
+	       == 0 && (ref = attr_find( e->e_attrs, "ref" )) != NULL &&
+	       scope == LDAP_SCOPE_SUBTREE )
+	    {
+	      int	i, len;
+	      
+	      if ( ref->a_vals == NULL ) {
+		Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 0,
+		       0, 0 );
+	      } else {
+		for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
+		  /* referral + newline + null */
+		  MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
+		  *rcur++ = '\n';
+		  strncpy( rcur, ref->a_vals[i]->bv_val,
+			   ref->a_vals[i]->bv_len );
+		  rcur = rcur + ref->a_vals[i]->bv_len;
+		  *rcur = '\0';
+		  nrefs++;
 		}
-		pthread_mutex_unlock( &op->o_abandonmutex );
+	      }
 
-		/* check time limit */
-		pthread_mutex_lock( &currenttime_mutex );
-		time( &currenttime );
-		if ( tlimit != -1 && currenttime > stoptime ) {
-			pthread_mutex_unlock( &currenttime_mutex );
-			send_ldap_search_result( conn, op,
-			    LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
-			    NULL, nentries );
-			idl_free( candidates );
-			free( rbuf );
-			return( 0 );
+	      /* otherwise it's an entry - see if it matches the filter */
+	    } else {
+	      /* if it matches the filter and scope, send it */
+	      if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+		int		scopeok;
+		char	*dn;
+		
+		/* check scope */
+		scopeok = 1;
+		if ( scope == LDAP_SCOPE_ONELEVEL ) {
+		  if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
+		    (void) dn_normalize( dn );
+		    scopeok = (dn == realBase) ? 1 : (! strcasecmp( dn, realBase ));
+		  } else {
+		    scopeok = (realBase == NULL || *realBase == '\0');
+		  }
+		  free( dn );
+		} else if ( scope == LDAP_SCOPE_SUBTREE ) {
+		  dn = strdup( e->e_dn );
+		  (void) dn_normalize( dn );
+		  scopeok = dn_issuffix( dn, realBase );
+		  free( dn );
 		}
-		pthread_mutex_unlock( &currenttime_mutex );
-
-		/* get the entry */
-		if ( (e = id2entry( be, id )) == NULL ) {
-			Debug( LDAP_DEBUG_ARGS, "candidate %d not found\n", id,
-			    0, 0 );
-			continue;
+		
+		if ( scopeok ) {
+		  /* check size limit */
+		  if ( --slimit == -1 ) {
+		    cache_return_entry( &li->li_cache, e );
+		    send_ldap_search_result( conn, op,
+					     LDAP_SIZELIMIT_EXCEEDED, NULL,
+					     nrefs > 0 ? rbuf : NULL, nentries );
+		    idl_free( candidates );
+		    free( rbuf );
+		    return( 0 );
+		  }
+		  
+		  /* 
+                   * check and apply aliasing where the dereferencing applies to 
+                   * the subordinates of the base
+                   */
+		  switch ( deref ) {
+                  case LDAP_DEREF_SEARCHING:
+                  case LDAP_DEREF_ALWAYS: {
+		    e = derefAlias ( be, conn, op, e ); 
+		    break;
+                    }
+                  }
+		
+		  switch ( send_search_entry( be, conn, op, e,
+					    attrs, attrsonly ) ) {
+		case 0:		/* entry sent ok */
+		  nentries++;
+		  break;
+		case 1:		/* entry not sent */
+		  break;
+		case -1:	/* connection closed */
+		  cache_return_entry( &li->li_cache, e );
+		  idl_free( candidates );
+		  free( rbuf );
+		  return( 0 );
 		}
-
-		/*
-		 * if it's a referral, add it to the list of referrals. only do
-		 * this for subtree searches, and don't check the filter explicitly
-		 * here since it's only a candidate anyway.
-		 */
-		if ( e->e_dn != NULL && strncasecmp( e->e_dn, "ref=", 4 )
-		    == 0 && (ref = attr_find( e->e_attrs, "ref" )) != NULL &&
-		    scope == LDAP_SCOPE_SUBTREE )
-		{
-			int	i, len;
-
-			if ( ref->a_vals == NULL ) {
-				Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 0,
-				    0, 0 );
-			} else {
-				for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
-					/* referral + newline + null */
-					MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
-					*rcur++ = '\n';
-					strncpy( rcur, ref->a_vals[i]->bv_val,
-					  ref->a_vals[i]->bv_len );
-					rcur = rcur + ref->a_vals[i]->bv_len;
-					*rcur = '\0';
-					nrefs++;
-				}
-			}
-
-		/* otherwise it's an entry - see if it matches the filter */
-		} else {
-			/* if it matches the filter and scope, send it */
-			if ( test_filter( be, conn, op, e, filter ) == 0 ) {
-				int		scopeok;
-				char	*dn;
-
-				/* check scope */
-				scopeok = 1;
-				if ( scope == LDAP_SCOPE_ONELEVEL ) {
-					if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
-						(void) dn_normalize( dn );
-						scopeok = (dn == base) ? 1 : (! strcasecmp( dn, base ));
-					} else {
-						scopeok = (base == NULL || *base == '\0');
-					}
-					free( dn );
-				} else if ( scope == LDAP_SCOPE_SUBTREE ) {
-					dn = strdup( e->e_dn );
-					(void) dn_normalize( dn );
-					scopeok = dn_issuffix( dn, base );
-					free( dn );
-				}
-
-				if ( scopeok ) {
-					/* check size limit */
-					if ( --slimit == -1 ) {
-						cache_return_entry( &li->li_cache, e );
-						send_ldap_search_result( conn, op,
-							LDAP_SIZELIMIT_EXCEEDED, NULL,
-							nrefs > 0 ? rbuf : NULL, nentries );
-						idl_free( candidates );
-						free( rbuf );
-						return( 0 );
-					}
-
-					switch ( send_search_entry( be, conn, op, e,
-						attrs, attrsonly ) ) {
-					case 0:		/* entry sent ok */
-						nentries++;
-						break;
-					case 1:		/* entry not sent */
-						break;
-					case -1:	/* connection closed */
-						cache_return_entry( &li->li_cache, e );
-						idl_free( candidates );
-						free( rbuf );
-						return( 0 );
-					}
-				}
-			}
+		
 		}
+	      }
+	    }
 
-		cache_return_entry( &li->li_cache, e );
-
-		pthread_yield();
+	  cache_return_entry( &li->li_cache, e );
+	  
+	  pthread_yield();
 	}
 	idl_free( candidates );
 	if ( nrefs > 0 ) {
@@ -253,7 +287,8 @@
     char	**attrs,
     int		attrsonly,
     char	**matched,
-    int		*err
+    int		*err,
+    int		deref
 )
 {
 	struct ldbminfo	*li = (struct ldbminfo *) be->be_private;
@@ -286,7 +321,8 @@
     char	**attrs,
     int		attrsonly,
     char	**matched,
-    int		*err
+    int		*err,
+    int		deref
 )
 {
 	struct ldbminfo	*li = (struct ldbminfo *) be->be_private;
@@ -344,7 +380,8 @@
     char	**matched,
     Entry	*e,
     int		*err,
-    int		lookupbase
+    int		lookupbase,
+    int		deref
 )
 {
 	struct ldbminfo	*li = (struct ldbminfo *) be->be_private;
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/backend.c new.ldap/servers/slapd/backend.c
--- ldap/servers/slapd/backend.c	Tue Sep 15 20:10:53 1998
+++ new.ldap/servers/slapd/backend.c	Tue Oct 13 13:46:58 1998
@@ -186,6 +186,25 @@
 		}
 	}
 
+        /* if no proper suffix could be found then check for aliases */
+        for ( i = 0; i < nbackends; i++ ) {
+                for ( j = 0; backends[i].be_suffixAlias != NULL &&
+                    backends[i].be_suffixAlias[j] != NULL; j += 2 )
+                {
+                        len = strlen( backends[i].be_suffixAlias[j] );
+
+                        if ( len > dnlen ) {
+                                continue;
+                        }
+
+                        if ( strcasecmp( backends[i].be_suffixAlias[j],
+                            dn + (dnlen - len) ) == 0 ) {
+                                return( &backends[i] );
+                        }
+                }
+        }
+
+
 	return( NULL );
 }
 
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/bind.c new.ldap/servers/slapd/bind.c
--- ldap/servers/slapd/bind.c	Sat Aug  8 15:43:13 1998
+++ new.ldap/servers/slapd/bind.c	Wed Oct 14 23:56:32 1998
@@ -19,6 +19,7 @@
 #include "slap.h"
 
 extern Backend	*select_backend();
+extern char  	*suffixAlias();
 
 extern char	*default_referral;
 
@@ -150,6 +151,9 @@
 		}
 		return;
 	}
+
+	/* alias suffix */
+	dn = suffixAlias ( dn, op, be );
 
 	if ( be->be_bind != NULL ) {
 		if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/config.c new.ldap/servers/slapd/config.c
--- ldap/servers/slapd/config.c	Sat Aug  8 15:43:13 1998
+++ new.ldap/servers/slapd/config.c	Tue Oct 20 17:10:45 1998
@@ -81,6 +81,9 @@
 			*bep = new_backend( cargv[1] );
 			be = *bep;
 
+			/* assign a default depth limit for alias deref */
+			be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
+
 		/* set size limit */
 		} else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
 			if ( cargc < 2 ) {
@@ -131,7 +134,54 @@
 				charray_add( &be->be_suffix, dn );
 			}
 
-		/* set magic "root" dn for this database */
+                /* set database suffixAlias */
+                } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
+                        if ( cargc < 2 ) {
+                                Debug( LDAP_DEBUG_ANY,
+                    "%s: line %d: missing alias and aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
+                                    fname, lineno, 0 );
+                                exit( 1 );
+                        } else if ( cargc < 3 ) {
+                                Debug( LDAP_DEBUG_ANY,
+                    "%s: line %d: missing aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
+                                    fname, lineno, 0 );
+                                exit( 1 );
+                        } else if ( cargc > 3 ) {
+                                Debug( LDAP_DEBUG_ANY,
+    "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
+                                    fname, lineno, 0 );
+                        }
+                        if ( be == NULL ) {
+                                Debug( LDAP_DEBUG_ANY,
+"%s: line %d: suffixAlias line must appear inside a database definition (ignored)\n",
+                                    fname, lineno, 0 );
+                        } else {
+                                dn = strdup( cargv[1] );
+                                (void) dn_normalize( dn );
+                                charray_add( &be->be_suffixAlias, dn );
+
+                                dn = strdup( cargv[2] );
+                                (void) dn_normalize( dn );
+                                charray_add( &be->be_suffixAlias, dn );
+                        }
+
+		/* set max deref depth */
+		} else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
+			if ( cargc < 2 ) {
+				Debug( LDAP_DEBUG_ANY,
+		    "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
+				    fname, lineno, 0 );
+				exit( 1 );
+			}
+			if ( be == NULL ) {
+				Debug( LDAP_DEBUG_ANY,
+"%s: line %d: depth line must appear inside a database definition (ignored)\n",
+				    fname, lineno, 0 );
+			} else {
+			    be->be_maxDerefDepth = atoi (cargv[1]);
+			}
+
+	/* set magic "root" dn for this database */
 		} else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
 			if ( cargc < 2 ) {
 				Debug( LDAP_DEBUG_ANY,
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/delete.c new.ldap/servers/slapd/delete.c
--- ldap/servers/slapd/delete.c	Sat Aug  8 15:43:13 1998
+++ new.ldap/servers/slapd/delete.c	Wed Oct 14 23:56:32 1998
@@ -17,6 +17,7 @@
 #include "slap.h"
 
 extern Backend	*select_backend();
+extern char 	*suffixAlias();
 
 extern char	*default_referral;
 
@@ -61,6 +62,9 @@
 		    default_referral );
 		return;
 	}
+
+  	/* alias suffix if approp */
+	dn = suffixAlias ( dn, op, be );
 
 	/*
 	 * do the delete if 1 && (2 || 3)
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/modify.c new.ldap/servers/slapd/modify.c
--- ldap/servers/slapd/modify.c	Tue Aug 18 16:30:57 1998
+++ new.ldap/servers/slapd/modify.c	Wed Oct 14 23:56:32 1998
@@ -147,6 +147,9 @@
 		return;
 	}
 
+	/* alias suffix if approp */
+	dn = suffixAlias ( dn, op, be );
+
 	/*
 	 * do the modify if 1 && (2 || 3)
 	 * 1) there is a modify function implemented in this backend;
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/operation.c new.ldap/servers/slapd/operation.c
--- ldap/servers/slapd/operation.c	Sat Aug  8 15:43:13 1998
+++ new.ldap/servers/slapd/operation.c	Tue Oct 13 13:46:58 1998
@@ -17,6 +17,12 @@
 	if ( op->o_dn != NULL ) {
 		free( op->o_dn );
 	}
+	if ( op->o_suffix != NULL ) {
+		free( op->o_suffix );
+	}
+	if ( op->o_suffixAliased != NULL ) {
+		free( op->o_suffixAliased );
+	}
 	/* pthread_mutex_destroy( &op->o_abandonmutex ); */
 	free( (char *) op );
 }
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/result.c new.ldap/servers/slapd/result.c
--- ldap/servers/slapd/result.c	Thu Aug 20 21:33:42 1998
+++ new.ldap/servers/slapd/result.c	Tue Oct 13 13:46:58 1998
@@ -23,6 +23,7 @@
 extern long		num_entries_sent;
 extern long		num_bytes_sent;
 extern pthread_mutex_t	num_sent_mutex;
+extern char *ch_malloc();
 
 void	close_connection();
 
@@ -196,9 +197,9 @@
 {
 	BerElement	*ber;
 	Attribute	*a;
-	int		i, rc, bytes, sd;
+	int		i, rc, bytes, sd, prefixLength;
 	struct acl	*acl;
-	char            *edn;
+	char            *edn, *resultDN;
 
 	Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
 
@@ -211,6 +212,29 @@
 
 	edn = dn_normalize_case( strdup( e->e_dn ) );
 
+        resultDN = strdup( e->e_dn );
+        if (op->o_suffixAliased != NULL) {
+                Debug( LDAP_DEBUG_TRACE, "=> dereferencing suffix alias for (%s)\n", resultDN, 0, 0 );
+                Debug( LDAP_DEBUG_TRACE, "=> converting (%s) to (%s)\n", op->o_suffix, op->o_suffixAliased, 0 );
+                prefixLength = strlen (resultDN) - strlen (op->o_suffix);
+                if (prefixLength > 0) {
+                        if (!strcasecmp(op->o_suffix, resultDN + prefixLength)) {
+                                char *newDN;
+                                Debug( LDAP_DEBUG_TRACE, "=> match found for (%s)\n", resultDN, 0, 0 );
+                                newDN = ch_malloc (prefixLength + strlen(op->o_suffixAliased) + 1);
+                                strncpy (newDN, resultDN, prefixLength);
+                                strcpy (newDN + prefixLength, op->o_suffixAliased);
+                                Debug( LDAP_DEBUG_TRACE, "=> newDN built to be (%s)\n", newDN, 0, 0 );
+                                free (resultDN);
+				resultDN = strdup (newDN);
+                        }
+                        else {
+                                Debug( LDAP_DEBUG_TRACE, "=> deref failed for (%s)\n", edn, 0, 0 );
+                        }
+                }
+        }
+
+
 #ifdef COMPAT30
 	if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
 		== NULLBER )
@@ -228,12 +252,12 @@
 #ifdef COMPAT30
 	if ( conn->c_version == 30 ) {
 		rc = ber_printf( ber, "{it{{s{", op->o_msgid,
-		    LDAP_RES_SEARCH_ENTRY, e->e_dn );
+		    LDAP_RES_SEARCH_ENTRY, resultDN );
 	} else
 #endif
 	{
 		rc = ber_printf( ber, "{it{s{", op->o_msgid,
-			LDAP_RES_SEARCH_ENTRY, e->e_dn );
+			LDAP_RES_SEARCH_ENTRY, resultDN );
 	}
 
 	if ( rc == -1 ) {
@@ -242,6 +266,7 @@
 		send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
 		    "ber_printf dn" );
 		free(edn);
+		free(resultDN);
 		return( 1 );
 	}
 
@@ -278,6 +303,7 @@
 			send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
 			    NULL, "ber_printf type" );
 			free(edn);
+			free(resultDN);
 			return( 1 );
 		}
 
@@ -301,6 +327,7 @@
 					    LDAP_OPERATIONS_ERROR, NULL,
 					    "ber_printf value" );
                                         free(edn);
+                                        free(resultDN);
 					return( 1 );
 				}
 			}
@@ -312,11 +339,13 @@
 			send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
 			    NULL, "ber_printf type end" );
                         free(edn);
+                        free(resultDN);
 			return( 1 );
 		}
 	}
 
 	free(edn);
+	free(resultDN);
 
 #ifdef COMPAT30
 	if ( conn->c_version == 30 ) {
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/search.c new.ldap/servers/slapd/search.c
--- ldap/servers/slapd/search.c	Sat Aug  8 15:43:13 1998
+++ new.ldap/servers/slapd/search.c	Wed Oct 14 23:56:33 1998
@@ -19,6 +19,8 @@
 
 extern int	get_filter();
 extern Backend	*select_backend();
+extern char	*ch_malloc();
+extern char	*suffixAlias();
 
 extern char	*default_referral;
 
@@ -27,7 +29,7 @@
     Connection	*conn;	/* where to send results 		       */
     Operation	*op;	/* info about the op to which we're responding */
 {
-	int		i, err;
+	int		i, j, err;
 	int		scope, deref, attrsonly;
 	int		sizelimit, timelimit;
 	char		*base, *fstr;
@@ -161,6 +163,9 @@
 		return;
 	}
 
+	/* translate the base if it matches an aliased base part */
+	base = suffixAlias ( base, op, be );
+
 	/* actually do the search and send the result(s) */
 	if ( be->be_search != NULL ) {
 		(*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
@@ -177,3 +182,4 @@
 		charray_free( attrs );
 	}
 }
+
diff -urx *.o -x CVS -x Makefile ldap/servers/slapd/slap.h new.ldap/servers/slapd/slap.h
--- ldap/servers/slapd/slap.h	Thu Aug 20 21:33:42 1998
+++ new.ldap/servers/slapd/slap.h	Tue Oct 20 16:29:24 1998
@@ -172,9 +172,11 @@
 
 typedef struct backend {
 	char	**be_suffix;	/* the DN suffixes of data in this backend */
+	char	**be_suffixAlias;	/* the DN suffix aliases of data in this backend */
 	char	*be_rootdn;	/* the magic "root" dn for this db   	   */
 	char	*be_rootpw;	/* the magic "root" password for this db   */
 	int	be_readonly;	/* 1 => db is in "read only" mode	   */
+	int	be_maxDerefDepth;	/* limit for depth of an alias deref  */
 	int	be_sizelimit;	/* size limit for this backend   	   */
 	int	be_timelimit;	/* time limit for this backend       	   */
 	struct acl *be_acl;	/* access control list for this backend	   */
@@ -215,6 +217,8 @@
 	unsigned long	o_tag;		/* tag of the request		  */
 	time_t		o_time;		/* time op was initiated	  */
 	char		*o_dn;		/* dn bound when op was initiated */
+	char		*o_suffix;	/* suffix if aliased              */
+	char		*o_suffixAliased;	/* pending suffix translation     */
 	int		o_authtype;	/* auth method used to bind dn	  */
 					/* values taken from ldap.h	  */
 					/* LDAP_AUTH_*			  */
Only in new.ldap/servers/slapd: suffixAlias.c
/* alias.c */
/*
 * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to ITSD, Government of BC. The name of ITSD
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
 */

#include <stdio.h>
#include <string.h>
#include "slap.h"
#include "back-ldbm.h"

extern ID		dn2id();
extern Entry		*id2entry();
extern Entry		*dn2entry();
extern Attribute	*attr_find();

/*
 * given an alias object, dereference it to its end point.
 */
Entry *derefAlias ( Backend     *be,
		    Connection	*conn,
		    Operation	*op,
		    Entry       *e,
		    int         deref
		    )
{
  Attribute *a;
  ID        id;
  int       depth;
  char      **pastAliases;

  Debug( LDAP_DEBUG_TRACE, 
	 "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );

  /*
   * try to deref fully, up to a maximum depth.  If the max depth exceeded
   * then send an error
   */
  for ( depth = 0;
	( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
	  ( depth < be->be_maxDerefDepth );
	++depth) {

    /* 
     * make sure there is a defined aliasedobjectname.  
     * can only have one value so just use first value (0) in the attr list. 
     */	    
    if (a->a_vals[0] && a->a_vals[0]->bv_val) {
      char *newDN, *oldDN;

      Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n", 
	     e->e_dn, a->a_vals[0]->bv_val, 0 );
      newDN = strdup (a->a_vals[0]->bv_val);
      oldDN = strdup (e->e_dn);

      /*
       * ok, so what happens if there is an alias in the DN of a dereferenced
       * alias object?  
       */
      if ( (id = dn2id( be, newDN )) == NOID ||
	   (e = id2entry( be, id )) == NULL ) {

	/* could not deref return error  */
	Debug( LDAP_DEBUG_TRACE, 
	       "<= %s is a dangling alias to %s\n", 
	       oldDN, newDN, 0 );
	send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
			  "Dangling Alias" );
      }
      free (newDN);
      free (oldDN);
    }
    else {
      /*
       * there was an aliasedobjectname defined but no data.
       * this can't happen, right?
       */
	Debug( LDAP_DEBUG_TRACE, 
	       "<= %s has no data in aliasedobjectname attribute\n", 
	       e->e_dn, 0, 0 );
	send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
			  "Alias missing aliasedobjectname" );
    }
  }

  /*
   * warn if we pulled out due to exceeding the maximum deref depth
   */
  if ( depth >= be->be_maxDerefDepth ) {
    Debug( LDAP_DEBUG_TRACE, 
	   "<= %s exceeded maximum deref depth %d\n", 
	   e->e_dn, be->be_maxDerefDepth, 0 );
    send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
			"Maximum alias dereference depth exceeded" );
  }

  return e;
}

/*
 * given a DN fully deref it and return the real DN or original DN if it fails
 */
char *derefDN ( Backend     *be,
                Connection  *conn,
                Operation   *op,
                char        *dn,
		int 	    deref
)
{
  char 	*matched;
  char 	*newDN;
  int	depth;
  Entry 	*e;
  

  Debug( LDAP_DEBUG_TRACE, 
	 "<= dereferencing dn %s\n", 
	 dn, 0, 0 );
  
  newDN = strdup ( dn );
  
  /* while we don't have a matched dn, deref the DN */
  for ( depth = 0;
	( (e = dn2entry( be, newDN, &matched )) == NULL) &&
	  (depth < be->be_maxDerefDepth);
	++depth ) {
    
    if (*matched) {	
      char *submatch;
      
      /* 
       * make sure there actually is an entry for the matched part 
       */
      if ( (e = dn2entry( be, matched, &submatch )) != NULL) {
	char  *remainder; /* part before the aliased part */
	Entry *newE;
	int  rlen = strlen(newDN) - strlen(matched);
	
	Debug( LDAP_DEBUG_TRACE, 
	       "<= matched %s\n", 
	       matched, 0, 0 );
	
	remainder = ch_malloc (rlen + 1);
	strncpy ( remainder, newDN, rlen );
	remainder[rlen]	= '\0';
	
	Debug( LDAP_DEBUG_TRACE, 
	       "<= remainder %s\n",
	       remainder, 0, 0 );
	
	if ((newE = derefAlias (be, conn, op, e, deref)) == NULL) {
	  free (matched);
	  free (newDN);
	  break; /*  no associated entry, dont deref */
	}
	else {

	  Debug( LDAP_DEBUG_TRACE, 
		 "<= l&g we have %s vs %s \n",
		 matched, newE->e_dn, 0 );

	  if (!strcasecmp (matched, newE->e_dn)) {
	    /* newDN same as old so not an alias, no need to go further */
	    free (newDN);
	    free (matched);
	    break;
	  }

	  /* 
	   * we have dereferenced the aliased part so put
	   * the new dn together
	   */
	  free (newDN);
	  free (matched);
	  
	  newDN = ch_malloc (strlen(e->e_dn) + rlen + 1);
	  strcpy (newDN, remainder);
	  strcat (newDN, e->e_dn);
	  Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
	}
      }
      else {
	break; /* there was no entry for the matched part */
      }
    }
    else {
      break; /* there was no matched part */
    }
  }
  
  /*
   * the final part of the DN might be an alias 
   * so try to dereference it.
   */
  if ( (e = dn2entry( be, newDN, &matched )) != NULL) {
    if ((e = derefAlias (be, conn, op, e, deref)) != NULL) {
      free (newDN);
      newDN = strdup (e->e_dn);
    }
  }
  
  /*
   * warn if we exceeded the max depth as the resulting DN may not be dereferenced
   */
  if (depth >= be->be_maxDerefDepth) {
    Debug( LDAP_DEBUG_TRACE, 
	   "<= max deref depth exceeded in derefDN for %s, result %s\n", 
	   dn, newDN, 0 );
    send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
		      "Maximum alias dereference depth exceeded for base" );
  }
  
  Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of  %s\n", newDN, 0, 0 ); 

  return newDN;
}




/*
 * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to ITSD, Government of BC. The name of ITSD
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
 */

#include <stdio.h>
#include <string.h>
#include "slap.h"

/* 
 * given a dn (or root part), return an aliased dn if any of the 
 * alias suffixes match
 */
char *suffixAlias ( dn, op, be )
	char *dn;
	Operation *op;
	Backend *be;
{
	int 	i, dnLength;

	dnLength = strlen ( dn );
        op->o_suffix = NULL;
        op->o_suffixAliased = NULL;
        for ( i = 0;
              be->be_suffixAlias != NULL && be->be_suffixAlias[i] != NULL;
              i += 2) {
                int aliasLength = strlen (be->be_suffixAlias[i]);
                if (aliasLength > dnLength) {
                        continue;
                }

                if (!strcasecmp(be->be_suffixAlias[i], 
				dn + (dnLength - aliasLength))) {
                        char *oldDN = dn;
                        op->o_suffixAliased = strdup ( be->be_suffixAlias[i] );
                        dn = ch_malloc ( (dnLength - aliasLength) +
                                          strlen (be->be_suffixAlias[ i+1 ]) + 1);
                        strncpy (dn, oldDN, dnLength - aliasLength);
                        strcpy  (dn + (dnLength - aliasLength), be->be_suffixAlias[ i+1 ]);
                        op->o_suffix = strdup (dn);
                        Debug( LDAP_DEBUG_ARGS, "ALIAS: converted %s to %s", oldDN, dn, 0);
                        free (oldDN);
			break;
		}
	}
	return dn;
}