#include "ldb/include/ldb.h"
#include "ldb/include/ldb_errors.h"
#include "ldb/include/ldb_private.h"
+#include "librpc/gen_ndr/ndr_misc.h"
#include "dsdb/samdb/samdb.h"
+#include "libcli/security/security.h"
#include <time.h>
val = ldb_msg_find_ldb_val(msg, "distinguishedName");
if (val) {
ldb_msg_remove_attr(msg, "distinguishedName");
- if (ldb_msg_add_string(msg, "distinguishedName", new_dn))
+ if (ldb_msg_add_steal_string(msg, "distinguishedName", new_dn))
return False;
}
}
/* search */
+struct extended_context {
+
+ struct ldb_module *module;
+ void *up_context;
+ int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
+
+ const char * const *attrs;
+ BOOL remove_guid;
+ BOOL remove_sid;
+ int extended_type;
+};
+
+static int extended_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+{
+ struct extended_context *ac;
+
+ if (!context || !ares) {
+ ldb_set_errstring(ldb, "NULL Context or Result in callback");
+ goto error;
+ }
+
+ ac = talloc_get_type(context, struct extended_context);
+
+ if (ares->type == LDB_REPLY_ENTRY) {
+ /* for each record returned post-process to add any derived
+ attributes that have been asked for */
+ if (!inject_extended_dn(ares->message, ac->extended_type, ac->remove_guid, ac->remove_sid)) {
+ goto error;
+ }
+ }
+
+ return ac->up_callback(ldb, ac->up_context, ares);
+
+error:
+ talloc_free(ares);
+ return LDB_ERR_OPERATIONS_ERROR;
+}
+
static int extended_search(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_result *extended_result;
struct ldb_control *control;
- struct ldb_control **saved_controls;
struct ldb_extended_dn_control *extended_ctrl;
- int i, ret;
- const char * const *saved_attrs = NULL;
+ struct ldb_control **saved_controls;
+ struct extended_context *ac;
+ struct ldb_request *down_req;
char **new_attrs;
- BOOL remove_guid = False;
- BOOL remove_sid = False;
+ int ret;
- /* check if there's a paged request control */
+ /* check if there's an extended dn control */
control = get_control_from_list(req->controls, LDB_CONTROL_EXTENDED_DN_OID);
if (control == NULL) {
/* not found go on */
}
extended_ctrl = talloc_get_type(control->data, struct ldb_extended_dn_control);
+ if (!extended_ctrl) {
+ return LDB_ERR_PROTOCOL_ERROR;
+ }
- /* save it locally and remove it from the list */
- if (!save_controls(control, req, &saved_controls)) {
+ ac = talloc(req, struct extended_context);
+ if (ac == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->module = module;
+ ac->up_context = req->context;
+ ac->up_callback = req->callback;
+ ac->attrs = req->op.search.attrs;
+ ac->remove_guid = False;
+ ac->remove_sid = False;
+ ac->extended_type = extended_ctrl->type;
+
+ down_req = talloc_zero(req, struct ldb_request);
+ if (down_req == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
+ down_req->operation = req->operation;
+ down_req->op.search.base = req->op.search.base;
+ down_req->op.search.scope = req->op.search.scope;
+ down_req->op.search.tree = req->op.search.tree;
+
/* check if attrs only is specified, in that case check wether we need to modify them */
if (req->op.search.attrs) {
if (! is_attr_in_list(req->op.search.attrs, "objectGUID")) {
- remove_guid = True;
+ ac->remove_guid = True;
}
if (! is_attr_in_list(req->op.search.attrs, "objectSID")) {
- remove_sid = True;
+ ac->remove_sid = True;
}
- if (remove_guid || remove_sid) {
- new_attrs = copy_attrs(req, req->op.search.attrs);
- if (!new_attrs)
+ if (ac->remove_guid || ac->remove_sid) {
+ new_attrs = copy_attrs(down_req, req->op.search.attrs);
+ if (new_attrs == NULL)
return LDB_ERR_OPERATIONS_ERROR;
- saved_attrs = req->op.search.attrs;
-
- if (remove_guid) {
- if (!add_attrs(req, &new_attrs, "objectGUID"))
+ if (ac->remove_guid) {
+ if (!add_attrs(down_req, &new_attrs, "objectGUID"))
return LDB_ERR_OPERATIONS_ERROR;
}
- if (remove_sid) {
- if (!add_attrs(req, &new_attrs, "objectSID"))
+ if (ac->remove_sid) {
+ if (!add_attrs(down_req, &new_attrs, "objectSID"))
return LDB_ERR_OPERATIONS_ERROR;
}
- req->op.search.attrs = (const char * const *)new_attrs;
+ down_req->op.search.attrs = (const char * const *)new_attrs;
}
}
- ret = ldb_next_request(module, req);
+ down_req->controls = req->controls;
- /* put request back into original shape */
- /* TODO: build a new req and don't touch the original one */
+ /* save it locally and remove it from the list */
+ /* we do not need to replace them later as we
+ * are keeping the original req intact */
+ if (!save_controls(control, down_req, &saved_controls)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
- if (req->controls) talloc_free(req->controls);
- req->controls = saved_controls;
+ down_req->context = ac;
+ down_req->callback = extended_callback;
+ ldb_set_timeout_from_prev_req(module->ldb, req, down_req);
- if (saved_attrs) {
- talloc_free(new_attrs);
- req->op.search.attrs = saved_attrs;
- }
+ /* perform the search */
+ ret = ldb_next_request(module, down_req);
- if (ret != LDB_SUCCESS) {
- return ret;
+ /* do not free down_req as the call results may be linked to it,
+ * it will be freed when the upper level request get freed */
+ if (ret == LDB_SUCCESS) {
+ req->handle = down_req->handle;
}
- extended_result = req->op.search.res;
-
- for (i = 0; i < extended_result->count; i++) {
- /* TODO: the following funtion updates only dn and
- * distinguishedName. We still need to address other
- * DN entries like objectCategory
- */
- if (!inject_extended_dn(extended_result->msgs[i],
- extended_ctrl->type,
- remove_guid, remove_sid)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- }
-
- return LDB_SUCCESS;
+ return ret;
}
-static int extended_request(struct ldb_module *module, struct ldb_request *req)
+static int extended_init(struct ldb_module *module)
{
- switch (req->operation) {
+ struct ldb_request *req;
+ int ret;
- case LDB_REQ_SEARCH:
- return extended_search(module, req);
+ req = talloc(module, struct ldb_request);
+ if (req == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
- default:
- return ldb_next_request(module, req);
+ req->operation = LDB_REQ_REGISTER_CONTROL;
+ req->op.reg_control.oid = LDB_CONTROL_EXTENDED_DN_OID;
+ req->controls = NULL;
+ ret = ldb_request(module->ldb, req);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "extended_dn: Unable to register control with rootdse!\n");
+ talloc_free(req);
+ return LDB_ERR_OPERATIONS_ERROR;
}
+
+ talloc_free(req);
+ return ldb_next_init(module);
}
static const struct ldb_module_ops extended_dn_ops = {
.name = "extended_dn",
- .request = extended_request,
+ .search = extended_search,
+ .init_context = extended_init
};
-#ifdef HAVE_DLOPEN_DISABLED
-struct ldb_module *init_module(struct ldb_context *ldb, int stage, const char *options[])
-#else
-struct ldb_module *extended_dn_module_init(struct ldb_context *ldb, int stage, const char *options[])
-#endif
+int ldb_extended_dn_init(void)
{
- struct ldb_module *ctx;
-
- if (stage == LDB_MODULES_INIT_STAGE_2) {
- struct ldb_request request;
- int ret;
-
- request.operation = LDB_REQ_REGISTER;
- request.op.reg.oid = LDB_CONTROL_EXTENDED_DN_OID;
- request.controls = NULL;
-
- ret = ldb_request(ldb, &request);
- if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "extended_dn: Unable to register control with rootdse!\n");
- }
-
- return NULL;
- }
-
- ctx = talloc(ldb, struct ldb_module);
- if (!ctx)
- return NULL;
-
- ctx->ldb = ldb;
- ctx->prev = ctx->next = NULL;
- ctx->ops = &extended_dn_ops;
- ctx->private_data = NULL;
-
- return ctx;
+ return ldb_register_module(&extended_dn_ops);
}