Exemplo n.º 1
0
/* Map a message element into the remote partition. */
static struct ldb_message_element *ldb_msg_el_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old)
{
	struct ldb_message_element *el;
	int i;

	el = talloc_zero(mem_ctx, struct ldb_message_element);
	if (el == NULL) {
		map_oom(module);
		return NULL;
	}

	el->num_values = old->num_values;
	el->values = talloc_array(el, struct ldb_val, el->num_values);
	if (el->values == NULL) {
		talloc_free(el);
		map_oom(module);
		return NULL;
	}

	el->name = map_attr_map_local(el, map, old->name);

	for (i = 0; i < el->num_values; i++) {
		el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
	}

	return el;
}
Exemplo n.º 2
0
/* Rename a record. */
int ldb_map_rename(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_request *search_req = NULL;
	struct ldb_context *ldb;
	struct map_context *ac;
	int ret;

	ldb = ldb_module_get_ctx(module);

	/* Do not manipulate our control entries */
	if (ldb_dn_is_special(req->op.rename.olddn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping requested (perhaps no DN mapping specified).
	 * Skip to next module */
	if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
	    (!ldb_dn_check_local(module, req->op.rename.newdn))) {
		return ldb_next_request(module, req);
	}

	/* Rename into/out of the mapped partition requested, bail out */
	if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
	    !ldb_dn_check_local(module, req->op.rename.newdn)) {
		return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
	}

	/* Prepare context and handle */
	ac = map_init_context(module, req);
	if (ac == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Prepare the remote operation */
	ret = ldb_build_rename_req(&ac->remote_req, ldb, ac,
				   ldb_dn_map_local(module, ac, req->op.rename.olddn),
				   ldb_dn_map_local(module, ac, req->op.rename.newdn),
				   req->controls,
				   ac, map_op_remote_callback,
				   req);
	LDB_REQ_SET_LOCATION(ac->remote_req);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* No local db, just run the remote request */
	if (!map_check_local_db(ac->module)) {
		/* Do the remote request. */
		return ldb_next_remote_request(ac->module, ac->remote_req);
	}

	/* Prepare the search operation */
	ret = map_search_self_req(&search_req, ac, req->op.rename.olddn);
	if (ret != LDB_SUCCESS) {
		map_oom(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return ldb_next_request(module, search_req);
}
Exemplo n.º 3
0
/* Create a request context and handle. */
struct ldb_handle *map_init_handle(struct ldb_request *req, struct ldb_module *module)
{
	struct map_context *ac;
	struct ldb_handle *h;

	h = talloc_zero(req, struct ldb_handle);
	if (h == NULL) {
		map_oom(module);
		return NULL;
	}

	h->module = module;

	ac = map_init_context(h, req);
	if (ac == NULL) {
		talloc_free(h);
		return NULL;
	}

	h->private_data = (void *)ac;

	h->state = LDB_ASYNC_INIT;
	h->status = LDB_SUCCESS;

	return h;
}
Exemplo n.º 4
0
/* Build a request to search the local record by its DN. */
static int map_search_self_req(struct ldb_request **req,
				struct map_context *ac,
				struct ldb_dn *dn)
{
	/* attrs[] is returned from this function in
	 * ac->search_req->op.search.attrs, so it must be static, as
	 * otherwise the compiler can put it on the stack */
	static const char * const attrs[] = { IS_MAPPED, NULL };
	struct ldb_parse_tree *tree;

	/* Limit search to records with 'IS_MAPPED' present */
	tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)");
	if (tree == NULL) {
		map_oom(ac->module);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	*req = map_search_base_req(ac, dn, attrs, tree,
				   ac, map_search_self_callback);
	if (*req == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return LDB_SUCCESS;
}
Exemplo n.º 5
0
/* Create a generic request context. */
static struct map_context *map_init_context(struct ldb_handle *h, struct ldb_request *req)
{
	struct map_context *ac;

	ac = talloc_zero(h, struct map_context);
	if (ac == NULL) {
		map_oom(h->module);
		return NULL;
	}

	ac->module = h->module;
	ac->orig_req = req;

	return ac;
}
Exemplo n.º 6
0
/* Create a search request context. */
struct map_search_context *map_init_search_context(struct map_context *ac, struct ldb_reply *ares)
{
	struct map_search_context *sc;

	sc = talloc_zero(ac, struct map_search_context);
	if (sc == NULL) {
		map_oom(ac->module);
		return NULL;
	}

	sc->ac = ac;
	sc->local_res = NULL;
	sc->remote_res = ares;

	return sc;
}
Exemplo n.º 7
0
/* Merge two lists of attributes into a single one. */
int map_attrs_merge(struct ldb_module *module, void *mem_ctx, 
		    const char ***attrs, const char * const *more_attrs)
{
	int i, j, k;

	for (i = 0; *attrs && (*attrs)[i]; i++) /* noop */ ;
	for (j = 0; more_attrs && more_attrs[j]; j++) /* noop */ ;
	
	*attrs = talloc_realloc(mem_ctx, *attrs, const char *, i+j+1);
	if (*attrs == NULL) {
		map_oom(module);
		return -1;
	}

	for (k = 0; k < j; k++) {
		(*attrs)[i + k] = more_attrs[k];
	}

	(*attrs)[i+k] = NULL;

	return 0;
}
Exemplo n.º 8
0
/* Add a message element either to a local or to a remote message,
 * depending on whether it goes into the local or remote partition. */
static int ldb_msg_el_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg, const char *attr_name, /* const char * const names[], */ const struct ldb_message_element *old)
{
	const struct ldb_map_context *data = map_get_context(module);
	const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
	struct ldb_message_element *el=NULL;

	/* Unknown attribute: ignore */
	if (map == NULL) {
		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
			  "Not mapping attribute '%s': no mapping found\n",
			  old->name);
		goto local;
	}

	switch (map->type) {
	case MAP_IGNORE:
		goto local;

	case MAP_CONVERT:
		if (map->u.convert.convert_local == NULL) {
			ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
				  "Not mapping attribute '%s': "
				  "'convert_local' not set\n",
				  map->local_name);
			goto local;
		}
		/* fall through */
	case MAP_KEEP:
	case MAP_RENAME:
		el = ldb_msg_el_map_local(module, remote, map, old);
		break;

	case MAP_GENERATE:
		if (map->u.generate.generate_remote == NULL) {
			ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
				  "Not mapping attribute '%s': "
				  "'generate_remote' not set\n",
				  map->local_name);
			goto local;
		}

		/* TODO: if this attr requires context:
		 *	 make sure all context attrs are mappable (in 'names')
		 *	 make sure all context attrs have already been mapped?
		 *	 maybe postpone generation until they have been mapped?
		 */

		map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
		return 0;
	}

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

	return ldb_msg_add(remote, el, old->flags);

local:
	el = talloc(local, struct ldb_message_element);
	if (el == NULL) {
		map_oom(module);
		return -1;
	}

	*el = *old;			/* copy the old element */

	return ldb_msg_add(local, el, old->flags);
}
Exemplo n.º 9
0
/* Add a record. */
int map_add(struct ldb_module *module, struct ldb_request *req)
{
	const struct ldb_message *msg = req->op.add.message;
	struct ldb_handle *h;
	struct map_context *ac;
	struct ldb_message *local, *remote;
	const char *dn;

	/* Do not manipulate our control entries */
	if (ldb_dn_is_special(msg->dn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping requested (perhaps no DN mapping specified), skip to next module */
	if (!ldb_dn_check_local(module, msg->dn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping needed, fail */
	if (!ldb_msg_check_remote(module, msg)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Prepare context and handle */
	h = map_init_handle(req, module);
	if (h == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ac = talloc_get_type(h->private_data, struct map_context);

	/* Prepare the local operation */
	ac->local_req = talloc(ac, struct ldb_request);
	if (ac->local_req == NULL) {
		goto oom;
	}

	*(ac->local_req) = *req;	/* copy the request */

	ac->local_req->context = NULL;
	ac->local_req->callback = NULL;

	/* Prepare the remote operation */
	ac->remote_req = talloc(ac, struct ldb_request);
	if (ac->remote_req == NULL) {
		goto oom;
	}

	*(ac->remote_req) = *req;	/* copy the request */

	ac->remote_req->context = NULL;
	ac->remote_req->callback = NULL;

	/* Prepare the local message */
	local = ldb_msg_new(ac->local_req);
	if (local == NULL) {
		goto oom;
	}
	local->dn = msg->dn;

	/* Prepare the remote message */
	remote = ldb_msg_new(ac->remote_req);
	if (remote == NULL) {
		goto oom;
	}
	remote->dn = ldb_dn_map_local(ac->module, remote, msg->dn);

	/* Split local from remote message */
	ldb_msg_partition(module, local, remote, msg);
	ac->local_req->op.add.message = local;
	ac->remote_req->op.add.message = remote;

	if ((local->num_elements == 0) || (!map_check_local_db(ac->module))) {
		/* No local data or db, just run the remote request */
		talloc_free(ac->local_req);
		req->handle = h;	/* return our own handle to deal with this call */
		return map_add_do_remote(h);
	}

	/* Store remote DN in 'IS_MAPPED' */
	/* TODO: use GUIDs here instead */
	dn = ldb_dn_linearize(local, remote->dn);
	if (ldb_msg_add_string(local, IS_MAPPED, dn) != 0) {
		goto failed;
	}

	req->handle = h;		/* return our own handle to deal with this call */
	return map_add_do_local(h);

oom:
	map_oom(module);
failed:
	talloc_free(h);
	return LDB_ERR_OPERATIONS_ERROR;
}
Exemplo n.º 10
0
/* Map a DN into the local partition. */
struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_dn *dn)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_dn *newdn;
	const struct ldb_map_attribute *map;
	enum ldb_map_attr_type map_type;
	const char *name;
	struct ldb_val value;
	int i, ret;

	if (dn == NULL) {
		return NULL;
	}

	newdn = ldb_dn_copy(mem_ctx, dn);
	if (newdn == NULL) {
		map_oom(module);
		return NULL;
	}

	/* For each RDN, map the component name and possibly the value */
	for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) {
		map = map_attr_find_remote(data, ldb_dn_get_component_name(dn, i));

		/* Unknown attribute - leave this RDN as is and hope the best... */
		if (map == NULL) {
			map_type = MAP_KEEP;
		} else {
			map_type = map->type;
		}

		switch (map_type) {
		case MAP_IGNORE:
		case MAP_GENERATE:
			ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
				  "MAP_IGNORE/MAP_GENERATE attribute '%s' "
				  "used in DN!\n", ldb_dn_get_component_name(dn, i));
			goto failed;

		case MAP_CONVERT:
			if (map->u.convert.convert_remote == NULL) {
				ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
					  "'convert_remote' not set for attribute '%s' "
					  "used in DN!\n", ldb_dn_get_component_name(dn, i));
				goto failed;
			}
			/* fall through */
		case MAP_KEEP:
		case MAP_RENAME:
			name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i));
			if (name == NULL) goto failed;

			value = ldb_val_map_remote(module, newdn, map, ldb_dn_get_component_val(dn, i));
			if (value.data == NULL) goto failed;

			ret = ldb_dn_set_component(newdn, i, name, value);
			if (ret != LDB_SUCCESS) {
				goto failed;
			}

			break;
		}
	}

	return newdn;

failed:
	talloc_free(newdn);
	return NULL;
}
Exemplo n.º 11
0
/* Modify a record. */
int ldb_map_modify(struct ldb_module *module, struct ldb_request *req)
{
	const struct ldb_message *msg = req->op.mod.message;
	struct ldb_request *search_req = NULL;
	struct ldb_message *remote_msg;
	struct ldb_context *ldb;
	struct map_context *ac;
	int ret;

	ldb = ldb_module_get_ctx(module);

	/* Do not manipulate our control entries */
	if (ldb_dn_is_special(msg->dn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping requested (perhaps no DN mapping specified), skip to next module */
	if (!ldb_dn_check_local(module, msg->dn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping needed, skip to next module */
	/* TODO: What if the remote part exists, the local doesn't,
	 *	 and this request wants to modify local data and thus
	 *	 add the local record? */
	if (!ldb_msg_check_remote(module, msg)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Prepare context and handle */
	ac = map_init_context(module, req);
	if (ac == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Prepare the local message */
	ac->local_msg = ldb_msg_new(ac);
	if (ac->local_msg == NULL) {
		map_oom(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ac->local_msg->dn = msg->dn;

	/* Prepare the remote message */
	remote_msg = ldb_msg_new(ac->remote_req);
	if (remote_msg == NULL) {
		map_oom(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);

	/* Split local from remote message */
	ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg);

	/* Prepare the remote operation */
	ret = ldb_build_mod_req(&ac->remote_req, ldb,
				ac, remote_msg,
				req->controls,
				ac, map_op_remote_callback,
				req);
	LDB_REQ_SET_LOCATION(ac->remote_req);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if ((ac->local_msg->num_elements == 0) ||
	    ( ! map_check_local_db(ac->module))) {
		/* No local data or db, just run the remote request */
		return ldb_next_remote_request(ac->module, ac->remote_req);
	}

	/* prepare the search operation */
	ret = map_search_self_req(&search_req, ac, msg->dn);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return ldb_next_request(module, search_req);
}
Exemplo n.º 12
0
/* Add a record. */
int ldb_map_add(struct ldb_module *module, struct ldb_request *req)
{
	const struct ldb_message *msg = req->op.add.message;
	struct ldb_context *ldb;
	struct map_context *ac;
	struct ldb_message *remote_msg;
	int ret;

	ldb = ldb_module_get_ctx(module);

	/* Do not manipulate our control entries */
	if (ldb_dn_is_special(msg->dn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping requested (perhaps no DN mapping specified), skip to next module */
	if (!ldb_dn_check_local(module, msg->dn)) {
		return ldb_next_request(module, req);
	}

	/* No mapping needed, fail */
	if (!ldb_msg_check_remote(module, msg)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Prepare context and handle */
	ac = map_init_context(module, req);
	if (ac == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}


	/* Prepare the local message */
	ac->local_msg = ldb_msg_new(ac);
	if (ac->local_msg == NULL) {
		map_oom(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ac->local_msg->dn = msg->dn;

	/* Prepare the remote message */
	remote_msg = ldb_msg_new(ac);
	if (remote_msg == NULL) {
		map_oom(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);

	/* Split local from remote message */
	ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg);

	/* Prepare the remote operation */
	ret = ldb_build_add_req(&ac->remote_req, ldb,
				ac, remote_msg,
				req->controls,
				ac, map_op_remote_callback,
				req);
	LDB_REQ_SET_LOCATION(ac->remote_req);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if ((ac->local_msg->num_elements == 0) ||
	    ( ! map_check_local_db(ac->module))) {
		/* No local data or db, just run the remote request */
		return ldb_next_remote_request(ac->module, ac->remote_req);
	}

	/* Store remote DN in 'IS_MAPPED' */
	/* TODO: use GUIDs here instead */
	ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
					remote_msg->dn);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return map_add_do_local(ac);
}