Home | History | Annotate | Line # | Download | only in back-mdb
add.c revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  tls /*	$NetBSD: add.c,v 1.1.1.1.2.2 2014/08/10 07:09:49 tls Exp $	*/
      2  1.1.1.1.2.2  tls 
      3  1.1.1.1.2.2  tls /* add.c - ldap mdb back-end add routine */
      4  1.1.1.1.2.2  tls /* $OpenLDAP$ */
      5  1.1.1.1.2.2  tls /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  1.1.1.1.2.2  tls  *
      7  1.1.1.1.2.2  tls  * Copyright 2000-2014 The OpenLDAP Foundation.
      8  1.1.1.1.2.2  tls  * All rights reserved.
      9  1.1.1.1.2.2  tls  *
     10  1.1.1.1.2.2  tls  * Redistribution and use in source and binary forms, with or without
     11  1.1.1.1.2.2  tls  * modification, are permitted only as authorized by the OpenLDAP
     12  1.1.1.1.2.2  tls  * Public License.
     13  1.1.1.1.2.2  tls  *
     14  1.1.1.1.2.2  tls  * A copy of this license is available in the file LICENSE in the
     15  1.1.1.1.2.2  tls  * top-level directory of the distribution or, alternatively, at
     16  1.1.1.1.2.2  tls  * <http://www.OpenLDAP.org/license.html>.
     17  1.1.1.1.2.2  tls  */
     18  1.1.1.1.2.2  tls 
     19  1.1.1.1.2.2  tls #include "portable.h"
     20  1.1.1.1.2.2  tls 
     21  1.1.1.1.2.2  tls #include <stdio.h>
     22  1.1.1.1.2.2  tls #include <ac/string.h>
     23  1.1.1.1.2.2  tls 
     24  1.1.1.1.2.2  tls #include "back-mdb.h"
     25  1.1.1.1.2.2  tls 
     26  1.1.1.1.2.2  tls int
     27  1.1.1.1.2.2  tls mdb_add(Operation *op, SlapReply *rs )
     28  1.1.1.1.2.2  tls {
     29  1.1.1.1.2.2  tls 	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
     30  1.1.1.1.2.2  tls 	struct berval	pdn;
     31  1.1.1.1.2.2  tls 	Entry		*p = NULL, *oe = op->ora_e;
     32  1.1.1.1.2.2  tls 	char textbuf[SLAP_TEXT_BUFLEN];
     33  1.1.1.1.2.2  tls 	size_t textlen = sizeof textbuf;
     34  1.1.1.1.2.2  tls 	AttributeDescription *children = slap_schema.si_ad_children;
     35  1.1.1.1.2.2  tls 	AttributeDescription *entry = slap_schema.si_ad_entry;
     36  1.1.1.1.2.2  tls 	MDB_txn		*txn = NULL;
     37  1.1.1.1.2.2  tls 	MDB_cursor	*mc = NULL;
     38  1.1.1.1.2.2  tls 	MDB_cursor	*mcd;
     39  1.1.1.1.2.2  tls 	ID eid, pid = 0;
     40  1.1.1.1.2.2  tls 	mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo;
     41  1.1.1.1.2.2  tls 	int subentry;
     42  1.1.1.1.2.2  tls 
     43  1.1.1.1.2.2  tls 	int		success;
     44  1.1.1.1.2.2  tls 
     45  1.1.1.1.2.2  tls 	LDAPControl **postread_ctrl = NULL;
     46  1.1.1.1.2.2  tls 	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
     47  1.1.1.1.2.2  tls 	int num_ctrls = 0;
     48  1.1.1.1.2.2  tls 
     49  1.1.1.1.2.2  tls #ifdef LDAP_X_TXN
     50  1.1.1.1.2.2  tls 	int settle = 0;
     51  1.1.1.1.2.2  tls #endif
     52  1.1.1.1.2.2  tls 
     53  1.1.1.1.2.2  tls 	Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(mdb_add) ": %s\n",
     54  1.1.1.1.2.2  tls 		op->ora_e->e_name.bv_val, 0, 0);
     55  1.1.1.1.2.2  tls 
     56  1.1.1.1.2.2  tls #ifdef LDAP_X_TXN
     57  1.1.1.1.2.2  tls 	if( op->o_txnSpec ) {
     58  1.1.1.1.2.2  tls 		/* acquire connection lock */
     59  1.1.1.1.2.2  tls 		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
     60  1.1.1.1.2.2  tls 		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
     61  1.1.1.1.2.2  tls 			rs->sr_text = "invalid transaction identifier";
     62  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_X_TXN_ID_INVALID;
     63  1.1.1.1.2.2  tls 			goto txnReturn;
     64  1.1.1.1.2.2  tls 		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
     65  1.1.1.1.2.2  tls 			settle=1;
     66  1.1.1.1.2.2  tls 			goto txnReturn;
     67  1.1.1.1.2.2  tls 		}
     68  1.1.1.1.2.2  tls 
     69  1.1.1.1.2.2  tls 		if( op->o_conn->c_txn_backend == NULL ) {
     70  1.1.1.1.2.2  tls 			op->o_conn->c_txn_backend = op->o_bd;
     71  1.1.1.1.2.2  tls 
     72  1.1.1.1.2.2  tls 		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
     73  1.1.1.1.2.2  tls 			rs->sr_text = "transaction cannot span multiple database contexts";
     74  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
     75  1.1.1.1.2.2  tls 			goto txnReturn;
     76  1.1.1.1.2.2  tls 		}
     77  1.1.1.1.2.2  tls 
     78  1.1.1.1.2.2  tls 		/* insert operation into transaction */
     79  1.1.1.1.2.2  tls 
     80  1.1.1.1.2.2  tls 		rs->sr_text = "transaction specified";
     81  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
     82  1.1.1.1.2.2  tls 
     83  1.1.1.1.2.2  tls txnReturn:
     84  1.1.1.1.2.2  tls 		/* release connection lock */
     85  1.1.1.1.2.2  tls 		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
     86  1.1.1.1.2.2  tls 
     87  1.1.1.1.2.2  tls 		if( !settle ) {
     88  1.1.1.1.2.2  tls 			send_ldap_result( op, rs );
     89  1.1.1.1.2.2  tls 			return rs->sr_err;
     90  1.1.1.1.2.2  tls 		}
     91  1.1.1.1.2.2  tls 	}
     92  1.1.1.1.2.2  tls #endif
     93  1.1.1.1.2.2  tls 
     94  1.1.1.1.2.2  tls 	ctrls[num_ctrls] = 0;
     95  1.1.1.1.2.2  tls 
     96  1.1.1.1.2.2  tls 	/* check entry's schema */
     97  1.1.1.1.2.2  tls 	rs->sr_err = entry_schema_check( op, op->ora_e, NULL,
     98  1.1.1.1.2.2  tls 		get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
     99  1.1.1.1.2.2  tls 	if ( rs->sr_err != LDAP_SUCCESS ) {
    100  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    101  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": entry failed schema check: "
    102  1.1.1.1.2.2  tls 			"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
    103  1.1.1.1.2.2  tls 		goto return_results;
    104  1.1.1.1.2.2  tls 	}
    105  1.1.1.1.2.2  tls 
    106  1.1.1.1.2.2  tls 	/* begin transaction */
    107  1.1.1.1.2.2  tls 	rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi );
    108  1.1.1.1.2.2  tls 	rs->sr_text = NULL;
    109  1.1.1.1.2.2  tls 	if( rs->sr_err != 0 ) {
    110  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    111  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": txn_begin failed: %s (%d)\n",
    112  1.1.1.1.2.2  tls 			mdb_strerror(rs->sr_err), rs->sr_err, 0 );
    113  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    114  1.1.1.1.2.2  tls 		rs->sr_text = "internal error";
    115  1.1.1.1.2.2  tls 		goto return_results;
    116  1.1.1.1.2.2  tls 	}
    117  1.1.1.1.2.2  tls 	txn = moi->moi_txn;
    118  1.1.1.1.2.2  tls 
    119  1.1.1.1.2.2  tls 	/* add opattrs to shadow as well, only missing attrs will actually
    120  1.1.1.1.2.2  tls 	 * be added; helps compatibility with older OL versions */
    121  1.1.1.1.2.2  tls 	rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
    122  1.1.1.1.2.2  tls 	if ( rs->sr_err != LDAP_SUCCESS ) {
    123  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    124  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": entry failed op attrs add: "
    125  1.1.1.1.2.2  tls 			"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
    126  1.1.1.1.2.2  tls 		goto return_results;
    127  1.1.1.1.2.2  tls 	}
    128  1.1.1.1.2.2  tls 
    129  1.1.1.1.2.2  tls 	if ( get_assert( op ) &&
    130  1.1.1.1.2.2  tls 		( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
    131  1.1.1.1.2.2  tls 	{
    132  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_ASSERTION_FAILED;
    133  1.1.1.1.2.2  tls 		goto return_results;
    134  1.1.1.1.2.2  tls 	}
    135  1.1.1.1.2.2  tls 
    136  1.1.1.1.2.2  tls 	subentry = is_entry_subentry( op->ora_e );
    137  1.1.1.1.2.2  tls 
    138  1.1.1.1.2.2  tls 	/*
    139  1.1.1.1.2.2  tls 	 * Get the parent dn and see if the corresponding entry exists.
    140  1.1.1.1.2.2  tls 	 */
    141  1.1.1.1.2.2  tls 	if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
    142  1.1.1.1.2.2  tls 		pdn = slap_empty_bv;
    143  1.1.1.1.2.2  tls 	} else {
    144  1.1.1.1.2.2  tls 		dnParent( &op->ora_e->e_nname, &pdn );
    145  1.1.1.1.2.2  tls 	}
    146  1.1.1.1.2.2  tls 
    147  1.1.1.1.2.2  tls 	rs->sr_err = mdb_cursor_open( txn, mdb->mi_dn2id, &mcd );
    148  1.1.1.1.2.2  tls 	if( rs->sr_err != 0 ) {
    149  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    150  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": mdb_cursor_open failed (%d)\n",
    151  1.1.1.1.2.2  tls 			rs->sr_err, 0, 0 );
    152  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    153  1.1.1.1.2.2  tls 		rs->sr_text = "internal error";
    154  1.1.1.1.2.2  tls 		goto return_results;
    155  1.1.1.1.2.2  tls 	}
    156  1.1.1.1.2.2  tls 
    157  1.1.1.1.2.2  tls 	/* get entry or parent */
    158  1.1.1.1.2.2  tls 	rs->sr_err = mdb_dn2entry( op, txn, mcd, &op->ora_e->e_nname, &p, NULL, 1 );
    159  1.1.1.1.2.2  tls 	switch( rs->sr_err ) {
    160  1.1.1.1.2.2  tls 	case 0:
    161  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_ALREADY_EXISTS;
    162  1.1.1.1.2.2  tls 		mdb_entry_return( op, p );
    163  1.1.1.1.2.2  tls 		p = NULL;
    164  1.1.1.1.2.2  tls 		goto return_results;
    165  1.1.1.1.2.2  tls 	case MDB_NOTFOUND:
    166  1.1.1.1.2.2  tls 		break;
    167  1.1.1.1.2.2  tls 	case LDAP_BUSY:
    168  1.1.1.1.2.2  tls 		rs->sr_text = "ldap server busy";
    169  1.1.1.1.2.2  tls 		goto return_results;
    170  1.1.1.1.2.2  tls 	default:
    171  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    172  1.1.1.1.2.2  tls 		rs->sr_text = "internal error";
    173  1.1.1.1.2.2  tls 		goto return_results;
    174  1.1.1.1.2.2  tls 	}
    175  1.1.1.1.2.2  tls 
    176  1.1.1.1.2.2  tls 	if ( !p )
    177  1.1.1.1.2.2  tls 		p = (Entry *)&slap_entry_root;
    178  1.1.1.1.2.2  tls 
    179  1.1.1.1.2.2  tls 	if ( !bvmatch( &pdn, &p->e_nname ) ) {
    180  1.1.1.1.2.2  tls 		rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
    181  1.1.1.1.2.2  tls 			op->o_tmpmemctx );
    182  1.1.1.1.2.2  tls 		if ( p != (Entry *)&slap_entry_root && is_entry_referral( p )) {
    183  1.1.1.1.2.2  tls 			BerVarray ref = get_entry_referrals( op, p );
    184  1.1.1.1.2.2  tls 			rs->sr_ref = referral_rewrite( ref, &p->e_name,
    185  1.1.1.1.2.2  tls 				&op->o_req_dn, LDAP_SCOPE_DEFAULT );
    186  1.1.1.1.2.2  tls 			ber_bvarray_free( ref );
    187  1.1.1.1.2.2  tls 		} else {
    188  1.1.1.1.2.2  tls 			rs->sr_ref = NULL;
    189  1.1.1.1.2.2  tls 		}
    190  1.1.1.1.2.2  tls 		if ( p != (Entry *)&slap_entry_root )
    191  1.1.1.1.2.2  tls 			mdb_entry_return( op, p );
    192  1.1.1.1.2.2  tls 		p = NULL;
    193  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    194  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": parent "
    195  1.1.1.1.2.2  tls 			"does not exist\n", 0, 0, 0 );
    196  1.1.1.1.2.2  tls 
    197  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_REFERRAL;
    198  1.1.1.1.2.2  tls 		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
    199  1.1.1.1.2.2  tls 		goto return_results;
    200  1.1.1.1.2.2  tls 	}
    201  1.1.1.1.2.2  tls 
    202  1.1.1.1.2.2  tls 	rs->sr_err = access_allowed( op, p,
    203  1.1.1.1.2.2  tls 		children, NULL, ACL_WADD, NULL );
    204  1.1.1.1.2.2  tls 
    205  1.1.1.1.2.2  tls 	if ( ! rs->sr_err ) {
    206  1.1.1.1.2.2  tls 		if ( p != (Entry *)&slap_entry_root )
    207  1.1.1.1.2.2  tls 			mdb_entry_return( op, p );
    208  1.1.1.1.2.2  tls 		p = NULL;
    209  1.1.1.1.2.2  tls 
    210  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    211  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": no write access to parent\n",
    212  1.1.1.1.2.2  tls 			0, 0, 0 );
    213  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
    214  1.1.1.1.2.2  tls 		rs->sr_text = "no write access to parent";
    215  1.1.1.1.2.2  tls 		goto return_results;;
    216  1.1.1.1.2.2  tls 	}
    217  1.1.1.1.2.2  tls 
    218  1.1.1.1.2.2  tls 	if ( p != (Entry *)&slap_entry_root ) {
    219  1.1.1.1.2.2  tls 		if ( is_entry_subentry( p ) ) {
    220  1.1.1.1.2.2  tls 			mdb_entry_return( op, p );
    221  1.1.1.1.2.2  tls 			p = NULL;
    222  1.1.1.1.2.2  tls 			/* parent is a subentry, don't allow add */
    223  1.1.1.1.2.2  tls 			Debug( LDAP_DEBUG_TRACE,
    224  1.1.1.1.2.2  tls 				LDAP_XSTRING(mdb_add) ": parent is subentry\n",
    225  1.1.1.1.2.2  tls 				0, 0, 0 );
    226  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
    227  1.1.1.1.2.2  tls 			rs->sr_text = "parent is a subentry";
    228  1.1.1.1.2.2  tls 			goto return_results;;
    229  1.1.1.1.2.2  tls 		}
    230  1.1.1.1.2.2  tls 
    231  1.1.1.1.2.2  tls 		if ( is_entry_alias( p ) ) {
    232  1.1.1.1.2.2  tls 			mdb_entry_return( op, p );
    233  1.1.1.1.2.2  tls 			p = NULL;
    234  1.1.1.1.2.2  tls 			/* parent is an alias, don't allow add */
    235  1.1.1.1.2.2  tls 			Debug( LDAP_DEBUG_TRACE,
    236  1.1.1.1.2.2  tls 				LDAP_XSTRING(mdb_add) ": parent is alias\n",
    237  1.1.1.1.2.2  tls 				0, 0, 0 );
    238  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_ALIAS_PROBLEM;
    239  1.1.1.1.2.2  tls 			rs->sr_text = "parent is an alias";
    240  1.1.1.1.2.2  tls 			goto return_results;;
    241  1.1.1.1.2.2  tls 		}
    242  1.1.1.1.2.2  tls 
    243  1.1.1.1.2.2  tls 		if ( is_entry_referral( p ) ) {
    244  1.1.1.1.2.2  tls 			BerVarray ref = get_entry_referrals( op, p );
    245  1.1.1.1.2.2  tls 			/* parent is a referral, don't allow add */
    246  1.1.1.1.2.2  tls 			rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
    247  1.1.1.1.2.2  tls 				op->o_tmpmemctx );
    248  1.1.1.1.2.2  tls 			rs->sr_ref = referral_rewrite( ref, &p->e_name,
    249  1.1.1.1.2.2  tls 				&op->o_req_dn, LDAP_SCOPE_DEFAULT );
    250  1.1.1.1.2.2  tls 			ber_bvarray_free( ref );
    251  1.1.1.1.2.2  tls 			mdb_entry_return( op, p );
    252  1.1.1.1.2.2  tls 			p = NULL;
    253  1.1.1.1.2.2  tls 			Debug( LDAP_DEBUG_TRACE,
    254  1.1.1.1.2.2  tls 				LDAP_XSTRING(mdb_add) ": parent is referral\n",
    255  1.1.1.1.2.2  tls 				0, 0, 0 );
    256  1.1.1.1.2.2  tls 
    257  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_REFERRAL;
    258  1.1.1.1.2.2  tls 			rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
    259  1.1.1.1.2.2  tls 			goto return_results;
    260  1.1.1.1.2.2  tls 		}
    261  1.1.1.1.2.2  tls 
    262  1.1.1.1.2.2  tls 	}
    263  1.1.1.1.2.2  tls 
    264  1.1.1.1.2.2  tls 	if ( subentry ) {
    265  1.1.1.1.2.2  tls 		/* FIXME: */
    266  1.1.1.1.2.2  tls 		/* parent must be an administrative point of the required kind */
    267  1.1.1.1.2.2  tls 	}
    268  1.1.1.1.2.2  tls 
    269  1.1.1.1.2.2  tls 	/* free parent */
    270  1.1.1.1.2.2  tls 	if ( p != (Entry *)&slap_entry_root ) {
    271  1.1.1.1.2.2  tls 		pid = p->e_id;
    272  1.1.1.1.2.2  tls 		if ( p->e_nname.bv_len ) {
    273  1.1.1.1.2.2  tls 			struct berval ppdn;
    274  1.1.1.1.2.2  tls 
    275  1.1.1.1.2.2  tls 			/* ITS#5326: use parent's DN if differs from provided one */
    276  1.1.1.1.2.2  tls 			dnParent( &op->ora_e->e_name, &ppdn );
    277  1.1.1.1.2.2  tls 			if ( !dn_match( &p->e_name, &ppdn ) ) {
    278  1.1.1.1.2.2  tls 				struct berval rdn;
    279  1.1.1.1.2.2  tls 				struct berval newdn;
    280  1.1.1.1.2.2  tls 
    281  1.1.1.1.2.2  tls 				dnRdn( &op->ora_e->e_name, &rdn );
    282  1.1.1.1.2.2  tls 
    283  1.1.1.1.2.2  tls 				build_new_dn( &newdn, &p->e_name, &rdn, NULL );
    284  1.1.1.1.2.2  tls 				if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val )
    285  1.1.1.1.2.2  tls 					ber_memfree( op->ora_e->e_name.bv_val );
    286  1.1.1.1.2.2  tls 				op->ora_e->e_name = newdn;
    287  1.1.1.1.2.2  tls 
    288  1.1.1.1.2.2  tls 				/* FIXME: should check whether
    289  1.1.1.1.2.2  tls 				 * dnNormalize(newdn) == e->e_nname ... */
    290  1.1.1.1.2.2  tls 			}
    291  1.1.1.1.2.2  tls 		}
    292  1.1.1.1.2.2  tls 
    293  1.1.1.1.2.2  tls 		mdb_entry_return( op, p );
    294  1.1.1.1.2.2  tls 	}
    295  1.1.1.1.2.2  tls 	p = NULL;
    296  1.1.1.1.2.2  tls 
    297  1.1.1.1.2.2  tls 	rs->sr_err = access_allowed( op, op->ora_e,
    298  1.1.1.1.2.2  tls 		entry, NULL, ACL_WADD, NULL );
    299  1.1.1.1.2.2  tls 
    300  1.1.1.1.2.2  tls 	if ( ! rs->sr_err ) {
    301  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    302  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": no write access to entry\n",
    303  1.1.1.1.2.2  tls 			0, 0, 0 );
    304  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
    305  1.1.1.1.2.2  tls 		rs->sr_text = "no write access to entry";
    306  1.1.1.1.2.2  tls 		goto return_results;;
    307  1.1.1.1.2.2  tls 	}
    308  1.1.1.1.2.2  tls 
    309  1.1.1.1.2.2  tls 	/*
    310  1.1.1.1.2.2  tls 	 * Check ACL for attribute write access
    311  1.1.1.1.2.2  tls 	 */
    312  1.1.1.1.2.2  tls 	if (!acl_check_modlist(op, oe, op->ora_modlist)) {
    313  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    314  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": no write access to attribute\n",
    315  1.1.1.1.2.2  tls 			0, 0, 0 );
    316  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
    317  1.1.1.1.2.2  tls 		rs->sr_text = "no write access to attribute";
    318  1.1.1.1.2.2  tls 		goto return_results;;
    319  1.1.1.1.2.2  tls 	}
    320  1.1.1.1.2.2  tls 
    321  1.1.1.1.2.2  tls 	rs->sr_err = mdb_cursor_open( txn, mdb->mi_id2entry, &mc );
    322  1.1.1.1.2.2  tls 	if( rs->sr_err != 0 ) {
    323  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    324  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": mdb_cursor_open failed (%d)\n",
    325  1.1.1.1.2.2  tls 			rs->sr_err, 0, 0 );
    326  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    327  1.1.1.1.2.2  tls 		rs->sr_text = "internal error";
    328  1.1.1.1.2.2  tls 		goto return_results;
    329  1.1.1.1.2.2  tls 	}
    330  1.1.1.1.2.2  tls 
    331  1.1.1.1.2.2  tls 	rs->sr_err = mdb_next_id( op->o_bd, mc, &eid );
    332  1.1.1.1.2.2  tls 	if( rs->sr_err != 0 ) {
    333  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    334  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": next_id failed (%d)\n",
    335  1.1.1.1.2.2  tls 			rs->sr_err, 0, 0 );
    336  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    337  1.1.1.1.2.2  tls 		rs->sr_text = "internal error";
    338  1.1.1.1.2.2  tls 		goto return_results;
    339  1.1.1.1.2.2  tls 	}
    340  1.1.1.1.2.2  tls 	op->ora_e->e_id = eid;
    341  1.1.1.1.2.2  tls 
    342  1.1.1.1.2.2  tls 	/* dn2id index */
    343  1.1.1.1.2.2  tls 	rs->sr_err = mdb_dn2id_add( op, mcd, mcd, pid, 1, 1, op->ora_e );
    344  1.1.1.1.2.2  tls 	mdb_cursor_close( mcd );
    345  1.1.1.1.2.2  tls 	if ( rs->sr_err != 0 ) {
    346  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    347  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": dn2id_add failed: %s (%d)\n",
    348  1.1.1.1.2.2  tls 			mdb_strerror(rs->sr_err), rs->sr_err, 0 );
    349  1.1.1.1.2.2  tls 
    350  1.1.1.1.2.2  tls 		switch( rs->sr_err ) {
    351  1.1.1.1.2.2  tls 		case MDB_KEYEXIST:
    352  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_ALREADY_EXISTS;
    353  1.1.1.1.2.2  tls 			break;
    354  1.1.1.1.2.2  tls 		default:
    355  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_OTHER;
    356  1.1.1.1.2.2  tls 		}
    357  1.1.1.1.2.2  tls 		goto return_results;
    358  1.1.1.1.2.2  tls 	}
    359  1.1.1.1.2.2  tls 
    360  1.1.1.1.2.2  tls 	/* attribute indexes */
    361  1.1.1.1.2.2  tls 	rs->sr_err = mdb_index_entry_add( op, txn, op->ora_e );
    362  1.1.1.1.2.2  tls 	if ( rs->sr_err != LDAP_SUCCESS ) {
    363  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    364  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": index_entry_add failed\n",
    365  1.1.1.1.2.2  tls 			0, 0, 0 );
    366  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    367  1.1.1.1.2.2  tls 		rs->sr_text = "index generation failed";
    368  1.1.1.1.2.2  tls 		goto return_results;
    369  1.1.1.1.2.2  tls 	}
    370  1.1.1.1.2.2  tls 
    371  1.1.1.1.2.2  tls 	/* id2entry index */
    372  1.1.1.1.2.2  tls 	rs->sr_err = mdb_id2entry_add( op, txn, mc, op->ora_e );
    373  1.1.1.1.2.2  tls 	if ( rs->sr_err != 0 ) {
    374  1.1.1.1.2.2  tls 		Debug( LDAP_DEBUG_TRACE,
    375  1.1.1.1.2.2  tls 			LDAP_XSTRING(mdb_add) ": id2entry_add failed\n",
    376  1.1.1.1.2.2  tls 			0, 0, 0 );
    377  1.1.1.1.2.2  tls 		rs->sr_err = LDAP_OTHER;
    378  1.1.1.1.2.2  tls 		rs->sr_text = "entry store failed";
    379  1.1.1.1.2.2  tls 		goto return_results;
    380  1.1.1.1.2.2  tls 	}
    381  1.1.1.1.2.2  tls 
    382  1.1.1.1.2.2  tls 	/* post-read */
    383  1.1.1.1.2.2  tls 	if( op->o_postread ) {
    384  1.1.1.1.2.2  tls 		if( postread_ctrl == NULL ) {
    385  1.1.1.1.2.2  tls 			postread_ctrl = &ctrls[num_ctrls++];
    386  1.1.1.1.2.2  tls 			ctrls[num_ctrls] = NULL;
    387  1.1.1.1.2.2  tls 		}
    388  1.1.1.1.2.2  tls 		if ( slap_read_controls( op, rs, op->ora_e,
    389  1.1.1.1.2.2  tls 			&slap_post_read_bv, postread_ctrl ) )
    390  1.1.1.1.2.2  tls 		{
    391  1.1.1.1.2.2  tls 			Debug( LDAP_DEBUG_TRACE,
    392  1.1.1.1.2.2  tls 				"<=- " LDAP_XSTRING(mdb_add) ": post-read "
    393  1.1.1.1.2.2  tls 				"failed!\n", 0, 0, 0 );
    394  1.1.1.1.2.2  tls 			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
    395  1.1.1.1.2.2  tls 				/* FIXME: is it correct to abort
    396  1.1.1.1.2.2  tls 				 * operation if control fails? */
    397  1.1.1.1.2.2  tls 				goto return_results;
    398  1.1.1.1.2.2  tls 			}
    399  1.1.1.1.2.2  tls 		}
    400  1.1.1.1.2.2  tls 	}
    401  1.1.1.1.2.2  tls 
    402  1.1.1.1.2.2  tls 	if ( moi == &opinfo ) {
    403  1.1.1.1.2.2  tls 		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next );
    404  1.1.1.1.2.2  tls 		opinfo.moi_oe.oe_key = NULL;
    405  1.1.1.1.2.2  tls 		if ( op->o_noop ) {
    406  1.1.1.1.2.2  tls 			mdb_txn_abort( txn );
    407  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_X_NO_OPERATION;
    408  1.1.1.1.2.2  tls 			txn = NULL;
    409  1.1.1.1.2.2  tls 			goto return_results;
    410  1.1.1.1.2.2  tls 		}
    411  1.1.1.1.2.2  tls 
    412  1.1.1.1.2.2  tls 		rs->sr_err = mdb_txn_commit( txn );
    413  1.1.1.1.2.2  tls 		txn = NULL;
    414  1.1.1.1.2.2  tls 		if ( rs->sr_err != 0 ) {
    415  1.1.1.1.2.2  tls 			rs->sr_text = "txn_commit failed";
    416  1.1.1.1.2.2  tls 			Debug( LDAP_DEBUG_ANY,
    417  1.1.1.1.2.2  tls 				LDAP_XSTRING(mdb_add) ": %s : %s (%d)\n",
    418  1.1.1.1.2.2  tls 				rs->sr_text, mdb_strerror(rs->sr_err), rs->sr_err );
    419  1.1.1.1.2.2  tls 			rs->sr_err = LDAP_OTHER;
    420  1.1.1.1.2.2  tls 			goto return_results;
    421  1.1.1.1.2.2  tls 		}
    422  1.1.1.1.2.2  tls 	}
    423  1.1.1.1.2.2  tls 
    424  1.1.1.1.2.2  tls 	Debug(LDAP_DEBUG_TRACE,
    425  1.1.1.1.2.2  tls 		LDAP_XSTRING(mdb_add) ": added%s id=%08lx dn=\"%s\"\n",
    426  1.1.1.1.2.2  tls 		op->o_noop ? " (no-op)" : "",
    427  1.1.1.1.2.2  tls 		op->ora_e->e_id, op->ora_e->e_dn );
    428  1.1.1.1.2.2  tls 
    429  1.1.1.1.2.2  tls 	rs->sr_text = NULL;
    430  1.1.1.1.2.2  tls 	if( num_ctrls ) rs->sr_ctrls = ctrls;
    431  1.1.1.1.2.2  tls 
    432  1.1.1.1.2.2  tls return_results:
    433  1.1.1.1.2.2  tls 	success = rs->sr_err;
    434  1.1.1.1.2.2  tls 	send_ldap_result( op, rs );
    435  1.1.1.1.2.2  tls 
    436  1.1.1.1.2.2  tls 	if( moi == &opinfo ) {
    437  1.1.1.1.2.2  tls 		if( txn != NULL ) {
    438  1.1.1.1.2.2  tls 			mdb_txn_abort( txn );
    439  1.1.1.1.2.2  tls 		}
    440  1.1.1.1.2.2  tls 		if ( opinfo.moi_oe.oe_key ) {
    441  1.1.1.1.2.2  tls 			LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next );
    442  1.1.1.1.2.2  tls 		}
    443  1.1.1.1.2.2  tls 	} else {
    444  1.1.1.1.2.2  tls 		moi->moi_ref--;
    445  1.1.1.1.2.2  tls 	}
    446  1.1.1.1.2.2  tls 
    447  1.1.1.1.2.2  tls 	if( success == LDAP_SUCCESS ) {
    448  1.1.1.1.2.2  tls #if 0
    449  1.1.1.1.2.2  tls 		if ( mdb->bi_txn_cp_kbyte ) {
    450  1.1.1.1.2.2  tls 			TXN_CHECKPOINT( mdb->bi_dbenv,
    451  1.1.1.1.2.2  tls 				mdb->bi_txn_cp_kbyte, mdb->bi_txn_cp_min, 0 );
    452  1.1.1.1.2.2  tls 		}
    453  1.1.1.1.2.2  tls #endif
    454  1.1.1.1.2.2  tls 	}
    455  1.1.1.1.2.2  tls 
    456  1.1.1.1.2.2  tls 	slap_graduate_commit_csn( op );
    457  1.1.1.1.2.2  tls 
    458  1.1.1.1.2.2  tls 	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
    459  1.1.1.1.2.2  tls 		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
    460  1.1.1.1.2.2  tls 		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
    461  1.1.1.1.2.2  tls 	}
    462  1.1.1.1.2.2  tls 	return rs->sr_err;
    463  1.1.1.1.2.2  tls }
    464