From bf6c1e0ad2a9bb7e7ecce016aaa22cd5ffb87a1f Mon Sep 17 00:00:00 2001
From: Kurt Zeilenga <kurt@openldap.org>
Date: Sat, 24 Oct 1998 02:42:38 +0000
Subject: [PATCH] Added Will Ballantyne's General Aliasing code. Not quite sure
 if the entry lock handling is correct yet.

---
 include/ldapconfig.h.edit                 |  2 +
 servers/slapd/Make-template               |  6 ++-
 servers/slapd/back-ldbm/Make-template     |  6 ++-
 servers/slapd/back-ldbm/proto-back-ldbm.h | 15 ++++++-
 servers/slapd/back-ldbm/search.c          | 44 +++++++++++++++----
 servers/slapd/backend.c                   | 21 ++++++++++
 servers/slapd/bind.c                      |  4 ++
 servers/slapd/config.c                    | 51 +++++++++++++++++++++++
 servers/slapd/delete.c                    |  4 ++
 servers/slapd/modify.c                    |  5 +++
 servers/slapd/proto-slap.h                |  5 +++
 servers/slapd/search.c                    |  4 ++
 servers/slapd/slap.h                      |  4 ++
 13 files changed, 159 insertions(+), 12 deletions(-)

diff --git a/include/ldapconfig.h.edit b/include/ldapconfig.h.edit
index 9bf23812d4..ea88f22a5d 100644
--- a/include/ldapconfig.h.edit
+++ b/include/ldapconfig.h.edit
@@ -284,6 +284,8 @@ Please try again later.\r\n"
  */
 	/* location of the default slapd config file */
 #define SLAPD_DEFAULT_CONFIGFILE	"%ETCDIR%/slapd.conf"
+	/* default max deref depth for aliases */
+#define SLAPD_DEFAULT_MAXDEREFDEPTH	15	
 	/* default sizelimit on number of entries from a search */
 #define SLAPD_DEFAULT_SIZELIMIT		500
 	/* default timelimit to spend on a search */
diff --git a/servers/slapd/Make-template b/servers/slapd/Make-template
index 9ce0c6cf1c..116ae69a51 100644
--- a/servers/slapd/Make-template
+++ b/servers/slapd/Make-template
@@ -23,14 +23,16 @@ SRCS	= main.c daemon.c connection.c search.c filter.c add.c charray.c \
 		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
 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
 
 INCLUDES= -I. -I$(HDIR) $(KRBINCLUDEFLAG)
 DEFINES = $(DEFS) $(SERVERDEFS)
diff --git a/servers/slapd/back-ldbm/Make-template b/servers/slapd/back-ldbm/Make-template
index 4cc4e0a173..2a4d5b3493 100644
--- a/servers/slapd/back-ldbm/Make-template
+++ b/servers/slapd/back-ldbm/Make-template
@@ -20,11 +20,13 @@ VERSIONFILE = $(LDAPSRC)/build/version
 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)
diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h
index 1bc9fdd0e1..e834e8eeaf 100644
--- a/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -1,6 +1,20 @@
 #ifndef _PROTO_BACK_LDBM
 #define _PROTO_BACK_LDBM
 
+/*
+ * alias.c
+ */
+Entry *derefAlias ( Backend     *be,
+		    Connection	*conn,
+		    Operation	*op,
+		    Entry       *e
+		    );
+char *derefDN ( Backend     *be,
+                Connection  *conn,
+                Operation   *op,
+                char        *dn
+);
+
 /*
  * attr.c
  */
@@ -41,7 +55,6 @@ int ldbm_cache_delete( struct dbcache *db, Datum key );
 int dn2id_add( Backend *be, char *dn, ID id );
 ID dn2id( Backend *be, char *dn );
 int dn2id_delete( Backend *be, char *dn );
-/*Entry * dn2entry( Backend *be, char *dn, char **matched );*/
 Entry * dn2entry_r( Backend *be, char *dn, char **matched );
 Entry * dn2entry_w( Backend *be, char *dn, char **matched );
 
diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c
index fd9db48491..f41483c620 100644
--- a/servers/slapd/back-ldbm/search.c
+++ b/servers/slapd/back-ldbm/search.c
@@ -59,6 +59,7 @@ ldbm_back_search(
 	int		rmaxsize, nrefs;
 	char		*rbuf, *rcur, *r;
 	int		nentries = 0;
+	char		*realBase;
 
 	Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0);
 
@@ -76,19 +77,37 @@ ldbm_back_search(
 		    be->be_sizelimit : slimit;
 	}
 
+	/*
+	 * check and apply aliasing where the dereferencing applies to
+	 * the subordinates of the base
+	 */
+	realBase = strdup (base);
+	switch ( deref ) {
+	case LDAP_DEREF_FINDING:
+	case LDAP_DEREF_ALWAYS:
+		free (realBase);
+		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,
+		candidates = base_candidates( be, conn, op, realBase, filter,
 		    attrs, attrsonly, &matched, &err );
 		break;
 
 	case LDAP_SCOPE_ONELEVEL:
-		candidates = onelevel_candidates( be, conn, op, base, filter,
+		candidates = onelevel_candidates( be, conn, op, realBase, filter,
 		    attrs, attrsonly, &matched, &err );
 		break;
 
 	case LDAP_SCOPE_SUBTREE:
-		candidates = subtree_candidates( be, conn, op, base, filter,
+		candidates = subtree_candidates( be, conn, op, realBase, filter,
 		    attrs, attrsonly, &matched, NULL, &err, 1 );
 		break;
 
@@ -165,7 +184,7 @@ ldbm_back_search(
 					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 );
+						ref->a_vals[i]->bv_len );
 					rcur = rcur + ref->a_vals[i]->bv_len;
 					*rcur = '\0';
 					nrefs++;
@@ -184,15 +203,15 @@ ldbm_back_search(
 				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 ));
+						scopeok = (dn == realBase) ? 1 : (! strcasecmp( dn, realBase ));
 					} else {
-						scopeok = (base == NULL || *base == '\0');
+						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, base );
+					scopeok = dn_issuffix( dn, realBase );
 					free( dn );
 				}
 
@@ -208,6 +227,17 @@ ldbm_back_search(
 						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 */
diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c
index 67dafc69ec..076910a4e5 100644
--- a/servers/slapd/backend.c
+++ b/servers/slapd/backend.c
@@ -186,6 +186,27 @@ select_backend( char * dn )
 		}
 	}
 
+        /* 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 --git a/servers/slapd/bind.c b/servers/slapd/bind.c
index fbffeebc9f..5f6ec17621 100644
--- a/servers/slapd/bind.c
+++ b/servers/slapd/bind.c
@@ -19,6 +19,7 @@
 #include "slap.h"
 
 extern Backend	*select_backend();
+extern char	*suffixAlias();
 
 extern char	*default_referral;
 
@@ -155,6 +156,9 @@ do_bind(
 		return;
 	}
 
+        /* alias suffix */
+        dn = suffixAlias ( dn, op, be );
+
 	if ( be->be_bind != NULL ) {
 		if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
 			pthread_mutex_lock( &conn->c_dnmutex );
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index 66050586ab..6c03ebb5fd 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -81,6 +81,9 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 			*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,6 +134,54 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				charray_add( &be->be_suffix, dn );
 			}
 
+                /* 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 ) {
diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c
index bbab47806c..001d8e161c 100644
--- a/servers/slapd/delete.c
+++ b/servers/slapd/delete.c
@@ -17,6 +17,7 @@
 #include "slap.h"
 
 extern Backend	*select_backend();
+extern char     *suffixAlias();
 
 extern char	*default_referral;
 
@@ -62,6 +63,9 @@ do_delete(
 		return;
 	}
 
+        /* alias suffix if approp */
+        dn = suffixAlias ( dn, op, be );
+
 	/*
 	 * do the delete if 1 && (2 || 3)
 	 * 1) there is a delete function implemented in this backend;
diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c
index 2629291563..2d9958362b 100644
--- a/servers/slapd/modify.c
+++ b/servers/slapd/modify.c
@@ -27,6 +27,8 @@ extern int		global_lastmod;
 
 static void	modlist_free();
 static void	add_lastmods();
+extern char     *suffixAlias();
+
 
 void
 do_modify(
@@ -147,6 +149,9 @@ do_modify(
 		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 --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 83e4872d15..095b785bc9 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -210,4 +210,9 @@ int value_ncmp( struct berval *v1, struct berval *v2, int syntax, int len,
 int value_find( struct berval **vals, struct berval *v, int syntax,
 	int normalize );
 
+/*
+ * suffixAlias.c
+ */
+char *suffixAlias ( char *dn, Operation *op, Backend *be );
+
 #endif /* _proto_slap */
diff --git a/servers/slapd/search.c b/servers/slapd/search.c
index fc96d2fd02..0cadfed276 100644
--- a/servers/slapd/search.c
+++ b/servers/slapd/search.c
@@ -19,6 +19,7 @@
 
 extern int	get_filter();
 extern Backend	*select_backend();
+extern char	*suffixAlias();
 
 extern char	*default_referral;
 
@@ -161,6 +162,9 @@ do_search( conn, op )
 		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,
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 43f1eae8d1..5cffeab89c 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -178,9 +178,11 @@ struct objclass {
 
 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	   */
@@ -221,6 +223,8 @@ typedef struct op {
 	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_*			  */
-- 
GitLab