Exemplo n.º 1
0
/* TODO: free old DNs and messages? */
int ldb_next_remote_request(struct ldb_module *module, struct ldb_request *request)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_context *ldb;
	struct ldb_message *msg;

	ldb = ldb_module_get_ctx(module);

	switch (request->operation) {
	case LDB_SEARCH:
		if (request->op.search.base) {
			request->op.search.base = ldb_dn_rebase_remote(request, data, request->op.search.base);
		} else {
			request->op.search.base = data->remote_base_dn;
			/* TODO: adjust scope? */
		}
		break;

	case LDB_ADD:
		msg = ldb_msg_copy_shallow(request, request->op.add.message);
		if (msg == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
		msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn);
		request->op.add.message = msg;
		break;

	case LDB_MODIFY:
		msg = ldb_msg_copy_shallow(request, request->op.mod.message);
		if (msg == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
		msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn);
		request->op.mod.message = msg;
		break;

	case LDB_DELETE:
		request->op.del.dn = ldb_dn_rebase_remote(request, data, request->op.del.dn);
		break;

	case LDB_RENAME:
		request->op.rename.olddn = ldb_dn_rebase_remote(request, data, request->op.rename.olddn);
		request->op.rename.newdn = ldb_dn_rebase_remote(request, data, request->op.rename.newdn);
		break;

	default:
		ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
			  "Invalid remote request!");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return ldb_next_request(module, request);
}
Exemplo n.º 2
0
/*
  copy a message, allocating new memory for all parts
*/
struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
				 const struct ldb_message *msg)
{
	struct ldb_message *msg2;
	unsigned int i, j;

	msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
	if (msg2 == NULL) return NULL;

	msg2->dn = ldb_dn_copy(msg2, msg2->dn);
	if (msg2->dn == NULL) goto failed;

	for (i=0;i<msg2->num_elements;i++) {
		struct ldb_message_element *el = &msg2->elements[i];
		struct ldb_val *values = el->values;
		el->name = talloc_strdup(msg2->elements, el->name);
		if (el->name == NULL) goto failed;
		el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
		if (el->values == NULL) goto failed;
		for (j=0;j<el->num_values;j++) {
			el->values[j] = ldb_val_dup(el->values, &values[j]);
			if (el->values[j].data == NULL && values[j].length != 0) {
				goto failed;
			}
		}
	}

	return msg2;

failed:
	talloc_free(msg2);
	return NULL;
}
Exemplo n.º 3
0
/*
 * @brief Encrypt all the secret attributes on an ldb_message
 *
 * Encrypt all the secret attributes on an ldb_message. Any secret
 * attributes are removed from message and encrypted copies of the
 * attributes added.  In the event of an error the contents of the
 * message will be inconsistent.
 *
 * @param err Pointer to an error code, set to:
 *            LDB_SUCESS               If the value was successfully encrypted
 *            LDB_ERR_OPERATIONS_ERROR If there was an error.
 * @param ldb ldb context, to allow logging.
 * @param msg The ldb_message to have it's secret attributes encrypted.
 *
 * @param data The context data for this module.
 */
static const struct ldb_message *encrypt_secret_attributes(
	int *err,
	TALLOC_CTX *ctx,
	struct ldb_context *ldb,
	const struct ldb_message *msg,
	const struct es_data *data)
{

	struct ldb_message *encrypted_msg = NULL;

	int i;

	if (ldb_dn_is_special(msg->dn)) {
		return NULL;
	}

	for (i = 0; i < msg->num_elements; i++) {

		const struct ldb_message_element *el = &msg->elements[i];
		if (should_encrypt(el)) {
			struct ldb_message_element* enc = NULL;
			if (encrypted_msg == NULL) {
				encrypted_msg = ldb_msg_copy_shallow(ctx, msg);
				encrypted_msg->dn = msg->dn;
			}
			enc = encrypt_element(err,
					      msg->elements,
					      ldb,
					      el,
					      data);
			if (*err != LDB_SUCCESS) {
				return NULL;
			}
			encrypted_msg->elements[i] = *enc;
		}
	}
	return encrypted_msg;
}
Exemplo n.º 4
0
static int sample_add(struct ldb_module *mod, struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(mod);
	struct ldb_control *control = NULL;
	struct ldb_message *msg = NULL;
	struct ldb_request *down_req = NULL;
	int ret;

	/* check if there's a relax control */
	control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
	if (control != NULL) {
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	msg = ldb_msg_copy_shallow(req, req->op.add.message);
	if (msg == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ldb_msg_add_fmt(msg, "touchedBy", "sample");
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = ldb_build_add_req(&down_req, ldb, req,
				msg,
				req->controls,
				req, sample_add_callback,
				req);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	talloc_steal(down_req, msg);

	/* go on with the call chain */
	return ldb_next_request(mod, down_req);
}
/* add_record: add instancetype attribute */
static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_request *down_req;
	struct ldb_message *msg;
	struct ldb_message_element *el;
	uint32_t instanceType;
	int ret;

	/* do not manipulate our control entries */
	if (ldb_dn_is_special(req->op.add.message->dn)) {
		return ldb_next_request(module, req);
	}

	ldb_debug(ldb, LDB_DEBUG_TRACE, "instancetype_add\n");

	el = ldb_msg_find_element(req->op.add.message, "instanceType");
	if (el != NULL) {
		if (el->num_values != 1) {
			ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute is single-valued!");
			return LDB_ERR_UNWILLING_TO_PERFORM;
		}

		instanceType = ldb_msg_find_attr_as_uint(req->op.add.message,
							 "instanceType", 0);
		if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
			/*
			 * If we have no NC add operation (no TYPE_IS_NC_HEAD)
			 * then "instanceType" can only be "0" or "TYPE_WRITE".
			 */
			if ((instanceType != 0) &&
			    ((instanceType & INSTANCE_TYPE_WRITE) == 0)) {
				ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD wasn't set, then only TYPE_WRITE or 0 are allowed!");
				return LDB_ERR_UNWILLING_TO_PERFORM;
			}
		} else {
			/*
			 * If we have a NC add operation then we need also the
			 * "TYPE_WRITE" flag in order to succeed,
			 * unless this NC is not instantiated
			*/
			if (!(instanceType & INSTANCE_TYPE_UNINSTANT) &&
			    !(instanceType & INSTANCE_TYPE_WRITE)) {
				ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD was set, then also TYPE_WRITE is requested!");
				return LDB_ERR_UNWILLING_TO_PERFORM;
			}
		}

		/* we did only tests, so proceed with the original request */
		return ldb_next_request(module, req);
	}

	/* we have to copy the message as the caller might have it as a const */
	msg = ldb_msg_copy_shallow(req, req->op.add.message);
	if (msg == NULL) {
		return ldb_oom(ldb);
	}

	/*
	 * TODO: calculate correct instance type
	 */
	instanceType = INSTANCE_TYPE_WRITE;

	ret = samdb_msg_add_uint(ldb, msg, msg, "instanceType", instanceType);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = ldb_build_add_req(&down_req, ldb, req,
				msg,
				req->controls,
				req, dsdb_next_callback,
				req);
	LDB_REQ_SET_LOCATION(down_req);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	/* go on with the call chain */
	return ldb_next_request(module, down_req);
}
Exemplo n.º 6
0
static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb;
	struct ldb_request *down_req;
	struct rename_context *ac;
	struct ldb_message *msg;
	struct ldb_message_element *attribute;
	const struct ldb_schema_attribute *a;
	const char *rdn_name;
	struct ldb_val rdn_val;
	int i, ret;

	ldb = ldb_module_get_ctx(module);

	/* do not manipulate our control entries */
	if (ldb_dn_is_special(req->op.add.message->dn)) {
		return ldb_next_request(module, req);
	}

	ac = talloc_zero(req, struct rename_context);
	if (ac == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ac->module = module;
	ac->req = req;

	msg = ldb_msg_copy_shallow(req, req->op.add.message);
	if (msg == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	rdn_name = ldb_dn_get_rdn_name(msg->dn);
	if (rdn_name == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	
	rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(msg->dn));
	
	/* Perhaps someone above us tried to set this? */
	if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
		attribute->num_values = 0;
	}

	if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	attribute = rdn_name_find_attribute(msg, rdn_name);

	if (!attribute) {
		if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
	} else {
		a = ldb_schema_attribute_by_name(ldb, rdn_name);

		for (i = 0; i < attribute->num_values; i++) {
			ret = a->syntax->comparison_fn(ldb, msg,
					&rdn_val, &attribute->values[i]);
			if (ret == 0) {
				/* overwrite so it matches in case */
				attribute->values[i] = rdn_val;
				break;
			}
		}
		if (i == attribute->num_values) {
			char *rdn_errstring = talloc_asprintf(ac,
				"RDN mismatch on %s: %s (%.*s) should match one of:", 
				ldb_dn_get_linearized(msg->dn), rdn_name, 
				(int)rdn_val.length, (const char *)rdn_val.data);
			for (i = 0; i < attribute->num_values; i++) {
				rdn_errstring = talloc_asprintf_append(
					rdn_errstring, " (%.*s)",
					(int)attribute->values[i].length, 
					(const char *)attribute->values[i].data);
			}
			ldb_set_errstring(ldb, rdn_errstring);
			/* Match AD's error here */
			return LDB_ERR_INVALID_DN_SYNTAX;
		}
	}

	ret = ldb_build_add_req(&down_req, ldb, req,
				msg,
				req->controls,
				ac, rdn_name_add_callback,
				req);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	talloc_steal(down_req, msg);

	/* go on with the call chain */
	return ldb_next_request(module, down_req);
}