Exemplo n.º 1
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;
}
Exemplo n.º 2
0
static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
{
	struct ldb_message *msg;
	int ret;

	msg = talloc(module, 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, dn, msg);
	if (ret != LDB_SUCCESS) {
		/* not finding the old record is an error */
		goto done;
	}

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

	/* remove one level attribute */
	ret = ltdb_index_one(module, msg, 0);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

	/* remove any indexed attributes */
	ret = ltdb_index_del(module, msg);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

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

done:
	talloc_free(msg);
	return ret;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/*
  return a list of dn's that might match a simple indexed search or
 */
static int ltdb_index_dn_simple(struct ldb_module *module, 
				const struct ldb_parse_tree *tree,
				const struct ldb_message *index_list,
				struct dn_list *list)
{
	struct ldb_context *ldb = module->ldb;
	struct ldb_dn *dn;
	int ret;
	unsigned int i, j;
	struct ldb_message *msg;

	list->count = 0;
	list->dn = NULL;

	/* if the attribute isn't in the list of indexed attributes then
	   this node needs a full search */
	if (ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* the attribute is indexed. Pull the list of DNs that match the 
	   search criterion */
	dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value);
	if (!dn) return LDB_ERR_OPERATIONS_ERROR;

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

	ret = ltdb_search_dn1(module, dn, msg);
	talloc_free(dn);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	for (i=0;i<msg->num_elements;i++) {
		struct ldb_message_element *el;

		if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
			continue;
		}

		el = &msg->elements[i];

		list->dn = talloc_array(list, char *, el->num_values);
		if (!list->dn) {
			talloc_free(msg);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		for (j=0;j<el->num_values;j++) {
			list->dn[list->count] = 
				talloc_strdup(list->dn, (char *)el->values[j].data);
			if (!list->dn[list->count]) {
				talloc_free(msg);
				return LDB_ERR_OPERATIONS_ERROR;
			}
			list->count++;
		}
	}

	talloc_free(msg);

	if (list->count > 1) {
		qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp);
	}

	return LDB_SUCCESS;
}
Exemplo n.º 7
0
/*
  register any special handlers from @ATTRIBUTES
*/
static int ltdb_attributes_load(struct ldb_module *module)
{
	struct ldb_context *ldb;
	void *data = ldb_module_get_private(module);
	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
	struct ldb_message *msg = ltdb->cache->attributes;
	struct ldb_dn *dn;
	unsigned int i;
	int r;

	ldb = ldb_module_get_ctx(module);

	if (ldb->schema.attribute_handler_override) {
		/* we skip loading the @ATTRIBUTES record when a module is supplying
		   its own attribute handling */
		return 0;
	}

	dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES);
	if (dn == NULL) goto failed;

	r = ltdb_search_dn1(module, dn, msg);
	talloc_free(dn);
	if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
		goto failed;
	}
	if (r == LDB_ERR_NO_SUCH_OBJECT) {
		return 0;
	}
	/* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
	   but its close enough for now */
	for (i=0;i<msg->num_elements;i++) {
		unsigned flags;
		const char *syntax;
		const struct ldb_schema_syntax *s;

		if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
			ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'", msg->elements[i].name);
			goto failed;
		}
		switch (flags & ~LTDB_FLAG_HIDDEN) {
		case 0:
			syntax = LDB_SYNTAX_OCTET_STRING;
			break;
		case LTDB_FLAG_CASE_INSENSITIVE:
			syntax = LDB_SYNTAX_DIRECTORY_STRING;
			break;
		case LTDB_FLAG_INTEGER:
			syntax = LDB_SYNTAX_INTEGER;
			break;
		default:
			ldb_debug(ldb, LDB_DEBUG_ERROR, 
				  "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES",
				  flags, msg->elements[i].name);
			goto failed;
		}

		s = ldb_standard_syntax_by_name(ldb, syntax);
		if (s == NULL) {
			ldb_debug(ldb, LDB_DEBUG_ERROR, 
				  "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES",
				  syntax, msg->elements[i].name);
			goto failed;
		}

		flags |= LDB_ATTR_FLAG_ALLOCATED;
		if (ldb_schema_attribute_add_with_syntax(ldb, msg->elements[i].name, flags, s) != 0) {
			goto failed;
		}
	}

	return 0;
failed:
	return -1;
}