mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-06-09 16:50:05 -04:00
Integrate LDBM changes into BDB2...
This commit is contained in:
parent
6f72de8c8c
commit
78ebd3d965
11 changed files with 1569 additions and 763 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
206
servers/slapd/back-bdb2/dn2id.c
Normal file
206
servers/slapd/back-bdb2/dn2id.c
Normal 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 );
|
||||
}
|
||||
|
||||
|
||||
181
servers/slapd/back-bdb2/group.c
Normal file
181
servers/slapd/back-bdb2/group.c
Normal 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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
}
|
||||
|
|
|
|||
245
servers/slapd/back-bdb2/proto-back-bdb2.h
Normal file
245
servers/slapd/back-bdb2/proto-back-bdb2.h
Normal 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
|
||||
|
|
@ -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 );
|
||||
|
|
|
|||
Loading…
Reference in a new issue