if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
entry_free( e );
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( -1 );
}
pdn = dn_parent( be, e->e_ndn );
if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
- char *matched = NULL;
+ Entry *matched = NULL;
assert( *pdn != '\0' );
/* get parent with writer lock */
if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
- 0, 0 );
+ char *matched_dn;
+ struct berval **refs;
+
+ if( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ bdb2i_cache_return_entry_w( &li->li_cache, matched );
+
+ } else {
+ matched_dn = NULL;
+ refs = default_referral;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0 );
+
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL, NULL );
+ matched_dn, NULL, NULL, NULL );
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
entry_free( e );
free(pdn);
- if ( matched != NULL ) {
- free( matched );
- }
-
if ( ! access_allowed( be, conn, op, p,
"children", NULL, ACL_WRITE ) )
{
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+
+ if ( is_entry_alias( p ) ) {
+ /* parent is an alias, don't allow add */
+
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+ if ( is_entry_referral( p ) ) {
+ /* parent is an referral, don't allow add */
+ char *matched_dn = ch_strdup( matched->e_dn );
+ struct berval **refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
/* free parent and writer lock */
bdb2i_cache_return_entry_w( &li->li_cache, p );
+ Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
entry_free( e );
return -1;
}
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
entry_free( e );
return -1;
/* free the entry */
entry_free( e );
- if(rc > 0) {
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
- } else {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
- }
+ send_ldap_result( conn, op,
+ rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
if ( bdb2i_index_add_entry( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
0, 0 );
(void) bdb2i_dn2id_delete( be, e->e_ndn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
return_results:;
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
-
}
/* check, if a new default attribute index will be created,
/*
- * 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.
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include "back-bdb2.h"
#include "proto-back-bdb2.h"
-/*
- * given an alias object, dereference it to its end point.
- * Entry returned has reader lock or is NULL. Starting entry is not released.
- */
-Entry *bdb2i_derefAlias_r ( BackendDB *be,
- Connection *conn,
- Operation *op,
- Entry *e)
+static char* get_alias_dn(
+ Entry *e,
+ int *err,
+ char **errmsg );
+
+static char* new_superior(
+ char *dn,
+ char *oldSup,
+ char *newSup );
+
+static int dnlist_subordinate(
+ char** dnlist,
+ char *dn );
+
+Entry *bdb2i_deref_r(
+ Backend* be,
+ Entry* alias,
+ char* dn,
+ int* err,
+ Entry** matched,
+ char** text )
{
- /* to free cache entries */
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Attribute *a;
- int depth;
- char *matched;
- Entry *origDN = e;
-
- if (!e) return NULL; /* be sure we have a starting entry */
-
- 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 = ch_strdup (a->a_vals[0]->bv_val);
- oldDN = ch_strdup (e->e_ndn);
-
- /*
- * release past lock if not original
- */
- if ( (depth > 0) && e ) {
- bdb2i_cache_return_entry_r(&li->li_cache, e);
- }
-
- /* make sure new and old DN are not same to avoid loops */
- dn_normalize_case (newDN);
- if ( strcmp (newDN, oldDN) == 0 ) {
-
- Debug( LDAP_DEBUG_TRACE,
- "<= %s alias is same as current %s\n",
- oldDN, newDN, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
- NULL, "circular alias", NULL );
- free (newDN);
- free (oldDN);
- break;
- }
-
- /* make sure new and original are not same to avoid deadlocks */
- if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= %s alias is same as original %s\n",
- oldDN, origDN->e_ndn, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
- NULL, "circular alias", NULL );
- free (newDN);
- free (oldDN);
- break;
- }
-
- /*
- * ok, so what happens if there is an alias in the DN of a dereferenced
- * alias object?
- */
- if ( (e = bdb2i_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_DEREF_PROBLEM,
- NULL, "dangling alias", NULL );
-
- if(matched != NULL) free(matched);
- free (newDN);
- free (oldDN);
- break;
- }
-
- 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->e_dn) ? e->e_dn : "(null)", 0, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
- NULL, "alias missing aliasedObjectname", NULL );
- break;
- }
- }
-
- /*
- * warn if we pulled out due to exceeding the maximum deref depth
- */
- if ( depth >= be->be_maxDerefDepth ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n",
- origDN->e_dn ? origDN->e_dn : "(null)",
- be->be_maxDerefDepth,
- (e && e->e_ndn) ? e->e_ndn : "(null)");
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
- NULL, "maximum alias dereference depth exceeded", NULL );
- }
-
- return e;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *entry;
+ Entry *sup;
+ unsigned depth;
+ char **dnlist;
+
+ assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
+
+ *matched = NULL;
+ *err = LDAP_SUCCESS;
+ *text = NULL;
+
+ if( alias == NULL ) {
+ dn = ch_strdup( dn );
+ entry = bdb2i_dn2entry_r( be, dn, &sup );
+
+ } else {
+ dn = ch_strdup( alias->e_ndn );
+ entry = alias;
+ sup = NULL;
+ }
+
+ dnlist = NULL;
+ charray_add( &dnlist, dn );
+
+ for( depth=0 ; ; depth++ ) {
+ if( entry != NULL ) {
+ Entry *newe;
+ char *aliasDN;
+
+ /* have entry, may be an alias */
+
+ if( !is_entry_alias( entry ) ) {
+ /* entry is not an alias */
+ break;
+ }
+
+ /* entry is alias */
+ if( depth > be->be_max_deref_depth ) {
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_DEREF_PROBLEM;
+ *text = "maximum deref depth exceeded";
+ break;
+ }
+
+ /* deref entry */
+ aliasDN = get_alias_dn( entry, err, text );
+
+ if( aliasDN == NULL ) {
+ *matched = entry;
+ entry = NULL;
+ break;
+ }
+
+ /* check if aliasDN is a subordinate of any DN in our list */
+ if( dnlist_subordinate( dnlist, aliasDN ) ) {
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "circular alias";
+ break;
+ }
+
+ /* attempt to dereference alias */
+
+ newe = bdb2i_dn2entry_r( be, aliasDN, &sup );
+
+ if( newe != NULL ) {
+ free( dn );
+ bdb2i_cache_return_entry_r(&li->li_cache, entry );
+ entry = newe;
+ dn = ch_strdup( entry->e_ndn );
+ charray_add( &dnlist, dn );
+ continue;
+
+ }
+
+ if ( sup != NULL ) {
+ bdb2i_cache_return_entry_r(&li->li_cache, entry );
+ entry = NULL;
+ continue;
+ }
+
+ /* no newe and no superior, we're done */
+ break;
+
+ } else if( sup != NULL ) {
+ /* have superior, may be an alias */
+ Entry *newe;
+ Entry *newSup;
+ char *supDN;
+ char *aliasDN;
+
+ if( !is_entry_alias( sup ) ) {
+ /* entry is not an alias */
+ *matched = sup;
+ sup = NULL;
+ break;
+ }
+
+ /* entry is alias */
+ if( depth > be->be_max_deref_depth ) {
+ *matched = sup;
+ entry = NULL;
+ *err = LDAP_ALIAS_DEREF_PROBLEM;
+ *text = "maximum deref depth exceeded";
+ break;
+ }
+
+ /* deref entry */
+ supDN = get_alias_dn( sup, err, text );
+
+ if( supDN == NULL ) {
+ *matched = sup;
+ break;
+ }
+
+ aliasDN = new_superior( dn, sup->e_ndn, supDN );
+
+ if( aliasDN == NULL ) {
+ free(aliasDN);
+ *matched = sup;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "superior alias problem";
+ break;
+ }
+
+ /* check if aliasDN is a subordinate of any DN in our list */
+ if( dnlist_subordinate( dnlist, aliasDN ) ) {
+ free(aliasDN);
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "subordinate circular alias";
+ break;
+ }
+
+ /* attempt to dereference alias */
+ newe = bdb2i_dn2entry_r( be, aliasDN, &newSup );
+
+ if( newe != NULL ) {
+ free(aliasDN);
+ free( dn );
+ bdb2i_cache_return_entry_r(&li->li_cache, sup );
+ entry = newe;
+ dn = ch_strdup( entry->e_ndn );
+ charray_add( &dnlist, dn );
+ continue;
+
+ }
+
+ if ( newSup != NULL ) {
+ free( dn );
+ bdb2i_cache_return_entry_r(&li->li_cache, sup );
+ sup = newSup;
+ dn = aliasDN;
+ continue;
+ }
+
+ break;
+
+ } else {
+ /* no newe and no superior, we're done */
+ break;
+ }
+ }
+
+ free( dn );
+ return entry;
}
-/*
- * given a DN fully deref it and return the real DN or original DN if it fails
- * This involves finding the last matched part then reconstructing forward
- * e.g.
- * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
- * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
- * dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
- * dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
- * remainder is ou=MyOU
- * dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
- * release lock on o=MyAliasedOrg,c=MyCountry entry
- * reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
- * release lock on o=MyOrg,c=MyCountry entry
- */
-char *bdb2i_derefDN ( BackendDB *be,
- Connection *conn,
- Operation *op,
- char *dn
-)
-{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = 0;
- char *newDN = NULL;
- int depth, i;
- Entry *eMatched;
- Entry *eDeref;
- Entry *eNew;
-
- if (!dn) return NULL;
-
- Debug( LDAP_DEBUG_TRACE,
- "<= dereferencing dn: \"%s\"\n",
- dn, 0, 0 );
-
- newDN = ch_strdup ( dn );
-
- /* while we don't have a matched dn, deref the DN */
- for ( depth = 0;
- ( (eMatched = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL) &&
- (depth < be->be_maxDerefDepth);
- ++depth ) {
-
- if ((matched != NULL) && *matched) {
- char *submatch;
-
- /*
- * make sure there actually is an entry for the matched part
- */
- if ( (eMatched = bdb2i_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 = bdb2i_derefAlias_r( be, conn, op, eMatched )) == NULL) {
- free (matched);
- matched = NULL;
- free (newDN);
- newDN = NULL;
- free (remainder);
- remainder = NULL;
-
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- eMatched = NULL;
- break; /* no associated entry, dont deref */
+
+static char* get_alias_dn(
+ Entry *e,
+ int *err,
+ char **errmsg )
+{
+ Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" );
+
+ if( a == NULL ) {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ */
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias missing aliasedObjectName attribute";
+ return NULL;
}
- else {
-
- Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
-
- i = strcasecmp (matched, eNew->e_dn);
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eNew);
-
- free (matched);
- matched = NULL;
-
- if (! i) {
- /* newDN same as old so not an alias, no need to go further */
- free (newDN);
- newDN = NULL;
- free (remainder);
-
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- eMatched = NULL;
- break;
- }
-
- /*
- * we have dereferenced the aliased part so put
- * the new dn together
- */
- free (newDN);
- 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);
+
+ /*
+ * aliasedObjectName should be SINGLE-VALUED with a single value.
+ */
+ if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val != NULL ) {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ */
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias missing aliasedObjectName value";
+ return NULL;
}
- /* free reader lock */
- bdb2i_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 */
- }
- }
-
- /* release lock if a match terminated the loop, there should be no
- * outstanding locks at this point
- */
- if(eMatched != NULL) {
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- }
-
- /*
- * the final part of the DN might be an alias so try to dereference it.
- * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
- * and the above loop complete but we would still be left with an aliased DN.
- */
- if (newDN != NULL) {
- if ( (eNew = bdb2i_dn2entry_r( be, newDN, &matched )) != NULL) {
- if ((eDeref = bdb2i_derefAlias_r( be, conn, op, eNew )) != NULL) {
- free (newDN);
- newDN = ch_strdup (eDeref->e_dn);
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eDeref);
- }
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eNew);
- }
- }
- if (matched != NULL) free(matched);
-
- /*
- * warn if we exceeded the max depth as the resulting DN may not be dereferenced
- */
- if (depth >= be->be_maxDerefDepth) {
- if (newDN) {
- Debug( LDAP_DEBUG_TRACE,
- "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
- dn, newDN, 0 );
- free (newDN);
- newDN = NULL;
- } else {
- Debug( LDAP_DEBUG_TRACE,
- "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
- dn, 0, 0 );
+
+ if( a->a_vals[1] != NULL ) {
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias has multivalued aliasedObjectName";
+ return NULL;
}
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
- NULL, "maximum alias dereference depth exceeded for base", NULL );
- }
- if (newDN == NULL) {
- newDN = ch_strdup ( dn );
- }
-
- Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
+ return a->a_vals[0]->bv_val;
+}
+
+static char* new_superior(
+ char *dn,
+ char *oldSup,
+ char *newSup )
+{
+ char *newDN;
+ size_t dnlen, olen, nlen;
+ assert( dn && oldSup && newSup );
+
+ dnlen = strlen( dn );
+ olen = strlen( oldSup );
+ nlen = strlen( newSup );
+
+ newDN = ch_malloc( dnlen - olen + nlen + 1 );
+
+ memcpy( newDN, dn, dnlen - olen );
+ memcpy( &newDN[dnlen - olen], newSup, nlen );
+ newDN[dnlen - olen + nlen] = '\0';
- return newDN;
+ return newDN;
}
+
+static int dnlist_subordinate(
+ char** dnlist,
+ char *dn )
+{
+ int i;
+ assert( dnlist );
+
+ for( i = 0; dnlist[i] != NULL; i++ ) {
+ if( dn_issuffix( dnlist[i], dn ) ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
Entry *e;
Attribute *a;
int rc;
- char *matched;
+ Entry *matched;
#ifdef HAVE_KERBEROS
char krbname[MAX_K_NAME_SZ + 1];
AUTH_DAT ad;
/* get entry with reader lock */
if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
/* allow noauth binds */
rc = 1;
if ( method == LDAP_AUTH_SIMPLE ) {
if( cred->bv_len == 0 ) {
/* SUCCESS */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
} else if ( be_isroot_pw( be, dn, cred ) ) {
/* front end will send result */
rc = 0;
} else {
- send_ldap_result( conn, op,
- LDAP_NO_SUCH_OBJECT, matched, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
}
} else if ( method == LDAP_AUTH_SASL ) {
if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
/* insert DIGEST calls here */
- send_ldap_result( conn, op,
- LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op,
- LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
}
} else {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
rc = 1;
}
+
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
return( rc );
}
"entry", NULL, ACL_AUTH ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( is_entry_alias( e ) ) {
+ /* entry is a alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ rc = 1;
+ goto return_results;
+ }
+
+
+ if ( is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow bind */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
rc = 1;
goto return_results;
}
switch ( method ) {
case LDAP_AUTH_SIMPLE:
if ( cred->bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
"userpassword", NULL, ACL_AUTH ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
/* stop front end from sending result */
rc = 1;
if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
{
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
/* stop front end from sending result */
rc = 1;
goto return_results;
case LDAP_AUTH_KRBV41:
if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
"krbname", NULL, ACL_AUTH ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
break;
}
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
} else { /* look for krbName match */
if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
break;
case LDAP_AUTH_KRBV42:
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
goto return_results;
default:
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
- NULL, "auth method not supported", NULL );
+ NULL, "auth method not supported", NULL, NULL );
rc = 1;
goto return_results;
}
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( 1 );
}
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
+ Entry *matched;
Entry *e;
Attribute *a;
int rc;
+ int manageDSAit = get_manageDSAit( op );
/* get entry with reader lock */
if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL, NULL );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
- if(matched == NULL) free(matched);
return( 1 );
}
- /* check for deleted */
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
+ }
+
if ( ! access_allowed( be, conn, op, e,
ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
else
send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
rc = 0;
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( 1 );
}
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
+ Entry *matched = NULL;
char *pdn = NULL;
Entry *e, *p = NULL;
- int rc = -1;
+ int rc = -1, manageDSAit;
Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
/* get entry with writer lock */
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL, NULL );
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
}
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
return( -1 );
}
- /* check for deleted */
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ goto return_results;
+ }
+
if ( bdb2i_has_children( be, e ) ) {
Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
dn, 0, 0);
send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"<=- bdb2i_back_delete: insufficient access %s\n",
dn, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
#endif
Debug( LDAP_DEBUG_TRACE,
"<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
}
"<=- bdb2i_back_delete: operations error %s\n",
dn, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"<=- bdb2i_back_delete: operations error %s\n",
dn, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"<=- bdb2i_back_delete: operations error %s\n",
dn, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
return_results:;
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( -1 );
-
}
ret = bdb2i_back_delete_internal( be, conn, op, dn );
--- /dev/null
+/* dn2id.c - routines to deal with the dn2id index */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+int
+bdb2i_dn2id_add(
+ BackendDB *be,
+ char *dn,
+ ID id
+)
+{
+ int rc, flags;
+ struct dbcache *db;
+ Datum key, data;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( -1 );
+ }
+
+ dn = ch_strdup( dn );
+ dn_normalize_case( dn );
+
+ key.dptr = dn;
+ key.dsize = strlen( dn ) + 1;
+ data.dptr = (char *) &id;
+ data.dsize = sizeof(ID);
+
+ flags = LDBM_INSERT;
+ if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
+
+ rc = bdb2i_cache_store( db, key, data, flags );
+
+ free( dn );
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_add %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+ID
+bdb2i_dn2id(
+ BackendDB *be,
+ char *dn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct dbcache *db;
+ ID id;
+ Datum key, data;
+
+ ldbm_datum_init( key );
+ ldbm_datum_init( data );
+
+ dn = ch_strdup( dn );
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id( \"%s\" )\n", dn, 0, 0 );
+ dn_normalize_case( dn );
+
+ /* first check the cache */
+ if ( (id = bdb2i_cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
+ free( dn );
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %ld (in cache)\n", id,
+ 0, 0 );
+ return( id );
+ }
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ free( dn );
+ Debug( LDAP_DEBUG_ANY, "<= bdb2i_dn2id could not open dn2id%s\n",
+ BDB2_SUFFIX, 0, 0 );
+ return( NOID );
+ }
+
+ key.dptr = dn;
+ key.dsize = strlen( dn ) + 1;
+
+ data = bdb2i_cache_fetch( db, key );
+
+ bdb2i_cache_close( be, db );
+ free( dn );
+
+ if ( data.dptr == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id NOID\n", 0, 0, 0 );
+ return( NOID );
+ }
+
+ (void) memcpy( (char *) &id, data.dptr, sizeof(ID) );
+
+ ldbm_datum_free( db->dbc_db, data );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id %ld\n", id, 0, 0 );
+ return( id );
+}
+
+int
+bdb2i_dn2id_delete(
+ BackendDB *be,
+ char *dn
+)
+{
+ struct dbcache *db;
+ Datum key;
+ int rc;
+
+ ldbm_datum_init( key );
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id_delete( \"%s\" )\n", dn, 0, 0 );
+
+ if ( (db = bdb2i_cache_open( be, "dn2id", BDB2_SUFFIX, LDBM_WRCREAT ))
+ == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "<= bdb2i_dn2id_delete could not open dn2id%s\n", BDB2_SUFFIX,
+ 0, 0 );
+ return( -1 );
+ }
+
+ dn = ch_strdup( dn );
+ dn_normalize_case( dn );
+ key.dptr = dn;
+ key.dsize = strlen( dn ) + 1;
+
+ rc = bdb2i_cache_delete( db, key );
+
+ free( dn );
+
+ bdb2i_cache_close( be, db );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb2i_dn2id_delete %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+/*
+ * dn2entry - look up dn in the cache/indexes and return the corresponding
+ * entry.
+ */
+
+Entry *
+bdb2i_dn2entry_rw(
+ BackendDB *be,
+ char *dn,
+ Entry **matched,
+ int rw
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ ID id;
+ Entry *e = NULL;
+ char *pdn;
+
+ Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
+ rw ? "w" : "r", dn, 0);
+
+ if( matched != NULL ) {
+ /* caller cares about match */
+ *matched = NULL;
+ }
+
+ if ( (id = bdb2i_dn2id( be, dn )) != NOID &&
+ (e = bdb2i_id2entry_rw( be, id, rw )) != NULL )
+ {
+ return( e );
+ }
+
+ if ( id != NOID ) {
+ Debug(LDAP_DEBUG_ANY,
+ "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
+ rw ? "w" : "r", id, dn);
+ /* must have been deleted from underneath us */
+ /* treat as if NOID was found */
+ }
+
+ /* caller doesn't care about match */
+ if( matched == NULL ) return NULL;
+
+ /* entry does not exist - see how much of the dn does exist */
+ /* dn_parent checks returns NULL if dn is suffix */
+ if ( (pdn = dn_parent( be, dn )) != NULL ) {
+ /* get entry with reader lock */
+ if ( (e = bdb2i_dn2entry_r( be, pdn, matched )) != NULL ) {
+ *matched = e;
+ }
+ free( pdn );
+ }
+
+ return( NULL );
+}
+
+
--- /dev/null
+/* group.c - bdb2 backend acl group routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+
+/* return 0 IFF op_dn is a value in member attribute
+ * of entry with gr_dn AND that entry has an objectClass
+ * value of groupOfNames
+ */
+static int
+bdb2i_back_group_internal(
+ BackendDB *be,
+ Entry *target,
+ char *gr_ndn,
+ char *op_ndn,
+ char *objectclassValue,
+ char *groupattrName
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *e;
+ int rc = 1;
+ Attribute *attr;
+ struct berval bv;
+
+ Debug( LDAP_DEBUG_ARGS,
+ "=> bdb2i_back_group: gr dn: \"%s\"\n",
+ gr_ndn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS,
+ "=> bdb2i_back_group: op dn: \"%s\"\n",
+ op_ndn, 0, 0 );
+ Debug( LDAP_DEBUG_ARGS,
+ "=> bdb2i_back_group: objectClass: \"%s\" attrName: \"%s\"\n",
+ objectclassValue, groupattrName, 0 );
+
+ Debug( LDAP_DEBUG_ARGS,
+ "=> bdb2i_back_group: tr dn: \"%s\"\n",
+ target->e_ndn, 0, 0 );
+
+ if (strcmp(target->e_ndn, gr_ndn) == 0) {
+ /* we already have a LOCKED copy of the entry */
+ e = target;
+ Debug( LDAP_DEBUG_ARGS,
+ "=> bdb2i_back_group: target is group: \"%s\"\n",
+ gr_ndn, 0, 0 );
+
+ } else {
+ /* can we find group entry with reader lock */
+ if ((e = bdb2i_dn2entry_r(be, gr_ndn, NULL )) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "=> bdb2i_back_group: cannot find group: \"%s\"\n",
+ gr_ndn, 0, 0 );
+ return( 1 );
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "=> bdb2i_back_group: found group: \"%s\"\n",
+ gr_ndn, 0, 0 );
+ }
+
+ /* find it's objectClass and member attribute values
+ * make sure this is a group entry
+ * finally test if we can find op_dn in the member attribute value list
+ */
+
+ rc = 1;
+
+ if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = "ALIAS";
+ bv.bv_len = sizeof("ALIAS")-1;
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: group is an alias\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = "REFERRAL";
+ bv.bv_len = sizeof("REFERRAL")-1;
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: group is a referral\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = objectclassValue;
+ bv.bv_len = strlen( bv.bv_val );
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: failed to find %s in objectClass\n",
+ objectclassValue, 0, 0 );
+ goto return_results;
+ }
+
+ if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: failed to find %s\n",
+ groupattrName, 0, 0 );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: found objectClass %s and %s\n",
+ objectclassValue, groupattrName, 0 );
+
+
+ bv.bv_val = op_ndn;
+ bv.bv_len = strlen( op_ndn );
+
+ if (value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 ) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+ rc = 0;
+
+return_results:
+ if( target != e ) {
+ /* free entry and reader lock */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ }
+
+ Debug( LDAP_DEBUG_ARGS, "bdb2i_back_group: rc: %d\n", rc, 0, 0 );
+ return(rc);
+}
+
+
+int
+bdb2_back_group(
+ BackendDB *be,
+ Entry *target,
+ char *gr_ndn,
+ char *op_ndn,
+ char *objectclassValue,
+ char *groupattrName
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
+
+ return( 1 );
+
+ }
+
+ ret = bdb2i_back_group_internal( be, target, gr_ndn, op_ndn,
+ objectclassValue, groupattrName );
+
+ (void) bdb2i_leave_backend_r( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "GRP", NULL, NULL );
+
+ return( ret );
+}
+
+
Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
- send_ldap_result( conn, op, err, NULL, NULL, NULL );
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
- send_ldap_result( conn, op, err, NULL, NULL, NULL );
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
}
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto error_return;
}
/* modify indexes */
if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto error_return;
}
/* change the entry itself */
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto error_return;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
bdb2i_cache_return_entry_w( &li->li_cache, e );
return( 0 );
DB_LOCK lock;
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
struct timeval time1;
- int ret;
- char *matched;
+ int ret, manageDSAit;
+ Entry *matched;
Entry *e;
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( -1 );
}
}
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL, NULL );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
}
- return( -1 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ ret = -1;
+ goto done;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+ ber_bvecfree( refs );
+
+ ret = -1;
+ goto done;
}
- ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+ ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+
+done:
(void) bdb2i_leave_backend_w( lock );
bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op );
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
+ Entry *matched = NULL;
char *p_dn = NULL, *p_ndn = NULL;
char *new_dn = NULL, *new_ndn = NULL;
char sep[2];
Entry *e, *p = NULL;
- int rc = -1;
+ int rc = -1, manageDSAit;
/* Added to support LDAP v2 correctly (deleteoldrdn thing) */
char *new_rdn_val = NULL; /* Val of new rdn */
char *new_rdn_type = NULL; /* Type of new rdn */
/* get entry with writer lock */
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, NULL, NULL );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
}
+
return( -1 );
}
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ goto return_results;
+ }
+
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
/* check parent for "children" acl */
if ( ! access_allowed( be, conn, op, e,
Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
#endif
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
np_ndn, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: no wr to newSup children\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
new_ndn, 0, 0 );
if ( (bdb2i_dn2id ( be, new_ndn ) ) != NOID ) {
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* delete old one */
if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* add new one */
if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: can't figure out type of newrdn\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: can't figure out val of newrdn\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: can't figure out old_rdn from dn\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: can't figure out the old_rdn type\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results;
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
entry_free( e );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto return_results_after;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
goto return_results_after;
if( p_dn != NULL ) free( p_dn );
if( p_ndn != NULL ) free( p_ndn );
- if( matched != NULL ) free( matched );
-
/* LDAP v2 supporting correct attribute handling. */
if( new_rdn_type != NULL ) free(new_rdn_type);
if( new_rdn_val != NULL ) free(new_rdn_val);
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( -1 );
}
--- /dev/null
+#ifndef _PROTO_BACK_BDB2
+#define _PROTO_BACK_BDB2
+
+#include <ldap_cdefs.h>
+
+#include <ac/time.h> /* Needed in add.c compare.c struct timeval */
+
+#include "external.h"
+
+LDAP_BEGIN_DECL
+
+/*
+ * add.c
+ */
+int bdb2i_release_add_lock LDAP_P(());
+
+/*
+ * alias.c
+ */
+
+Entry * bdb2i_deref_r LDAP_P((
+ Backend *be,
+ Entry *e,
+ char *dn,
+ int *err,
+ Entry **matched,
+ char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+ bdb2i_deref_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+ bdb2i_deref_r( be, NULL, dn, err, matched, text )
+
+/*
+ * attr.c
+ */
+
+void bdb2i_attr_masks LDAP_P(( struct ldbminfo *li, char *type, int *indexmask,
+ int *syntaxmask ));
+void bdb2i_attr_index_config LDAP_P(( struct ldbminfo *li, char *fname,
+ int lineno, int argc, char **argv, int init ));
+
+/*
+ * cache.c
+ */
+
+int bdb2i_cache_add_entry_rw LDAP_P(( struct cache *cache, Entry *e, int rw ));
+int bdb2i_cache_update_entry LDAP_P(( struct cache *cache, Entry *e ));
+void bdb2i_cache_return_entry_rw LDAP_P(( struct cache *cache, Entry *e,
+ int rw ));
+#define bdb2i_cache_return_entry_r(c, e) bdb2i_cache_return_entry_rw((c), (e), 0)
+#define bdb2i_cache_return_entry_w(c, e) bdb2i_cache_return_entry_rw((c), (e), 1)
+
+ID bdb2i_cache_find_entry_dn2id LDAP_P(( BackendDB *be, struct cache *cache,
+ char *dn ));
+Entry * bdb2i_cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw ));
+int bdb2i_cache_delete_entry LDAP_P(( struct cache *cache, Entry *e ));
+
+/*
+ * dbcache.c
+ */
+
+struct dbcache * bdb2i_cache_open LDAP_P(( BackendDB *be, char *name, char *suffix,
+ int flags ));
+void bdb2i_cache_close LDAP_P(( BackendDB *be, struct dbcache *db ));
+void bdb2i_cache_really_close LDAP_P(( BackendDB *be, struct dbcache *db ));
+void bdb2i_cache_flush_all LDAP_P(( BackendDB *be ));
+Datum bdb2i_cache_fetch LDAP_P(( struct dbcache *db, Datum key ));
+int bdb2i_cache_store LDAP_P(( struct dbcache *db, Datum key, Datum data, int flags ));
+int bdb2i_cache_delete LDAP_P(( struct dbcache *db, Datum key ));
+
+/*
+ * dn2id.c
+ */
+
+int bdb2i_dn2id_add LDAP_P(( BackendDB *be, char *dn, ID id ));
+ID bdb2i_dn2id LDAP_P(( BackendDB *be, char *dn ));
+int bdb2i_dn2id_delete LDAP_P(( BackendDB *be, char *dn ));
+
+Entry * bdb2i_dn2entry_rw LDAP_P((
+ BackendDB *be,
+ char *dn,
+ Entry **matched,
+ int rw ));
+
+#define bdb2i_dn2entry_r(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 0)
+#define bdb2i_dn2entry_w(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 1)
+
+/*
+ * entry.c
+ */
+int bdb2_back_entry_release_rw LDAP_P(( BackendDB *be, Entry *e, int rw ));
+
+/*
+ * filterindex.c
+ */
+
+ID_BLOCK * bdb2i_filter_candidates LDAP_P(( BackendDB *be, Filter *f ));
+
+/*
+ * id2children.c
+ */
+
+int bdb2i_id2children_add LDAP_P(( BackendDB *be, Entry *p, Entry *e ));
+int bdb2i_id2children_remove LDAP_P(( BackendDB *be, Entry *p, Entry *e ));
+int bdb2i_has_children LDAP_P(( BackendDB *be, Entry *p ));
+
+/*
+ * id2entry.c
+ */
+
+int bdb2i_id2entry_add LDAP_P(( BackendDB *be, Entry *e ));
+int bdb2i_id2entry_delete LDAP_P(( BackendDB *be, Entry *e ));
+
+Entry * bdb2i_id2entry_rw LDAP_P(( BackendDB *be, ID id, int rw ));
+#define bdb2i_id2entry_r(be, id) bdb2i_id2entry_rw((be), (id), 0)
+#define bdb2i_id2entry_w(be, id) bdb2i_id2entry_rw((be), (id), 1)
+
+/*
+ * idl.c
+ */
+
+ID_BLOCK * bdb2i_idl_alloc LDAP_P(( unsigned int nids ));
+ID_BLOCK * bdb2i_idl_allids LDAP_P(( BackendDB *be ));
+void bdb2i_idl_free LDAP_P(( ID_BLOCK *idl ));
+ID_BLOCK * bdb2i_idl_fetch LDAP_P(( BackendDB *be, struct dbcache *db, Datum key ));
+int bdb2i_idl_insert_key LDAP_P(( BackendDB *be, struct dbcache *db, Datum key, ID id ));
+int bdb2i_idl_insert LDAP_P(( ID_BLOCK **idl, ID id, unsigned int maxids ));
+int bdb2i_idl_delete_key LDAP_P(( BackendDB *be, struct dbcache *db, Datum key, ID id ));
+ID_BLOCK * bdb2i_idl_intersection LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID_BLOCK * bdb2i_idl_union LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID_BLOCK * bdb2i_idl_notin LDAP_P(( BackendDB *be, ID_BLOCK *a, ID_BLOCK *b ));
+ID bdb2i_idl_firstid LDAP_P(( ID_BLOCK *idl ));
+ID bdb2i_idl_nextid LDAP_P(( ID_BLOCK *idl, ID id ));
+
+/*
+ * index.c
+ */
+
+int bdb2i_index_add_entry LDAP_P(( BackendDB *be, Entry *e ));
+int bdb2i_index_add_mods LDAP_P(( BackendDB *be, LDAPModList *ml, ID id ));
+ID_BLOCK * bdb2i_index_read LDAP_P(( BackendDB *be, char *type, int indextype, char *val ));
+int bdb2i_index_add_values LDAP_P(( BackendDB *be, char *type, struct berval **vals, ID id ));
+
+/*
+ * kerberos.c
+ */
+
+#ifdef HAVE_KERBEROS
+/* bdb2i_krbv4_ldap_auth LDAP_P(( BackendDB *be, struct berval *cred, AUTH_DAT *ad )); */
+#endif
+
+/*
+ * modify.c
+ * These prototypes are placed here because they are used by modify and
+ * modify rdn which are implemented in different files.
+ *
+ * We need bdb2i_back_modify_internal here because of LDAP modrdn & modify use
+ * it. If we do not add this, there would be a bunch of code replication
+ * here and there and of course the likelihood of bugs increases.
+ * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
+ *
+ */
+
+int bdb2i_add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int bdb2i_delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int bdb2i_replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+int bdb2i_back_modify_internal LDAP_P((Backend *be, Connection *conn, Operation *op,
+ char *dn, LDAPModList *mods, Entry *e));
+/*
+ * nextid.c
+ */
+
+ID bdb2i_next_id LDAP_P(( BackendDB *be ));
+void bdb2i_next_id_return LDAP_P(( BackendDB *be, ID id ));
+ID bdb2i_next_id_get LDAP_P(( BackendDB *be ));
+int bdb2i_next_id_save LDAP_P(( BackendDB *be ));
+
+/*
+ * startup.c
+ */
+
+int bdb2i_back_startup LDAP_P(( BackendInfo *bi ));
+int bdb2i_back_shutdown LDAP_P(( BackendInfo *bi ));
+int bdb2i_back_db_startup LDAP_P(( BackendDB *be ));
+int bdb2i_back_db_shutdown LDAP_P(( BackendDB *be ));
+
+/*
+ * timing.c
+ */
+
+void bdb2i_uncond_start_timing LDAP_P(( struct timeval *time1 ));
+#define bdb2i_start_timing(bi,time1) if ( with_timing( bi )) bdb2i_uncond_start_timing( (time1) )
+void bdb2i_uncond_stop_timing LDAP_P(( struct timeval time1,
+ char *func, Connection *conn, Operation *op, int level ));
+#define bdb2i_stop_timing(bi,time1,func,conn,op) if ( with_timing( bi )) bdb2i_uncond_stop_timing( (time1), (func), (conn), (op), LDAP_DEBUG_ANY )
+
+/*
+ * porter.c
+ */
+
+int bdb2i_enter_backend_rw LDAP_P(( DB_LOCK *lock, int writer ));
+#define bdb2i_enter_backend_r(lock) bdb2i_enter_backend_rw((lock), 0 )
+#define bdb2i_enter_backend_w(lock) bdb2i_enter_backend_rw((lock), 1 )
+int bdb2i_leave_backend_rw LDAP_P(( DB_LOCK lock, int writer ));
+#define bdb2i_leave_backend_r(lock) bdb2i_leave_backend_rw((lock), 0 )
+#define bdb2i_leave_backend_w(lock) bdb2i_leave_backend_rw((lock), 1 )
+
+/*
+ * txn.c
+ */
+
+int bdb2i_txn_head_init LDAP_P(( BDB2_TXN_HEAD *head ));
+void bdb2i_txn_attr_config LDAP_P((
+ struct ldbminfo *li,
+ char *attr,
+ int open ));
+int bdb2i_txn_open_files LDAP_P(( BackendDB *be ));
+void bdb2i_txn_close_files LDAP_P(( BackendDB *be ));
+BDB2_TXN_FILES *bdb2i_get_db_file_cache LDAP_P((
+ struct ldbminfo *li,
+ char *name ));
+int bdb2i_check_additional_attr_index LDAP_P(( struct ldbminfo *li ));
+void bdb2i_check_default_attr_index_add LDAP_P((
+ struct ldbminfo *li,
+ Entry *e ));
+void bdb2i_check_default_attr_index_mod LDAP_P((
+ struct ldbminfo *li,
+ LDAPModList *modlist ));
+ID bdb2i_get_nextid LDAP_P(( BackendDB *be ));
+int bdb2i_put_nextid LDAP_P(( BackendDB *be, ID id ));
+LDBM bdb2i_db_open LDAP_P(( char *name, int type, int rw, int mode,
+ int dbcachesize ));
+int bdb2i_db_store LDAP_P(( LDBM ldbm, Datum key, Datum data, int flags ));
+int bdb2i_db_delete LDAP_P(( LDBM ldbm, Datum key ));
+Datum bdb2i_db_fetch LDAP_P(( LDBM ldbm, Datum key ));
+Datum bdb2i_db_firstkey LDAP_P(( LDBM ldbm, DBC **dbch ));
+Datum bdb2i_db_nextkey LDAP_P(( LDBM ldbm, Datum key, DBC *dbcp ));
+int bdb2i_start_transction LDAP_P(( DB_TXNMGR *txmgr ));
+int bdb2i_finish_transaction LDAP_P(( ));
+int bdb2i_set_txn_checkpoint LDAP_P(( DB_TXNMGR *txmgr, int forced ));
+
+
+LDAP_END_DECL
+#endif
#include "back-bdb2.h"
#include "proto-back-bdb2.h"
-static ID_BLOCK *base_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK *onelevel_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK *subtree_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
-
-#define GRABSIZE BUFSIZ
-
-#define MAKE_SPACE( n ) { \
- if ( rcur + (n) > rbuf + rmaxsize ) { \
- int offset = rcur - rbuf; \
- rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
- rmaxsize += GRABSIZE; \
- rcur = rbuf + offset; \
- } \
-}
+static ID_BLOCK *base_candidate(
+ Backend *be, Entry *e );
+
+static ID_BLOCK *search_candidates(
+ Backend *be, Entry *e, Filter *filter,
+ int scope, int deref, int manageDSAit );
static int
bdb2i_back_search_internal(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- int err;
+ int rc, err;
+ char *text;
time_t stoptime;
ID_BLOCK *candidates;
ID id;
Entry *e;
- Attribute *ref;
- struct berval **refs;
- char *matched = NULL;
+ struct berval **v2refs = NULL;
+ Entry *matched = NULL;
+ char *realbase = NULL;
int nentries = 0;
- char *realBase;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_TRACE, "=> bdb2_back_search\n", 0, 0, 0);
+
+ /* get entry with reader lock */
+ if ( deref & LDAP_DEREF_FINDING ) {
+ e = deref_dn_r( be, base, &err, &matched, &text );
+
+ } else {
+ e = bdb2i_dn2entry_r( be, base, &matched );
+ err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+ text = NULL;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, err,
+ matched_dn, text, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
- Debug(LDAP_DEBUG_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
+ return 1;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ char *matched_dn = ch_strdup( e->e_dn );
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+
+ return 1;
+ }
if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
tlimit = -1; /* allow root to set no limit */
be->be_timelimit : tlimit;
stoptime = op->o_time + tlimit;
}
+
if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
slimit = -1; /* allow root to set no limit */
} else {
be->be_sizelimit : slimit;
}
- /*
- * 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 = bdb2i_derefDN ( be, conn, op, base );
- break;
- default:
- realBase = ch_strdup(base);
- }
-
- (void) dn_normalize_case( realBase );
-
- Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
- realBase, 0, 0 );
-
- switch ( scope ) {
- case LDAP_SCOPE_BASE:
- candidates = base_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, &err );
- break;
-
- case LDAP_SCOPE_ONELEVEL:
- candidates = onelevel_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, &err );
- break;
+ if ( scope == LDAP_SCOPE_BASE) {
+ candidates = base_candidate( be, e );
- case LDAP_SCOPE_SUBTREE:
- candidates = subtree_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, NULL, &err, 1 );
- break;
-
- default:
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
- NULL, "Bad scope", NULL );
- if( realBase != NULL) {
- free( realBase );
- }
- return( -1 );
+ } else {
+ candidates = search_candidates( be, e, filter,
+ scope, deref, manageDSAit );
}
- /* null candidates means we could not find the base object */
+ /* need normalized dn below */
+ realbase = ch_strdup( e->e_ndn );
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
if ( candidates == NULL ) {
- send_ldap_result( conn, op, err, matched, NULL, NULL );
- if ( matched != NULL ) {
- free( matched );
- }
- if( realBase != NULL) {
- free( realBase );
- }
- return( -1 );
- }
+ /* no candidates */
+ Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+ 0, 0 );
- if ( matched != NULL ) {
- free( matched );
- }
+ send_search_result( conn, op,
+ LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 0 );
- refs = NULL;
+ rc = 1;
+ goto done;
+ }
for ( id = bdb2i_idl_firstid( candidates ); id != NOID;
- id = bdb2i_idl_nextid( candidates, id ) ) {
+ id = bdb2i_idl_nextid( candidates, id ) )
+ {
+ int scopeok = 0;
+
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- bdb2i_idl_free( candidates );
- ber_bvecfree( refs );
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
+ rc = 0;
+ goto done;
}
+
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
if ( tlimit != -1 && slap_get_time() > stoptime ) {
send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
- NULL, NULL, refs, nentries );
- bdb2i_idl_free( candidates );
- ber_bvecfree( refs );
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
+ NULL, NULL, v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
}
/* get the entry with reader lock */
- if ( (e = bdb2i_id2entry_r( be, id )) == NULL ) {
- Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
- id, 0, 0 );
- continue;
+ e = bdb2i_id2entry_r( be, id );
+
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+ id, 0, 0 );
+
+ goto loop_continue;
+ }
+
+ if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+ Entry *matched;
+ int err;
+ char *text;
+
+ e = deref_entry_r( be, e, &err, &matched, &text );
+
+ if( e == NULL ) {
+ e = matched;
+ goto loop_continue;
+ }
+
+ if( e->e_id == id ) {
+ /* circular loop */
+ goto loop_continue;
+ }
+
+ /* need to skip alias which deref into scope */
+ if( scope & LDAP_SCOPE_ONELEVEL ) {
+ char *pdn = dn_parent( NULL, e->e_ndn );
+ if ( pdn != NULL ) {
+ if( strcmp( pdn, realbase ) ) {
+ free( pdn );
+ goto loop_continue;
+ }
+ free(pdn);
+ }
+
+ } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+ /* alias is within scope */
+ Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+ e->e_dn, 0, 0 );
+ goto loop_continue;
+ }
+
+ scopeok = 1;
}
/*
* 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.
+ * this for non-base searches, and don't check the filter
+ * explicitly here since it's only a candidate anyway.
*/
- if ( scope == LDAP_SCOPE_SUBTREE &&
- e->e_ndn != NULL &&
- strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
- (ref = attr_find( e->e_attrs, "ref" )) != NULL )
+ if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+ is_entry_referral( e ) )
{
+ struct berval **refs = get_entry_referrals(
+ be, conn, op, e );
+
send_search_reference( be, conn, op,
- e, ref->a_vals, &refs );
+ e, refs, scope, NULL, &v2refs );
- /* 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;
+ ber_bvecfree( refs );
- /* check scope */
- scopeok = 1;
- if ( scope == LDAP_SCOPE_ONELEVEL ) {
- if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
- (void) dn_normalize_case( dn );
- scopeok = (dn == realBase)
- ? 1
- : (strcmp( dn, realBase ) ? 0 : 1 );
- free( dn );
- } else {
- scopeok = (realBase == NULL || *realBase == '\0');
- }
- } else if ( scope == LDAP_SCOPE_SUBTREE ) {
- dn = ch_strdup( e->e_ndn );
- scopeok = dn_issuffix( dn, realBase );
+ goto loop_continue;
+ }
+
+ /* if it matches the filter and scope, send it */
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ char *dn;
+
+ /* check scope */
+ if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+ if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realbase)
+ ? 1
+ : (strcmp( dn, realbase ) ? 0 : 1 );
free( dn );
+
+ } else {
+ scopeok = (realbase == NULL || *realbase == '\0');
}
- if ( scopeok ) {
- /* check size limit */
- if ( --slimit == -1 ) {
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- send_search_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
- NULL, NULL, refs, nentries );
- bdb2i_idl_free( candidates );
- ber_bvecfree( refs );
-
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
- }
+ } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realbase );
+ free( dn );
- /*
- * 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 = bdb2i_derefAlias_r( be, conn, op, e );
- if ( newe == NULL ) { /* problem with the alias */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- e = NULL;
- }
- else if ( newe != e ) { /* reassign e */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- e = newe;
- }
- }
- break;
- }
+ } else {
+ scopeok = 1;
+ }
+
+ if ( scopeok ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+ v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
+ }
- if (e) {
- switch ( send_search_entry( be, conn, op, e,
- attrs, attrsonly, 0, NULL ) ) {
- case 0: /* entry sent ok */
- nentries++;
- break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- bdb2i_idl_free( candidates );
- ber_bvecfree( refs );
-
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
- }
+ if (e) {
+ switch ( send_search_entry( be, conn, op, e,
+ attrs, attrsonly, 0, NULL ) ) {
+ case 0: /* entry sent ok */
+ nentries++;
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ rc = 0;
+ goto done;
}
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+ id, 0, 0 );
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+ id, 0, 0 );
}
+loop_continue:
if( e != NULL ) {
/* free reader lock */
bdb2i_cache_return_entry_r( &li->li_cache, e );
ldap_pvt_thread_yield();
}
- bdb2i_idl_free( candidates );
-
send_search_result( conn, op,
- refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
- NULL, NULL, refs, nentries );
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, NULL, nentries );
- ber_bvecfree( refs );
+ rc = 0;
- if( realBase != NULL) {
- free( realBase );
- }
+done:
+ bdb2i_idl_free( candidates );
+
+ ber_bvecfree( v2refs );
+ if( realbase ) free( realbase );
- return( 0 );
+ return rc;
}
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
return( -1 );
}
static ID_BLOCK *
-base_candidates(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+base_candidate(
+ Backend *be,
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
ID_BLOCK *idl;
- Entry *e;
-
- Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
- *err = LDAP_SUCCESS;
-
- /* get entry with reader lock */
- if ( (e = bdb2i_dn2entry_r( be, base, matched )) == NULL ) {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
-
- /* check for deleted */
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+ e->e_dn, 0, 0);
idl = bdb2i_idl_alloc( 1 );
bdb2i_idl_insert( &idl, e->e_id, 1 );
-
- /* free reader lock */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
-
return( idl );
}
static ID_BLOCK *
-onelevel_candidates(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *base,
+search_candidates(
+ Backend *be,
+ Entry *e,
Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+ int scope,
+ int deref,
+ int manageDSAit
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e = NULL;
- Filter *f;
- char buf[20];
ID_BLOCK *candidates;
+ Filter *f, *rf, *af, *lf;
- Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
+ Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+ e->e_ndn, scope, deref );
- *err = LDAP_SUCCESS;
+ f = NULL;
- /* get the base object with reader lock */
- if ( base != NULL && *base != '\0' &&
- (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
- {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
+ if( !manageDSAit ) {
+ /* match referrals */
+ rf = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_next = NULL;
+ rf->f_choice = LDAP_FILTER_OR;
+ rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ rf->f_or->f_avtype = ch_strdup( "objectclass" );
+ rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+ rf->f_or->f_next = filter;
+ f = rf;
+ } else {
+ rf = NULL;
+ f = filter;
}
- /*
- * modify the filter to be something like this:
- *
- * parent=baseobject & originalfilter
- */
-
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_EQUALITY;
- f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
- sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
- f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
- f->f_and->f_ava.ava_value.bv_len = strlen( buf );
- f->f_and->f_next = filter;
-
- /* from here, it's just like subtree_candidates */
- candidates = subtree_candidates( be, conn, op, base, f, attrs,
- attrsonly, matched, e, err, 0 );
-
- /* free up just the filter stuff we allocated above */
- f->f_and->f_next = NULL;
- filter_free( f );
-
- /* free entry and reader lock */
- if( e != NULL ) {
- bdb2i_cache_return_entry_r( &li->li_cache, e );
+ if( deref & LDAP_DEREF_SEARCHING ) {
+ /* match aliases */
+ af = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_next = NULL;
+ af->f_choice = LDAP_FILTER_OR;
+ af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ af->f_or->f_avtype = ch_strdup( "objectclass" );
+ af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+ af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+ af->f_or->f_next = f;
+ f = af;
+ } else {
+ af = NULL;
}
- return( candidates );
-}
-static ID_BLOCK *
-subtree_candidates(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- Entry *e,
- int *err,
- int lookupbase
-)
-{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Filter *f, **filterarg_ptr;
- ID_BLOCK *candidates;
+ if ( scope == LDAP_SCOPE_SUBTREE ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
- base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
-
- /*
- * get the base object - unless we already have it (from one-level).
- * also, unless this is a one-level search or a subtree search
- * starting at the very top of our subtree, we need to modify the
- * filter to be something like this:
- *
- * dn=*baseobjectdn & (originalfilter | ref=*)
- *
- * the "objectclass=referral" part is used to select referrals to return
- */
-
- *err = LDAP_SUCCESS;
- f = NULL;
- if ( lookupbase ) {
- e = NULL;
+ lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
+ lf->f_and->f_sub_type = ch_strdup( "dn" );
+ lf->f_and->f_sub_initial = NULL;
+ lf->f_and->f_sub_any = NULL;
+ lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
- if ( base != NULL && *base != '\0' &&
- (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
- {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
+ lf->f_and->f_next = f;
+ f = lf;
- if (e) {
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- }
+ } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+ char buf[16];
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_OR;
- f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_or->f_choice = LDAP_FILTER_EQUALITY;
- f->f_or->f_avtype = ch_strdup( "objectclass" );
- /* Patch to use normalized uppercase */
- f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
- f->f_or->f_avvalue.bv_len = sizeof( "REFERRAL" )-1;
- filterarg_ptr = &f->f_or->f_next;
- *filterarg_ptr = filter;
- filter = f;
-
- if ( ! be_issuffix( be, base ) ) {
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
- f->f_and->f_sub_type = ch_strdup( "dn" );
- f->f_and->f_sub_initial = NULL;
- f->f_and->f_sub_any = NULL;
- f->f_and->f_sub_final = ch_strdup( base );
- value_normalize( f->f_and->f_sub_final, SYNTAX_DN|SYNTAX_CIS );
- f->f_and->f_next = filter;
- filter = f;
- }
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+ lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
+ lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+ sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+ lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
+ lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else {
+ lf = NULL;
}
- candidates = bdb2i_filter_candidates( be, filter );
+ candidates = bdb2i_filter_candidates( be, f );
+
+ /* free up filter additions we allocated above */
+ if( lf != NULL ) {
+ lf->f_and->f_next = NULL;
+ filter_free( lf );
+ }
+
+ if( af != NULL ) {
+ af->f_or->f_next = NULL;
+ filter_free( af );
+ }
- /* free up just the parts we allocated above */
- if ( f != NULL ) {
- *filterarg_ptr = NULL;
- filter_free( f );
+ if( rf != NULL ) {
+ rf->f_or->f_next = NULL;
+ filter_free( rf );
}
return( candidates );