The branch, master has been updated
       via  aa32725... s4:ldap.py - add some "objectclass" behaviour tests
       via  e3c686d... s4:objectclass LDB module - rework the code which 
handles the objectclasses modification
       via  17f465a... s4:ldap.py - enhance the attributes testcase to 
demonstrate how the attributes are checked against the schema and the specified 
objectclasses
       via  ee278bf... s4:acl LDB module - LDB attribute names should be 
compared using "ldb_attr_cmp" or "strcasecmp"
       via  566d13c... s4:acl LDB module - adaption for "objectclass_attrs" 
module
       via  e7eef53... s4:objectclass LDB module - remove "fix_check_attributes"
       via  227144e... s4:samldb LDB module - adjust the module to set always a 
"defaultObjectCategory" on objectclass add operations
       via  bd91095... s4:remove the "validate_update" LDB module - the task is 
now handled by the far more complete "objectclass_attrs" LDB module
       via  2586cba... s4:dsdb - introduce a new "objectclass_attrs" LDB module 
which performs the objectclass attributes checking
       via  9e56b54... s4:objectclass LDB module - instanciate the schema 
variable centrally on the "ac" context creation
       via  da90868... s4:samldb LDB module - finally we can remove the RDN 
check
       via  9ab3365... s4:ldap.py - enhance the rename tests to demonstrate the 
functionality
       via  ec9b6f3... s4:objectclass LDB module - finally implement the 
correct entry rename protections
       via  0ca17ea... s4:objectclass LDB module - cosmetic change
       via  c6020cc... s4:objectclass LDB module - remove duplicated code
       via  95da724... s4:objectclass LDB module - fix counter variable types
       via  0408ec1... s4:objectclass LDB module - explain why the search can 
return with an empty return
       via  6afa5a7... s4:objectclass LDB module - this "talloc_steal" is not 
necessary
       via  2d3760c... s4:objectclass LDB module - fix error result if an entry 
doesn't contain a structural objectclass
       via  2a294d3... s4:objectclass LDB module - use "ldb_oom" for expressing 
out of memory
       via  3c4336b... s4:objectclass LDB module - fix header and add my 
copyright
      from  04c7484... s3-waf: Build rpc_server/srv_spoolss_util.c too.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit aa3272588662f1389138a177a4c6644668c052fa
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Thu Jun 3 20:58:43 2010 +0200

    s4:ldap.py - add some "objectclass" behaviour tests

commit e3c686daec130fb3c4a7457943173f31851a8e7d
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Jun 5 23:02:25 2010 +0200

    s4:objectclass LDB module - rework the code which handles the objectclasses 
modification
    
    Before it has been very incomplete. We try now to match the Windows Server
    behaviour as close as possible.

commit 17f465a4ac5562bec1b40dc97ac414fb3920175b
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sun Jun 6 23:09:28 2010 +0200

    s4:ldap.py - enhance the attributes testcase to demonstrate how the 
attributes are checked against the schema and the specified objectclasses
    
    This demonstrates the bew "objectclass_attrs" LDB module behaviour.

commit ee278bf0c48dbc8b7afc37762ad4f305014a2e2c
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sun Jun 6 19:06:58 2010 +0200

    s4:acl LDB module - LDB attribute names should be compared using 
"ldb_attr_cmp" or "strcasecmp"

commit 566d13c5d11ae832285c09f74d25ffdcf0397735
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Jun 5 20:19:31 2010 +0200

    s4:acl LDB module - adaption for "objectclass_attrs" module
    
    Since the attribute schema checking code moved back we need to give here the
    "LDB_ERR_NO_SUCH_ATTRIBUTE" error.

commit e7eef53fe543c940f7a792b16d037fed8d7743ec
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Jun 5 19:11:25 2010 +0200

    s4:objectclass LDB module - remove "fix_check_attributes"
    
    Also this task is now performed by the "objectclass_attrs" LDB module.

commit 227144e0503504d4c716af4a4e92dc6397c705de
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sun Jun 6 19:53:33 2010 +0200

    s4:samldb LDB module - adjust the module to set always a 
"defaultObjectCategory" on objectclass add operations
    
    This is needed to make the "objectclass_attrs" LDB module happy. The search
    check and case adjustment are done as it was using a second modify 
operation.

commit bd910952ba2256ff54c0e48a6feda285b9fbb8a5
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Jun 5 19:09:51 2010 +0200

    s4:remove the "validate_update" LDB module - the task is now handled by the 
far more complete "objectclass_attrs" LDB module

commit 2586cbaadcdf9baf77be5ec5b612cff324ab19a8
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Jun 5 17:34:35 2010 +0200

    s4:dsdb - introduce a new "objectclass_attrs" LDB module which performs the 
objectclass attributes checking
    
    Until now we had no real consistent mechanism which allowed us to check if
    attributes belong to the specified objectclasses.

commit 9e56b54414ce9f62edbd8f87c09885dbb4b3ccea
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Thu Jun 3 19:17:16 2010 +0200

    s4:objectclass LDB module - instanciate the schema variable centrally on 
the "ac" context creation
    
    This unifies the position when the schema is read and prevents multiple
    instanciations (eg on a modification operation).

commit da90868907c7dc7f9894dc06bd49df701ff442eb
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 22:13:03 2010 +0200

    s4:samldb LDB module - finally we can remove the RDN check
    
    This is now dynamically always done by the objectclass LDB module

commit 9ab3365fa5a37257d818c414925264a336eb103c
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 22:06:39 2010 +0200

    s4:ldap.py - enhance the rename tests to demonstrate the functionality

commit ec9b6f3c608f61d694f2defe816b55bdc6d169ea
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 21:55:08 2010 +0200

    s4:objectclass LDB module - finally implement the correct entry rename 
protections
    
    Only the "systemFlags" check is still missing.

commit 0ca17eaa15641708acf182b9ed1cb33222b05617
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 21:43:55 2010 +0200

    s4:objectclass LDB module - cosmetic change

commit c6020ccb87337b9045c51674d4d01c19f43fd288
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 21:42:06 2010 +0200

    s4:objectclass LDB module - remove duplicated code

commit 95da72432560c042400faccb7f16d9ab9cd38df1
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 21:24:49 2010 +0200

    s4:objectclass LDB module - fix counter variable types

commit 0408ec11a9503a6e523651cc078334158c8c6f53
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 21:23:34 2010 +0200

    s4:objectclass LDB module - explain why the search can return with an empty 
return

commit 6afa5a733c3ab12fd03e6980898e21f8d112bc3b
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 19:44:22 2010 +0200

    s4:objectclass LDB module - this "talloc_steal" is not necessary
    
    The "parent_dn" was created on the "ac" context which lives anyway longer
    than this child request.

commit 2d3760c04cd4a17a8c85196a0a7c4275e3b7050c
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Fri Jun 4 20:48:52 2010 +0200

    s4:objectclass LDB module - fix error result if an entry doesn't contain a 
structural objectclass
    
    We need to return LDB_ERR_UNWILLING_TO_PERFORM (not 
LDB_ERR_NAMING_VIOLATION).

commit 2a294d380f13edad6fcdd3572336ba797baaa0e1
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Jun 5 13:06:54 2010 +0200

    s4:objectclass LDB module - use "ldb_oom" for expressing out of memory

commit 3c4336bf949a47084ebcb068b2b9223eba4137e3
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Wed Jun 2 22:42:59 2010 +0200

    s4:objectclass LDB module - fix header and add my copyright

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/samdb/ldb_modules/acl.c               |   24 +-
 source4/dsdb/samdb/ldb_modules/objectclass.c       |  624 +++++++++++---------
 source4/dsdb/samdb/ldb_modules/objectclass_attrs.c |  392 ++++++++++++
 source4/dsdb/samdb/ldb_modules/samba_dsdb.c        |    2 +-
 source4/dsdb/samdb/ldb_modules/samldb.c            |  133 ++---
 source4/dsdb/samdb/ldb_modules/validate_update.c   |  120 ----
 source4/dsdb/samdb/ldb_modules/wscript_build       |   15 +-
 source4/dsdb/schema/schema_syntax.c                |   13 -
 source4/lib/ldb/tests/python/ldap.py               |  304 ++++++++++-
 9 files changed, 1116 insertions(+), 511 deletions(-)
 create mode 100644 source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
 delete mode 100644 source4/dsdb/samdb/ldb_modules/validate_update.c


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/acl.c 
b/source4/dsdb/samdb/ldb_modules/acl.c
index 1b84e8a..ccc7edf 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -730,21 +730,31 @@ static int acl_modify(struct ldb_module *module, struct 
ldb_request *req)
        for (i=0; i < req->op.mod.message->num_elements; i++){
                const struct dsdb_attribute *attr;
                /* clearTextPassword is not in schema */
-               if (strcmp("clearTextPassword", 
req->op.mod.message->elements[i].name) == 0) {
+               if (ldb_attr_cmp("clearTextPassword", 
req->op.mod.message->elements[i].name) == 0) {
                        attr = dsdb_attribute_by_lDAPDisplayName(schema, 
"unicodePwd");
                } else {
                        attr = dsdb_attribute_by_lDAPDisplayName(schema,
                                                                 
req->op.mod.message->elements[i].name);
                }
-               if (strcmp("nTSecurityDescriptor", 
req->op.mod.message->elements[i].name) == 0) {
+
+               /* This basic attribute existence check with the right errorcode
+                * is needed since this module is the first one which requests
+                * schema attribute informations.
+                * The complete attribute checking is done in the
+                * "objectclass_attrs" module behind this one.
+                */
+               if (!attr) {
+                       ldb_asprintf_errstring(ldb, "acl_modify: attribute '%s' 
on entry '%s' was not found in the schema!",
+                                              
req->op.mod.message->elements[i].name,
+                                              
ldb_dn_get_linearized(req->op.mod.message->dn));
+                       talloc_free(tmp_ctx);
+                       return LDB_ERR_NO_SUCH_ATTRIBUTE;
+               }
+
+               if (ldb_attr_cmp("nTSecurityDescriptor", 
req->op.mod.message->elements[i].name) == 0) {
                        modify_sd = true;
                } else {
 
-                       if (!attr) {
-                               DEBUG(10, ("acl_modify: cannot find attribute 
%s\n",
-                                          
req->op.mod.message->elements[i].name));
-                               goto fail;
-                       }
                        if (!insert_in_object_tree(tmp_ctx,
                                                   
&attr->attributeSecurityGUID, SEC_ADS_WRITE_PROP,
                                                   &new_node, &new_node)) {
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c 
b/source4/dsdb/samdb/ldb_modules/objectclass.c
index fdff3a8..b15dff0 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -3,6 +3,7 @@
 
    Copyright (C) Simo Sorce  2006-2008
    Copyright (C) Andrew Bartlett <abart...@samba.org> 2005-2009
+   Copyright (C) Matthias Dieter Wallnöfer 2010
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,13 +22,14 @@
 /*
  *  Name: ldb
  *
- *  Component: objectClass sorting module
+ *  Component: objectClass sorting and constraint checking module
  *
  *  Description: 
  *  - sort the objectClass attribute into the class
- *    hierarchy, 
- *  - fix DNs and attributes into 'standard' case
- *  - Add objectCategory and ntSecurityDescriptor defaults
+ *    hierarchy and perform constraint checks (correct RDN name,
+ *    valid parent),
+ *  - fix DNs into 'standard' case
+ *  - Add objectCategory and some other attribute defaults
  *
  *  Author: Andrew Bartlett
  */
@@ -49,8 +51,10 @@ struct oc_context {
 
        struct ldb_module *module;
        struct ldb_request *req;
+       const struct dsdb_schema *schema;
 
        struct ldb_reply *search_res;
+       struct ldb_reply *search_res2;
 
        int (*step_fn)(struct oc_context *);
 };
@@ -70,12 +74,13 @@ static struct oc_context *oc_init_context(struct ldb_module 
*module,
 
        ac = talloc_zero(req, struct oc_context);
        if (ac == NULL) {
-               ldb_set_errstring(ldb, "Out of Memory");
+               ldb_oom(ldb);
                return NULL;
        }
 
        ac->module = module;
        ac->req = req;
+       ac->schema = dsdb_get_schema(ldb, ac);
 
        return ac;
 }
@@ -346,42 +351,6 @@ static int fix_dn(TALLOC_CTX *mem_ctx,
        return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
 }
 
-/* Fix all attribute names to be in the correct case, and check they are all 
valid per the schema */
-static int fix_check_attributes(struct ldb_context *ldb,
-                               const struct dsdb_schema *schema,
-                               struct ldb_message *msg,
-                               enum ldb_request_type op)
-{
-       unsigned int i;
-       for (i=0; i < msg->num_elements; i++) {
-               const struct dsdb_attribute *attribute = 
dsdb_attribute_by_lDAPDisplayName(schema, msg->elements[i].name);
-               /* Add in a very special case for 'clearTextPassword',
-                * which is used for internal processing only, and is
-                * not presented in the schema */
-               if (!attribute) {
-                       if (strcasecmp(msg->elements[i].name, 
"clearTextPassword") != 0) {
-                               ldb_asprintf_errstring(ldb, "attribute %s is 
not a valid attribute in schema", msg->elements[i].name);
-                               /* Apparently Windows sends exactly this 
behaviour */
-                               return LDB_ERR_NO_SUCH_ATTRIBUTE;
-                       }
-               } else {
-                       msg->elements[i].name = attribute->lDAPDisplayName;
-
-                       /* We have to deny write operations on constructed 
attributes */
-                       if ((attribute->systemFlags & 
DS_FLAG_ATTR_IS_CONSTRUCTED) != 0) {
-                               ldb_asprintf_errstring(ldb, "attribute %s is 
constructed", msg->elements[i].name);
-                               if (op == LDB_ADD) {
-                                       return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
-                               } else {
-                                       return LDB_ERR_CONSTRAINT_VIOLATION;
-                               }
-                       }
-
-               }
-       }
-
-       return LDB_SUCCESS;
-}
 
 static int objectclass_do_add(struct oc_context *ac);
 
@@ -435,7 +404,6 @@ static int objectclass_add(struct ldb_module *module, 
struct ldb_request *req)
        if (ret != LDB_SUCCESS) {
                return ret;
        }
-       talloc_steal(search_req, parent_dn);
 
        ac->step_fn = objectclass_do_add;
 
@@ -445,7 +413,6 @@ static int objectclass_add(struct ldb_module *module, 
struct ldb_request *req)
 static int objectclass_do_add(struct oc_context *ac)
 {
        struct ldb_context *ldb;
-       const struct dsdb_schema *schema;
        struct ldb_request *add_req;
        char *value;
        struct ldb_message_element *objectclass_element, *el;
@@ -458,7 +425,6 @@ static int objectclass_do_add(struct oc_context *ac)
        const char *rdn_name = NULL;
 
        ldb = ldb_module_get_ctx(ac->module);
-       schema = dsdb_get_schema(ldb, ac);
 
        mem_ctx = talloc_new(ac);
        if (mem_ctx == NULL) {
@@ -468,7 +434,8 @@ static int objectclass_do_add(struct oc_context *ac)
 
        msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
 
-       /* Check we have a valid parent */
+       /* Check if we have a valid parent - this check is needed since
+        * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
        if (ac->search_res == NULL) {
                if (ldb_dn_compare(ldb_get_root_basedn(ldb), msg->dn) == 0) {
                        /* Allow the tree to be started */
@@ -483,27 +450,22 @@ static int objectclass_do_add(struct oc_context *ac)
                }
        } else {
 
-               /* Fix up the DN to be in the standard form, taking particular 
care to match the parent DN */
+               /* Fix up the DN to be in the standard form, taking
+                * particular care to match the parent DN */
                ret = fix_dn(msg, 
                             ac->req->op.add.message->dn,
                             ac->search_res->message->dn,
                             &msg->dn);
 
                if (ret != LDB_SUCCESS) {
-                       ldb_asprintf_errstring(ldb, "Could not munge DN %s into 
normal form", 
+                       ldb_asprintf_errstring(ldb, "objectclass: Could not 
munge DN %s into normal form",
                                               
ldb_dn_get_linearized(ac->req->op.add.message->dn));
                        talloc_free(mem_ctx);
                        return ret;
                }
 
        }
-       if (schema) {
-               ret = fix_check_attributes(ldb, schema, msg, 
ac->req->operation);
-               if (ret != LDB_SUCCESS) {
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
-
+       if (ac->schema != NULL) {
                /* This is now the objectClass list from the database */
                objectclass_element = ldb_msg_find_element(msg, "objectClass");
 
@@ -512,7 +474,8 @@ static int objectclass_do_add(struct oc_context *ac)
                        talloc_free(mem_ctx);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
-               ret = objectclass_sort(ac->module, schema, mem_ctx, 
objectclass_element, &sorted);
+               ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
+                                      objectclass_element, &sorted);
                if (ret != LDB_SUCCESS) {
                        talloc_free(mem_ctx);
                        return ret;
@@ -551,12 +514,13 @@ static int objectclass_do_add(struct oc_context *ac)
                objectclass_element = ldb_msg_find_element(msg, "objectClass");
 
                /* Make sure its valid to add an object of this type */
-               objectclass = 
get_last_structural_class(schema,objectclass_element);
+               objectclass = get_last_structural_class(ac->schema,
+                                                       objectclass_element);
                if(objectclass == NULL) {
                        ldb_asprintf_errstring(ldb,
-                                               "Failed to find a structural 
class for %s",
-                                                 
ldb_dn_get_linearized(msg->dn));
-                       return LDB_ERR_NAMING_VIOLATION;
+                                              "Failed to find a structural 
class for %s",
+                                              ldb_dn_get_linearized(msg->dn));
+                       return LDB_ERR_UNWILLING_TO_PERFORM;
                }
 
                rdn_name = ldb_dn_get_rdn_name(msg->dn);
@@ -573,28 +537,20 @@ static int objectclass_do_add(struct oc_context *ac)
                                = ldb_msg_find_element(ac->search_res->message, 
"objectClass");
 
                        bool allowed_class = false;
-                       int i, j;
+                       unsigned int i, j;
                        for (i=0; allowed_class == false && oc_el && i < 
oc_el->num_values; i++) {
                                const struct dsdb_class *sclass;
 
-                               sclass = 
dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
+                               sclass = 
dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
+                                                                              
&oc_el->values[i]);
                                if (!sclass) {
                                        /* We don't know this class?  what is 
going on? */
                                        continue;
                                }
-                               if (ldb_request_get_control(ac->req, 
LDB_CONTROL_RELAX_OID)) {
-                                       for (j=0; 
sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
-                                               if 
(ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) 
== 0) {
-                                                       allowed_class = true;
-                                                       break;
-                                               }
-                                       }
-                               } else {
-                                       for (j=0; 
sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
-                                               if 
(ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) 
== 0) {
-                                                       allowed_class = true;
-                                                       break;
-                                               }
+                               for (j=0; sclass->systemPossibleInferiors && 
sclass->systemPossibleInferiors[j]; j++) {
+                                       if 
(ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) 
== 0) {
+                                               allowed_class = true;
+                                               break;
                                        }
                                }
                        }
@@ -700,12 +656,9 @@ static int objectclass_modify(struct ldb_module *module, 
struct ldb_request *req
        struct ldb_context *ldb = ldb_module_get_ctx(module);
        struct ldb_message_element *objectclass_element;
        struct ldb_message *msg;
-       const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
-       struct class_list *sorted, *current;
        struct ldb_request *down_req;
        struct oc_context *ac;
-       TALLOC_CTX *mem_ctx;
-       char *value;
+       bool oc_changes = false;
        int ret;
 
        ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
@@ -714,11 +667,6 @@ static int objectclass_modify(struct ldb_module *module, 
struct ldb_request *req
        if (ldb_dn_is_special(req->op.mod.message->dn)) {
                return ldb_next_request(module, req);
        }
-       
-       /* Without schema, there isn't much to do here */
-       if (!schema) {
-               return ldb_next_request(module, req);
-       }
 
        /* As with the "real" AD we don't accept empty messages */
        if (req->op.mod.message->num_elements == 0) {
@@ -729,150 +677,32 @@ static int objectclass_modify(struct ldb_module *module, 
struct ldb_request *req
 
        ac = oc_init_context(module, req);
        if (ac == NULL) {
-               ldb_oom(ldb);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       if (!talloc_reference(ac, schema)) {
-               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       /* If no part of this touches the objectClass, then we don't
-        * need to make any changes.  */
-       objectclass_element = ldb_msg_find_element(req->op.mod.message, 
"objectClass");
-
-       /* If the only operation is the deletion of the objectClass
-        * then go on with just fixing the attribute case */
-       if (!objectclass_element) {
-               msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
-               if (msg == NULL) {
-                       return LDB_ERR_OPERATIONS_ERROR;
-               }
-               
-               ret = fix_check_attributes(ldb, schema, msg, req->operation);
-               if (ret != LDB_SUCCESS) {
-                       return ret;
-               }
-
-               ret = ldb_build_mod_req(&down_req, ldb, ac,
-                                       msg,
-                                       req->controls,
-                                       ac, oc_op_callback,
-                                       req);
-               if (ret != LDB_SUCCESS) {
-                       return ret;
-               }
-
-               /* go on with the call chain */
-               return ldb_next_request(module, down_req);
-       }
-
-       switch (objectclass_element->flags & LDB_FLAG_MOD_MASK) {
-       case LDB_FLAG_MOD_DELETE:
-               if (objectclass_element->num_values == 0) {
-                       return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
-               }
-               break;
-
-       case LDB_FLAG_MOD_REPLACE:
-               mem_ctx = talloc_new(ac);
-               if (mem_ctx == NULL) {
-                       return LDB_ERR_OPERATIONS_ERROR;
-               }
-
-               msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
-               if (msg == NULL) {
-                       talloc_free(mem_ctx);
-                       return LDB_ERR_OPERATIONS_ERROR;
-               }
-
-               ret = fix_check_attributes(ldb, schema, msg, req->operation);
-               if (ret != LDB_SUCCESS) {
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
-
-               ret = objectclass_sort(module, schema, mem_ctx, 
objectclass_element, &sorted);
-               if (ret != LDB_SUCCESS) {
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
-
-               /* We must completely replace the existing objectClass entry,
-                * because we need it sorted */
-               
-               ldb_msg_remove_attr(msg, "objectClass");
-               ret = ldb_msg_add_empty(msg, "objectClass", 
LDB_FLAG_MOD_REPLACE, NULL);
-               
-               if (ret != LDB_SUCCESS) {
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
-
-               /* Move from the linked list back into an ldb msg */
-               for (current = sorted; current; current = current->next) {
-                       /* copy the value as this string is on the schema
-                        * context and we can't rely on it not changing
-                        * before the operation is over */
-                       value = talloc_strdup(msg,
-                                       current->objectclass->lDAPDisplayName);
-                       if (value == NULL) {
-                               ldb_oom(ldb);
-                               talloc_free(mem_ctx);
-                               return LDB_ERR_OPERATIONS_ERROR;
-                       }
-                       ret = ldb_msg_add_string(msg, "objectClass", value);
-                       if (ret != LDB_SUCCESS) {
-                               ldb_set_errstring(ldb,
-                                       "objectclass: could not re-add sorted "
-                                       "objectclass to modify msg");
-                               talloc_free(mem_ctx);
-                               return ret;
-                       }
-               }
-               
-               talloc_free(mem_ctx);
-
-               ret = ldb_msg_sanity_check(ldb, msg);
-               if (ret != LDB_SUCCESS) {
-                       return ret;
-               }
-
-               ret = ldb_build_mod_req(&down_req, ldb, ac,
-                                       msg,
-                                       req->controls,
-                                       ac, oc_op_callback,
-                                       req);
-               if (ret != LDB_SUCCESS) {
-                       return ret;
-               }
-
-               /* go on with the call chain */
-               return ldb_next_request(module, down_req);
+       /* Without schema, there isn't much to do here */
+       if (ac->schema == NULL) {
+               talloc_free(ac);
+               return ldb_next_request(module, req);
        }
 
-       /* This isn't the default branch of the switch, but a 'in any
-        * other case'.  When a delete isn't for all objectClasses for
-        * example
-        */
-
        msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
        if (msg == NULL) {
-               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       ret = fix_check_attributes(ldb, schema, msg, req->operation);
-       if (ret != LDB_SUCCESS) {
-               ldb_oom(ldb);
-               return ret;
+       /* For now change everything except the objectclasses */
+
+       objectclass_element = ldb_msg_find_element(msg, "objectClass");
+       if (objectclass_element != NULL) {
+               ldb_msg_remove_attr(msg, "objectClass");
+               oc_changes = true;
        }
 
        ret = ldb_build_mod_req(&down_req, ldb, ac,
                                msg,
-                               req->controls,
-                               ac, oc_modify_callback,
+                               req->controls, ac,
+                               oc_changes ? oc_modify_callback : 
oc_op_callback,
                                req);
        if (ret != LDB_SUCCESS) {
                return ret;
@@ -883,8 +713,8 @@ static int objectclass_modify(struct ldb_module *module, 
struct ldb_request *req
 
 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
 {
-       struct ldb_context *ldb;
        static const char * const attrs[] = { "objectClass", NULL };
+       struct ldb_context *ldb;
        struct ldb_request *search_req;
        struct oc_context *ac;
        int ret;
@@ -914,8 +744,11 @@ static int oc_modify_callback(struct ldb_request *req, 
struct ldb_reply *ares)
 
        talloc_free(ares);
 
-       ret = ldb_build_search_req(&search_req, ldb, ac,
-                                  ac->req->op.mod.message->dn, LDB_SCOPE_BASE,
+       /* this looks up the real existing object for fetching some important
+        * informations (objectclasses) */
+       ret = ldb_build_search_req(&search_req, ldb,
+                                  ac, ac->req->op.mod.message->dn,
+                                  LDB_SCOPE_BASE,
                                   "(objectClass=*)",
                                   attrs, NULL, 
                                   ac, get_search_callback,
@@ -930,75 +763,197 @@ static int oc_modify_callback(struct ldb_request *req, 
struct ldb_reply *ares)
        if (ret != LDB_SUCCESS) {
                return ldb_module_done(ac->req, NULL, NULL, ret);
        }
+
        return LDB_SUCCESS;
 }
 
 static int objectclass_do_mod(struct oc_context *ac)
 {
        struct ldb_context *ldb;
-       const struct dsdb_schema *schema;
        struct ldb_request *mod_req;
        char *value;


-- 
Samba Shared Repository

Reply via email to