r17788: fix compiler warnings
[ira/wip.git] / source4 / dsdb / samdb / ldb_modules / extended_dn.c
index 49af8604d5eb6cebd5618a3092657c66f76e7c33..64600fff8bd6f76927d68d42b2b1cf713582def3 100644 (file)
@@ -36,7 +36,9 @@
 #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>
 
@@ -157,7 +159,7 @@ static BOOL inject_extended_dn(struct ldb_message *msg,
        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;
        }
 
@@ -165,19 +167,55 @@ static BOOL inject_extended_dn(struct ldb_message *msg,
 }
 
 /* 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 */
@@ -185,124 +223,116 @@ static int extended_search(struct ldb_module *module, struct ldb_request *req)
        }
 
        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);
 }