コード例 #1
0
ファイル: slapi_ops.c プロジェクト: dago/openldap
int
slapi_modify_internal_pb( Slapi_PBlock *pb )
{
	SlapReply		*rs;

	if ( pb == NULL ) {
		return -1;
	}

	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODIFY );

	rs = pb->pb_rs;

	if ( pb->pb_op->orm_modlist == NULL ) {
		rs->sr_err = LDAP_PARAM_ERROR;
		goto cleanup;
	}

	if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		goto cleanup;
	}

	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->orm_modlist,
		&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
	if ( rs->sr_err != LDAP_SUCCESS ) {
                goto cleanup;
        }

	slapi_int_func_internal_pb( pb, op_modify );

cleanup:

	return 0;
}
コード例 #2
0
ファイル: slapi_ops.c プロジェクト: dago/openldap
int
slapi_add_internal_pb( Slapi_PBlock *pb )
{
	SlapReply		*rs;
	Slapi_Entry		*entry_orig = NULL;
	OpExtraDB oex;
	int rc;

	if ( pb == NULL ) {
		return -1;
	}

	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD );

	rs = pb->pb_rs;

	entry_orig = pb->pb_op->ora_e;
	pb->pb_op->ora_e = NULL;

	/*
	 * The caller can specify a new entry, or a target DN and set
	 * of modifications, but not both.
	 */
	if ( entry_orig != NULL ) {
		if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
			rs->sr_err = LDAP_PARAM_ERROR;
			goto cleanup;
		}

		assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */
		ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name );
		ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname );
	} else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
		rs->sr_err = LDAP_PARAM_ERROR;
		goto cleanup;
	}

	pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) );
	ber_dupbv( &pb->pb_op->ora_e->e_name,  &pb->pb_op->o_req_dn );
	ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn );

	if ( entry_orig != NULL ) {
		assert( pb->pb_op->ora_modlist == NULL );

		rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist,
			&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			goto cleanup;
		}
	} else {
		assert( pb->pb_op->ora_modlist != NULL );
	}

	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text,
		pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
	if ( rs->sr_err != LDAP_SUCCESS ) {
                goto cleanup;
        }

	/* Duplicate the values, because we may call slapi_entry_free() */
	rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e,
		1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		goto cleanup;
	}

	oex.oe.oe_key = (void *)do_add;
	oex.oe_db = NULL;
	LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next);
	rc = slapi_int_func_internal_pb( pb, op_add );
	LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next);

	if ( !rc ) {
		if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) {
			BackendDB	*bd = pb->pb_op->o_bd;

			pb->pb_op->o_bd = oex.oe_db;
			be_entry_release_w( pb->pb_op, pb->pb_op->ora_e );
			pb->pb_op->ora_e = NULL;
			pb->pb_op->o_bd = bd;
		}
	}

cleanup:

	if ( pb->pb_op->ora_e != NULL ) {
		slapi_entry_free( pb->pb_op->ora_e );
		pb->pb_op->ora_e = NULL;
	}
	if ( entry_orig != NULL ) {
		pb->pb_op->ora_e = entry_orig;
		slap_mods_free( pb->pb_op->ora_modlist, 1 );
		pb->pb_op->ora_modlist = NULL;
	}

	return 0;
}
コード例 #3
0
ファイル: sasl.c プロジェクト: MPlatform/mdb
static int
slap_auxprop_store(
	void *glob_context,
	sasl_server_params_t *sparams,
	struct propctx *prctx,
	const char *user,
	unsigned ulen)
{
	Operation op = {0};
	Opheader oph;
	int rc, i;
	unsigned j;
	Connection *conn = NULL;
	const struct propval *pr;
	Modifications *modlist = NULL, **modtail = &modlist, *mod;
	slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
	char textbuf[SLAP_TEXT_BUFLEN];
	const char *text;
	size_t textlen = sizeof(textbuf);
#ifdef SLAP_AUXPROP_DONTUSECOPY
	int dontUseCopy = 0;
	BackendDB *dontUseCopy_bd = NULL;
#endif /* SLAP_AUXPROP_DONTUSECOPY */

	/* just checking if we are enabled */
	if (!prctx) return SASL_OK;

	if (!sparams || !user) return SASL_BADPARAM;

	pr = sparams->utils->prop_get( sparams->propctx );

	/* Find our DN and conn first */
	for( i = 0; pr[i].name; i++ ) {
		if ( pr[i].name[0] == '*' ) {
			if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) {
				if ( pr[i].values && pr[i].values[0] )
					AC_MEMCPY( &conn, pr[i].values[0], sizeof( conn ) );
				continue;
			}
			if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) {
				if ( pr[i].values && pr[i].values[0] )
					AC_MEMCPY( &op.o_req_ndn.bv_len, pr[i].values[0],
						sizeof( op.o_req_ndn.bv_len ) );
			} else if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) {
				if ( pr[i].values )
					op.o_req_ndn.bv_val = (char *)pr[i].values[0];
			}
#ifdef SLAP_AUXPROP_DONTUSECOPY
			if ( slap_dontUseCopy_propnames != NULL ) {
				struct berval bv;
				ber_str2bv( &pr[i].name[1], 0, 1, &bv );
				for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ] ); j++ ) {
					if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) {
						dontUseCopy = 1;
						break;
					}
				}
			}
#endif /* SLAP_AUXPROP_DONTUSECOPY */
		}
	}
	if (!conn || !op.o_req_ndn.bv_val) return SASL_BADPARAM;

	op.o_bd = select_backend( &op.o_req_ndn, 1 );

	if ( !op.o_bd || !op.o_bd->be_modify ) return SASL_FAIL;

#ifdef SLAP_AUXPROP_DONTUSECOPY
	if ( SLAP_SHADOW( op.o_bd ) && dontUseCopy ) {
		dontUseCopy_bd = op.o_bd;
		op.o_bd = frontendDB;
		op.o_dontUseCopy = SLAP_CONTROL_CRITICAL;
	}
#endif /* SLAP_AUXPROP_DONTUSECOPY */

	pr = sparams->utils->prop_get( prctx );
	if (!pr) return SASL_BADPARAM;

	for (i=0; pr[i].name; i++);
	if (!i) return SASL_BADPARAM;

	for (i=0; pr[i].name; i++) {
		mod = (Modifications *)ch_malloc( sizeof(Modifications) );
		mod->sml_op = LDAP_MOD_REPLACE;
		mod->sml_flags = 0;
		ber_str2bv( pr[i].name, 0, 0, &mod->sml_type );
		mod->sml_numvals = pr[i].nvalues;
		mod->sml_values = (struct berval *)ch_malloc( (pr[i].nvalues + 1) *
			sizeof(struct berval));
		for (j=0; j<pr[i].nvalues; j++) {
			ber_str2bv( pr[i].values[j], 0, 1, &mod->sml_values[j]);
		}
		BER_BVZERO( &mod->sml_values[j] );
		mod->sml_nvalues = NULL;
		mod->sml_desc = NULL;
		*modtail = mod;
		modtail = &mod->sml_next;
	}
	*modtail = NULL;

	rc = slap_mods_check( &op, modlist, &text, textbuf, textlen, NULL );

	if ( rc == LDAP_SUCCESS ) {
		rc = slap_mods_no_user_mod_check( &op, modlist,
			&text, textbuf, textlen );

		if ( rc == LDAP_SUCCESS ) {
			if ( conn->c_sasl_bindop ) {
				op.o_hdr = conn->c_sasl_bindop->o_hdr;
			} else {
				op.o_hdr = &oph;
				memset( &oph, 0, sizeof(oph) );
				operation_fake_init( conn, &op, ldap_pvt_thread_pool_context(), 0 );
			}
			op.o_tag = LDAP_REQ_MODIFY;
			op.o_ndn = op.o_req_ndn;
			op.o_callback = &cb;
			slap_op_time( &op.o_time, &op.o_tincr );
			op.o_do_not_cache = 1;
			op.o_is_auth_check = 1;
			op.o_req_dn = op.o_req_ndn;
			op.orm_modlist = modlist;

			for (;;) {
				SlapReply rs = {REP_RESULT};
				rc = op.o_bd->be_modify( &op, &rs );

#ifdef SLAP_AUXPROP_DONTUSECOPY
				if ( dontUseCopy &&
					rs.sr_err == LDAP_UNAVAILABLE &&
					slap_dontUseCopy_ignore )
				{
					op.o_bd = dontUseCopy_bd;
					op.o_dontUseCopy = SLAP_CONTROL_NONE;
					dontUseCopy = 0;
					continue;
				}
#endif /* SLAP_AUXPROP_DONTUSECOPY */
				break;
			}
		}
	}
	slap_mods_free( modlist, 1 );
	return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK;
}
コード例 #4
0
ファイル: modify.c プロジェクト: fcelda/openldap
int
do_modify(
    Operation	*op,
    SlapReply	*rs )
{
	struct berval dn = BER_BVNULL;
	char		textbuf[ SLAP_TEXT_BUFLEN ];
	size_t		textlen = sizeof( textbuf );
#ifdef LDAP_DEBUG
	Modifications	*tmp;
#endif

	Debug( LDAP_DEBUG_TRACE, "%s do_modify\n",
		op->o_log_prefix, 0, 0 );
	/*
	 * Parse the modify request.  It looks like this:
	 *
	 *	ModifyRequest := [APPLICATION 6] SEQUENCE {
	 *		name	DistinguishedName,
	 *		mods	SEQUENCE OF SEQUENCE {
	 *			operation	ENUMERATED {
	 *				add	(0),
	 *				delete	(1),
	 *				replace	(2)
	 *			},
	 *			modification	SEQUENCE {
	 *				type	AttributeType,
	 *				values	SET OF AttributeValue
	 *			}
	 *		}
	 *	}
	 */

	if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n",
			op->o_log_prefix, 0, 0 );
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
		return SLAPD_DISCONNECT;
	}

	Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n",
		op->o_log_prefix, dn.bv_val, 0 );

	rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n",
			op->o_log_prefix, rs->sr_err, rs->sr_text );
		send_ldap_result( op, rs );
		goto cleanup;
	}

	if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: get_ctrls failed\n",
			op->o_log_prefix, 0, 0 );
		/* get_ctrls has sent results.	Now clean up. */
		goto cleanup;
	}

	rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
		op->o_tmpmemctx );
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: invalid dn (%s)\n",
			op->o_log_prefix, dn.bv_val, 0 );
		send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
		goto cleanup;
	}

	op->orm_no_opattrs = 0;

#ifdef LDAP_DEBUG
	Debug( LDAP_DEBUG_ARGS, "%s modifications:\n",
			op->o_log_prefix, 0, 0 );

	for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) {
		Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
			tmp->sml_op == LDAP_MOD_ADD ? "add" :
				(tmp->sml_op == LDAP_MOD_INCREMENT ? "increment" :
				(tmp->sml_op == LDAP_MOD_DELETE ? "delete" :
					"replace")), tmp->sml_type.bv_val, 0 );

		if ( tmp->sml_values == NULL ) {
			Debug( LDAP_DEBUG_ARGS, "%s\n",
			   "\t\tno values", NULL, NULL );
		} else if ( BER_BVISNULL( &tmp->sml_values[ 0 ] ) ) {
			Debug( LDAP_DEBUG_ARGS, "%s\n",
			   "\t\tzero values", NULL, NULL );
		} else if ( BER_BVISNULL( &tmp->sml_values[ 1 ] ) ) {
			Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n",
			   "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL );
		} else {
			Debug( LDAP_DEBUG_ARGS, "%s\n",
			   "\t\tmultiple values", NULL, NULL );
		}
	}

	if ( StatslogTest( LDAP_DEBUG_STATS ) ) {
		char abuf[BUFSIZ/2], *ptr = abuf;
		int len = 0;

		Statslog( LDAP_DEBUG_STATS, "%s MOD dn=\"%s\"\n",
			op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );

		for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) {
			if (len + 1 + tmp->sml_type.bv_len > sizeof(abuf)) {
				Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
				    op->o_log_prefix, abuf, 0, 0, 0 );

				len = 0;
				ptr = abuf;

				if( 1 + tmp->sml_type.bv_len > sizeof(abuf)) {
					Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
						op->o_log_prefix, tmp->sml_type.bv_val, 0, 0, 0 );
					continue;
				}
			}
			if (len) {
				*ptr++ = ' ';
				len++;
			}
			ptr = lutil_strcopy(ptr, tmp->sml_type.bv_val);
			len += tmp->sml_type.bv_len;
		}
		if (len) {
			Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
	    			op->o_log_prefix, abuf, 0, 0, 0 );
		}
	}
#endif	/* LDAP_DEBUG */

	rs->sr_err = slap_mods_check( op, op->orm_modlist,
		&rs->sr_text, textbuf, textlen, NULL );

	if ( rs->sr_err != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	op->o_bd = frontendDB;
	rs->sr_err = frontendDB->be_modify( op, rs );

#ifdef LDAP_X_TXN
	if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
		/* skip cleanup */
		return rs->sr_err;
	}
#endif

cleanup:
	op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
	op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
	if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );

	return rs->sr_err;
}
コード例 #5
0
ファイル: add.c プロジェクト: BackupTheBerlios/wl530g-svn
int
do_add( Connection *conn, Operation *op )
{
	BerElement	*ber = op->o_ber;
	char		*last;
	struct berval dn = { 0, NULL };
	ber_len_t	len;
	ber_tag_t	tag;
	Entry		*e;
	Backend		*be;
	Modifications	*modlist = NULL;
	Modifications	**modtail = &modlist;
	Modifications	tmp;
	const char *text;
	int			rc = LDAP_SUCCESS;
	int	manageDSAit;
#ifdef LDAP_SLAPI
	Slapi_PBlock	*pb = NULL;
#endif /* LDAP_SLAPI */

#ifdef NEW_LOGGING
	LDAP_LOG( OPERATION, ENTRY, "do_add: conn %d enter\n", conn->c_connid,0,0 );
#else
	Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
#endif
	/*
	 * Parse the add request.  It looks like this:
	 *
	 *	AddRequest := [APPLICATION 14] SEQUENCE {
	 *		name	DistinguishedName,
	 *		attrs	SEQUENCE OF SEQUENCE {
	 *			type	AttributeType,
	 *			values	SET OF AttributeValue
	 *		}
	 *	}
	 */

	/* get the name */
	if ( ber_scanf( ber, "{m", /*}*/ &dn ) == LBER_ERROR ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, ERR, 
			"do_add: conn %d ber_scanf failed\n", conn->c_connid,0,0 );
#else
		Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
#endif
		send_ldap_disconnect( conn, op,
			LDAP_PROTOCOL_ERROR, "decoding error" );
		return -1;
	}

	e = (Entry *) ch_calloc( 1, sizeof(Entry) );

	rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname );

	if( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, ERR, 
			"do_add: conn %d invalid dn (%s)\n", conn->c_connid, dn.bv_val, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn.bv_val, 0, 0 );
#endif
		send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
			    "invalid DN", NULL, NULL );
		goto done;
	}

#ifdef NEW_LOGGING
	LDAP_LOG( OPERATION, ARGS, 
		"do_add: conn %d  dn (%s)\n", conn->c_connid, e->e_dn, 0 );
#else
	Debug( LDAP_DEBUG_ARGS, "do_add: dn (%s)\n", e->e_dn, 0, 0 );
#endif

	/* get the attrs */
	for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
	    tag = ber_next_element( ber, &len, last ) )
	{
		Modifications *mod;
		ber_tag_t rtag;

		rtag = ber_scanf( ber, "{m{W}}", &tmp.sml_type, &tmp.sml_bvalues );

		if ( rtag == LBER_ERROR ) {
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, ERR, 
				   "do_add: conn %d	 decoding error \n", conn->c_connid, 0, 0 );
#else
			Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 );
#endif
			send_ldap_disconnect( conn, op,
				LDAP_PROTOCOL_ERROR, "decoding error" );
			rc = -1;
			goto done;
		}

		if ( tmp.sml_bvalues == NULL ) {
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, INFO, 
				"do_add: conn %d	 no values for type %s\n",
				conn->c_connid, tmp.sml_type.bv_val, 0 );
#else
			Debug( LDAP_DEBUG_ANY, "no values for type %s\n",
				tmp.sml_type.bv_val, 0, 0 );
#endif
			send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
				NULL, "no values for attribute type", NULL, NULL );
			goto done;
		}
		mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
		
		mod->sml_op = LDAP_MOD_ADD;
		mod->sml_next = NULL;
		mod->sml_desc = NULL;
		mod->sml_type = tmp.sml_type;
		mod->sml_bvalues = tmp.sml_bvalues;

		*modtail = mod;
		modtail = &mod->sml_next;
	}

	if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, ERR, 
			"do_add: conn %d ber_scanf failed\n", conn->c_connid, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
#endif
		send_ldap_disconnect( conn, op,
			LDAP_PROTOCOL_ERROR, "decoding error" );
		rc = -1;
		goto done;
	}

	if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, INFO, 
			"do_add: conn %d get_ctrls failed\n", conn->c_connid, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
#endif
		goto done;
	} 

	if ( modlist == NULL ) {
		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
			NULL, "no attributes provided", NULL, NULL );
		goto done;
	}

	Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu ADD dn=\"%s\"\n",
	    op->o_connid, op->o_opid, e->e_dn, 0, 0 );

	if( e->e_nname.bv_len == 0 ) {
		/* protocolError may be a more appropriate error */
		send_ldap_result( conn, op, rc = LDAP_ALREADY_EXISTS,
			NULL, "root DSE already exists",
			NULL, NULL );
		goto done;

	} else if ( bvmatch( &e->e_nname, &global_schemandn ) ) {
		send_ldap_result( conn, op, rc = LDAP_ALREADY_EXISTS,
			NULL, "subschema subentry already exists",
			NULL, NULL );
		goto done;
	}

	manageDSAit = get_manageDSAit( op );

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	be = select_backend( &e->e_nname, manageDSAit, 0 );
	if ( be == NULL ) {
		BerVarray ref = referral_rewrite( default_referral,
			NULL, &e->e_name, LDAP_SCOPE_DEFAULT );
		if ( ref == NULL ) ref = default_referral;
		if ( ref != NULL ) {
			send_ldap_result( conn, op, rc = LDAP_REFERRAL,
				NULL, NULL, ref, NULL );

			if ( ref != default_referral ) ber_bvarray_free( ref );
		} else {
			send_ldap_result( conn, op,
					rc = LDAP_UNWILLING_TO_PERFORM,
					NULL, "referral missing", NULL, NULL );
		}
		goto done;
	}

	/* check restrictions */
	rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
	if( rc != LDAP_SUCCESS ) {
		send_ldap_result( conn, op, rc,
			NULL, text, NULL, NULL );
		goto done;
	}

	/* check for referrals */
	rc = backend_check_referrals( be, conn, op, &e->e_name, &e->e_nname );
	if ( rc != LDAP_SUCCESS ) {
		goto done;
	}

#ifdef LDAP_SLAPI
	pb = initAddPlugin( be, conn, op, &dn, e, manageDSAit );
#endif /* LDAP_SLAPI */

	/*
	 * do the add if 1 && (2 || 3)
	 * 1) there is an add function implemented in this backend;
	 * 2) this backend is master for what it holds;
	 * 3) it's a replica and the dn supplied is the updatedn.
	 */
	if ( be->be_add ) {
		/* do the update here */
		int repl_user = be_isupdate(be, &op->o_ndn );
#ifndef SLAPD_MULTIMASTER
		if ( !be->be_update_ndn.bv_len || repl_user )
#endif
		{
			int update = be->be_update_ndn.bv_len;
			char textbuf[SLAP_TEXT_BUFLEN];
			size_t textlen = sizeof textbuf;

			rc = slap_mods_check( modlist, update, &text,
				textbuf, textlen );

			if( rc != LDAP_SUCCESS ) {
				send_ldap_result( conn, op, rc,
					NULL, text, NULL, NULL );
				goto done;
			}

			if ( !repl_user ) {
				for( modtail = &modlist;
					*modtail != NULL;
					modtail = &(*modtail)->sml_next )
				{
					assert( (*modtail)->sml_op == LDAP_MOD_ADD );
					assert( (*modtail)->sml_desc != NULL );
				}
				rc = slap_mods_opattrs( be, op, modlist, modtail, &text,
					textbuf, textlen );
				if( rc != LDAP_SUCCESS ) {
					send_ldap_result( conn, op, rc,
						NULL, text, NULL, NULL );
					goto done;
				}
			}

			rc = slap_mods2entry( modlist, &e, repl_user, &text,
				textbuf, textlen );
			if( rc != LDAP_SUCCESS ) {
				send_ldap_result( conn, op, rc,
					NULL, text, NULL, NULL );
				goto done;
			}

#ifdef LDAP_SLAPI
			/*
			 * Call the preoperation plugin here, because the entry
			 * will actually contain something.
			 */
			rc = doPreAddPluginFNs( be, pb );
			if ( rc != LDAP_SUCCESS ) {
				/* plugin will have sent result */
				goto done;
			}
#endif /* LDAP_SLAPI */

			if ( (*be->be_add)( be, conn, op, e ) == 0 ) {
#ifdef SLAPD_MULTIMASTER
				if ( !repl_user )
#endif
				{
					replog( be, op, &e->e_name, &e->e_nname, e );
				}
				be_entry_release_w( be, conn, op, e );
				e = NULL;
			}

#ifndef SLAPD_MULTIMASTER
		} else {
			BerVarray defref;
			BerVarray ref;
#ifdef LDAP_SLAPI
			/*
			 * SLAPI_ADD_ENTRY will be empty, but this may be acceptable
			 * on replicas (for now, it involves the minimum code intrusion).
			 */
			rc = doPreAddPluginFNs( be, pb );
			if ( rc != LDAP_SUCCESS ) {
				/* plugin will have sent result */
				goto done;
			}
#endif /* LDAP_SLAPI */

			defref = be->be_update_refs
				? be->be_update_refs : default_referral;

			if ( defref ) {
				ref = referral_rewrite( defref,
					NULL, &e->e_name, LDAP_SCOPE_DEFAULT );

				send_ldap_result( conn, op, rc = LDAP_REFERRAL,
						NULL, NULL,
						ref ? ref : defref, NULL );

				if ( ref ) ber_bvarray_free( ref );
			} else {
				send_ldap_result( conn, op,
						rc = LDAP_UNWILLING_TO_PERFORM,
						NULL, "referral missing",
						NULL, NULL );
			}
#endif /* SLAPD_MULTIMASTER */
		}
	} else {
#ifdef LDAP_SLAPI
	    rc = doPreAddPluginFNs( be, pb );
	    if ( rc != LDAP_SUCCESS ) {
		/* plugin will have sent result */
		goto done;
	    }
#endif
#ifdef NEW_LOGGING
	    LDAP_LOG( OPERATION, INFO, 
		       "do_add: conn %d	 no backend support\n", conn->c_connid, 0, 0 );
#else
	    Debug( LDAP_DEBUG_ARGS, "	 do_add: no backend support\n", 0, 0, 0 );
#endif
	    send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
			      NULL, "operation not supported within namingContext", NULL, NULL );
	}

#ifdef LDAP_SLAPI
	doPostAddPluginFNs( be, pb );
#endif /* LDAP_SLAPI */

done:
	if( modlist != NULL ) {
		slap_mods_free( modlist );
	}
	if( e != NULL ) {
		entry_free( e );
	}

	return rc;
}