Integrate LDBM changes into BDB2...

This commit is contained in:
Kurt Zeilenga 1999-07-16 01:53:38 +00:00
parent 6f72de8c8c
commit 78ebd3d965
11 changed files with 1569 additions and 763 deletions

View file

@ -32,7 +32,8 @@ bdb2i_back_add_internal(
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 );
}
@ -42,7 +43,7 @@ bdb2i_back_add_internal(
entry_free( e );
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
NULL, NULL, NULL );
NULL, NULL, NULL, NULL );
return( -1 );
}
@ -55,19 +56,37 @@ bdb2i_back_add_internal(
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 );
@ -77,21 +96,54 @@ bdb2i_back_add_internal(
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;
}
@ -109,7 +161,7 @@ bdb2i_back_add_internal(
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL );
NULL, NULL, NULL, NULL );
entry_free( e );
return -1;
@ -142,11 +194,9 @@ bdb2i_back_add_internal(
/* 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 );
}
@ -162,7 +212,8 @@ bdb2i_back_add_internal(
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 );
@ -182,7 +233,8 @@ bdb2i_back_add_internal(
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 );
@ -197,7 +249,8 @@ bdb2i_back_add_internal(
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 );
@ -213,7 +266,8 @@ bdb2i_back_add_internal(
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 );
@ -222,7 +276,8 @@ bdb2i_back_add_internal(
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:;
@ -255,10 +310,9 @@ bdb2_back_add(
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,

View file

@ -1,13 +1,6 @@
/*
* 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"
@ -19,302 +12,273 @@
#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;
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Entry *entry;
Entry *sup;
unsigned depth;
char **dnlist;
if (!e) return NULL; /* be sure we have a starting entry */
assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
*matched = NULL;
*err = LDAP_SUCCESS;
*text = NULL;
/*
* 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)
{
if( alias == NULL ) {
dn = ch_strdup( dn );
entry = bdb2i_dn2entry_r( be, dn, &sup );
/*
* 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;
}
/*
* 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 */
}
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);
}
/* 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 );
dn = ch_strdup( alias->e_ndn );
entry = alias;
sup = 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 );
dnlist = NULL;
charray_add( &dnlist, dn );
return newDN;
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;
}
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;
}
/*
* 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;
}
if( a->a_vals[1] != NULL ) {
*err = LDAP_ALIAS_PROBLEM;
*errmsg = "alias has multivalued aliasedObjectName";
return NULL;
}
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;
}
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;
}

View file

@ -74,7 +74,7 @@ bdb2i_back_bind_internal(
Entry *e;
Attribute *a;
int rc;
char *matched;
Entry *matched;
#ifdef HAVE_KERBEROS
char krbname[MAX_K_NAME_SZ + 1];
AUTH_DAT ad;
@ -86,12 +86,26 @@ bdb2i_back_bind_internal(
/* 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 */
@ -99,28 +113,30 @@ bdb2i_back_bind_internal(
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 );
}
@ -133,7 +149,37 @@ bdb2i_back_bind_internal(
"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;
}
@ -141,7 +187,8 @@ bdb2i_back_bind_internal(
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;
@ -161,14 +208,14 @@ bdb2i_back_bind_internal(
"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;
@ -178,7 +225,7 @@ bdb2i_back_bind_internal(
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;
@ -190,7 +237,7 @@ bdb2i_back_bind_internal(
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;
}
@ -199,7 +246,7 @@ bdb2i_back_bind_internal(
"krbname", NULL, ACL_AUTH ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
@ -216,7 +263,7 @@ bdb2i_back_bind_internal(
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 */
@ -227,7 +274,7 @@ bdb2i_back_bind_internal(
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;
}
@ -236,7 +283,8 @@ bdb2i_back_bind_internal(
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;
@ -247,7 +295,7 @@ bdb2i_back_bind_internal(
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;
}
@ -282,7 +330,7 @@ bdb2_back_bind(
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
NULL, NULL, NULL );
NULL, NULL, NULL, NULL );
return( 1 );
}

View file

@ -21,43 +21,77 @@ bdb2i_back_compare_internal(
)
{
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;
@ -86,7 +120,7 @@ bdb2_back_compare(
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
NULL, NULL, NULL );
NULL, NULL, NULL, NULL );
return( 1 );
}

View file

@ -20,32 +20,63 @@ bdb2i_back_delete_internal(
)
{
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;
}
@ -57,7 +88,7 @@ bdb2i_back_delete_internal(
"<=- 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
@ -68,7 +99,7 @@ bdb2i_back_delete_internal(
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;
}
@ -79,7 +110,7 @@ bdb2i_back_delete_internal(
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;
}
@ -89,7 +120,7 @@ bdb2i_back_delete_internal(
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;
}
}
@ -99,7 +130,7 @@ bdb2i_back_delete_internal(
"<=- 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;
}
@ -109,7 +140,7 @@ bdb2i_back_delete_internal(
"<=- 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;
}
@ -119,11 +150,12 @@ bdb2i_back_delete_internal(
"<=- 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:;
@ -161,9 +193,8 @@ bdb2_back_delete(
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 );

View file

@ -0,0 +1,206 @@
/* 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 );
}

View file

@ -0,0 +1,181 @@
/* 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 );
}

View file

@ -104,7 +104,8 @@ bdb2i_back_modify_internal(
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;
}
@ -141,7 +142,8 @@ bdb2i_back_modify_internal(
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;
}
}
@ -150,7 +152,7 @@ bdb2i_back_modify_internal(
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;
}
@ -165,7 +167,7 @@ bdb2i_back_modify_internal(
/* 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;
}
@ -180,11 +182,12 @@ bdb2i_back_modify_internal(
/* 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 );
@ -206,15 +209,15 @@ bdb2_back_modify(
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 );
}
@ -230,15 +233,53 @@ bdb2_back_modify(
}
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;
}
ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
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 );
done:
(void) bdb2i_leave_backend_w( lock );
bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op );

View file

@ -36,12 +36,12 @@ bdb2i_back_modrdn_internal(
)
{
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 */
@ -65,14 +65,46 @@ bdb2i_back_modrdn_internal(
/* 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,
@ -81,7 +113,7 @@ bdb2i_back_modrdn_internal(
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
@ -92,7 +124,7 @@ bdb2i_back_modrdn_internal(
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;
}
@ -103,7 +135,7 @@ bdb2i_back_modrdn_internal(
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;
}
@ -119,7 +151,7 @@ bdb2i_back_modrdn_internal(
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;
}
@ -152,7 +184,7 @@ bdb2i_back_modrdn_internal(
"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;
}
@ -168,7 +200,7 @@ bdb2i_back_modrdn_internal(
"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;
}
@ -192,7 +224,8 @@ bdb2i_back_modrdn_internal(
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;
}
@ -207,7 +240,7 @@ bdb2i_back_modrdn_internal(
/* 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;
}
@ -221,7 +254,7 @@ bdb2i_back_modrdn_internal(
/* 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;
}
@ -235,7 +268,7 @@ bdb2i_back_modrdn_internal(
"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;
}
@ -246,7 +279,7 @@ bdb2i_back_modrdn_internal(
"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;
}
@ -263,7 +296,7 @@ bdb2i_back_modrdn_internal(
"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;
}
@ -274,7 +307,7 @@ bdb2i_back_modrdn_internal(
"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;
}
@ -326,7 +359,7 @@ bdb2i_back_modrdn_internal(
"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;
@ -380,11 +413,12 @@ bdb2i_back_modrdn_internal(
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;
@ -399,8 +433,6 @@ 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);
@ -444,7 +476,7 @@ bdb2_back_modrdn(
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
NULL, NULL, NULL );
NULL, NULL, NULL, NULL );
return( -1 );
}

View file

@ -0,0 +1,245 @@
#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

View file

@ -12,20 +12,12 @@
#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);
static ID_BLOCK *base_candidate(
Backend *be, Entry *e );
#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 *search_candidates(
Backend *be, Entry *e, Filter *filter,
int scope, int deref, int manageDSAit );
static int
bdb2i_back_search_internal(
@ -44,18 +36,76 @@ 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_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
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 );
}
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 */
@ -64,6 +114,7 @@ bdb2i_back_search_internal(
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 {
@ -71,199 +122,183 @@ bdb2i_back_search_internal(
be->be_sizelimit : slimit;
}
/*
* check and apply aliasing where the dereferencing applies to
* the subordinates of the base
*/
if ( scope == LDAP_SCOPE_BASE) {
candidates = base_candidate( be, e );
switch ( deref ) {
case LDAP_DEREF_FINDING:
case LDAP_DEREF_ALWAYS:
realBase = bdb2i_derefDN ( be, conn, op, base );
break;
default:
realBase = ch_strdup(base);
} else {
candidates = search_candidates( be, e, filter,
scope, deref, manageDSAit );
}
(void) dn_normalize_case( realBase );
/* need normalized dn below */
realbase = ch_strdup( e->e_ndn );
bdb2i_cache_return_entry_r( &li->li_cache, e );
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;
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 );
}
/* null candidates means we could not find the base object */
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 );
free( dn );
}
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 );
}
/*
* 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;
}
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 );
}
}
}
}
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');
}
} else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
dn = ch_strdup( e->e_ndn );
scopeok = dn_issuffix( dn, realbase );
free( dn );
} 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 );
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 );
@ -271,19 +306,19 @@ bdb2i_back_search_internal(
ldap_pvt_thread_yield();
}
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
NULL, NULL, v2refs, NULL, nentries );
rc = 0;
done:
bdb2i_idl_free( candidates );
send_search_result( conn, op,
refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
NULL, NULL, refs, nentries );
ber_bvecfree( v2refs );
if( realbase ) free( realbase );
ber_bvecfree( refs );
if( realBase != NULL) {
free( realBase );
}
return( 0 );
return rc;
}
@ -312,7 +347,7 @@ bdb2_back_search(
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
NULL, NULL, NULL );
NULL, NULL, NULL, NULL );
return( -1 );
}
@ -328,191 +363,126 @@ bdb2_back_search(
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,
Filter *filter,
char **attrs,
int attrsonly,
char **matched,
int *err
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Entry *e = NULL;
Filter *f;
char buf[20];
ID_BLOCK *candidates;
Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
*err = LDAP_SUCCESS;
/* 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 );
}
/*
* 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 );
}
return( candidates );
}
static ID_BLOCK *
subtree_candidates(
BackendDB *be,
Connection *conn,
Operation *op,
char *base,
Filter *filter,
char **attrs,
int attrsonly,
char **matched,
search_candidates(
Backend *be,
Entry *e,
int *err,
int lookupbase
Filter *filter,
int scope,
int deref,
int manageDSAit
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Filter *f, **filterarg_ptr;
ID_BLOCK *candidates;
Filter *f, *rf, *af, *lf;
Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
e->e_ndn, scope, deref );
/*
* 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;
if ( base != NULL && *base != '\0' &&
(e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
{
*err = LDAP_NO_SUCH_OBJECT;
return( NULL );
}
if (e) {
bdb2i_cache_return_entry_r( &li->li_cache, e );
}
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;
}
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;
}
candidates = bdb2i_filter_candidates( be, filter );
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;
}
/* free up just the parts we allocated above */
if ( f != NULL ) {
*filterarg_ptr = NULL;
filter_free( f );
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) );
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 );
lf->f_and->f_next = f;
f = lf;
} else if ( scope == LDAP_SCOPE_ONELEVEL ) {
char buf[16];
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, 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 );
}
if( rf != NULL ) {
rf->f_or->f_next = NULL;
filter_free( rf );
}
return( candidates );