Esempio n. 1
0
int nssov_uid2dn(Operation *op,nssov_info *ni,struct berval *uid,struct berval *dn)
{
	nssov_mapinfo *mi = &ni->ni_maps[NM_passwd];
	char fbuf[1024];
	struct berval filter = {sizeof(fbuf),fbuf};
	slap_callback cb = {0};
	SlapReply rs = {REP_RESULT};
	Operation op2;
	int rc;

	/* if it isn't a valid username, just bail out now */
	if (!isvalidusername(uid))
		return 0;
	/* we have to look up the entry */
	nssov_filter_byid(mi,UID_KEY,uid,&filter);
	BER_BVZERO(dn);
	cb.sc_private = dn;
	cb.sc_response = nssov_name2dn_cb;
	op2 = *op;
	op2.o_callback = &cb;
	op2.o_req_dn = mi->mi_base;
	op2.o_req_ndn = mi->mi_base;
	op2.ors_scope = mi->mi_scope;
	op2.ors_filterstr = filter;
	op2.ors_filter = str2filter_x( op, filter.bv_val );
	op2.ors_attrs = slap_anlist_no_attrs;
	op2.ors_tlimit = SLAP_NO_LIMIT;
	op2.ors_slimit = SLAP_NO_LIMIT;
	rc = op2.o_bd->be_search( &op2, &rs );
	filter_free_x( op, op2.ors_filter, 1 );
	return rc == LDAP_SUCCESS && !BER_BVISNULL(dn);
}
Esempio n. 2
0
static int
retcode_op_internal( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;

	Operation	op2 = *op;
	BackendDB	db = *op->o_bd;
	slap_callback	sc = { 0 };
	retcode_cb_t	rdc;

	int		rc;

	op2.o_tag = LDAP_REQ_SEARCH;
	op2.ors_scope = LDAP_SCOPE_BASE;
	op2.ors_deref = LDAP_DEREF_NEVER;
	op2.ors_tlimit = SLAP_NO_LIMIT;
	op2.ors_slimit = SLAP_NO_LIMIT;
	op2.ors_limit = NULL;
	op2.ors_attrsonly = 0;
	op2.ors_attrs = slap_anlist_all_attributes;

	ber_str2bv_x( "(objectClass=errAbsObject)",
		STRLENOF( "(objectClass=errAbsObject)" ),
		1, &op2.ors_filterstr, op2.o_tmpmemctx );
	op2.ors_filter = str2filter_x( &op2, op2.ors_filterstr.bv_val );

	/* errAbsObject is defined by this overlay! */
	assert( op2.ors_filter != NULL );

	db.bd_info = on->on_info->oi_orig;
	op2.o_bd = &db;

	rdc.rdc_info = on->on_info->oi_orig;
	rdc.rdc_flags = RETCODE_FINDIR;
	if ( op->o_tag == LDAP_REQ_SEARCH ) {
		rdc.rdc_attrs = op->ors_attrs;
	}
	rdc.rdc_tag = op->o_tag;
	sc.sc_response = retcode_cb_response;
	sc.sc_private = &rdc;
	op2.o_callback = ≻

	rc = op2.o_bd->be_search( &op2, rs );
	op->o_abandon = op2.o_abandon;

	filter_free_x( &op2, op2.ors_filter, 1 );
	ber_memfree_x( op2.ors_filterstr.bv_val, op2.o_tmpmemctx );

	if ( rdc.rdc_flags == SLAP_CB_CONTINUE ) {
		return SLAP_CB_CONTINUE;
	}

	return rc;
}
Esempio n. 3
0
Filter *
str2filter( const char *str )
{
	Operation op = {0};
	Opheader ohdr = {0};

	op.o_hdr = &ohdr;
	op.o_tmpmemctx = NULL;
	op.o_tmpmfuncs = &ch_mfuncs;

	return str2filter_x( &op, str );
}
Esempio n. 4
0
/* 
** Builds a filter for searching for the 
** group entries, according to the objectClass. 
*/
static int
autogroup_build_def_filter( autogroup_def_t *agd, Operation *op )
{
	char	*ptr;

	Debug( LDAP_DEBUG_TRACE, "==> autogroup_build_def_filter\n", 0, 0, 0);

	op->ors_filterstr.bv_len = STRLENOF( "(=)" ) 
			+ slap_schema.si_ad_objectClass->ad_cname.bv_len
			+ agd->agd_oc->soc_cname.bv_len;
	ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
	*ptr++ = '(';
	ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
	*ptr++ = '=';
	ptr = lutil_strcopy( ptr, agd->agd_oc->soc_cname.bv_val );
	*ptr++ = ')';
	*ptr = '\0';

	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );

	assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );

	return 0;
}
Esempio n. 5
0
static int
vernum_repair( BackendDB *be )
{
	slap_overinst *on = (slap_overinst *)be->bd_info;
	vernum_t *vn = (vernum_t *)on->on_bi.bi_private;
	void *ctx = ldap_pvt_thread_pool_context();
	Connection conn = { 0 };
	OperationBuffer opbuf;
	Operation *op;
	BackendDB db;
	slap_callback sc = { 0 };
	vernum_repair_cb_t rcb = { 0 };
	SlapReply rs = { REP_RESULT };
	vernum_mod_t *rmod;
	int nrepaired = 0;

	connection_fake_init2( &conn, &opbuf, ctx, 0 );
	op = &opbuf.ob_op;

	op->o_tag = LDAP_REQ_SEARCH;
	memset( &op->oq_search, 0, sizeof( op->oq_search ) );

	assert( !BER_BVISNULL( &be->be_nsuffix[ 0 ] ) );

	op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 );
	assert( op->o_bd != NULL );
	assert( op->o_bd->be_nsuffix != NULL );

	op->o_req_dn = op->o_bd->be_suffix[ 0 ];
	op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];

	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;

	op->ors_scope = LDAP_SCOPE_SUBTREE;
	op->ors_tlimit = SLAP_NO_LIMIT;
	op->ors_slimit = SLAP_NO_LIMIT;
	op->ors_attrs = slap_anlist_no_attrs;

	op->ors_filterstr.bv_len = STRLENOF( "(&(=*)(!(=*)))" )
		+ vn->vn_attr->ad_cname.bv_len
		+ vn->vn_vernum->ad_cname.bv_len;
	op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
	snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1,
		"(&(%s=*)(!(%s=*)))",
		vn->vn_attr->ad_cname.bv_val,
		vn->vn_vernum->ad_cname.bv_val );

	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
	if ( op->ors_filter == NULL ) {
		rs.sr_err = LDAP_OTHER;
		goto done_search;
	}
	
	op->o_callback = ≻
	sc.sc_response = vernum_repair_cb;
	sc.sc_private = &rcb;
	rcb.bd = &db;
	db = *be;
	db.bd_info = (BackendInfo *)on;

	(void)op->o_bd->bd_info->bi_op_search( op, &rs );

	op->o_tag = LDAP_REQ_MODIFY;
	sc.sc_response = slap_null_cb;
	sc.sc_private = NULL;
	memset( &op->oq_modify, 0, sizeof( req_modify_s ) );

	for ( rmod = rcb.mods; rmod != NULL; ) {
		vernum_mod_t *rnext;
		Modifications mod;
		struct berval vals[2] = { BER_BVNULL };
		SlapReply rs2 = { REP_RESULT };

		mod.sml_flags = SLAP_MOD_INTERNAL;
		mod.sml_op = LDAP_MOD_REPLACE;
		mod.sml_desc = vn->vn_vernum;
		mod.sml_type = vn->vn_vernum->ad_cname;
		mod.sml_values = vals;
		mod.sml_values[0] = val_init;
		mod.sml_nvalues = NULL;
		mod.sml_numvals = 1;
		mod.sml_next = NULL;

		op->o_req_dn = rmod->ndn;
		op->o_req_ndn = rmod->ndn;

		op->orm_modlist = &mod;

		op->o_bd->be_modify( op, &rs2 );

		slap_mods_free( op->orm_modlist->sml_next, 1 );
		if ( rs2.sr_err == LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "%s: vernum_repair: entry DN=\"%s\" repaired\n",
				op->o_log_prefix, rmod->ndn.bv_val, 0 );
			nrepaired++;

		} else {
			Debug( LDAP_DEBUG_ANY, "%s: vernum_repair: entry DN=\"%s\" repair failed (%d)\n",
				op->o_log_prefix, rmod->ndn.bv_val, rs2.sr_err );
		}

		rnext = rmod->next;
		op->o_tmpfree( rmod, op->o_tmpmemctx );
		rmod = rnext;
	}

done_search:;
	op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	filter_free_x( op, op->ors_filter, 1 );

	Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
		"vernum: repaired=%d\n", nrepaired );

	return 0;
}
Esempio n. 6
0
static int
dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
{
	Attribute	*a, *id = NULL;
	slap_callback	cb = { 0 };
	Operation	o = *op;
	struct berval	*url;
	Entry		*e;
	int		opattrs,
			userattrs;
	dynlist_sc_t	dlc = { 0 };
	dynlist_map_t	*dlm;

	a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad );
	if ( a == NULL ) {
		/* FIXME: error? */
		return SLAP_CB_CONTINUE;
	}

	opattrs = SLAP_OPATTRS( rs->sr_attr_flags );
	userattrs = SLAP_USERATTRS( rs->sr_attr_flags );

	/* Don't generate member list if it wasn't requested */
	for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
		AttributeDescription *ad = dlm->dlm_mapped_ad ? dlm->dlm_mapped_ad : dlm->dlm_member_ad;
		if ( userattrs || ad_inlist( ad, rs->sr_attrs ) ) 
			break;
	}
	if ( dli->dli_dlm && !dlm )
		return SLAP_CB_CONTINUE;

	if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) {
		Attribute *authz = NULL;

		/* if not rootdn and dgAuthz is present,
		 * check if user can be authorized as dgIdentity */
		if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op )
			&& ( authz = attrs_find( rs->sr_entry->e_attrs, ad_dgAuthz ) ) )
		{
			if ( slap_sasl_matches( op, authz->a_nvals,
				&o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS )
			{
				return SLAP_CB_CONTINUE;
			}
		}

		o.o_dn = id->a_vals[0];
		o.o_ndn = id->a_nvals[0];
		o.o_groups = NULL;
	}

	e = rs->sr_entry;
	/* ensure e is modifiable, but do not replace
	 * sr_entry yet since we have pointers into it */
	if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
		e = entry_dup( rs->sr_entry );
	}

	dlc.dlc_e = e;
	dlc.dlc_dli = dli;
	cb.sc_private = &dlc;
	cb.sc_response = dynlist_sc_update;

	o.o_callback = &cb;
	o.ors_deref = LDAP_DEREF_NEVER;
	o.ors_limit = NULL;
	o.ors_tlimit = SLAP_NO_LIMIT;
	o.ors_slimit = SLAP_NO_LIMIT;

	for ( url = a->a_nvals; !BER_BVISNULL( url ); url++ ) {
		LDAPURLDesc	*lud = NULL;
		int		i, j;
		struct berval	dn;
		int		rc;

		BER_BVZERO( &o.o_req_dn );
		BER_BVZERO( &o.o_req_ndn );
		o.ors_filter = NULL;
		o.ors_attrs = NULL;
		BER_BVZERO( &o.ors_filterstr );

		if ( ldap_url_parse( url->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
			/* FIXME: error? */
			continue;
		}

		if ( lud->lud_host != NULL ) {
			/* FIXME: host not allowed; reject as illegal? */
			Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): "
				"illegal URI \"%s\"\n",
				e->e_name.bv_val, url->bv_val, 0 );
			goto cleanup;
		}

		if ( lud->lud_dn == NULL ) {
			/* note that an empty base is not honored in terms
			 * of defaultSearchBase, because select_backend()
			 * is not aware of the defaultSearchBase option;
			 * this can be useful in case of a database serving
			 * the empty suffix */
			BER_BVSTR( &dn, "" );

		} else {
			ber_str2bv( lud->lud_dn, 0, 0, &dn );
		}
		rc = dnPrettyNormal( NULL, &dn, &o.o_req_dn, &o.o_req_ndn, op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			/* FIXME: error? */
			goto cleanup;
		}
		o.ors_scope = lud->lud_scope;

		for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
			if ( dlm->dlm_mapped_ad != NULL ) {
				break;
			}
		}

		if ( dli->dli_dlm && !dlm ) {
			/* if ( lud->lud_attrs != NULL ),
			 * the URL should be ignored */
			o.ors_attrs = slap_anlist_no_attrs;

		} else if ( lud->lud_attrs == NULL ) {
			o.ors_attrs = rs->sr_attrs;

		} else {
			for ( i = 0; lud->lud_attrs[i]; i++)
				/* just count */ ;

			o.ors_attrs = op->o_tmpcalloc( i + 1, sizeof( AttributeName ), op->o_tmpmemctx );
			for ( i = 0, j = 0; lud->lud_attrs[i]; i++) {
				const char	*text = NULL;
	
				ber_str2bv( lud->lud_attrs[i], 0, 0, &o.ors_attrs[j].an_name );
				o.ors_attrs[j].an_desc = NULL;
				(void)slap_bv2ad( &o.ors_attrs[j].an_name, &o.ors_attrs[j].an_desc, &text );
				/* FIXME: ignore errors... */

				if ( rs->sr_attrs == NULL ) {
					if ( o.ors_attrs[j].an_desc != NULL &&
							is_at_operational( o.ors_attrs[j].an_desc->ad_type ) )
					{
						continue;
					}

				} else {
					if ( o.ors_attrs[j].an_desc != NULL &&
							is_at_operational( o.ors_attrs[j].an_desc->ad_type ) )
					{
						if ( !opattrs ) {
							continue;
						}

						if ( !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) {
							/* lookup if mapped -- linear search,
							 * not very efficient unless list
							 * is very short */
							for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
								if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) {
									break;
								}
							}

							if ( dlm == NULL ) {
								continue;
							}
						}

					} else {
						if ( !userattrs && 
								o.ors_attrs[j].an_desc != NULL &&
								!ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) )
						{
							/* lookup if mapped -- linear search,
							 * not very efficient unless list
							 * is very short */
							for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
								if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) {
									break;
								}
							}

							if ( dlm == NULL ) {
								continue;
							}
						}
					}
				}

				j++;
			}

			if ( j == 0 ) {
				goto cleanup;
			}
		
			BER_BVZERO( &o.ors_attrs[j].an_name );
		}

		if ( lud->lud_filter == NULL ) {
			ber_dupbv_x( &o.ors_filterstr,
					&dli->dli_default_filter, op->o_tmpmemctx );

		} else {
			struct berval	flt;
			ber_str2bv( lud->lud_filter, 0, 0, &flt );
			if ( dynlist_make_filter( op, rs->sr_entry, url->bv_val, &flt, &o.ors_filterstr ) ) {
				/* error */
				goto cleanup;
			}
		}
		o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val );
		if ( o.ors_filter == NULL ) {
			goto cleanup;
		}
		
		o.o_bd = select_backend( &o.o_req_ndn, 1 );
		if ( o.o_bd && o.o_bd->be_search ) {
			SlapReply	r = { REP_SEARCH };
			r.sr_attr_flags = slap_attr_flags( o.ors_attrs );
			(void)o.o_bd->be_search( &o, &r );
		}

cleanup:;
		if ( id ) {
			slap_op_groups_free( &o );
		}
		if ( o.ors_filter ) {
			filter_free_x( &o, o.ors_filter, 1 );
		}
		if ( o.ors_attrs && o.ors_attrs != rs->sr_attrs
				&& o.ors_attrs != slap_anlist_no_attrs )
		{
			op->o_tmpfree( o.ors_attrs, op->o_tmpmemctx );
		}
		if ( !BER_BVISNULL( &o.o_req_dn ) ) {
			op->o_tmpfree( o.o_req_dn.bv_val, op->o_tmpmemctx );
		}
		if ( !BER_BVISNULL( &o.o_req_ndn ) ) {
			op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx );
		}
		assert( BER_BVISNULL( &o.ors_filterstr )
			|| o.ors_filterstr.bv_val != lud->lud_filter );
		op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
		ldap_free_urldesc( lud );
	}

	if ( e != rs->sr_entry ) {
		rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
		rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
	}

	return SLAP_CB_CONTINUE;
}
Esempio n. 7
0
static int
constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply *rs)
{
	if ((!c) || (!bv)) return LDAP_SUCCESS;
	
	if ((c->re) &&
		(regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
		return LDAP_CONSTRAINT_VIOLATION; /* regular expression violation */

	if ((c->size) && (bv->bv_len > c->size))
		return LDAP_CONSTRAINT_VIOLATION; /* size violation */

	if (c->lud) {
		Operation nop = *op;
		slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
		slap_callback cb;
		SlapReply nrs = { REP_RESULT };
		int i;
		int found;
		int rc;
		size_t len;
		struct berval filterstr;
		char *ptr;

		found = 0;

		nrs.sr_entry = NULL;
		nrs.sr_nentries = 0;

		cb.sc_next = NULL;
		cb.sc_response = constraint_uri_cb;
		cb.sc_cleanup = NULL;
		cb.sc_private = &found;

		nop.o_protocol = LDAP_VERSION3;
		nop.o_tag = LDAP_REQ_SEARCH;
		nop.o_time = slap_get_time();
		if (c->lud->lud_dn) {
			struct berval dn;

			ber_str2bv(c->lud->lud_dn, 0, 0, &dn);
			nop.o_req_dn = dn;
			nop.o_req_ndn = dn;
			nop.o_bd = select_backend(&nop.o_req_ndn, 1 );
			if (!nop.o_bd) {
				return LDAP_NO_SUCH_OBJECT; /* unexpected error */
			}
			if (!nop.o_bd->be_search) {
				return LDAP_OTHER; /* unexpected error */
			}
		} else {
			nop.o_req_dn = nop.o_bd->be_nsuffix[0];
			nop.o_req_ndn = nop.o_bd->be_nsuffix[0];
			nop.o_bd = on->on_info->oi_origdb;
		}
		nop.o_do_not_cache = 1;
		nop.o_callback = &cb;

		nop.ors_scope = c->lud->lud_scope;
		nop.ors_deref = LDAP_DEREF_NEVER;
		nop.ors_slimit = SLAP_NO_LIMIT;
		nop.ors_tlimit = SLAP_NO_LIMIT;
		nop.ors_limit = NULL;

		nop.ors_attrsonly = 0;
		nop.ors_attrs = slap_anlist_no_attrs;

		len = STRLENOF("(&(") + 
			  c->filter.bv_len +
			  STRLENOF(")(|");

		for (i = 0; c->attrs[i]; i++) {
			len += STRLENOF("(") +
				   c->attrs[i]->ad_cname.bv_len +
				   STRLENOF("=") + 
				   bv->bv_len +
				   STRLENOF(")");
		}

		len += STRLENOF("))");
		filterstr.bv_len = len;
		filterstr.bv_val = op->o_tmpalloc(len + 1, op->o_tmpmemctx);

		ptr = filterstr.bv_val +
			snprintf(filterstr.bv_val, len, "(&(%s)(|", c->lud->lud_filter);
		for (i = 0; c->attrs[i]; i++) {
			*ptr++ = '(';
			ptr = lutil_strcopy( ptr, c->attrs[i]->ad_cname.bv_val );
			*ptr++ = '=';
			ptr = lutil_strcopy( ptr, bv->bv_val );
			*ptr++ = ')';
		}
		*ptr++ = ')';
		*ptr++ = ')';
		*ptr++ = '\0';

		nop.ors_filterstr = filterstr;
		nop.ors_filter = str2filter_x(&nop, filterstr.bv_val);
		if ( nop.ors_filter == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"%s constraint_violation uri filter=\"%s\" invalid\n",
				op->o_log_prefix, filterstr.bv_val, 0 );
			rc = LDAP_OTHER;

		} else {
			Debug(LDAP_DEBUG_TRACE, 
				"==> constraint_violation uri filter = %s\n",
				filterstr.bv_val, 0, 0);

			rc = nop.o_bd->be_search( &nop, &nrs );
		
			Debug(LDAP_DEBUG_TRACE, 
				"==> constraint_violation uri rc = %d, found = %d\n",
				rc, found, 0);
		}
		op->o_tmpfree(filterstr.bv_val, op->o_tmpmemctx);

		if ((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) {
			return rc; /* unexpected error */
		}

		if (!found)
			return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */
			
	}

	return LDAP_SUCCESS;
}
Esempio n. 8
0
static int
pguid_repair( BackendDB *be )
{
	slap_overinst *on = (slap_overinst *)be->bd_info;
	void *ctx = ldap_pvt_thread_pool_context();
	Connection conn = { 0 };
	OperationBuffer opbuf;
	Operation *op;
	slap_callback sc = { 0 };
	pguid_repair_cb_t pcb = { 0 };
	SlapReply rs = { REP_RESULT };
	pguid_mod_t *pmod;
	int nrepaired = 0;

	connection_fake_init2( &conn, &opbuf, ctx, 0 );
	op = &opbuf.ob_op;

	op->o_tag = LDAP_REQ_SEARCH;
	memset( &op->oq_search, 0, sizeof( op->oq_search ) );

	op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 );

	op->o_req_dn = op->o_bd->be_suffix[ 0 ];
	op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];

	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;

	op->ors_scope = LDAP_SCOPE_SUBORDINATE;
	op->ors_tlimit = SLAP_NO_LIMIT;
	op->ors_slimit = SLAP_NO_LIMIT;
	op->ors_attrs = slap_anlist_no_attrs;

	op->ors_filterstr.bv_len = STRLENOF( "(!(=*))" ) + ad_parentUUID->ad_cname.bv_len;
	op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
	snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1,
		"(!(%s=*))", ad_parentUUID->ad_cname.bv_val );

	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
	if ( op->ors_filter == NULL ) {
		rs.sr_err = LDAP_OTHER;
		goto done_search;
	}
	
	op->o_callback = ≻
	sc.sc_response = pguid_repair_cb;
	sc.sc_private = &pcb;
	pcb.on = on;

	(void)op->o_bd->bd_info->bi_op_search( op, &rs );

	op->o_tag = LDAP_REQ_MODIFY;
	sc.sc_response = slap_null_cb;
	sc.sc_private = NULL;
	memset( &op->oq_modify, 0, sizeof( req_modify_s ) );

	for ( pmod = pcb.mods; pmod != NULL; ) {
		pguid_mod_t *pnext;

		Modifications *mod;
		SlapReply rs2 = { REP_RESULT };

		mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
		mod->sml_flags = SLAP_MOD_INTERNAL;
		mod->sml_op = LDAP_MOD_REPLACE;
		mod->sml_desc = ad_parentUUID;
		mod->sml_type = ad_parentUUID->ad_cname;
		mod->sml_values = ch_malloc( sizeof( struct berval ) * 2 );
		mod->sml_nvalues = NULL;
		mod->sml_numvals = 1;
		mod->sml_next = NULL;

		ber_dupbv( &mod->sml_values[0], &pmod->pguid );
		BER_BVZERO( &mod->sml_values[1] );

		op->o_req_dn = pmod->ndn;
		op->o_req_ndn = pmod->ndn;

		op->orm_modlist = mod;
		op->o_bd->be_modify( op, &rs2 );
		slap_mods_free( op->orm_modlist, 1 );
		if ( rs2.sr_err == LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "%s: pguid_repair: entry DN=\"%s\" repaired\n",
				op->o_log_prefix, pmod->ndn.bv_val, 0 );
			nrepaired++;

		} else {
			Debug( LDAP_DEBUG_ANY, "%s: pguid_repair: entry DN=\"%s\" repair failed (%d)\n",
				op->o_log_prefix, pmod->ndn.bv_val, rs2.sr_err );
		}

		pnext = pmod->next;
		op->o_tmpfree( pmod, op->o_tmpmemctx );
		pmod = pnext;
	}

done_search:;
	op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	filter_free_x( op, op->ors_filter, 1 );

	Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
		"pguid: repaired=%d\n", nrepaired );

	return rs.sr_err;
}
Esempio n. 9
0
int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
{
	struct berval dn, uid, svc, ruser, rhost, tty;
	struct berval authzmsg = BER_BVNULL;
	int32_t tmpint32;
	char dnc[1024];
	char uidc[32];
	char svcc[256];
	char ruserc[32];
	char rhostc[256];
	char ttyc[256];
	int rc;
	Entry *e = NULL;
	Attribute *a;
	slap_callback cb = {0};

	READ_STRING(fp,uidc);
	uid.bv_val = uidc;
	uid.bv_len = tmpint32;
	READ_STRING(fp,dnc);
	dn.bv_val = dnc;
	dn.bv_len = tmpint32;
	READ_STRING(fp,svcc);
	svc.bv_val = svcc;
	svc.bv_len = tmpint32;
	READ_STRING(fp,ruserc);
	ruser.bv_val = ruserc;
	ruser.bv_len = tmpint32;
	READ_STRING(fp,rhostc);
	rhost.bv_val = rhostc;
	rhost.bv_len = tmpint32;
	READ_STRING(fp,ttyc);
	tty.bv_val = ttyc;
	tty.bv_len = tmpint32;

	Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0);

	/* If we didn't do authc, we don't have a DN yet */
	if (BER_BVISEMPTY(&dn)) {
		struct paminfo pi;
		pi.uid = uid;
		pi.svc = svc;

		rc = pam_uid2dn(ni, op, &pi);
		if (rc) goto finish;
		dn = pi.dn;
	}

	/* See if they have access to the host and service */
	if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) {
		AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
		struct berval hostdn = BER_BVNULL;
		struct berval odn = op->o_ndn;
		SlapReply rs = {REP_RESULT};
		op->o_dn = dn;
		op->o_ndn = dn;
		{
			nssov_mapinfo *mi = &ni->ni_maps[NM_host];
			char fbuf[1024];
			struct berval filter = {sizeof(fbuf),fbuf};
			SlapReply rs2 = {REP_RESULT};

			/* Lookup the host entry */
			nssov_filter_byname(mi,0,&global_host_bv,&filter);
			cb.sc_private = &hostdn;
			cb.sc_response = nssov_name2dn_cb;
			op->o_callback = &cb;
			op->o_req_dn = mi->mi_base;
			op->o_req_ndn = mi->mi_base;
			op->ors_scope = mi->mi_scope;
			op->ors_filterstr = filter;
			op->ors_filter = str2filter_x(op, filter.bv_val);
			op->ors_attrs = slap_anlist_no_attrs;
			op->ors_tlimit = SLAP_NO_LIMIT;
			op->ors_slimit = 2;
			rc = op->o_bd->be_search(op, &rs2);
			filter_free_x(op, op->ors_filter, 1);

			if (BER_BVISEMPTY(&hostdn) &&
				!BER_BVISEMPTY(&ni->ni_pam_defhost)) {
				filter.bv_len = sizeof(fbuf);
				filter.bv_val = fbuf;
				rs_reinit(&rs2, REP_RESULT);
				nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter);
				op->ors_filterstr = filter;
				op->ors_filter = str2filter_x(op, filter.bv_val);
				rc = op->o_bd->be_search(op, &rs2);
				filter_free_x(op, op->ors_filter, 1);
			}

			/* no host entry, no default host -> deny */
			if (BER_BVISEMPTY(&hostdn)) {
				rc = NSLCD_PAM_PERM_DENIED;
				authzmsg = hostmsg;
				goto finish;
			}
		}

		cb.sc_response = pam_compare_cb;
		cb.sc_private = NULL;
		op->o_tag = LDAP_REQ_COMPARE;
		op->o_req_dn = hostdn;
		op->o_req_ndn = hostdn;
		ava.aa_desc = nssov_pam_svc_ad;
		ava.aa_value = svc;
		op->orc_ava = &ava;
		rc = op->o_bd->be_compare( op, &rs );
		if ( cb.sc_private == NULL ) {
			authzmsg = svcmsg;
			rc = NSLCD_PAM_PERM_DENIED;
			goto finish;
		}
		op->o_dn = odn;
		op->o_ndn = odn;
	}

	/* See if they're a member of the group */
	if ((ni->ni_pam_opts & NI_PAM_USERGRP) &&
		!BER_BVISEMPTY(&ni->ni_pam_group_dn) &&
		ni->ni_pam_group_ad) {
		AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
		SlapReply rs = {REP_RESULT};
		op->o_callback = &cb;
		cb.sc_response = slap_null_cb;
		op->o_tag = LDAP_REQ_COMPARE;
		op->o_req_dn = ni->ni_pam_group_dn;
		op->o_req_ndn = ni->ni_pam_group_dn;
		ava.aa_desc = ni->ni_pam_group_ad;
		ava.aa_value = dn;
		op->orc_ava = &ava;
		rc = op->o_bd->be_compare( op, &rs );
		if ( rs.sr_err != LDAP_COMPARE_TRUE ) {
			authzmsg = grpmsg;
			rc = NSLCD_PAM_PERM_DENIED;
			goto finish;
		}
	}

	/* We need to check the user's entry for these bits */
	if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) ||
		ni->ni_pam_template_ad ||
		ni->ni_pam_min_uid || ni->ni_pam_max_uid ) {
		rc = be_entry_get_rw( op, &dn, NULL, NULL, 0, &e );
		if (rc != LDAP_SUCCESS) {
			rc = NSLCD_PAM_USER_UNKNOWN;
			goto finish;
		}
	}
	if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) {
		a = attr_find(e->e_attrs, nssov_pam_host_ad);
		if (!a || attr_valfind( a,
			SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
			SLAP_MR_VALUE_OF_SYNTAX,
			&global_host_bv, NULL, op->o_tmpmemctx )) {
			rc = NSLCD_PAM_PERM_DENIED;
			authzmsg = hostmsg;
			goto finish;
		}
	}
	if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) {
		a = attr_find(e->e_attrs, nssov_pam_svc_ad);
		if (!a || attr_valfind( a,
			SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
			SLAP_MR_VALUE_OF_SYNTAX,
			&svc, NULL, op->o_tmpmemctx )) {
			rc = NSLCD_PAM_PERM_DENIED;
			authzmsg = svcmsg;
			goto finish;
		}
	}

/* from passwd.c */
#define UIDN_KEY	2

	if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) {
		int id;
		char *tmp;
		nssov_mapinfo *mi = &ni->ni_maps[NM_passwd];
		a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc);
		if (!a) {
			rc = NSLCD_PAM_PERM_DENIED;
			authzmsg = uidmsg;
			goto finish;
		}
		id = (int)strtol(a->a_vals[0].bv_val,&tmp,0);
		if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') {
			rc = NSLCD_PAM_PERM_DENIED;
			authzmsg = uidmsg;
			goto finish;
		}
		if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) ||
			(ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) {
			rc = NSLCD_PAM_PERM_DENIED;
			authzmsg = uidmsg;
			goto finish;
		}
	}

	if (ni->ni_pam_template_ad) {
		a = attr_find(e->e_attrs, ni->ni_pam_template_ad);
		if (a)
			uid = a->a_vals[0];
		else if (!BER_BVISEMPTY(&ni->ni_pam_template))
			uid = ni->ni_pam_template;
	}
	rc = NSLCD_PAM_SUCCESS;

finish:
	WRITE_INT32(fp,NSLCD_VERSION);
	WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
	WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
	WRITE_BERVAL(fp,&uid);
	WRITE_BERVAL(fp,&dn);
	WRITE_INT32(fp,rc);
	WRITE_BERVAL(fp,&authzmsg);
	if (e) {
		be_entry_release_r(op, e);
	}
	return 0;
}
Esempio n. 10
0
static int
rdnval_unique_check( Operation *op, BerVarray vals )
{
	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;

	BackendDB db = *op->o_bd;
	Operation op2 = *op;
	SlapReply rs2 = { 0 };
	int i;
	BerVarray fvals;
	char *ptr;
	int gotit = 0;
	slap_callback cb = { 0 };

	/* short-circuit attempts to add suffix entry */
	if ( op->o_tag == LDAP_REQ_ADD
		&& be_issuffix( op->o_bd, &op->o_req_ndn ) )
	{
		return LDAP_SUCCESS;
	}

	op2.o_bd = &db;
	op2.o_bd->bd_info = (BackendInfo *)on->on_info;
	op2.o_tag = LDAP_REQ_SEARCH;
	op2.o_dn = op->o_bd->be_rootdn;
	op2.o_ndn = op->o_bd->be_rootndn;
	op2.o_callback = &cb;
	cb.sc_response = rdnval_unique_check_cb;
	cb.sc_private = (void *)&gotit;

	dnParent( &op->o_req_ndn, &op2.o_req_dn );
	op2.o_req_ndn = op2.o_req_dn;

	op2.ors_limit = NULL;
	op2.ors_slimit = 1;
	op2.ors_tlimit = SLAP_NO_LIMIT;
	op2.ors_attrs = slap_anlist_no_attrs;
	op2.ors_attrsonly = 1;
	op2.ors_deref = LDAP_DEREF_NEVER;
	op2.ors_scope = LDAP_SCOPE_ONELEVEL;

	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ )
		/* just count */ ;

	fvals = op->o_tmpcalloc( sizeof( struct berval ), i + 1,
		op->o_tmpmemctx );

	op2.ors_filterstr.bv_len = 0;
	if ( i > 1 ) {
		op2.ors_filterstr.bv_len = STRLENOF( "(&)" );
	}

	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
		ldap_bv2escaped_filter_value_x( &vals[ i ], &fvals[ i ],
			1, op->o_tmpmemctx );
		op2.ors_filterstr.bv_len += ad_rdnValue->ad_cname.bv_len
			+ fvals[ i ].bv_len + STRLENOF( "(=)" );
	}

	op2.ors_filterstr.bv_val = op->o_tmpalloc( op2.ors_filterstr.bv_len + 1, op->o_tmpmemctx );

	ptr = op2.ors_filterstr.bv_val;
	if ( i > 1 ) {
		ptr = lutil_strcopy( ptr, "(&" );
	}
	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
		*ptr++ = '(';
		ptr = lutil_strncopy( ptr, ad_rdnValue->ad_cname.bv_val, ad_rdnValue->ad_cname.bv_len );
		*ptr++ = '=';
		ptr = lutil_strncopy( ptr, fvals[ i ].bv_val, fvals[ i ].bv_len );
		*ptr++ = ')';
	}

	if ( i > 1 ) {
		*ptr++ = ')';
	}
	*ptr = '\0';

	assert( ptr == op2.ors_filterstr.bv_val + op2.ors_filterstr.bv_len );
	op2.ors_filter = str2filter_x( op, op2.ors_filterstr.bv_val );
	assert( op2.ors_filter != NULL );

	(void)op2.o_bd->be_search( &op2, &rs2 );

	filter_free_x( op, op2.ors_filter, 1 );
	op->o_tmpfree( op2.ors_filterstr.bv_val, op->o_tmpmemctx );
	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
		if ( vals[ i ].bv_val != fvals[ i ].bv_val ) {
			op->o_tmpfree( fvals[ i ].bv_val, op->o_tmpmemctx );
		}
	}
	op->o_tmpfree( fvals, op->o_tmpmemctx );

	if ( rs2.sr_err != LDAP_SUCCESS || gotit > 0 ) {
		return LDAP_CONSTRAINT_VIOLATION;
	}

	return LDAP_SUCCESS;
}
Esempio n. 11
0
/* count dynamic objects existing in the database at startup */
static int
dds_count( void *ctx, BackendDB *be )
{
	slap_overinst	*on = (slap_overinst *)be->bd_info;
	dds_info_t	*di = (dds_info_t *)on->on_bi.bi_private;

	Connection	conn = { 0 };
	OperationBuffer opbuf;
	Operation	*op;
	slap_callback	sc = { 0 };
	SlapReply	rs = { REP_RESULT };

	int		rc;
	char		*extra = "";

	connection_fake_init2( &conn, &opbuf, ctx, 0 );
	op = &opbuf.ob_op;

	op->o_tag = LDAP_REQ_SEARCH;
	memset( &op->oq_search, 0, sizeof( op->oq_search ) );

	op->o_bd = be;

	op->o_req_dn = op->o_bd->be_suffix[ 0 ];
	op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];

	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;

	op->ors_scope = LDAP_SCOPE_SUBTREE;
	op->ors_tlimit = SLAP_NO_LIMIT;
	op->ors_slimit = SLAP_NO_LIMIT;
	op->ors_attrs = slap_anlist_no_attrs;

	op->ors_filterstr.bv_len = STRLENOF( "(objectClass=" ")" )
		+ slap_schema.si_oc_dynamicObject->soc_cname.bv_len;
	op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
	snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1,
		"(objectClass=%s)",
		slap_schema.si_oc_dynamicObject->soc_cname.bv_val );

	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
	if ( op->ors_filter == NULL ) {
		rs.sr_err = LDAP_OTHER;
		goto done_search;
	}

	op->o_callback = &sc;
	sc.sc_response = dds_count_cb;
	sc.sc_private = &di->di_num_dynamicObjects;
	di->di_num_dynamicObjects = 0;

	op->o_bd->bd_info = (BackendInfo *)on->on_info;
	(void)op->o_bd->bd_info->bi_op_search( op, &rs );
	op->o_bd->bd_info = (BackendInfo *)on;

done_search:;
	op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	filter_free_x( op, op->ors_filter, 1 );

	rc = rs.sr_err;
	switch ( rs.sr_err ) {
	case LDAP_SUCCESS:
		Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
			"DDS non-expired=%d\n",
			di->di_num_dynamicObjects );
		break;

	case LDAP_NO_SUCH_OBJECT:
		/* (ITS#5267) database not created yet? */
		rs.sr_err = LDAP_SUCCESS;
		extra = " (ignored)";
		/* fallthru */

	default:
		Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
			"DDS non-expired objects lookup failed err=%d%s\n",
			rc, extra );
		break;
	}

	return rs.sr_err;
}
Esempio n. 12
0
static int
dds_expire( void *ctx, dds_info_t *di )
{
	Connection	conn = { 0 };
	OperationBuffer opbuf;
	Operation	*op;
	slap_callback	sc = { 0 };
	dds_cb_t	dc = { 0 };
	dds_expire_t	*de = NULL, **dep;
	SlapReply	rs = { REP_RESULT };

	time_t		expire;
	char		tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	struct berval	ts;

	int		ndeletes, ntotdeletes;

	int		rc;
	char		*extra = "";

	connection_fake_init2( &conn, &opbuf, ctx, 0 );
	op = &opbuf.ob_op;

	op->o_tag = LDAP_REQ_SEARCH;
	memset( &op->oq_search, 0, sizeof( op->oq_search ) );

	op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0 );

	op->o_req_dn = op->o_bd->be_suffix[ 0 ];
	op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];

	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;

	op->ors_scope = LDAP_SCOPE_SUBTREE;
	op->ors_tlimit = DDS_INTERVAL( di )/2 + 1;
	op->ors_slimit = SLAP_NO_LIMIT;
	op->ors_attrs = slap_anlist_no_attrs;

	expire = slap_get_time() - di->di_tolerance;
	ts.bv_val = tsbuf;
	ts.bv_len = sizeof( tsbuf );
	slap_timestamp( &expire, &ts );

	op->ors_filterstr.bv_len = STRLENOF( "(&(objectClass=" ")(" "<=" "))" )
		+ slap_schema.si_oc_dynamicObject->soc_cname.bv_len
		+ ad_entryExpireTimestamp->ad_cname.bv_len
		+ ts.bv_len;
	op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
	snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1,
		"(&(objectClass=%s)(%s<=%s))",
		slap_schema.si_oc_dynamicObject->soc_cname.bv_val,
		ad_entryExpireTimestamp->ad_cname.bv_val, ts.bv_val );

	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
	if ( op->ors_filter == NULL ) {
		rs.sr_err = LDAP_OTHER;
		goto done_search;
	}

	op->o_callback = &sc;
	sc.sc_response = dds_expire_cb;
	sc.sc_private = &dc;

	(void)op->o_bd->bd_info->bi_op_search( op, &rs );

done_search:;
	op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	filter_free_x( op, op->ors_filter, 1 );

	rc = rs.sr_err;
	switch ( rs.sr_err ) {
	case LDAP_SUCCESS:
		break;

	case LDAP_NO_SUCH_OBJECT:
		/* (ITS#5267) database not created yet? */
		rs.sr_err = LDAP_SUCCESS;
		extra = " (ignored)";
		/* fallthru */

	default:
		Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
			"DDS expired objects lookup failed err=%d%s\n",
			rc, extra );
		goto done;
	}

	op->o_tag = LDAP_REQ_DELETE;
	op->o_callback = &sc;
	sc.sc_response = slap_null_cb;
	sc.sc_private = NULL;

	slap_biglock_acquire(op->o_bd);
	for ( ntotdeletes = 0, ndeletes = 1; dc.dc_ndnlist != NULL  && ndeletes > 0; ) {
		ndeletes = 0;

		for ( dep = &dc.dc_ndnlist; *dep != NULL; ) {
			de = *dep;

			op->o_req_dn = de->de_ndn;
			op->o_req_ndn = de->de_ndn;
			(void)op->o_bd->bd_info->bi_op_delete( op, &rs );
			switch ( rs.sr_err ) {
			case LDAP_SUCCESS:
				Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
					"DDS dn=\"%s\" expired.\n",
					de->de_ndn.bv_val );
				ndeletes++;
				break;

			case LDAP_NOT_ALLOWED_ON_NONLEAF:
				Log1( LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
					"DDS dn=\"%s\" is non-leaf; "
					"deferring.\n",
					de->de_ndn.bv_val );
				dep = &de->de_next;
				de = NULL;
				break;

			default:
				Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
					"DDS dn=\"%s\" err=%d; "
					"deferring.\n",
					de->de_ndn.bv_val, rs.sr_err );
				break;
			}

			if ( de != NULL ) {
				*dep = de->de_next;
				op->o_tmpfree( de, op->o_tmpmemctx );
			}
		}

		ntotdeletes += ndeletes;
	}
	slap_biglock_release(op->o_bd);

	rs.sr_err = LDAP_SUCCESS;

	Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
		"DDS expired=%d\n", ntotdeletes );

done:;
	return rs.sr_err;
}