General code cleanup.
const char *text = NULL;
AttributeDescription *children = slap_schema.si_ad_children;
DB_TXN *ltid = NULL;
+ struct bdb_op_info opinfo;
Debug(LDAP_DEBUG_ARGS, "==> bdb_add: %s\n", e->e_dn, 0, 0);
goto return_results;
}
- op->o_private = ltid;
+ opinfo.boi_bdb = be;
+ opinfo.boi_txn = ltid;
+ opinfo.boi_err = 0;
+ op->o_private = &opinfo;
/*
* Get the parent dn and see if the corresponding entry exists.
if( pdn != NULL && *pdn != '\0' ) {
Entry *matched = NULL;
- /* get parent with reader lock */
- rc = dn2entry_r( be, ltid, pdn, &p, &matched );
+ /* get parent */
+ rc = bdb_dn2entry( be, ltid, pdn, &p, &matched, 0 );
ch_free( pdn );
switch( rc ) {
0, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
- matched_dn, NULL, refs, NULL );
+ matched_dn, NULL, refs, NULL );
if( matched != NULL ) {
ber_bvecfree( refs );
0, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
- matched_dn, NULL, refs, NULL );
+ matched_dn, NULL, refs, NULL );
ber_bvecfree( refs );
free( matched_dn );
#define bi_id2entry bi_databases[BDB_ID2ENTRY]
#define bi_dn2id bi_databases[BDB_DN2ID]
+struct bdb_op_info {
+ BackendDB* boi_bdb;
+ DB_TXN* boi_txn;
+ int boi_err;
+};
+
LDAP_END_DECL
#include "proto-bdb.h"
# End Source File
# Begin Source File
+SOURCE=.\extended.c
+# End Source File
+# Begin Source File
+
SOURCE=.\external.h
# End Source File
# Begin Source File
# End Source File
# Begin Source File
+SOURCE=.\modify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modrdn.c
+# End Source File
+# Begin Source File
+
SOURCE=.\nextid.c
# End Source File
# Begin Source File
+SOURCE=.\passwd.c
+# End Source File
+# Begin Source File
+
SOURCE=".\proto-bdb.h"
# End Source File
# Begin Source File
int
bdb_bind(
- Backend *be,
- Connection *conn,
- Operation *op,
- const char *dn,
- const char *ndn,
- int method,
- struct berval *cred,
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
+ int method,
+ struct berval *cred,
char** edn
)
{
*edn = NULL;
- /* fetch entry */
- rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+ /* get entry */
+ rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
switch(rc) {
case DB_NOTFOUND:
break;
default:
send_ldap_result( conn, op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
+ NULL, "internal error", NULL, NULL );
return rc;
}
if ( is_entry_alias( e ) ) {
/* entry is an alias, don't allow bind */
Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
- 0, 0 );
+ 0, 0 );
send_ldap_result( conn, op, rc = LDAP_ALIAS_PROBLEM,
- NULL, "entry is alias", NULL, NULL );
+ NULL, "entry is alias", NULL, NULL );
goto done;
}
conn, op, e );
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
- 0, 0 );
+ 0, 0 );
if( refs != NULL ) {
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
if ( (a = attr_find( e->e_attrs, password )) == NULL ) {
send_ldap_result( conn, op, rc = LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto done;
}
case LDAP_AUTH_KRBV41:
if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
- NULL, NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto done;
}
}
sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
- : "", ad.pinst, ad.prealm );
+ : "", ad.pinst, ad.prealm );
if ( (a = attr_find( e->e_attrs, krbattr )) == NULL ) {
/*
break;
}
send_ldap_result( conn, op, rc = LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL, NULL, NULL );
+ NULL, NULL, NULL, NULL );
goto done;
} else { /* look for krbname match */
if ( value_find( a->a_desc, a->a_vals, &krbval ) != 0 ) {
send_ldap_result( conn, op,
- rc = LDAP_INVALID_CREDENTIALS,
+ rc = LDAP_INVALID_CREDENTIALS,
NULL, NULL, NULL, NULL );
goto done;
}
default:
send_ldap_result( conn, op, rc = LDAP_STRONG_AUTH_NOT_SUPPORTED,
- NULL, "authentication method not supported", NULL, NULL );
+ NULL, "authentication method not supported", NULL, NULL );
goto done;
}
int
bdb_compare(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- const char *dn,
- const char *ndn,
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
AttributeAssertion *ava
)
{
int manageDSAit = get_manageDSAit( op );
/* get entry */
- rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+ rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
switch( rc ) {
case DB_NOTFOUND:
conn, op, e );
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
- 0, 0 );
+ 0, 0 );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
- e->e_dn, NULL, refs, NULL );
+ e->e_dn, NULL, refs, NULL );
ber_bvecfree( refs );
goto done;
int
bdb_db_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv )
+ BackendDB *be,
+ const char *fname,
+ int lineno,
+ int argc,
+ char **argv )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
if ( bdb == NULL ) {
fprintf( stderr, "%s: line %d: "
"bdb database info is null!\n",
- fname, lineno );
+ fname, lineno );
return 1;
}
if ( argc < 2 ) {
fprintf( stderr, "%s: line %d: "
"missing dir in \"directory <dir>\" line\n",
- fname, lineno );
+ fname, lineno );
return 1;
}
if ( bdb->bi_dbenv_home ) {
if ( argc < 2 ) {
fprintf( stderr, "%s: line %d: "
"missing mode in \"mode <mode>\" line\n",
- fname, lineno );
+ fname, lineno );
return 1;
}
bdb->bi_dbenv_mode = strtol( argv[1], NULL, 0 );
if ( argc < 2 ) {
fprintf( stderr, "%s: line %d: "
"missing attr in \"index <attr> [pres,eq,approx,sub]\" line\n",
- fname, lineno );
+ fname, lineno );
return 1;
} else if ( argc > 3 ) {
fprintf( stderr, "%s: line %d: "
"extra junk after \"index <attr> [pres,eq,approx,sub]\" "
"line (ignored)\n",
- fname, lineno );
+ fname, lineno );
}
rc = attr_index_config( li, fname, lineno, argc - 1, &argv[1] );
} else {
fprintf( stderr, "%s: line %d: "
"unknown directive \"%s\" in bdb database definition (ignored)\n",
- fname, lineno, argv[0] );
+ fname, lineno, argv[0] );
}
return 0;
int
bdb_delete(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- const char *dn,
- const char *ndn
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn
)
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int manageDSAit = get_manageDSAit( op );
AttributeDescription *children = slap_schema.si_ad_children;
DB_TXN *ltid = NULL;
+ struct bdb_op_info opinfo;
Debug(LDAP_DEBUG_ARGS, "==> bdb_delete: %s\n", dn, 0, 0);
goto return_results;
}
- op->o_private = ltid;
+ opinfo.boi_bdb = be;
+ opinfo.boi_txn = ltid;
+ opinfo.boi_err = 0;
+ op->o_private = &opinfo;
- pdn = dn_parent( be, e->e_ndn );
+ /* get entry for read/modify/write */
+ rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, DB_RMW );
+
+ switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ Debug( LDAP_DEBUG_ARGS,
+ "<=- bdb_delete: no such object %s\n",
+ dn, 0, 0);
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb_entry_return( be, 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 );
+ }
+
+ rc = -1;
+ goto done;
+ }
+
+ pdn = dn_parent( be, ndn );
if( pdn != NULL && *pdn != '\0' ) {
- /* get parent with reader lock */
- rc = dn2entry_r( be, ltid, pdn, &p, NULL );
+ /* get parent */
+ rc = bdb_dn2entry( be, ltid, pdn, &p, NULL, 0 );
ch_free( pdn );
}
}
- /* get entry */
- rc = dn2entry_w( be, ltid, ndn, &e, &matched );
-
- switch( rc ) {
- case 0:
- case DB_NOTFOUND:
- break;
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- default:
- rc = LDAP_OTHER;
- text = "internal error";
- goto return_results;
- }
-
- if ( e == NULL ) {
- char *matched_dn = NULL;
- struct berval **refs = NULL;
-
- Debug( LDAP_DEBUG_ARGS,
- "<=- bdb_delete: no such object %s\n",
- dn, 0, 0);
-
- if ( matched != NULL ) {
- matched_dn = ch_strdup( matched->e_dn );
- refs = is_entry_referral( matched )
- ? get_entry_referrals( be, conn, op, matched )
- : NULL;
- bdb_entry_return( be, 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 );
- }
-
- rc = -1;
- goto done;
- }
-
- if ( !manageDSAit && is_entry_referral( e ) ) {
+ if ( !manageDSAit && is_entry_referral( e ) ) {
/* parent is a referral, don't allow add */
/* parent is an alias, don't allow add */
struct berval **refs = get_entry_referrals( be,
0, 0, 0 );
send_ldap_result( conn, op, LDAP_REFERRAL,
- e->e_dn, NULL, refs, NULL );
+ e->e_dn, NULL, refs, NULL );
ber_bvecfree( refs );
int
bdb_dn2entry(
- BackendDB *be,
+ BackendDB *be,
DB_TXN *tid,
- const char *dn,
+ const char *dn,
Entry **e,
- Entry **matched,
+ Entry **matched,
int flags )
{
int rc;
int
bdb_dn2id_add(
- BackendDB *be,
+ BackendDB *be,
DB_TXN *txn,
- const char *dn,
- ID id
+ const char *dn,
+ ID id
)
{
int rc;
int
bdb_dn2id_delete(
- BackendDB *be,
+ BackendDB *be,
DB_TXN *txn,
- const char *dn,
- ID id )
+ const char *dn,
+ ID id )
{
int rc;
DBT key;
int
bdb_dn2id(
- BackendDB *be,
+ BackendDB *be,
DB_TXN *txn,
- const char *dn,
+ const char *dn,
ID *id )
{
int rc;
int
bdb_dn2id_matched(
- BackendDB *be,
+ BackendDB *be,
DB_TXN *txn,
- const char *in,
+ const char *in,
ID *id,
char **matchedDN )
{
int
bdb_dn2id_children(
- BackendDB *be,
+ BackendDB *be,
DB_TXN *txn,
- const char *dn )
+ const char *dn )
{
int rc;
DBT key, data;
--- /dev/null
+/* extended.c - ldbm backend extended routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include "back-bdb.h"
+#include "external.h"
+
+struct exop {
+ char *oid;
+ SLAP_EXTENDED_FN extended;
+} exop_table[] = {
+ { LDAP_EXOP_X_MODIFY_PASSWD, bdb_exop_passwd },
+ { NULL, NULL }
+};
+
+int
+bdb_extended(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ const char *reqoid,
+ struct berval *reqdata,
+ char **rspoid,
+ struct berval **rspdata,
+ LDAPControl *** rspctrls,
+ const char** text,
+ struct berval *** refs
+)
+{
+ int i;
+
+ for( i=0; exop_table[i].oid != NULL; i++ ) {
+ if( strcmp( exop_table[i].oid, reqoid ) == 0 ) {
+ return (exop_table[i].extended)(
+ be, conn, op,
+ reqoid, reqdata,
+ rspoid, rspdata, rspctrls,
+ text, refs );
+ }
+ }
+
+ *text = "not supported within naming context";
+ return LDAP_OPERATIONS_ERROR;
+}
\ No newline at end of file
Connection *conn, Operation *op ));
extern int bdb_referrals(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- const char *dn,
- const char *ndn,
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
const char **text );
LDAP_END_DECL
return rc;
}
+int bdb_id2entry_update(
+ BackendDB *be,
+ DB_TXN *tid,
+ Entry *e )
+{
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ DB *db = bdb->bi_id2entry->bdi_db;
+ DBT key, data;
+ struct berval *bv;
+ int rc;
+
+ DBTzero( &key );
+ key.data = (char *) &e->e_id;
+ key.size = sizeof(ID);
+
+ rc = entry_encode( e, &bv );
+ if( rc != LDAP_SUCCESS ) {
+ return -1;
+ }
+
+ DBTzero( &data );
+ bv2DBT( bv, &data );
+
+ rc = db->put( db, tid, &key, &data, 0 );
+
+ ber_bvfree( bv );
+ return rc;
+}
+
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
int
bdb_idl_insert_key(
- BackendDB *be,
- DB *db,
+ BackendDB *be,
+ DB *db,
DB_TXN *tid,
- DBT *key,
- ID id )
+ DBT *key,
+ ID id )
{
int rc;
ID ids[BDB_IDL_DB_SIZE];
int
bdb_idl_delete_key(
- BackendDB *be,
- DB *db,
+ BackendDB *be,
+ DB *db,
DB_TXN *tid,
- DBT *key,
- ID id )
+ DBT *key,
+ ID id )
{
int rc;
ID ids[BDB_IDL_DB_SIZE];
#ifdef SLAPD_BDB_DYNAMIC
int back_bdb_LTX_init_module( int argc, char *argv[] ) {
- BackendInfo bi;
+ BackendInfo bi;
- memset( &bi, '\0', sizeof(bi) );
- bi.bi_type = "bdb";
- bi.bi_init = bdb_initialize;
+ memset( &bi, '\0', sizeof(bi) );
+ bi.bi_type = "bdb";
+ bi.bi_init = bdb_initialize;
- backend_add( &bi );
- return 0;
+ backend_add( &bi );
+ return 0;
}
#endif /* SLAPD_BDB_DYNAMIC */
int
bdb_initialize(
- BackendInfo *bi
+ BackendInfo *bi
)
{
static char *controls[] = {
bi->bi_op_bind = bdb_bind;
bi->bi_op_compare = bdb_compare;
bi->bi_op_delete = bdb_delete;
+ bi->bi_op_modify = bdb_modify;
+ bi->bi_op_modrdn = bdb_modrdn;
bi->bi_op_search = bdb_search;
#if 0
bi->bi_op_unbind = bdb_unbind;
- bi->bi_op_modify = bdb_modify;
- bi->bi_op_modrdn = bdb_modrdn;
bi->bi_op_abandon = bdb_abandon;
bi->bi_extended = bdb_extended;
bi->bi_acl_group = bdb_group;
bi->bi_acl_attribute = bdb_attribute;
- bi->bi_chk_referrals = bdb_referrals;
#endif
+ bi->bi_chk_referrals = bdb_referrals;
bi->bi_entry_release_rw = 0;
--- /dev/null
+/* modify.c - bdb backend modify routine */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "back-bdb.h"
+#include "external.h"
+
+static int add_values( Entry *e, Modification *mod, char *dn );
+static int delete_values( Entry *e, Modification *mod, char *dn );
+static int replace_values( Entry *e, Modification *mod, char *dn );
+
+int bdb_modify_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ DB_TXN *tid,
+ const char *dn,
+ Modifications *modlist,
+ Entry *e,
+ const char **text )
+{
+ int rc, err;
+ Modification *mod;
+ Modifications *ml;
+ Attribute *save_attrs;
+
+ Debug(LDAP_DEBUG_TRACE, "bdb_modify_internal: %s\n", dn, 0, 0);
+
+ if ( !acl_check_modlist( be, conn, op, e, modlist )) {
+ return LDAP_INSUFFICIENT_ACCESS;
+ }
+
+ save_attrs = e->e_attrs;
+ e->e_attrs = attrs_dup( e->e_attrs );
+
+ for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
+ mod = &ml->sml_mod;
+
+ switch ( mod->sm_op ) {
+ case LDAP_MOD_ADD:
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: add\n", 0, 0, 0);
+ err = add_values( e, mod, op->o_ndn );
+
+ if( err != LDAP_SUCCESS ) {
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+ err, *text, 0);
+ *text = "modify: add values failed";
+ }
+ break;
+
+ case LDAP_MOD_DELETE:
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: delete\n", 0, 0, 0);
+ err = delete_values( e, mod, op->o_ndn );
+ assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
+ if( err != LDAP_SUCCESS ) {
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+ err, *text, 0);
+ *text = "modify: delete values failed";
+ }
+ break;
+
+ case LDAP_MOD_REPLACE:
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: replace\n", 0, 0, 0);
+ err = replace_values( e, mod, op->o_ndn );
+ assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
+ if( err != LDAP_SUCCESS ) {
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+ err, *text, 0);
+ *text = "modify: replace values failed";
+ }
+ break;
+
+ case SLAP_MOD_SOFTADD:
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: softadd\n", 0, 0, 0);
+ /* Avoid problems in index_add_mods()
+ * We need to add index if necessary.
+ */
+ mod->sm_op = LDAP_MOD_ADD;
+ err = add_values( e, mod, op->o_ndn );
+
+ if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
+ err = LDAP_SUCCESS;
+ }
+
+ if( err != LDAP_SUCCESS ) {
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+ err, *text, 0);
+ *text = "modify: (soft)add values failed";
+ }
+ break;
+
+ default:
+ Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
+ mod->sm_op, 0, 0);
+ *text = "Invalid modify operation";
+ err = LDAP_OTHER;
+ Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
+ err, *text, 0);
+ }
+
+ if ( err != LDAP_SUCCESS ) {
+ attrs_free( e->e_attrs );
+ e->e_attrs = save_attrs;
+ /* unlock entry, delete from cache */
+ return err;
+ }
+ }
+
+ /* check that the entry still obeys the schema */
+ rc = entry_schema_check( e, save_attrs, text );
+ if ( rc != LDAP_SUCCESS ) {
+ attrs_free( e->e_attrs );
+ e->e_attrs = save_attrs;
+ Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n",
+ *text, 0, 0 );
+ return rc;
+ }
+
+#if 0
+ /* delete indices for old attributes */
+ rc = index_entry_del( be, tid, e, save_attrs);
+
+ /* add indices for new attributes */
+ rc = index_entry_add( be, tid, e, e->e_attrs);
+#endif
+
+ attrs_free( save_attrs );
+
+ return rc;
+}
+
+
+int
+bdb_modify(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
+ Modifications *modlist
+)
+{
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ int rc;
+ Entry *matched;
+ Entry *e;
+ int manageDSAit = get_manageDSAit( op );
+ const char *text = NULL;
+ DB_TXN *ltid;
+ struct bdb_op_info opinfo;
+
+ Debug(LDAP_DEBUG_ARGS, "bdb_back_modify: %s\n", dn, 0, 0);
+
+ if (0) {
+ /* transaction retry */
+retry: rc = txn_abort( ltid );
+ ltid = NULL;
+ op->o_private = NULL;
+ if( rc != 0 ) {
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+ }
+
+ /* begin transaction */
+ rc = txn_begin( bdb->bi_dbenv, NULL, <id, 0 );
+ if( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: txn_begin failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ opinfo.boi_bdb = be;
+ opinfo.boi_txn = ltid;
+ opinfo.boi_err = 0;
+ op->o_private = &opinfo;
+
+ /* get entry */
+ rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 );
+
+ if ( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: dn2entry failed (%d)\n",
+ rc, 0, 0 );
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ case DB_NOTFOUND:
+ break;
+ default:
+ rc = LDAP_OTHER;
+ }
+ text = "internal error";
+ goto return_results;
+ }
+
+ /* acquire and lock entry */
+ 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;
+ bdb_entry_return( be, matched );
+
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if ( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return rc;
+ }
+
+ if ( !manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: entry is referral\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ goto done;
+ }
+
+ /* Modify the entry */
+ rc = bdb_modify_internal( be, conn, op, ltid, ndn, modlist, e, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: modify failed (%d)\n",
+ rc, 0, 0 );
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+ goto return_results;
+ }
+
+ /* change the entry itself */
+ rc = bdb_id2entry_update( be, ltid, e );
+ if ( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: id2entry update failed (%d)\n",
+ rc, 0, 0 );
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+ text = "entry update failed";
+ goto return_results;
+ }
+
+ rc = txn_commit( ltid, 0 );
+ ltid = NULL;
+ op->o_private = NULL;
+
+ if( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: txn_commit failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+ rc = LDAP_OTHER;
+ text = "commit failed";
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify: added id=%08x dn=\"%s\"\n",
+ e->e_id, e->e_dn, 0 );
+ rc = LDAP_SUCCESS;
+ text = NULL;
+ }
+
+return_results:
+ send_ldap_result( conn, op, rc,
+ NULL, text, NULL, NULL );
+
+done:
+ if( ltid != NULL ) {
+ txn_abort( ltid );
+ op->o_private = NULL;
+ }
+
+ bdb_entry_return( be, e );
+ return rc;
+}
+
+static int
+add_values(
+ Entry *e,
+ Modification *mod,
+ char *dn
+)
+{
+ int i;
+ Attribute *a;
+
+ /* char *desc = mod->sm_desc->ad_cname->bv_val; */
+ MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
+
+ a = attr_find( e->e_attrs, mod->sm_desc );
+
+ /* check if the values we're adding already exist */
+ if ( a != NULL ) {
+ if( mr == NULL || !mr->smr_match ) {
+ /* do not allow add of additional attribute
+ if no equality rule exists */
+ return LDAP_INAPPROPRIATE_MATCHING;
+ }
+
+ for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
+ int rc;
+ int j;
+ const char *text = NULL;
+ struct berval *asserted;
+
+ rc = value_normalize( mod->sm_desc,
+ SLAP_MR_EQUALITY,
+ mod->sm_bvalues[i],
+ &asserted,
+ &text );
+
+ if( rc != LDAP_SUCCESS ) return rc;
+
+ for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+ int match;
+ int rc = value_match( &match, mod->sm_desc, mr,
+ SLAP_MR_MODIFY_MATCHING,
+ a->a_vals[j], asserted, &text );
+
+ if( rc == LDAP_SUCCESS && match == 0 ) {
+ ber_bvfree( asserted );
+ return LDAP_TYPE_OR_VALUE_EXISTS;
+ }
+ }
+
+ ber_bvfree( asserted );
+ }
+ }
+
+ /* no - add them */
+ if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
+ /* this should return result return of attr_merge */
+ return LDAP_OTHER;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+delete_values(
+ Entry *e,
+ Modification *mod,
+ char *dn
+)
+{
+ int i, j, k, found;
+ Attribute *a;
+ char *desc = mod->sm_desc->ad_cname->bv_val;
+ MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
+
+ /* delete the entire attribute */
+ if ( mod->sm_bvalues == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify_delete: removing entire attribute %s\n",
+ desc, 0, 0 );
+ return attr_delete( &e->e_attrs, mod->sm_desc )
+ ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS;
+ }
+
+ if( mr == NULL || !mr->smr_match ) {
+ /* disallow specific attributes from being deleted if
+ no equality rule */
+ return LDAP_INAPPROPRIATE_MATCHING;
+ }
+
+ /* delete specific values - find the attribute first */
+ if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify_delete: could not find attribute %s\n",
+ desc, 0, 0 );
+ return LDAP_NO_SUCH_ATTRIBUTE;
+ }
+
+ /* find each value to delete */
+ for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
+ int rc;
+ const char *text = NULL;
+
+ struct berval *asserted;
+
+ rc = value_normalize( mod->sm_desc,
+ SLAP_MR_EQUALITY,
+ mod->sm_bvalues[i],
+ &asserted,
+ &text );
+
+ if( rc != LDAP_SUCCESS ) return rc;
+
+ found = 0;
+ for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+ int match;
+ int rc = value_match( &match, mod->sm_desc, mr,
+ SLAP_MR_MODIFY_MATCHING,
+ a->a_vals[j], asserted, &text );
+
+ if( rc == LDAP_SUCCESS && match != 0 ) {
+ continue;
+ }
+
+ /* found a matching value */
+ found = 1;
+
+ /* delete it */
+ ber_bvfree( a->a_vals[j] );
+ for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
+ a->a_vals[k - 1] = a->a_vals[k];
+ }
+ a->a_vals[k - 1] = NULL;
+
+ break;
+ }
+
+ ber_bvfree( asserted );
+
+ /* looked through them all w/o finding it */
+ if ( ! found ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify_delete: could not find value for attr %s\n",
+ desc, 0, 0 );
+ return LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ }
+
+ /* if no values remain, delete the entire attribute */
+ if ( a->a_vals[0] == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modify_delete: removing entire attribute %s\n",
+ desc, 0, 0 );
+ if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
+ return LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+replace_values(
+ Entry *e,
+ Modification *mod,
+ char *dn
+)
+{
+ int rc = attr_delete( &e->e_attrs, mod->sm_desc );
+
+ if( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+ return rc;
+ }
+
+ if ( mod->sm_bvalues != NULL &&
+ attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 )
+ {
+ return LDAP_OTHER;
+ }
+
+ return LDAP_SUCCESS;
+}
--- /dev/null
+/* modrdn.c - bdb backend modrdn routine */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include "back-bdb.h"
+#include "external.h"
+
+int
+bdb_modrdn(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
+ const char *newrdn,
+ int deleteoldrdn,
+ const char *newSuperior
+)
+{
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ AttributeDescription *children = slap_schema.si_ad_children;
+ char *p_dn = NULL, *p_ndn = NULL;
+ char *new_dn = NULL, *new_ndn = NULL;
+ Entry *e, *p = NULL;
+ Entry *matched;
+ int rc;
+ const char *text = NULL;
+ DB_TXN * ltid;
+ struct bdb_op_info opinfo;
+
+ ID id;
+ char *new_rdn_val = NULL; /* Val of new rdn */
+ char *new_rdn_type = NULL; /* Type of new rdn */
+ char *old_rdn = NULL; /* Old rdn's attr type & val */
+ char *old_rdn_type = NULL; /* Type of old rdn attr. */
+ char *old_rdn_val = NULL; /* Old rdn attribute value */
+
+ Entry *np = NULL; /* newSuperior Entry */
+ char *np_dn = NULL; /* newSuperior dn */
+ char *np_ndn = NULL; /* newSuperior ndn */
+ char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
+
+ /* Used to interface with bdb_modify_internal() */
+ struct berval add_bv; /* Stores new rdn att */
+ struct berval *add_bvals[2]; /* Stores new rdn att */
+ struct berval del_bv; /* Stores old rdn att */
+ struct berval *del_bvals[2]; /* Stores old rdn att */
+ Modifications mod[2]; /* Used to delete old rdn */
+
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n",
+ dn, newrdn, (newSuperior ? newSuperior : "NULL") );
+
+ if (0) {
+ /* transaction retry */
+retry: rc = txn_abort( ltid );
+ ltid = NULL;
+ op->o_private = NULL;
+ if( rc != 0 ) {
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+ }
+
+ /* begin transaction */
+ rc = txn_begin( bdb->bi_dbenv, NULL, <id, 0 );
+ if( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_delete: txn_begin failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ opinfo.boi_bdb = be;
+ opinfo.boi_txn = ltid;
+ opinfo.boi_err = 0;
+ op->o_private = &opinfo;
+
+ /* get entry */
+ rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 );
+
+ switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ if ( e == NULL ) {
+ char* matched_dn = NULL;
+ struct berval** refs = NULL;
+
+ if( matched != NULL ) {
+ matched_dn = strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb_entry_return( be, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if ( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ goto done;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ goto done;
+ }
+
+ p_ndn = dn_parent( be, e->e_ndn );
+ if ( p_ndn != NULL ) {
+ /* Make sure parent entry exist and we can write its
+ * children.
+ */
+
+ rc = bdb_dn2entry( be, ltid, p_ndn, &p, NULL, 0 );
+
+ switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ if( p == NULL) {
+ Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent does not exist\n",
+ 0, 0, 0);
+ rc = LDAP_OTHER;
+ goto return_results;
+ }
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ children, NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: wr to children of entry %s OK\n",
+ p_ndn, 0, 0 );
+
+ p_dn = dn_parent( be, e->e_dn );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: parent dn=%s\n",
+ p_dn, 0, 0 );
+
+ } else {
+ /* no parent, modrdn entry directly under root */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: no parent & not root\n",
+ 0, 0, 0);
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: no parent, locked root\n",
+ 0, 0, 0 );
+ }
+
+ new_parent_dn = p_dn; /* New Parent unless newSuperior given */
+
+ if ( newSuperior != NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: new parent \"%s\" requested...\n",
+ newSuperior, 0, 0 );
+
+ np_dn = ch_strdup( newSuperior );
+ np_ndn = ch_strdup( np_dn );
+ (void) dn_normalize( np_ndn );
+
+ /* newSuperior == oldParent?, if so ==> ERROR */
+ /* newSuperior == entry being moved?, if so ==> ERROR */
+ /* Get Entry with dn=newSuperior. Does newSuperior exist? */
+
+ rc = bdb_dn2entry( be, ltid, np_ndn, &np, NULL, 0 );
+
+ switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ if( np == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: newSup(ndn=%s) not here!\n",
+ np_ndn, 0, 0);
+ rc = LDAP_OTHER;
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
+ np, np->e_id, 0 );
+
+ /* check newSuperior for "children" acl */
+ if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: no wr to newSup children\n",
+ 0, 0, 0 );
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto return_results;
+ }
+
+ if ( is_entry_alias( np ) ) {
+ /* entry is an alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is alias\n",
+ 0, 0, 0 );
+
+ rc = LDAP_ALIAS_PROBLEM;
+ goto return_results;
+ }
+
+ if ( is_entry_referral( np ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
+ 0, 0, 0 );
+
+ rc = LDAP_OPERATIONS_ERROR;
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: wr to new parent's children OK\n",
+ 0, 0, 0 );
+
+ new_parent_dn = np_dn;
+ }
+
+ /* Build target dn and make sure target entry doesn't exist already. */
+ build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
+
+ new_ndn = ch_strdup(new_dn);
+ (void) dn_normalize( new_ndn );
+
+ Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new ndn=%s\n",
+ new_ndn, 0, 0 );
+
+ rc = bdb_dn2id ( be, ltid, new_ndn, &id );
+ if( rc != 0 ) {
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ text = "internal error";
+ }
+
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: new ndn=%s does not exist\n",
+ new_ndn, 0, 0 );
+
+ /* Get attribute type and attribute value of our new rdn, we will
+ * need to add that to our new entry
+ */
+
+ new_rdn_type = rdn_attr_type( newrdn );
+ if ( new_rdn_type == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: can't figure out type of newrdn\n",
+ 0, 0, 0 );
+ rc = LDAP_OPERATIONS_ERROR;
+ text = "unknown type used in RDN";
+ goto return_results;
+ }
+
+ new_rdn_val = rdn_attr_value( newrdn );
+ if ( new_rdn_val == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: could not figure out val of newrdn\n",
+ 0, 0, 0 );
+ rc = LDAP_OPERATIONS_ERROR;
+ text = "could not parse RDN value";
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
+ new_rdn_val, new_rdn_type, 0 );
+
+ /* Retrieve the old rdn from the entry's dn */
+
+ if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: can't figure out old_rdn from dn\n",
+ 0, 0, 0 );
+ rc = LDAP_OTHER;
+ text = "could not parse old DN";
+ goto return_results;
+ }
+
+ if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_back_modrdn: can't figure out the old_rdn type\n",
+ 0, 0, 0 );
+ rc = LDAP_OTHER;
+ text = "cannot parse RDN from old DN";
+ goto return_results;
+ }
+
+ if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
+ /* Not a big deal but we may say something */
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
+ old_rdn_type, new_rdn_type, 0 );
+ }
+
+ /* Add new attribute value to the entry */
+ add_bvals[0] = &add_bv; /* Array of bervals */
+ add_bvals[1] = NULL;
+
+ add_bv.bv_val = new_rdn_val;
+ add_bv.bv_len = strlen(new_rdn_val);
+
+ mod[0].sml_desc = NULL;
+ rc = slap_str2ad( new_rdn_type, &mod[0].sml_desc, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: %s: %s (new)\n",
+ text, new_rdn_type, 0 );
+ goto return_results;
+ }
+ mod[0].sml_bvalues = add_bvals;
+ mod[0].sml_op = SLAP_MOD_SOFTADD;
+ mod[0].sml_next = NULL;
+
+ /* Remove old rdn value if required */
+
+ if (deleteoldrdn) {
+ /* Get value of old rdn */
+ old_rdn_val = rdn_attr_value( old_rdn );
+ if ( old_rdn_val == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: can't figure out old_rdn_val from old_rdn\n",
+ 0, 0, 0 );
+ rc = LDAP_OTHER;
+ text = "could not parse value from old RDN";
+ goto return_results;
+ }
+
+ del_bvals[0] = &del_bv; /* Array of bervals */
+ del_bvals[1] = NULL;
+
+ /* Remove old value of rdn as an attribute. */
+ del_bv.bv_val = old_rdn_val;
+ del_bv.bv_len = strlen(old_rdn_val);
+
+ mod[1].sml_desc = NULL;
+ rc = slap_str2ad( old_rdn_type, &mod[1].sml_desc, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: %s: %s (old)\n",
+ text, old_rdn_type, 0 );
+ goto return_results;
+ }
+
+ mod[0].sml_next = &mod[1];
+ mod[1].sml_bvalues = del_bvals;
+ mod[1].sml_op = LDAP_MOD_DELETE;
+ mod[1].sml_next = NULL;
+ }
+
+ /* delete old one */
+ rc = bdb_dn2id_delete( be, ltid, e->e_ndn, e->e_id );
+ if ( rc != 0 ) {
+ rc = LDAP_OTHER;
+ text = "DN index delete fail";
+ goto return_results;
+ }
+
+ free( e->e_dn );
+ free( e->e_ndn );
+ e->e_dn = new_dn;
+ e->e_ndn = new_ndn;
+ new_dn = NULL;
+ new_ndn = NULL;
+
+ /* add new one */
+ rc = bdb_dn2id_add( be, ltid, e->e_ndn, e->e_id );
+ if ( rc != 0 ) {
+ rc = LDAP_OTHER;
+ text = "DN index add failed";
+ goto return_results;
+ }
+
+ /* modify entry */
+ rc = bdb_modify_internal( be, conn, op, ltid, dn, &mod[0], e, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+ goto return_results;
+ }
+
+ /* NOTE: after this you must not free new_dn or new_ndn!
+ * They are used by cache.
+ */
+
+ /* id2entry index */
+ rc = bdb_id2entry_add( be, ltid, e );
+ if ( rc != 0 ) {
+ rc = LDAP_OTHER;
+ text = "entry update failed";
+ goto return_results;
+ }
+
+ rc = LDAP_SUCCESS;
+
+ rc = txn_commit( ltid, 0 );
+ ltid = NULL;
+ op->o_private = NULL;
+
+ if( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: txn_commit failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+ rc = LDAP_OTHER;
+ text = "commit failed";
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_modrdn: added id=%08x dn=\"%s\"\n",
+ e->e_id, e->e_dn, 0 );
+ rc = LDAP_SUCCESS;
+ text = NULL;
+ }
+
+return_results:
+ send_ldap_result( conn, op, rc,
+ NULL, text, NULL, NULL );
+
+done:
+ if( new_dn != NULL ) free( new_dn );
+ if( new_ndn != NULL ) free( new_ndn );
+
+ if( p_dn != NULL ) free( p_dn );
+ if( p_ndn != NULL ) free( p_ndn );
+
+ /* LDAP v2 supporting correct attribute handling. */
+ if( new_rdn_type != NULL ) free(new_rdn_type);
+ if( new_rdn_val != NULL ) free(new_rdn_val);
+ if( old_rdn != NULL ) free(old_rdn);
+ if( old_rdn_type != NULL ) free(old_rdn_type);
+ if( old_rdn_val != NULL ) free(old_rdn_val);
+
+
+ /* LDAP v3 Support */
+ if ( np_dn != NULL ) free( np_dn );
+ if ( np_ndn != NULL ) free( np_ndn );
+
+ if( np != NULL ) {
+ /* free new parent and writer lock */
+ bdb_entry_return( be, np );
+ }
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ bdb_entry_return( be, p );
+ }
+
+ /* free entry */
+ if( e != NULL ) {
+ bdb_entry_return( be, e );
+ }
+
+ if( ltid != NULL ) {
+ txn_abort( ltid );
+ op->o_private = NULL;
+ }
+
+ return rc;
+}
int
bdb_exop_passwd(
- Backend *be,
- Connection *conn,
- Operation *op,
+ Backend *be,
+ Connection *conn,
+ Operation *op,
const char *reqoid,
- struct berval *reqdata,
+ struct berval *reqdata,
char **rspoid,
- struct berval **rspdata,
+ struct berval **rspdata,
LDAPControl *** rspctrls,
const char **text,
- struct berval *** refs
-)
+ struct berval *** refs )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc;
Entry *e = NULL;
struct berval *hash = NULL;
- DB_TXN *ltid;
+ DB_TXN *ltid = NULL;
+ struct bdb_op_info opinfo;
struct berval *id = NULL;
struct berval *new = NULL;
goto done;
}
- /* fetch entry */
- rc = dn2entry_w( be, NULL, dn, &e, NULL );
+ if (0) {
+ /* transaction retry */
+retry: rc = txn_abort( ltid );
+ ltid = NULL;
+ op->o_private = NULL;
+ if( rc != 0 ) {
+ rc = LDAP_OTHER;
+ *text = "internal error";
+ goto done;
+ }
+ }
+
+ /* begin transaction */
+ rc = txn_begin( bdb->bi_dbenv, NULL, <id, 0 );
+ if( rc != 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "bdb_exop_passwd: txn_begin failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+ rc = LDAP_OTHER;
+ *text = "internal error";
+ goto done;
+ }
+
+ opinfo.boi_bdb = be;
+ opinfo.boi_txn = ltid;
+ opinfo.boi_err = 0;
+ op->o_private = &opinfo;
+
+ /* get entry */
+ rc = bdb_dn2entry( be, ltid, dn, &e, NULL, 0 );
switch(rc) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
case DB_NOTFOUND:
case 0:
break;
default:
- send_ldap_result( conn, op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
- return rc;
+ rc = LDAP_OTHER;
+ *text = "internal error";
+ goto done;
}
if( e == NULL ) {
goto done;
}
- rc = LDAP_OPERATIONS_ERROR;
if( is_entry_referral( e ) ) {
/* entry is an referral, don't allow operation */
*text = "authorization entry is referral";
+ rc = LDAP_OPERATIONS_ERROR;
goto done;
}
ml.sml_op = LDAP_MOD_REPLACE;
ml.sml_next = NULL;
- rc = bdb_modify_internal( be,
- conn, op, op->o_ndn, &ml, e, text );
+ rc = bdb_modify_internal( be, conn, op, ltid,
+ op->o_ndn, &ml, e, text );
+
+ switch(rc) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ bdb_entry_return( be, e );
+ e = NULL;
+ goto retry;
+ case 0:
+ break;
+ default:
+ rc = LDAP_OTHER;
+ *text = "entry modify failed";
+ goto done;
+ }
}
- if( rc == LDAP_SUCCESS ) {
- /* change the entry itself */
- if( bdb_id2entry_add( be, ltid, e ) != 0 ) {
- *text = "entry update failed";
- rc = LDAP_OTHER;
+ /* change the entry itself */
+ rc = bdb_id2entry_update( be, ltid, e );
+ if( rc != 0 ) {
+ switch(rc) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ bdb_entry_return( be, e );
+ goto retry;
}
+ *text = "entry update failed";
+ rc = LDAP_OTHER;
+ goto done;
}
-
+
done:
if( e != NULL ) {
bdb_entry_return( be, e );
ber_bvfree( hash );
}
+ if( ltid != NULL ) {
+ txn_abort( ltid );
+ op->o_private = NULL;
+ }
+
return rc;
}
int bdb_dn2entry LDAP_P(( BackendDB *be, DB_TXN *tid,
const char *dn, Entry **e, Entry **matched, int flags ));
-#define dn2entry_r(be, tid, dn, p, m) \
- bdb_dn2entry((be), (tid), (dn), (p), (m), 0 )
-
-#define dn2entry_w(be, tid, dn, p, m) \
- bdb_dn2entry((be), (tid), (dn), (p), (m), DB_RMW )
-
/*
* dn2id.c
*/
DB_TXN *tid,
Entry *e );
+int bdb_id2entry_update(
+ BackendDB *be,
+ DB_TXN *tid,
+ Entry *e );
+
int bdb_id2entry_delete(
BackendDB *be,
DB_TXN *tid,
*/
int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *id );
+/*
+ * modify.c
+ */
+int bdb_modify_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ DB_TXN *tid,
+ const char *dn,
+ Modifications *modlist,
+ Entry *e,
+ const char **text );
+
+/*
+ * passwd.c
+ */
+int
+bdb_exop_passwd(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ const char *reqoid,
+ struct berval *reqdata,
+ char **rspoid,
+ struct berval **rspdata,
+ LDAPControl *** rspctrls,
+ const char **text,
+ struct berval *** refs );
+
/*
* tools.c
*/
int
bdb_referrals(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- const char *dn,
- const char *ndn,
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
const char **text )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
return rc;
}
- /* fetch entry */
- rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+ /* get entry */
+ rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
switch(rc) {
case DB_NOTFOUND:
break;
default:
send_ldap_result( conn, op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
+ NULL, "internal error", NULL, NULL );
return rc;
}
if( refs != NULL ) {
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
- e->e_dn, NULL, refs, NULL );
+ e->e_dn, NULL, refs, NULL );
}
ber_bvecfree( refs );
#include "external.h"
static int base_candidate(
- BackendDB *be,
+ BackendDB *be,
Entry *e,
ID *ids );
static int search_candidates(
BackendDB *be,
Entry *e,
Filter *filter,
- int scope,
+ int scope,
int deref,
int manageDSAit,
ID *ids );
int
bdb_search(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- const char *base,
- const char *nbase,
- int scope,
- int deref,
- int slimit,
- int tlimit,
- Filter *filter,
- const char *filterstr,
- char **attrs,
- int attrsonly )
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ const char *base,
+ const char *nbase,
+ int scope,
+ int deref,
+ int slimit,
+ int tlimit,
+ Filter *filter,
+ const char *filterstr,
+ char **attrs,
+ int attrsonly )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int abandon;
} else
#endif
{
- /* obtain entry */
- rc = dn2entry_r( be, NULL, nbase, &e, &matched );
+ rc = bdb_dn2entry( be, NULL, nbase, &e, &matched, 0 );
}
switch(rc) {
break;
default:
send_ldap_result( conn, op, rc=LDAP_OTHER,
- NULL, "internal error", NULL, NULL );
+ NULL, "internal error", NULL, NULL );
return rc;
}
0, 0, 0 );
send_ldap_result( conn, op, LDAP_REFERRAL,
- matched_dn, NULL, refs, NULL );
+ matched_dn, NULL, refs, NULL );
ber_bvecfree( refs );
free( matched_dn );
tlimit = -1; /* allow root to set no limit */
} else {
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
- be->be_timelimit : tlimit;
+ be->be_timelimit : tlimit;
stoptime = op->o_time + tlimit;
}
slimit = -1; /* allow root to set no limit */
} else {
slimit = (slimit > be->be_sizelimit || slimit < 1) ?
- be->be_sizelimit : slimit;
+ be->be_sizelimit : slimit;
}
if ( scope == LDAP_SCOPE_BASE ) {
} else {
rc = search_candidates( be, e, filter,
- scope, deref, manageDSAit, candidates );
+ scope, deref, manageDSAit, candidates );
}
/* need normalized dn below */
for ( id = idl_first( candidates, &cursor );
id != NOID;
- id = idl_next( candidates, &cursor ) )
+ id = idl_next( candidates, &cursor ) )
{
int scopeok = 0;
static int base_candidate(
- BackendDB *be,
+ BackendDB *be,
Entry *e,
ID *ids )
{
BackendDB *be,
Entry *e,
Filter *filter,
- int scope,
+ int scope,
int deref,
int manageDSAit,
ID *ids )
{
- Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" (0x%08lx)\n",
- e->e_dn, (long) e->e_id, 0);
+ int rc;
+ Filter f, fand, rf, af, xf;
+ AttributeAssertion aa_ref, aa_alias;
+
+ Debug(LDAP_DEBUG_TRACE,
+ "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
+ e->e_dn, (long) e->e_id, scope );
+
+ xf.f_or = filter;
+ xf.f_choice = LDAP_FILTER_OR;
+ xf.f_next = NULL;
+
+ if( !manageDSAit ) {
+ /* match referrals */
+ static struct berval bv_ref = { sizeof("REFERRAL")-1, "REFERRAL" };
+ rf.f_choice = LDAP_FILTER_EQUALITY;
+ rf.f_ava = &aa_ref;
+ rf.f_av_desc = slap_schema.si_ad_objectClass;
+ rf.f_av_value = &bv_ref;
+ rf.f_next = xf.f_or;
+ xf.f_or = &rf;
+ }
+
+#ifdef BDB_ALIASES
+ if( deref & LDAP_DEREF_SEARCHING ) {
+ /* match aliases */
+ static struct berval bv_alias = { sizeof("ALIAS")-1, "ALIAS" };
+ af.f_choice = LDAP_FILTER_EQUALITY;
+ af.f_ava = &aa_alias;
+ af.f_av_desc = slap_schema.si_ad_objectClass;
+ af.f_av_value = &bv_alias;
+ af.f_next = xf.f_or;
+ xf.f_or = ⁡
+ }
+#endif
- /* return a RANGE IDL for now */
+ f.f_next = NULL;
+ f.f_choice = LDAP_FILTER_AND;
+ f.f_and = &fand;
+ fand.f_choice = scope == LDAP_SCOPE_SUBTREE
+ ? SLAPD_FILTER_DN_SUBTREE
+ : SLAPD_FILTER_DN_ONE;
+ fand.f_dn = e->e_ndn;
+ fand.f_next = xf.f_or == filter ? filter : &xf ;
+
+#if 0
+ rc = bdb_filter_candidates( be, &f, ids );
+#else
+ /* a quick hack */
ids[0] = NOID;
ids[1] = e->e_id;
ids[2] = e->e_id+128;
+ rc = 0;
+#endif
- return 0;
+ Debug(LDAP_DEBUG_TRACE,
+ "search_candidates: id=%ld first=%ld last=%ld\n",
+ ids[0], ids[1],
+ BDB_IDL_IS_RANGE( ids ) ? ids[2] : ids[ids[0]] );
+
+ return rc;
}
static ID idl_first( ID *ids, ID *cursor )