Be more careful in extended_dn_out
authorAndrew Bartlett <abartlet@samba.org>
Wed, 10 Dec 2008 03:20:20 +0000 (14:20 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 10 Dec 2008 03:20:20 +0000 (14:20 +1100)
This fixes the module to operate correctly when the init function has
not yet been called (say for a search during the initilisation of
another module), and to fix memory allocation issues in
dereference_control->dereference.

Andrew Bartlett

source4/dsdb/samdb/ldb_modules/extended_dn_out.c

index 0333b82..142db68 100644 (file)
@@ -151,7 +151,7 @@ static int inject_extended_dn_out(struct ldb_reply *ares,
 
 static int handle_dereference(struct ldb_dn *dn,
                              struct dsdb_openldap_dereference_result **dereference_attrs, 
-                             const char *attr, DATA_BLOB *val)
+                             const char *attr, const DATA_BLOB *val)
 {
        const struct ldb_val *entryUUIDblob, *sid_blob;
        struct ldb_message fake_msg; /* easier to use routines that expect an ldb_message */
@@ -211,7 +211,6 @@ struct extended_search_context {
        struct ldb_module *module;
        const struct dsdb_schema *schema;
        struct ldb_request *req;
-       struct ldb_control *control;
        bool inject;
        bool remove_guid;
        bool remove_sid;
@@ -261,13 +260,18 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
                }
        }
 
-       control = ldb_reply_get_control(ares, DSDB_OPENLDAP_DEREFERENCE_CONTROL);
-
-       if (private->dereference && control && control->data) {
-              dereference_control = talloc_get_type(control->data, struct dsdb_openldap_dereference_result_control);
+       if (private && private->dereference) {
+               control = ldb_reply_get_control(ares, DSDB_OPENLDAP_DEREFERENCE_CONTROL);
+       
+               if (control && control->data) {
+                       dereference_control = talloc_get_type(control->data, struct dsdb_openldap_dereference_result_control);
+               }
        }
-       for (i = 0; i < msg->num_elements; i++) {
+
+       /* Walk the retruned elements (but only if we have a schema to interpret the list with) */
+       for (i = 0; ac->schema && i < msg->num_elements; i++) {
                const struct dsdb_attribute *attribute;
+               /* distinguishedName has been dealt with above */
                if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) {
                        continue;
                }
@@ -345,13 +349,6 @@ static int extended_dn_out_search(struct ldb_module *module, struct ldb_request
                }
        }
 
-       /* If we have not been asked for the extended DN, and we are
-        * in dereference mode, then the normal action is to ignore
-        * this module */
-       if (!private || (!control && private->dereference)) {
-               return ldb_next_request(module, req);
-       }
-
        /* Look to see if, as we are in 'store DN+GUID+SID' mode, the
         * client is after the storage format (to fill in linked
         * attributes) */
@@ -373,20 +370,13 @@ static int extended_dn_out_search(struct ldb_module *module, struct ldb_request
        ac->module = module;
        ac->schema = dsdb_get_schema(module->ldb);
        ac->req = req;
-       ac->control = control;
        ac->inject = false;
        ac->remove_guid = false;
        ac->remove_sid = false;
        
        const_attrs = req->op.search.attrs;
 
-       if (!ac->schema) {
-               /* no schema yet? go on */
-               talloc_free(ac);
-               return ldb_next_request(module, req);
-       }
-
-       if (control || storage_format_control) {
+       if (control || (storage_format_control && private && !private->dereference)) {
                ac->inject = true;
                if (extended_ctrl) {
                        ac->extended_type = extended_ctrl->type;
@@ -432,7 +422,7 @@ static int extended_dn_out_search(struct ldb_module *module, struct ldb_request
                                      ac, extended_callback,
                                      req);
        if (ret != LDB_SUCCESS) {
-               return LDB_ERR_OPERATIONS_ERROR;
+               return ret;
        }
 
        /* Remove extended DN and storage format controls */
@@ -455,12 +445,15 @@ static int extended_dn_out_search(struct ldb_module *module, struct ldb_request
                }
        }
 
-       if (private->dereference) {
+       if (private && private->dereference && private->dereference_control) {
 
                /* Add in dereference control */
                ret = ldb_request_add_control(down_req,
                                              DSDB_OPENLDAP_DEREFERENCE_CONTROL,
                                              false, private->dereference_control);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
        }
 
        /* perform the search */
@@ -494,14 +487,14 @@ static int extended_dn_out_ldb_init(struct ldb_module *module)
 
 static int extended_dn_out_dereference_init(struct ldb_module *module)
 {
-       int ret, i;
-       struct extended_dn_out_private *private = talloc(module, struct extended_dn_out_private);
+       int ret, i = 0;
+       struct extended_dn_out_private *private;
        struct dsdb_openldap_dereference_control *dereference_control;
        struct dsdb_attribute *cur;
 
        struct dsdb_schema *schema;
 
-       module->private_data = private;
+       module->private_data = private = talloc_zero(module, struct extended_dn_out_private);
 
        if (!private) {
                ldb_oom(module->ldb);
@@ -525,12 +518,12 @@ static int extended_dn_out_dereference_init(struct ldb_module *module)
 
        schema = dsdb_get_schema(module->ldb);
        if (!schema) {
-               /* No schema on this DB */
+               /* No schema on this DB (yet) */
                return LDB_SUCCESS;
        }
 
        private->dereference_control = dereference_control
-               = talloc(private, struct dsdb_openldap_dereference_control);
+               = talloc_zero(private, struct dsdb_openldap_dereference_control);
 
        if (!private->dereference_control) {
                ldb_oom(module->ldb);
@@ -548,8 +541,8 @@ static int extended_dn_out_dereference_init(struct ldb_module *module)
                        continue;
                }
                dereference_control->dereference
-                       = talloc_realloc(private, dereference_control, 
-                                        struct dsdb_openldap_dereference *, i + 1);
+                       = talloc_realloc(private, dereference_control->dereference
+                                        struct dsdb_openldap_dereference *, i + 2);
                if (!dereference_control) {
                        ldb_oom(module->ldb);
                        return LDB_ERR_OPERATIONS_ERROR;