From: Kurt Zeilenga Date: Sun, 25 Oct 1998 01:04:47 +0000 (+0000) Subject: merge with main branch X-Git-Tag: PHP3_TOOL_0_0~18^2 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=refs%2Fheads%2FOPENLDAP_DEVEL_AC;p=openldap merge with main branch --- diff --git a/clients/gopher/go500gw.c b/clients/gopher/go500gw.c index 4600d5af89..df804c5024 100644 --- a/clients/gopher/go500gw.c +++ b/clients/gopher/go500gw.c @@ -778,15 +778,16 @@ char *query; e = ldap_first_entry( ld, res ); oc = ldap_get_values( ld, e, "objectClass" ); - if ( isnonleaf( ld, oc, dn ) ) { - dn = ldap_get_dn( ld, e ); + dn = ldap_get_dn( ld, e ); + if ( isnonleaf( ld, oc, dn ) ) { rc = do_menu( ld, fp, dn ); free( dn ); return( rc ); } + free( dn ); ldap_value_free( oc ); } diff --git a/clients/gopher/setproctitle.c b/clients/gopher/setproctitle.c index 1d1ae3b6d2..555b8a9286 100644 --- a/clients/gopher/setproctitle.c +++ b/clients/gopher/setproctitle.c @@ -23,6 +23,7 @@ int Argc; /* original argc */ /* VARARGS */ setproctitle( fmt, a, b, c ) char *fmt; +char *a, *b, *c; { static char *endargv = (char *)0; char *s; diff --git a/clients/ud/util.c b/clients/ud/util.c index 458179799a..ea0bbd1256 100644 --- a/clients/ud/util.c +++ b/clients/ud/util.c @@ -464,7 +464,7 @@ char *cp; return(tmp); } -char * code_to_str(i) +char * code_to_str(int i) { switch(i) { case LDAP_MOD_ADD : return("ADD"); diff --git a/include/avl.h b/include/avl.h index 19ed4408ad..eb8b8836fc 100644 --- a/include/avl.h +++ b/include/avl.h @@ -33,7 +33,7 @@ typedef struct avlnode { #define NULLAVL ((Avlnode *) NULL) /* balance factor values */ -#define LH -1 +#define LH (-1) #define EH 0 #define RH 1 @@ -79,7 +79,7 @@ avl_apply LDAP_P((Avlnode *, IFP, caddr_t, int, int)); #define AVL_INORDER 2 #define AVL_POSTORDER 3 /* what apply returns if it ran out of nodes */ -#define AVL_NOMORE -6 +#define AVL_NOMORE (-6) LDAP_END_DECL diff --git a/include/disptmpl.h b/include/disptmpl.h index dc39dc39f6..8ba58eff6f 100644 --- a/include/disptmpl.h +++ b/include/disptmpl.h @@ -125,13 +125,13 @@ struct ldap_tmplitem { #define NULLTMPLITEM ((struct ldap_tmplitem *)0) #define LDAP_SET_TMPLITEM_APPDATA( ti, datap ) \ - (ti)->ti_appdata = (void *)(datap) + ( (ti)->ti_appdata = (void *)(datap) ) #define LDAP_GET_TMPLITEM_APPDATA( ti, type ) \ - (type)((ti)->ti_appdata) + ( (type)((ti)->ti_appdata) ) #define LDAP_IS_TMPLITEM_OPTION_SET( ti, option ) \ - (((ti)->ti_options & option ) != 0 ) + ( ((ti)->ti_options & (option) ) != 0 ) /* @@ -201,13 +201,13 @@ struct ldap_disptmpl { #define NULLDISPTMPL ((struct ldap_disptmpl *)0) #define LDAP_SET_DISPTMPL_APPDATA( dt, datap ) \ - (dt)->dt_appdata = (void *)(datap) + ( (dt)->dt_appdata = (void *)(datap) ) #define LDAP_GET_DISPTMPL_APPDATA( dt, type ) \ - (type)((dt)->dt_appdata) + ( (type)((dt)->dt_appdata) ) #define LDAP_IS_DISPTMPL_OPTION_SET( dt, option ) \ - (((dt)->dt_options & option ) != 0 ) + ( ((dt)->dt_options & (option) ) != 0 ) #define LDAP_TMPL_ERR_VERSION 1 #define LDAP_TMPL_ERR_MEM 2 diff --git a/include/lber.h b/include/lber.h index 2617c86979..6f7c165e37 100644 --- a/include/lber.h +++ b/include/lber.h @@ -171,6 +171,7 @@ LDAP_F int ber_printf LDAP_P(( BerElement *ber, char *fmt, ... )); /* * in io.c: */ + LDAP_F long ber_read LDAP_P(( BerElement *ber, char *buf, unsigned long len )); LDAP_F long ber_write LDAP_P(( BerElement *ber, char *buf, unsigned long len, int nosos )); diff --git a/include/ldap.h b/include/ldap.h index 605356408d..0f90b1d508 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -57,16 +57,16 @@ extern int ldap_syslog_level; #ifdef LDAP_SYSLOG #define Debug( level, fmt, arg1, arg2, arg3 ) \ { \ - if ( ldap_debug & level ) \ - fprintf( stderr, fmt, arg1, arg2, arg3 ); \ + if ( ldap_debug & (level) ) \ + fprintf( stderr, (fmt), (arg1), (arg2), (arg3) ); \ if ( ldap_syslog & level ) \ - syslog( ldap_syslog_level, fmt, arg1, arg2, arg3 ); \ + syslog( ldap_syslog_level, (fmt), (arg1), (arg2), (arg3) ); \ } #else /* LDAP_SYSLOG */ #ifndef WINSOCK #define Debug( level, fmt, arg1, arg2, arg3 ) \ - if ( ldap_debug & level ) \ - fprintf( stderr, fmt, arg1, arg2, arg3 ); + if ( ldap_debug & (level) ) \ + fprintf( stderr, (fmt), (arg1), (arg2), (arg3) ); #else /* !WINSOCK */ extern void Debug( int level, char* fmt, ... ); #endif /* !WINSOCK */ @@ -479,7 +479,7 @@ typedef struct friendly { /* * handy macro to check whether LDAP struct is set up for CLDAP or not */ -#define LDAP_IS_CLDAP( ld ) ( ld->ld_sb.sb_naddr > 0 ) +#define LDAP_IS_CLDAP( ld ) ( (ld)->ld_sb.sb_naddr > 0 ) /* diff --git a/include/ldapconfig.h.edit b/include/ldapconfig.h.edit index ac0a858a51..8a053cad5b 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 "%SYSCONFDIR%/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/Makefile.in b/servers/slapd/Makefile.in index eb685ff960..55d3cedf34 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -9,14 +9,14 @@ 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 repl.c lock.c \ - schema.c schemaparse.c monitor.c configinfo.c + suffixAlias.c schema.c schemaparse.c monitor.c configinfo.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 repl.o lock.o \ - schema.o schemaparse.o monitor.o configinfo.o + suffixalias.o schema.o schemaparse.o monitor.o configinfo.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index cbd734612d..15d02dfd52 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -366,7 +366,7 @@ acl_access_allowed( /* b->a_group is an unexpanded entry name, expanded it should be an * entry with objectclass group* and we test to see if odn is one of - * the values in the attribute uniquegroup + * the values in the attribute group */ Debug( LDAP_DEBUG_ARGS, "<= check a_group: %s\n", b->a_group, 0, 0); diff --git a/servers/slapd/back-ldbm/Makefile.in b/servers/slapd/back-ldbm/Makefile.in index 0e2d15b61e..9ad580055f 100644 --- a/servers/slapd/back-ldbm/Makefile.in +++ b/servers/slapd/back-ldbm/Makefile.in @@ -1,11 +1,11 @@ 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 group.c \ modify.c modrdn.c delete.c init.c config.c bind.c attr.c \ - filterindex.c unbind.c kerberos.c close.c + filterindex.c unbind.c kerberos.c close.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 group.o \ modify.o modrdn.o delete.o init.o config.o bind.o attr.o \ - filterindex.o unbind.o kerberos.o close.o + filterindex.o unbind.o kerberos.o close.o alias.o LDAP_INCDIR= ../../../include LDAP_LIBDIR= ../../../libraries diff --git a/servers/slapd/back-ldbm/alias.c b/servers/slapd/back-ldbm/alias.c new file mode 100644 index 0000000000..b9c0d9481d --- /dev/null +++ b/servers/slapd/back-ldbm/alias.c @@ -0,0 +1,232 @@ +/* + * 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 +#include +#include "slap.h" +#include "back-ldbm.h" +#include "proto-back-ldbm.h" + +/* + * given an alias object, dereference it to its end point. + * entry returned has reader lock + */ +Entry *derefAlias_r ( Backend *be, + Connection *conn, + Operation *op, + Entry *e) +{ + Attribute *a; + int depth; + char **pastAliases; + char *matched; + + 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 ( (e = dn2entry_r( be, newDN, &matched )) == 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" ); + + if(matched != NULL) free(matched); + } + 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 +) +{ + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + char *matched; + char *newDN; + int depth; + Entry *eMatched; + Entry *eDeref; + Entry *eNew; + + + 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; + ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) && + (depth < be->be_maxDerefDepth); + ++depth ) { + + /* free reader lock */ + cache_return_entry_r(&li->li_cache, eMatched); + + if (*matched) { + char *submatch; + + /* + * make sure there actually is an entry for the matched part + */ + if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) { + char *remainder; /* part before the aliased part */ + 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 ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) { + free (matched); + free (newDN); + free (remainder); + break; /* no associated entry, dont deref */ + } + else { + + Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 ); + + if (!strcasecmp (matched, eNew->e_dn)) { + /* newDN same as old so not an alias, no need to go further */ + free (newDN); + free (matched); + free (remainder); + break; + } + + /* + * we have dereferenced the aliased part so put + * the new dn together + */ + free (newDN); + free (matched); + + newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1); + strcpy (newDN, remainder); + strcat (newDN, eMatched->e_dn); + Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 ); + + free (remainder); + + /* free reader lock */ + cache_return_entry_r(&li->li_cache, eNew); + } + /* free reader lock */ + cache_return_entry_r(&li->li_cache, eMatched); + } + else { + if(submatch != NULL) free(submatch); + 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 ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) { + if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) { + free (newDN); + newDN = strdup (eDeref->e_dn); + /* free reader lock */ + cache_return_entry_r(&li->li_cache, eDeref); + } + /* free reader lock */ + cache_return_entry_r(&li->li_cache, eNew); + } + + /* + * 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 ); + + free(matched); + + return newDN; +} diff --git a/servers/slapd/back-ldbm/group.c b/servers/slapd/back-ldbm/group.c index 16106d8904..536a48dd6b 100644 --- a/servers/slapd/back-ldbm/group.c +++ b/servers/slapd/back-ldbm/group.c @@ -17,7 +17,7 @@ extern Attribute *attr_find(); #ifdef SLAPD_ACLGROUPS /* return 0 IFF edn is a value in uniqueMember attribute * of entry with bdn AND that entry has an objectClass - * value of groupOfUniqueNames + * value of groupOfNames */ int ldbm_back_group( @@ -30,7 +30,7 @@ ldbm_back_group( Entry *e; char *matched; Attribute *objectClass; - Attribute *uniqueMember; + Attribute *member; int rc; Debug( LDAP_DEBUG_TRACE, "=> ldbm_back_group: bdn: %s\n", bdn, 0, 0 ); @@ -47,39 +47,40 @@ ldbm_back_group( /* check for deleted */ - /* find it's objectClass and uniqueMember attribute values + /* find it's objectClass and member attribute values * make sure this is a group entry - * finally test if we can find edn in the uniqueMember attribute value list * + * finally test if we can find edn in the member attribute value list * */ rc = 1; if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL) { Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 ); } - else if ((uniqueMember = attr_find(e->e_attrs, "uniquemember")) == NULL) { - Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find uniqueMember\n", 0, 0, 0 ); + else if ((member = attr_find(e->e_attrs, "member")) == NULL) { + Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find member\n", 0, 0, 0 ); } else { struct berval bvObjectClass; - struct berval bvUniqueMembers; + struct berval bvMembers; - Debug( LDAP_DEBUG_ARGS, "<= ldbm_back_group: found objectClass and uniqueMembers\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ARGS, "<= ldbm_back_group: found objectClass and members\n", 0, 0, 0 ); - bvObjectClass.bv_val = "groupofuniquenames"; + bvObjectClass.bv_val = "groupofnames"; bvObjectClass.bv_len = strlen( bvObjectClass.bv_val ); - bvUniqueMembers.bv_val = edn; - bvUniqueMembers.bv_len = strlen( edn ); + bvMembers.bv_val = edn; + bvMembers.bv_len = strlen( edn ); if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) { - Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find objectClass in groupOfUniqueNames\n", + Debug( LDAP_DEBUG_TRACE, + "<= ldbm_back_group: failed to find objectClass in groupOfNames\n", 0, 0, 0 ); } - else if (value_find(uniqueMember->a_vals, &bvUniqueMembers, SYNTAX_CIS, 1) != 0) { - Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: %s not in %s: groupOfUniqueNames\n", + else if (value_find(Member->a_vals, &bvMembers, SYNTAX_CIS, 1) != 0) { + Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: %s not in %s: groupOfNames\n", edn, bdn, 0 ); } else { - Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: %s is in %s: groupOfUniqueNames\n", + Debug( LDAP_DEBUG_ACL, "<= ldbm_back_group: %s is in %s: groupOfNames\n", edn, bdn, 0 ); rc = 0; } diff --git a/servers/slapd/back-ldbm/id2entry.c b/servers/slapd/back-ldbm/id2entry.c index 5e7582daf7..b2f0aebf8d 100644 --- a/servers/slapd/back-ldbm/id2entry.c +++ b/servers/slapd/back-ldbm/id2entry.c @@ -48,7 +48,7 @@ id2entry_add( Backend *be, Entry *e ) /* store it */ flags = LDBM_REPLACE; - if ( li->li_flush_wrt ) flags != LDBM_SYNC; + if ( li->li_flush_wrt ) flags |= LDBM_SYNC; rc = ldbm_cache_store( db, key, data, flags ); pthread_mutex_unlock( &entry2str_mutex ); diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index 371e8bf9c2..96eabe5850 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -5,6 +5,20 @@ LDAP_BEGIN_DECL +/* + * alias.c + */ +Entry *derefAlias_r LDAP_P(( + Backend *be, + Connection *conn, + Operation *op, + Entry *e )); +char *derefDN LDAP_P(( + Backend *be, + Connection *conn, + Operation *op, + char *dn )); + /* * attr.c */ @@ -45,7 +59,6 @@ int ldbm_cache_delete LDAP_P(( struct dbcache *db, Datum key )); int dn2id_add LDAP_P(( Backend *be, char *dn, ID id )); ID dn2id LDAP_P(( Backend *be, char *dn )); int dn2id_delete LDAP_P(( Backend *be, char *dn )); -/*Entry * dn2entry LDAP_P(( Backend *be, char *dn, char **matched ));*/ Entry * dn2entry_r LDAP_P(( Backend *be, char *dn, char **matched )); Entry * dn2entry_w LDAP_P(( Backend *be, char *dn, char **matched )); diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 705d6b47d6..5f0cf3a6fb 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -62,6 +62,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); @@ -79,19 +80,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; @@ -160,15 +179,15 @@ ldbm_back_search( int i, len; if ( ref->a_vals == NULL ) { - Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 0, - 0, 0 ); + Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", + e->e_dn, 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 ); + ref->a_vals[i]->bv_len ); rcur = rcur + ref->a_vals[i]->bv_len; *rcur = '\0'; nrefs++; @@ -187,15 +206,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 ); } @@ -211,6 +230,21 @@ 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: + { + Entry *newe = derefAlias_r( be, conn, op, e ); + cache_return_entry_r( &li->li_cache, e ); + e = newe; + } + 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 d40093b087..eab281a624 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -190,6 +190,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 12a913bd15..5c1e264636 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -22,6 +22,7 @@ #include "slap.h" extern Backend *select_backend(); +extern char *suffixAlias(); extern char *default_referral; @@ -146,14 +147,21 @@ do_bind( free( cred.bv_val ); } if ( cred.bv_len == 0 ) { - send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL ); + send_ldap_result( conn, op, LDAP_SUCCESS, + NULL, NULL ); + } else if ( default_referral && *default_referral ) { + send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, + NULL, default_referral ); } else { - send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL, - default_referral ); + send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, + NULL, 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 ); diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 66e8567962..f7aa3b688c 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -84,6 +84,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 ) { @@ -134,6 +137,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 \" line\n", + fname, lineno, 0 ); + exit( 1 ); + } else if ( cargc < 3 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing aliased_dn in \"suffixAlias \" 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 \" 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 eecf64090f..477e6f35f1 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -20,6 +20,7 @@ #include "slap.h" extern Backend *select_backend(); +extern char *suffixAlias(); extern char *default_referral; @@ -65,6 +66,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 1406b985b5..235acc536b 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -29,6 +29,8 @@ extern int global_lastmod; static void modlist_free(); static void add_lastmods(); +extern char *suffixAlias(); + void do_modify( @@ -149,6 +151,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 3b08579d76..a1f32ac54e 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -212,4 +212,9 @@ int value_ncmp LDAP_P(( struct berval *v1, struct berval *v2, int syntax, int le int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax, int normalize )); +/* + * suffixAlias.c + */ +char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be )); + #endif /* _proto_slap */ diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 07bf54540f..06df02159d 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -37,6 +37,9 @@ send_ldap_result2( int rc, sd; unsigned long tag, bytes; + if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') ) + err = LDAP_NO_SUCH_OBJECT; + Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n", err, matched ? matched : "", text ? text : "" ); diff --git a/servers/slapd/search.c b/servers/slapd/search.c index a1c34b76da..004678e82d 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -22,6 +22,7 @@ extern int get_filter(); extern Backend *select_backend(); +extern char *suffixAlias(); extern char *default_referral; @@ -164,6 +165,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 fad750b28d..150d384e7c 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -183,9 +183,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 */ @@ -226,6 +228,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_* */ diff --git a/servers/slapd/str2filter.c b/servers/slapd/str2filter.c index 5aea1d55b3..60ced1aee2 100644 --- a/servers/slapd/str2filter.c +++ b/servers/slapd/str2filter.c @@ -17,7 +17,7 @@ static int str2subvals(); Filter * str2filter( char *str ) { - Filter *f; + Filter *f = NULL; char *end; Debug( LDAP_DEBUG_FILTER, "str2filter \"%s\"\n", str, 0, 0 ); diff --git a/servers/slapd/suffixalias.c b/servers/slapd/suffixalias.c new file mode 100644 index 0000000000..f7c9534afe --- /dev/null +++ b/servers/slapd/suffixalias.c @@ -0,0 +1,54 @@ +/* + * 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 +#include +#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; +}