Not quite sure if the entry lock handling is correct yet.
*/
/* 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 */
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)
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)
#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
*/
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 );
int rmaxsize, nrefs;
char *rbuf, *rcur, *r;
int nentries = 0;
+ char *realBase;
Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0);
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;
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++;
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 );
}
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 */
}
}
+ /* 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 );
}
#include "slap.h"
extern Backend *select_backend();
+extern char *suffixAlias();
extern char *default_referral;
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 );
*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 ) {
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 ) {
#include "slap.h"
extern Backend *select_backend();
+extern char *suffixAlias();
extern char *default_referral;
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;
static void modlist_free();
static void add_lastmods();
+extern char *suffixAlias();
+
void
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;
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 */
extern int get_filter();
extern Backend *select_backend();
+extern char *suffixAlias();
extern char *default_referral;
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,
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 */
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_* */