The branch, master has been updated
       via  7cb858e... s4-dsdb: Add a test for adding, deleting, and appending 
a posixAccount objectClass to a user
       via  0806006... s4-dsdb: fix handling of AUX classes in objectclass_sort
       via  8b88925... s4-dsdb: return an error if samAccountName is not 
specified when creating a user.
       via  d99084f... s4-dsdb: Move get_last_structural class from 
descriptor.c to util.c
       via  2ad086e... s4-dsdb: Add a check to prevent acl_modify from debuging 
a NULL message
       via  027cba6... Return NULL in strlower_talloc if src is NULL
       via  c3d1e5c... s4:provision Give a more useful error message in 
guess_names
      from  0c1ff3b... Always map EMFILE to ERRDOS, ERRnofids, *NOT* 
NT_STATUS_TOO_MANY_OPENED_FILES. This is what W2KR3 does for NTCreateX and 
openX calls. May be the correct fix for bug 6837 - "Too many open files" when 
trying to access large number of files. Jeremy.

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


- Log -----------------------------------------------------------------
commit 7cb858e1516e7900fddc08d8f69dfa8d003a587f
Author: Brendan Powers <[email protected]>
Date:   Mon Dec 14 20:51:10 2009 -0500

    s4-dsdb: Add a test for adding, deleting, and appending a posixAccount 
objectClass to a user
    
    Signed-off-by: Andrew Bartlett <[email protected]>

commit 08060068bf9ad7cc5f450e805b0caab30d407a56
Author: Brendan Powers <[email protected]>
Date:   Mon Dec 14 20:47:18 2009 -0500

    s4-dsdb: fix handling of AUX classes in objectclass_sort
    
    This is done by sorting the classes by subClass_order, which will
    check if the last structural class is valid to add (in
    objectclass_do_add instead checking the last class in the list).
    
    They were being sorted by building a class tree, and adding the
    classes to the list in that order. However, AUX classes usually don't
    fit into that tree, so LDB_ERR_OBJECT_CLASS_VIOLATION was returned. I
    have changed the behavior to sort the classes by subClass_order
    instead.
    
    Signed-off-by: Andrew Bartlett <[email protected]>

commit 8b889256540e471c399f020871cf18fb4d89e694
Author: Brendan Powers <[email protected]>
Date:   Mon Dec 14 20:40:26 2009 -0500

    s4-dsdb: return an error if samAccountName is not specified when creating a 
user.
    
    Makes sure samAccountName has been specified before adding a
    user. This happened while I was trying to add a user with the
    posixAccount objectclass. I forgot to specify the user objectClass,
    and samba segfaulted. It now returns LDB_ERR_CONSTRAINT_VIOLATION.
    
    Signed-off-by: Andrew Bartlett <[email protected]>

commit d99084ffdb2c898c18bd4b264d8dd297dd0f1f25
Author: Brendan Powers <[email protected]>
Date:   Mon Dec 14 20:36:44 2009 -0500

    s4-dsdb: Move get_last_structural class from descriptor.c to util.c
    
    It can now also be used by objectclass.c
    
    get_last_structural_class now ignores AUX classes, because they are
    not structural
    
    Signed-off-by: Andrew Bartlett <[email protected]>

commit 2ad086e7f6ab39767cd691b059ab5d78b03d55c0
Author: Brendan Powers <[email protected]>
Date:   Mon Dec 14 20:32:28 2009 -0500

    s4-dsdb: Add a check to prevent acl_modify from debuging a NULL message
    
    Check to see if there were any messages passed to acl_modify before
    debugging the first one. I think I caused this by some malformed
    LDIF.
    
    Signed-off-by: Andrew Bartlett <[email protected]>

commit 027cba6a49fa1b7ed81d22d3cac7cc1d469d547a
Author: Brendan Powers <[email protected]>
Date:   Mon Dec 14 20:28:48 2009 -0500

    Return NULL in strlower_talloc if src is NULL
    
    Prevents strlower_talloc from segfaulting if you pass it a NULL string.
    
    Signed-off-by: Andrew Bartlett <[email protected]>

commit c3d1e5ca0c9f8d6c59a6fd4252a6e275b35e06de
Author: Andrew Bartlett <[email protected]>
Date:   Tue Dec 15 16:41:37 2009 +1100

    s4:provision Give a more useful error message in guess_names
    
    The problem here is that as we start to get 'real users' they still
    decide to do silly things, like load empty but existing smb.conf
    files.  Let's give them a better chance to discover what they did
    wrong.
    
    Andrew Bartlett

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

Summary of changes:
 lib/util/charset/util_unistr.c                 |    4 +
 source4/dsdb/samdb/ldb_modules/acl.c           |    6 +-
 source4/dsdb/samdb/ldb_modules/descriptor.c    |   17 +--
 source4/dsdb/samdb/ldb_modules/objectclass.c   |  279 +++++++++++------------
 source4/dsdb/samdb/ldb_modules/password_hash.c |    7 +
 source4/dsdb/samdb/ldb_modules/util.c          |   28 +++
 source4/dsdb/samdb/ldb_modules/util.h          |    1 +
 source4/lib/ldb/tests/python/ldap.py           |   30 +++
 source4/scripting/python/samba/provision.py    |   14 +-
 9 files changed, 220 insertions(+), 166 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c
index 045aa4a..f820726 100644
--- a/lib/util/charset/util_unistr.c
+++ b/lib/util/charset/util_unistr.c
@@ -430,6 +430,10 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char 
*src)
        char *dest;
        struct smb_iconv_convenience *iconv_convenience = 
get_iconv_convenience();
 
+       if(src == NULL) {
+               return NULL;
+       }
+
        /* this takes advantage of the fact that upper/lower can't
           change the length of a character by more than 1 byte */
        dest = talloc_array(ctx, char, 2*(strlen(src))+1);
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c 
b/source4/dsdb/samdb/ldb_modules/acl.c
index 6cb50b2..b70b895 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -760,7 +760,11 @@ static int acl_modify(struct ldb_module *module, struct 
ldb_request *req)
                NULL
        };
 
-       DEBUG(10, ("ldb:acl_modify: %s\n", 
req->op.mod.message->elements[0].name));
+       /* Don't print this debug statement if elements[0].name is going to be 
NULL */
+       if(req->op.mod.message->num_elements > 0)
+       {
+               DEBUG(10, ("ldb:acl_modify: %s\n", 
req->op.mod.message->elements[0].name));
+       }
        if (what_is_user(module) == SECURITY_SYSTEM) {
                return ldb_next_request(module, req);
        }
diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c 
b/source4/dsdb/samdb/ldb_modules/descriptor.c
index 7622f96..d5a5e36 100644
--- a/source4/dsdb/samdb/ldb_modules/descriptor.c
+++ b/source4/dsdb/samdb/ldb_modules/descriptor.c
@@ -41,6 +41,7 @@
 #include "libcli/security/security.h"
 #include "auth/auth.h"
 #include "param/param.h"
+#include "util.h"
 
 struct descriptor_data {
        int _dummy;
@@ -56,22 +57,6 @@ struct descriptor_context {
        int (*step_fn)(struct descriptor_context *);
 };
 
-static const struct dsdb_class * get_last_structural_class(const struct 
dsdb_schema *schema, struct ldb_message_element *element)
-{
-       const struct dsdb_class *last_class = NULL;
-       int i;
-       for (i = 0; i < element->num_values; i++){
-               if (!last_class) {
-                       last_class = 
dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
-               } else {
-                       const struct dsdb_class *tmp_class = 
dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
-                       if (tmp_class->subClass_order > 
last_class->subClass_order)
-                               last_class = tmp_class;
-               }
-       }
-       return last_class;
-}
-
 struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
                               struct ldb_dn *dn,
                               struct security_token *token,
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c 
b/source4/dsdb/samdb/ldb_modules/objectclass.c
index c47e360..475b53a 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -43,6 +43,7 @@
 #include "auth/auth.h"
 #include "param/param.h"
 #include "../libds/common/flags.h"
+#include "util.h"
 
 struct oc_context {
 
@@ -92,10 +93,8 @@ static int objectclass_sort(struct ldb_module *module,
                            struct class_list **sorted_out) 
 {
        struct ldb_context *ldb;
-       int i;
-       int layer;
-       struct class_list *sorted = NULL, *parent_class = NULL,
-               *subclass = NULL, *unsorted = NULL, *current, *poss_subclass, 
*poss_parent, *new_parent;
+       int i, lowest;
+       struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL, 
*poss_parent = NULL, *new_parent = NULL, *current_lowest = NULL;
 
        ldb = ldb_module_get_ctx(module);
 
@@ -148,20 +147,17 @@ static int objectclass_sort(struct ldb_module *module,
                        return LDB_ERR_NO_SUCH_ATTRIBUTE;
                }
 
-               /* this is the root of the tree.  We will start
-                * looking for subclasses from here */
-               if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) 
== 0) {
-                       DLIST_ADD_END(parent_class, current, struct class_list 
*);
-               } else {
+               /* Don't add top to list, we will do that later */
+               if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) 
!= 0) {
                        DLIST_ADD_END(unsorted, current, struct class_list *);
                }
        }
 
-       if (parent_class == NULL) {
-               current = talloc(mem_ctx, struct class_list);
-               current->objectclass = dsdb_class_by_lDAPDisplayName(schema, 
"top");
-               DLIST_ADD_END(parent_class, current, struct class_list *);
-       }
+       /* Add top here, to prevent duplicates */
+       current = talloc(mem_ctx, struct class_list);
+       current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
+       DLIST_ADD_END(sorted, current, struct class_list *);
+
 
        /* For each object:  find parent chain */
        for (current = unsorted; schema && current; current = current->next) {
@@ -180,43 +176,23 @@ static int objectclass_sort(struct ldb_module *module,
                DLIST_ADD_END(unsorted, new_parent, struct class_list *);
        }
 
-       /* DEBUGGING aid:  how many layers are we down now? */
-       layer = 0;
-       do {
-               layer++;
-               /* Find all the subclasses of classes in the
-                * parent_classes.  Push them onto the subclass list */
-
-               /* Ensure we don't bother if there are no unsorted entries left 
*/
-               for (current = parent_class; schema && unsorted && current; 
current = current->next) {
-                       /* Walk the list of possible subclasses in unsorted */
-                       for (poss_subclass = unsorted; poss_subclass; ) {
-                               struct class_list *next;
-                               
-                               /* Save the next pointer, as the DLIST_ macros 
will change poss_subclass->next */
-                               next = poss_subclass->next;
-
-                               if 
(ldb_attr_cmp(poss_subclass->objectclass->subClassOf, 
current->objectclass->lDAPDisplayName) == 0) {
-                                       DLIST_REMOVE(unsorted, poss_subclass);
-                                       DLIST_ADD(subclass, poss_subclass);
-                                       
-                                       break;
-                               }
-                               poss_subclass = next;
+       do
+       {
+               lowest = INT_MAX;
+               current_lowest = NULL;
+               for (current = unsorted; schema && current; current = 
current->next) {
+                       if(current->objectclass->subClass_order < lowest) {
+                               current_lowest = current;
+                               lowest = current->objectclass->subClass_order;
                        }
                }
 
-               /* Now push the parent_classes as sorted, we are done with
-               these.  Add to the END of the list by concatenation */
-               DLIST_CONCATENATE(sorted, parent_class, struct class_list *);
-
-               /* and now find subclasses of these */
-               parent_class = subclass;
-               subclass = NULL;
+               if(current_lowest != NULL) {
+                       DLIST_REMOVE(unsorted,current_lowest);
+                       DLIST_ADD_END(sorted,current_lowest, struct class_list 
*);
+               }
+       } while(unsorted);
 
-               /* If we didn't find any subclasses we will fall out
-                * the bottom here */
-       } while (parent_class);
 
        if (!unsorted) {
                *sorted_out = sorted;
@@ -466,11 +442,14 @@ static int objectclass_do_add(struct oc_context *ac)
        const struct dsdb_schema *schema;
        struct ldb_request *add_req;
        char *value;
-       struct ldb_message_element *objectclass_element;
+       struct ldb_message_element *objectclass_element, *el;
        struct ldb_message *msg;
        TALLOC_CTX *mem_ctx;
        struct class_list *sorted, *current;
        int ret;
+       const struct dsdb_class *objectclass;
+       int32_t systemFlags = 0;
+       const char *rdn_name = NULL;
 
        ldb = ldb_module_get_ctx(ac->module);
        schema = dsdb_get_schema(ldb);
@@ -560,120 +539,128 @@ static int objectclass_do_add(struct oc_context *ac)
                                talloc_free(mem_ctx);
                                return ret;
                        }
-                       /* Last one is the critical one */
-                       if (!current->next) {
-                               struct ldb_message_element *el;
-                               int32_t systemFlags = 0;
-                               const char *rdn_name = 
ldb_dn_get_rdn_name(msg->dn);
-                               if (current->objectclass->rDNAttID
-                                   && ldb_attr_cmp(rdn_name, 
current->objectclass->rDNAttID) != 0) {
-                                       ldb_asprintf_errstring(ldb,
-                                                              "RDN %s is not 
correct for most specific structural objectclass %s, should be %s",
-                                                              rdn_name, 
current->objectclass->lDAPDisplayName, current->objectclass->rDNAttID);
-                                       return LDB_ERR_NAMING_VIOLATION;
-                               }
+               }
+
+               /* Retrive the message again so get_last_structural_class works 
*/
+               objectclass_element = ldb_msg_find_element(msg, "objectClass");
 
-                               if (ac->search_res && ac->search_res->message) {
-                                       struct ldb_message_element *oc_el
-                                               = 
ldb_msg_find_element(ac->search_res->message, "objectClass");
+               /* Make sure its valid to add an object of this type */
+               objectclass = 
get_last_structural_class(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;
+               }
 
-                                       bool allowed_class = false;
-                                       int i, j;
-                                       for (i=0; allowed_class == false && 
oc_el && i < oc_el->num_values; i++) {
-                                               const struct dsdb_class *sclass;
+               rdn_name = ldb_dn_get_rdn_name(msg->dn);
+               if (objectclass->rDNAttID
+                       && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
+                       ldb_asprintf_errstring(ldb,
+                                               "RDN %s is not correct for most 
specific structural objectclass %s, should be %s",
+                                               rdn_name, 
objectclass->lDAPDisplayName, objectclass->rDNAttID);
+                       return LDB_ERR_NAMING_VIOLATION;
+               }
 
-                                               sclass = 
dsdb_class_by_lDAPDisplayName_ldb_val(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(current->objectclass->lDAPDisplayName, 
sclass->systemPossibleInferiors[j]) == 0) {
-                                                                       
allowed_class = true;
-                                                                       break;
-                                                               }
-                                                       }
-                                               } else {
-                                                       for (j=0; 
sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
-                                                               if 
(ldb_attr_cmp(current->objectclass->lDAPDisplayName, 
sclass->systemPossibleInferiors[j]) == 0) {
-                                                                       
allowed_class = true;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                       }
+               if (ac->search_res && ac->search_res->message) {
+                       struct ldb_message_element *oc_el
+                               = ldb_msg_find_element(ac->search_res->message, 
"objectClass");
 
-                                       if (!allowed_class) {
-                                               ldb_asprintf_errstring(ldb, 
"structural objectClass %s is not a valid child class for %s",
-                                                              
current->objectclass->lDAPDisplayName, 
ldb_dn_get_linearized(ac->search_res->message->dn));
-                                               return LDB_ERR_NAMING_VIOLATION;
-                                       }
-                               }
+                       bool allowed_class = false;
+                       int i, j;
+                       for (i=0; allowed_class == false && oc_el && i < 
oc_el->num_values; i++) {
+                               const struct dsdb_class *sclass;
 
-                               if (current->objectclass->systemOnly && 
!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
-                                       ldb_asprintf_errstring(ldb, 
"objectClass %s is systemOnly, rejecting creation of %s",
-                                                              
current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
-                                       return LDB_ERR_UNWILLING_TO_PERFORM;
+                               sclass = 
dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
+                               if (!sclass) {
+                                       /* We don't know this class?  what is 
going on? */
+                                       continue;
                                }
-
-                               if (!ldb_msg_find_element(msg, 
"objectCategory")) {
-                                       struct dsdb_extended_dn_store_format 
*dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct 
dsdb_extended_dn_store_format);
-                                       if (dn_format && 
dn_format->store_extended_dn_in_ldb == false) {
-                                               /* Strip off extended 
components */
-                                               struct ldb_dn *dn = 
ldb_dn_new(msg, ldb, current->objectclass->defaultObjectCategory);
-                                               value = 
ldb_dn_alloc_linearized(msg, dn);
-                                               talloc_free(dn);
-                                       } else {
-                                               value = talloc_strdup(msg, 
current->objectclass->defaultObjectCategory);
+                               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;
+                                               }
                                        }
-                                       if (value == NULL) {
-                                               ldb_oom(ldb);
-                                               talloc_free(mem_ctx);
-                                               return LDB_ERR_OPERATIONS_ERROR;
+                               } else {
+                                       for (j=0; 
sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+                                               if 
(ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) 
== 0) {
+                                                       allowed_class = true;
+                                                       break;
+                                               }
                                        }
-                                       ldb_msg_add_string(msg, 
"objectCategory", value);
-                               }
-                               if (!ldb_msg_find_element(msg, 
"showInAdvancedViewOnly") && (current->objectclass->defaultHidingValue == 
true)) {
-                                       ldb_msg_add_string(msg, 
"showInAdvancedViewOnly",
-                                                          "TRUE");
                                }
+                       }
 
-                               /* There are very special rules for 
systemFlags, see MS-ADTS 3.1.1.5.2.4 */
-                               el = ldb_msg_find_element(msg, "systemFlags");
+                       if (!allowed_class) {
+                               ldb_asprintf_errstring(ldb, "structural 
objectClass %s is not a valid child class for %s",
+                                               objectclass->lDAPDisplayName, 
ldb_dn_get_linearized(ac->search_res->message->dn));
+                               return LDB_ERR_NAMING_VIOLATION;
+                       }
+               }
 
-                               systemFlags = ldb_msg_find_attr_as_int(msg, 
"systemFlags", 0);
+               if (objectclass->systemOnly && 
!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+                       ldb_asprintf_errstring(ldb, "objectClass %s is 
systemOnly, rejecting creation of %s",
+                                               objectclass->lDAPDisplayName, 
ldb_dn_get_linearized(msg->dn));
+                       return LDB_ERR_UNWILLING_TO_PERFORM;
+               }
 
-                               if (el) {
-                                       /* Only these flags may be set by a 
client, but we can't tell between a client and our provision at this point */
-                                       /* systemFlags &= ( 
SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | 
SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
-                                       ldb_msg_remove_element(msg, el);
-                               }
+               if (!ldb_msg_find_element(msg, "objectCategory")) {
+                       struct dsdb_extended_dn_store_format *dn_format = 
talloc_get_type(ldb_module_get_private(ac->module), struct 
dsdb_extended_dn_store_format);
+                       if (dn_format && dn_format->store_extended_dn_in_ldb == 
false) {
+                               /* Strip off extended components */
+                               struct ldb_dn *dn = ldb_dn_new(msg, ldb, 
objectclass->defaultObjectCategory);
+                               value = ldb_dn_alloc_linearized(msg, dn);
+                               talloc_free(dn);
+                       } else {
+                               value = talloc_strdup(msg, 
objectclass->defaultObjectCategory);
+                       }
+                       if (value == NULL) {
+                               ldb_oom(ldb);
+                               talloc_free(mem_ctx);
+                               return LDB_ERR_OPERATIONS_ERROR;
+                       }
+                       ldb_msg_add_string(msg, "objectCategory", value);
+               }
+               if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && 
(objectclass->defaultHidingValue == true)) {
+                       ldb_msg_add_string(msg, "showInAdvancedViewOnly",
+                                               "TRUE");
+               }
 
-                               /* This flag is only allowed on attributeSchema 
objects */
-                               if 
(ldb_attr_cmp(current->objectclass->lDAPDisplayName, "attributeSchema") == 0) {
-                                       systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
-                               }
+               /* There are very special rules for systemFlags, see MS-ADTS 
3.1.1.5.2.4 */
+               el = ldb_msg_find_element(msg, "systemFlags");
 
-                               if 
(ldb_attr_cmp(current->objectclass->lDAPDisplayName, "server") == 0) {
-                                       systemFlags |= 
(int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME 
| SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
-                               } else if 
(ldb_attr_cmp(current->objectclass->lDAPDisplayName, "site") == 0
-                                          || 
ldb_attr_cmp(current->objectclass->lDAPDisplayName, "serverContainer") == 0
-                                          || 
ldb_attr_cmp(current->objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
-                                       systemFlags |= 
(int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
-
-                               } else if 
(ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLink") == 0
-                                          || 
ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLinkBridge") == 0
-                                          || 
ldb_attr_cmp(current->objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
-                                       systemFlags |= 
(int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
-                               }
+               systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
 
-                               /* TODO: If parent object is site or subnet, 
also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
+               if (el) {
+                       /* Only these flags may be set by a client, but we 
can't tell between a client and our provision at this point */
+                       /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | 
SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
+                       ldb_msg_remove_element(msg, el);
+               }
 
-                               if (el || systemFlags != 0) {
-                                       samdb_msg_add_int(ldb, msg, msg, 
"systemFlags", systemFlags);
-                               }
-                       }
+               /* This flag is only allowed on attributeSchema objects */
+               if (ldb_attr_cmp(objectclass->lDAPDisplayName, 
"attributeSchema") == 0) {
+                       systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
+               }
+
+               if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
+                       systemFlags |= 
(int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME 
| SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
+               } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") 
== 0
+                               || ldb_attr_cmp(objectclass->lDAPDisplayName, 
"serverContainer") == 0
+                               || ldb_attr_cmp(objectclass->lDAPDisplayName, 
"ntDSDSA") == 0) {
+                       systemFlags |= 
(int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
+
+               } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, 
"siteLink") == 0
+                               || ldb_attr_cmp(objectclass->lDAPDisplayName, 
"siteLinkBridge") == 0
+                               || ldb_attr_cmp(objectclass->lDAPDisplayName, 
"nTDSConnection") == 0) {
+                       systemFlags |= 
(int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
+               }
+
+               /* TODO: If parent object is site or subnet, also add 
(SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
+
+               if (el || systemFlags != 0) {
+                       samdb_msg_add_int(ldb, msg, msg, "systemFlags", 
systemFlags);
                }
        }
 
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c 
b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 4d4f500..df4a344 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -1487,6 +1487,13 @@ static int setup_io(struct ph_context *ac,
 
        io->n.lm_hash                   = samdb_result_hash(io->ac, new_msg, 
"dBCSPwd");
 
+       if(io->u.sAMAccountName == NULL)
+       {
+               ldb_asprintf_errstring(ldb, "samAccountName is missing on %s 
for attempted password set/change",
+                       ldb_dn_get_linearized(new_msg->dn));
+               return(LDB_ERR_CONSTRAINT_VIOLATION);
+       }
+
        return LDB_SUCCESS;
 }
 
diff --git a/source4/dsdb/samdb/ldb_modules/util.c 
b/source4/dsdb/samdb/ldb_modules/util.c
index d8d55ae..8d9930a 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -25,6 +25,7 @@
 #include "librpc/ndr/libndr.h"
 #include "dsdb/samdb/ldb_modules/util.h"
 #include "dsdb/samdb/samdb.h"
+#include "util.h"
 
 /*
   add a set of controls to a ldb_request structure based on a set of
@@ -337,3 +338,30 @@ int dsdb_module_rename(struct ldb_module *module,
        talloc_free(tmp_ctx);
        return ret;
 }
+
+const struct dsdb_class * get_last_structural_class(const struct dsdb_schema 
*schema,const struct ldb_message_element *element)
+{
+       const struct dsdb_class *last_class = NULL;
+       int i;
+
+       for (i = 0; i < element->num_values; i++){
+               const struct dsdb_class *tmp_class = 
dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
+
+               if(tmp_class == NULL) {
+                       continue;
+               }
+
+               if(tmp_class->objectClassCategory == 3) {
+                       continue;
+               }
+
+               if (!last_class) {
+                       last_class = tmp_class;
+               } else {
+                       if (tmp_class->subClass_order > 
last_class->subClass_order)
+                               last_class = tmp_class;
+               }
+       }
+
+       return last_class;
+}
diff --git a/source4/dsdb/samdb/ldb_modules/util.h 
b/source4/dsdb/samdb/ldb_modules/util.h
index 56db27d..41ec873 100644
--- a/source4/dsdb/samdb/ldb_modules/util.h
+++ b/source4/dsdb/samdb/ldb_modules/util.h
@@ -19,6 +19,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+struct dsdb_schema; /* predeclare schema struct */
 #include "dsdb/samdb/ldb_modules/util_proto.h"
 
 #define DSDB_SEARCH_SEARCH_ALL_PARTITIONS     0x0001
diff --git a/source4/lib/ldb/tests/python/ldap.py 
b/source4/lib/ldb/tests/python/ldap.py
index d0a0ed2..54b623a 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -1719,6 +1719,36 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + 
self.base_dn + """
         res = ldb.search(self.base_dn, expression="objectCategory=group", 
scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
         self.assertTrue(len(res) > 0)


-- 
Samba Shared Repository

Reply via email to