Beispiel #1
0
/*
  delete a record
*/
static int lldb_delete(struct lldb_context *lldb_ac)
{
	struct ldb_context *ldb;
	struct lldb_private *lldb = lldb_ac->lldb;
	struct ldb_module *module = lldb_ac->module;
	struct ldb_request *req = lldb_ac->req;
	char *dnstr;
	int ret;

	ldb = ldb_module_get_ctx(module);

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	dnstr = ldb_dn_alloc_linearized(lldb_ac, req->op.del.dn);

	ret = ldap_delete_ext(lldb->ldap, dnstr,
			      NULL,
			      NULL,
			      &lldb_ac->msgid);

	if (ret != LDAP_SUCCESS) {
		ldb_set_errstring(ldb, ldap_err2string(ret));
	}

	return lldb_ldap_to_ldb(ret);
}
Beispiel #2
0
/*
  modify a record
*/
static int lldb_modify(struct lldb_context *lldb_ac)
{
	struct ldb_context *ldb;
	struct lldb_private *lldb = lldb_ac->lldb;
	struct ldb_module *module = lldb_ac->module;
	struct ldb_request *req = lldb_ac->req;
	LDAPMod **mods;
	char *dn;
	int ret;

	ldb = ldb_module_get_ctx(module);

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	mods = lldb_msg_to_mods(lldb_ac, req->op.mod.message, 1);
	if (mods == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	dn = ldb_dn_alloc_linearized(lldb_ac, req->op.mod.message->dn);
	if (dn == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ldap_modify_ext(lldb->ldap, dn, mods,
			      NULL,
			      NULL,
			      &lldb_ac->msgid);

	if (ret != LDAP_SUCCESS) {
		ldb_set_errstring(ldb, ldap_err2string(ret));
	}

	return lldb_ldap_to_ldb(ret);
}
Beispiel #3
0
/*
  rename a record
*/
static int lldb_rename(struct lldb_context *lldb_ac)
{
	struct ldb_context *ldb;
	struct lldb_private *lldb = lldb_ac->lldb;
	struct ldb_module *module = lldb_ac->module;
	struct ldb_request *req = lldb_ac->req;
	const char *rdn_name;
	const struct ldb_val *rdn_val;
	char *old_dn;
	char *newrdn;
	char *parentdn;
	int ret;

	ldb = ldb_module_get_ctx(module);

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	old_dn = ldb_dn_alloc_linearized(lldb_ac, req->op.rename.olddn);
	if (old_dn == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	rdn_name = ldb_dn_get_rdn_name(req->op.rename.newdn);
	rdn_val = ldb_dn_get_rdn_val(req->op.rename.newdn);

	if ((rdn_name != NULL) && (rdn_val != NULL)) {
		newrdn = talloc_asprintf(lldb_ac, "%s=%s", rdn_name,
					 rdn_val->length > 0 ? ldb_dn_escape_value(lldb, *rdn_val) : "");
	} else {
		newrdn = talloc_strdup(lldb_ac, "");
	}
	if (!newrdn) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	parentdn = ldb_dn_alloc_linearized(lldb_ac, ldb_dn_get_parent(lldb_ac, req->op.rename.newdn));
	if (!parentdn) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
			  1, NULL, NULL,
			  &lldb_ac->msgid);

	if (ret != LDAP_SUCCESS) {
		ldb_set_errstring(ldb, ldap_err2string(ret));
	}

	return lldb_ldap_to_ldb(ret);
}
Beispiel #4
0
/*
  add a record to the database
*/
static int ltdb_add(struct ltdb_context *ctx)
{
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	int tret;

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	tret = ltdb_add_internal(module, req->op.add.message);
	if (tret != LDB_SUCCESS) {
		return tret;
	}

	return LDB_SUCCESS;
}
Beispiel #5
0
/*
  rename a record
*/
static int ltdb_rename(struct ltdb_context *ctx)
{
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	struct ldb_message *msg;
	int ret = LDB_SUCCESS;

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_cache_load(ctx->module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	msg = ldb_msg_new(ctx);
	if (msg == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* in case any attribute of the message was indexed, we need
	   to fetch the old record */
	ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
	if (ret != LDB_SUCCESS) {
		/* not finding the old record is an error */
		return ret;
	}

	/* Always delete first then add, to avoid conflicts with
	 * unique indexes. We rely on the transaction to make this
	 * atomic
	 */
	ret = ltdb_delete_internal(module, msg->dn);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
	if (msg->dn == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* We don't check single value as we can have more than 1 with
	 * deleted attributes. We could go through all elements but that's
	 * maybe not the most efficient way
	 */
	ret = ltdb_add_internal(module, msg, false);

	return ret;
}
Beispiel #6
0
/*
  delete a record from the database
*/
static int ltdb_delete(struct ltdb_context *ctx)
{
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	int ret = LDB_SUCCESS;

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_cache_load(module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ltdb_delete_internal(module, req->op.del.dn);

	return ret;
}
Beispiel #7
0
/*
  rename a record
*/
static int ltdb_rename(struct ltdb_context *ctx)
{
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	struct ldb_message *msg;
	int ret = LDB_SUCCESS;

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_cache_load(ctx->module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	msg = talloc(ctx, struct ldb_message);
	if (msg == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* in case any attribute of the message was indexed, we need
	   to fetch the old record */
	ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
	if (ret != LDB_SUCCESS) {
		/* not finding the old record is an error */
		return ret;
	}

	/* Always delete first then add, to avoid conflicts with
	 * unique indexes. We rely on the transaction to make this
	 * atomic
	 */
	ret = ltdb_delete_internal(module, msg->dn);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
	if (msg->dn == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ltdb_add_internal(module, msg);

	return ret;
}
Beispiel #8
0
/*
  modify a record
*/
static int ltdb_modify(struct ltdb_context *ctx)
{
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	int ret = LDB_SUCCESS;

	ret = ltdb_check_special_dn(module, req->op.mod.message);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_cache_load(module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ltdb_modify_internal(module, req->op.mod.message, req);

	return ret;
}
Beispiel #9
0
/*
  return sequenceNumber from @BASEINFO
*/
static int ltdb_sequence_number(struct ltdb_context *ctx,
				struct ldb_extended **ext)
{
	struct ldb_context *ldb;
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	TALLOC_CTX *tmp_ctx = NULL;
	struct ldb_seqnum_request *seq;
	struct ldb_seqnum_result *res;
	struct ldb_message *msg = NULL;
	struct ldb_dn *dn;
	const char *date;
	int ret = LDB_SUCCESS;

	ldb = ldb_module_get_ctx(module);

	seq = talloc_get_type(req->op.extended.data,
				struct ldb_seqnum_request);
	if (seq == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_lock_read(module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	res = talloc_zero(req, struct ldb_seqnum_result);
	if (res == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	tmp_ctx = talloc_new(req);
	if (tmp_ctx == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	dn = ldb_dn_new(tmp_ctx, ldb, LTDB_BASEINFO);
	if (dn == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	ret = ltdb_search_dn1(module, dn, msg);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

	switch (seq->type) {
	case LDB_SEQ_HIGHEST_SEQ:
		res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
		break;
	case LDB_SEQ_NEXT:
		res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
		res->seq_num++;
		break;
	case LDB_SEQ_HIGHEST_TIMESTAMP:
		date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
		if (date) {
			res->seq_num = ldb_string_to_time(date);
		} else {
			res->seq_num = 0;
			/* zero is as good as anything when we don't know */
		}
		break;
	}

	*ext = talloc_zero(req, struct ldb_extended);
	if (*ext == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}
	(*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
	(*ext)->data = talloc_steal(*ext, res);

done:
	talloc_free(tmp_ctx);
	ltdb_unlock_read(module);
	return ret;
}
Beispiel #10
0
/*
  rename a record
*/
static int ltdb_rename(struct ltdb_context *ctx)
{
	struct ldb_module *module = ctx->module;
	void *data = ldb_module_get_private(module);
	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
	struct ldb_request *req = ctx->req;
	struct ldb_message *msg;
	int ret = LDB_SUCCESS;
	TDB_DATA tdb_key, tdb_key_old;

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_cache_load(ctx->module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	msg = ldb_msg_new(ctx);
	if (msg == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* we need to fetch the old record to re-add under the new name */
	ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
	if (ret != LDB_SUCCESS) {
		/* not finding the old record is an error */
		return ret;
	}

	/* We need to, before changing the DB, check if the new DN
	 * exists, so we can return this error to the caller with an
	 * unmodified DB */
	tdb_key = ltdb_key(module, req->op.rename.newdn);
	if (!tdb_key.dptr) {
		talloc_free(msg);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	tdb_key_old = ltdb_key(module, req->op.rename.olddn);
	if (!tdb_key_old.dptr) {
		talloc_free(msg);
		talloc_free(tdb_key.dptr);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Only declare a conflict if the new DN already exists, and it isn't a case change on the old DN */
	if (tdb_key_old.dsize != tdb_key.dsize || memcmp(tdb_key.dptr, tdb_key_old.dptr, tdb_key.dsize) != 0) {
		if (tdb_exists(ltdb->tdb, tdb_key)) {
			talloc_free(tdb_key_old.dptr);
			talloc_free(tdb_key.dptr);
			ldb_asprintf_errstring(ldb_module_get_ctx(module),
					       "Entry %s already exists",
					       ldb_dn_get_linearized(msg->dn));
			/* finding the new record already in the DB is an error */
			talloc_free(msg);
			return LDB_ERR_ENTRY_ALREADY_EXISTS;
		}
	}
	talloc_free(tdb_key_old.dptr);
	talloc_free(tdb_key.dptr);

	/* Always delete first then add, to avoid conflicts with
	 * unique indexes. We rely on the transaction to make this
	 * atomic
	 */
	ret = ltdb_delete_internal(module, msg->dn);
	if (ret != LDB_SUCCESS) {
		talloc_free(msg);
		return ret;
	}

	msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
	if (msg->dn == NULL) {
		talloc_free(msg);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* We don't check single value as we can have more than 1 with
	 * deleted attributes. We could go through all elements but that's
	 * maybe not the most efficient way
	 */
	ret = ltdb_add_internal(module, msg, false);

	talloc_free(msg);

	return ret;
}
Beispiel #11
0
/*
  search for matching records
*/
static int lldb_search(struct lldb_context *lldb_ac)
{
	struct ldb_context *ldb;
	struct lldb_private *lldb = lldb_ac->lldb;
	struct ldb_module *module = lldb_ac->module;
	struct ldb_request *req = lldb_ac->req;
	struct timeval tv;
	int ldap_scope;
	char *search_base;
	char *expression;
	int ret;

	ldb = ldb_module_get_ctx(module);

	if (!req->callback || !req->context) {
		ldb_set_errstring(ldb, "Async interface called with NULL callback function or NULL context");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (req->op.search.tree == NULL) {
		ldb_set_errstring(ldb, "Invalid expression parse tree");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (req->controls != NULL) {
		ldb_debug(ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!");
	}

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	search_base = ldb_dn_alloc_linearized(lldb_ac, req->op.search.base);
	if (req->op.search.base == NULL) {
		search_base = talloc_strdup(lldb_ac, "");
	}
	if (search_base == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	expression = ldb_filter_from_tree(lldb_ac, req->op.search.tree);
	if (expression == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	switch (req->op.search.scope) {
	case LDB_SCOPE_BASE:
		ldap_scope = LDAP_SCOPE_BASE;
		break;
	case LDB_SCOPE_ONELEVEL:
		ldap_scope = LDAP_SCOPE_ONELEVEL;
		break;
	default:
		ldap_scope = LDAP_SCOPE_SUBTREE;
		break;
	}

	tv.tv_sec = req->timeout;
	tv.tv_usec = 0;

	ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope, 
			      expression, 
			      discard_const_p(char *, req->op.search.attrs),
			      0,
			      NULL,
			      NULL,
			      &tv,
			      LDAP_NO_LIMIT,
			      &lldb_ac->msgid);

	if (ret != LDAP_SUCCESS) {
		ldb_set_errstring(ldb, ldap_err2string(ret));
	}

	return lldb_ldap_to_ldb(ret);
}