Hi Mathias,

We try to get rid of the modify_ldif way of doing ldb modification.
It's better to create a ldb.Message() object and then do a ldb.modify() with it like this:


--- a/source4/scripting/python/samba/upgradehelpers.py
+++ b/source4/scripting/python/samba/upgradehelpers.py
@@ -835,14 +835,13 @@ def update_machine_account_password(samdb, secrets_ldb, names):
         res = samdb.search(expression=expression, attrs=[])
         assert(len(res) == 1)

+        msg = ldb.Message(res[0].dn)
         machinepass = samba.generate_random_password(128, 255)
-
-        samdb.modify_ldif("""
-dn: """ + str(res[0].dn) + """
-changetype: modify
-replace: clearTextPassword
-clearTextPassword:: """ + base64.b64encode(machinepass.encode('utf-16-le')) + """
-""")
+        mpu = machinepass.encode('utf-16-le')
+        msg["clearTextPassword"] = ldb.MessageElement(mpu,
+                                                ldb.FLAG_MOD_REPLACE,
+                                                "clearTextPassword")
+        samdb.modify(msg)

res = samdb.search(expression=("samAccountName=%s$" % names.netbiosname),
                      attrs=["msDs-keyVersionNumber"])

Matthieu.

On 11/11/2010 12:48, Matthias Dieter WallnXXfer wrote:
The branch, master has been updated
        via  bb241f5 s4:pytevent.c - fix a discard const warning
        via  f036790 ldb:ldb_ldap.c rename operation - check for the RDN name 
and value
        via  feb00fe s4:dsdb - proof against empty RDN values where expected
        via  4fe63d9 Cannot create OU using custom Schema class
        via  e96c9df s4:objectclass LDB module - allow RDNs also to come from 
superclasses
        via  4f86f29 s4:passwords.py - add a test for the normal "userPassword" 
behaviour
        via  7f171a9 s4:password_hash and acl LDB modules - handle the "userPassword" 
attribute according to the "dSHeuristics"
        via  d6c78fb s4:password_hash LDB module - move 
"samdb_msg_find_old_and_new_ldb_val" into the password_hash LDB module
        via  eff1e8c s4:libnet/libnet_samsync_ldb.c - remove "userPassword" 
remove code
        via  39f8661 s4:local_password LDB module - remove schema checking code 
and fix some typos
        via  ed704c2 s4:ldb_modules/util.c - "dsHeuristics" ->  "dSHeuristics"
        via  79548f0 s4:selftest/tests.py - skip the "passwords.py" suite on 
Windows 2000 domain function level
        via  5ded90e s4:acl.py - two password change tests are expected to 
fails on Windows 2000 function level
        via  2403aaa s4:upgradehelpers.py - use "clearTextPassword" rather than 
"userPassword"
        via  7c59ece s4:speedtest.py - use "unicodePwd" for setting user's 
password
        via  0e94569 s4:speedtest.py - remove duplicated code
        via  0a29e55 s4:speedtest.py - fix script name in the help text
        via  ed1ca1c s4:speedtest.py - make it executable
        via  cc7f390 s4:python tests - fix script names in the help text
       from  ee50bdd s4-loadparm: fix the FLAG_DEFAULT settings on specially 
handled parameters

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


- Log -----------------------------------------------------------------
commit bb241f5cf8424c2576d5bc33ac149e5720b82068
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 16:21:41 2010 +0100

     s4:pytevent.c - fix a discard const warning

     Autobuild-User: Matthias Dieter Wallnöfer<m...@samba.org>
     Autobuild-Date: Thu Nov 11 09:47:55 UTC 2010 on sn-devel-104

commit f0367905d9a6db76712f1dcf9734f64fe5c5e1b3
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 16:20:38 2010 +0100

     ldb:ldb_ldap.c rename operation - check for the RDN name and value

     Make it more similar to "ldb_ildap.c" and also more save

commit feb00fe7cc238a78b3832c116cb4634936597735
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 16:05:16 2010 +0100

     s4:dsdb - proof against empty RDN values where expected

     This should prevent crashes as pointed out on the mailing list.

commit 4fe63d927e5e684d3e2bec9642a1e77b056ab2ed
Author: Zahari Zahariev<zahari.zahar...@postpath.com>
Date:   Tue Nov 9 14:55:32 2010 +0200

     Cannot create OU using custom Schema class

     If we define our own child class 'subClassOf' system Schema class
     e.g. organizationalUnit then we cannot create OU in the Dafualt
     Naming Context that has this custom Schama class in the objectClass
     attribute.

commit e96c9df817326197a0866a18ad53621405b8bee8
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 15:12:02 2010 +0100

     s4:objectclass LDB module - allow RDNs also to come from superclasses

     Detected by a testcase written by Zahari Zahariev.

commit 4f86f297a22655067006f88eed5f6cb980742b81
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Tue Nov 9 15:04:47 2010 +0100

     s4:passwords.py - add a test for the normal "userPassword" behaviour

     Just to make sure that this works now too

commit 7f171a9e0f9b5945bd16a1330ba0908090659030
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Tue Nov 9 14:39:30 2010 +0100

     s4:password_hash and acl LDB modules - handle the "userPassword" attribute according 
to the "dSHeuristics"

commit d6c78fbd3a88e9fc7b625a03d163e9b5098b94d6
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Tue Nov 9 14:45:18 2010 +0100

     s4:password_hash LDB module - move "samdb_msg_find_old_and_new_ldb_val" 
into the password_hash LDB module

     It's only used there and so I think it doesn't really belong in
     "dsdb/common/util.c" (I first thought that it could be useful for ACL 
checking
     but obviously it wasn't).

commit eff1e8cd5d17ca990341e463da03fb1075bdb0d0
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Tue Nov 9 18:46:37 2010 +0100

     s4:libnet/libnet_samsync_ldb.c - remove "userPassword" remove code

     It could also be a normal attribute with a normal content, and if it's not
     like that then it's for sure empty.

commit 39f86619f5f30461d3c1896e88b6b3df2b51a26e
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Tue Nov 9 18:42:26 2010 +0100

     s4:local_password LDB module - remove schema checking code and fix some 
typos

     This is now done by the "objectclass_attrs" LDB module.

commit ed704c28b2f24228b61dee21d873f6b09bf98ca4
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Tue Nov 9 19:44:27 2010 +0100

     s4:ldb_modules/util.c - "dsHeuristics" ->  "dSHeuristics"

commit 79548f0da243884d60845f61fe2404e26eb52f65
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Thu Nov 11 10:01:26 2010 +0100

     s4:selftest/tests.py - skip the "passwords.py" suite on Windows 2000 
domain function level

     The "userPassword" password change functionality isn't available and so it
     causes big parts of the testsuite to fail. On the other hand we've basic 
tests
     in "acl.py" and indirectly also over SAMR and kpasswd so I propose to 
simply
     skip it.

commit 5ded90ef66744e8919868362ac455bdbf4b1568b
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Thu Nov 11 09:33:06 2010 +0100

     s4:acl.py - two password change tests are expected to fails on Windows 
2000 function level

commit 2403aaa7591e1827d91644579dbf503d8e9a7df6
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 14:01:58 2010 +0100

     s4:upgradehelpers.py - use "clearTextPassword" rather than "userPassword"

     It's the default internal s4 password change attribute

commit 7c59ecec5078c0ab8587bb322a228419f5a8c978
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 13:26:31 2010 +0100

     s4:speedtest.py - use "unicodePwd" for setting user's password

     It's available on all AD hosts (including Windows 2000) and on all 
configurations!

commit 0e945697f59b7215d46af0709ac698f7483850df
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 13:28:22 2010 +0100

     s4:speedtest.py - remove duplicated code

commit 0a29e552cb29cadbb75e64d8cc1278891132a7b0
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 13:37:46 2010 +0100

     s4:speedtest.py - fix script name in the help text

commit ed1ca1c49e10c9f97aa1334f9aedf631352d144c
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 13:29:14 2010 +0100

     s4:speedtest.py - make it executable

commit cc7f390bf940a2f009e16c3811e38424d62ca2dd
Author: Matthias Dieter Wallnöfer<m...@samba.org>
Date:   Wed Nov 10 13:35:30 2010 +0100

     s4:python tests - fix script names in the help text

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

Summary of changes:
  lib/tevent/pytevent.c                            |    2 +-
  source4/dsdb/common/util.c                       |   67 +------------
  source4/dsdb/samdb/ldb_modules/acl.c             |   25 ++++-
  source4/dsdb/samdb/ldb_modules/local_password.c  |   18 +--
  source4/dsdb/samdb/ldb_modules/objectclass.c     |   54 ++++++++--
  source4/dsdb/samdb/ldb_modules/password_hash.c   |  117 +++++++++++++++++-----
  source4/dsdb/samdb/ldb_modules/repl_meta_data.c  |    8 ++
  source4/dsdb/samdb/ldb_modules/samldb.c          |   13 ++-
  source4/dsdb/samdb/ldb_modules/util.c            |   24 ++++-
  source4/dsdb/samdb/ldb_modules/wscript_build     |    2 +-
  source4/dsdb/tests/python/acl.py                 |   19 +++-
  source4/dsdb/tests/python/ldap_schema.py         |   58 +++++++++++-
  source4/dsdb/tests/python/passwords.py           |  100 ++++++++++++++++++-
  source4/dsdb/tests/python/sec_descriptor.py      |    2 +-
  source4/dsdb/tests/python/urgent_replication.py  |    2 +-
  source4/lib/ldb/ldb_ldap/ldb_ldap.c              |   14 ++-
  source4/lib/ldb/modules/rdn_name.c               |   15 ++-
  source4/libnet/libnet_samsync_ldb.c              |    6 -
  source4/scripting/devel/speedtest.py             |    9 +-
  source4/scripting/python/samba/upgradehelpers.py |   13 ++-
  source4/selftest/tests.py                        |    6 +-
  21 files changed, 424 insertions(+), 150 deletions(-)
  mode change 100644 =>  100755 source4/scripting/devel/speedtest.py


Changeset truncated at 500 lines:

diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c
index 5999802..22541bb 100644
--- a/lib/tevent/pytevent.c
+++ b/lib/tevent/pytevent.c
@@ -629,7 +629,7 @@ static void py_tevent_context_dealloc(TeventContext_Object 
*self)

  static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, 
PyObject *kwargs)
  {
-       const char *kwnames[] = { "name", NULL };
+       const char * const kwnames[] = { "name", NULL };
        char *name = NULL;
        struct tevent_context *ev;
        TeventContext_Object *ret;
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 16d5011..7f6ce64 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -699,68 +699,6 @@ struct ldb_message_element *samdb_find_attribute(struct 
ldb_context *ldb,
        return NULL;
  }

-/*
- * This is intended for use by the "password hash" module since there
- * password changes can be specified through one message element with the
- * new password (to set) and another one with the old password (to unset).
- *
- * The first which sets a password (new value) can have flags
- * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
- * for entries). The latter (old value) has always specified
- * LDB_FLAG_MOD_DELETE.
- *
- * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
- * matching message elements are malformed in respect to the set/change rules.
- * Otherwise it returns LDB_SUCCESS.
- */
-int samdb_msg_find_old_and_new_ldb_val(const struct ldb_message *msg,
-                                      const char *name,
-                                      enum ldb_request_type operation,
-                                      const struct ldb_val **new_val,
-                                      const struct ldb_val **old_val)
-{
-       unsigned int i;
-
-       *new_val = NULL;
-       *old_val = NULL;
-
-       if (msg == NULL) {
-               return LDB_SUCCESS;
-       }
-
-       for (i = 0; i<  msg->num_elements; i++) {
-               if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
-                       continue;
-               }
-
-               if ((operation == LDB_MODIFY)&&
-                   (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == 
LDB_FLAG_MOD_DELETE)) {
-                       /* 0 values are allowed */
-                       if (msg->elements[i].num_values == 1) {
-                               *old_val =&msg->elements[i].values[0];
-                       } else if (msg->elements[i].num_values>  1) {
-                               return LDB_ERR_CONSTRAINT_VIOLATION;
-                       }
-               } else if ((operation == LDB_MODIFY)&&
-                          (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == 
LDB_FLAG_MOD_REPLACE)) {
-                       if (msg->elements[i].num_values>  0) {
-                               *new_val 
=&msg->elements[i].values[msg->elements[i].num_values - 1];
-                       } else {
-                               return LDB_ERR_UNWILLING_TO_PERFORM;
-                       }
-               } else {
-                       /* Add operations and LDB_FLAG_MOD_ADD */
-                       if (msg->elements[i].num_values>  0) {
-                               *new_val 
=&msg->elements[i].values[msg->elements[i].num_values - 1];
-                       } else {
-                               return LDB_ERR_CONSTRAINT_VIOLATION;
-                       }
-               }
-       }
-
-       return LDB_SUCCESS;
-}
-
  int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, 
const char *name, const char *set_value)
  {
        if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
@@ -1657,7 +1595,12 @@ int samdb_find_site_for_computer(struct ldb_context *ldb,
                talloc_free(dn);
                return LDB_ERR_INVALID_DN_SYNTAX;
        }
+
        rdn_val = ldb_dn_get_rdn_val(dn);
+       if (rdn_val == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        (*site_name) = talloc_strndup(mem_ctx, (const char *)rdn_val->data, 
rdn_val->length);
        talloc_free(dn);
        if (!*site_name) {
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c 
b/source4/dsdb/samdb/ldb_modules/acl.c
index 3cf768e..b6635b1 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -61,6 +61,7 @@ struct acl_context {
        bool allowedChildClasses;
        bool allowedChildClassesEffective;
        bool sDRightsEffective;
+       bool userPassword;
        const char * const *attrs;
        struct dsdb_schema *schema;
  };
@@ -542,7 +543,8 @@ static int acl_check_password_rights(TALLOC_CTX *mem_ctx,
                                     struct ldb_request *req,
                                     struct security_descriptor *sd,
                                     struct dom_sid *sid,
-                                    const struct GUID *oc_guid)
+                                    const struct GUID *oc_guid,
+                                    bool userPassword)
  {
        int ret = LDB_SUCCESS;
        unsigned int del_attr_cnt = 0, add_attr_cnt = 0, rep_attr_cnt = 0;
@@ -557,6 +559,10 @@ static int acl_check_password_rights(TALLOC_CTX *mem_ctx,
                return ldb_module_oom(module);
        }
        for (l = passwordAttrs; *l != NULL; l++) {
+               if ((!userPassword)&&  (ldb_attr_cmp(*l, "userPassword") == 0)) 
{
+                       continue;
+               }
+
                while ((el = ldb_msg_find_element(msg, *l)) != NULL) {
                        if (LDB_FLAG_MOD_TYPE(el->flags) == 
LDB_FLAG_MOD_DELETE) {
                                ++del_attr_cnt;
@@ -632,6 +638,7 @@ static int acl_modify(struct ldb_module *module, struct 
ldb_request *req)
        struct security_descriptor *sd;
        struct dom_sid *sid = NULL;
        struct ldb_control *as_system = ldb_request_get_control(req, 
LDB_CONTROL_AS_SYSTEM_OID);
+       bool userPassword = dsdb_user_password_support(module, req);
        TALLOC_CTX *tmp_ctx = talloc_new(req);
        static const char *acl_attrs[] = {
                "nTSecurityDescriptor",
@@ -732,14 +739,15 @@ static int acl_modify(struct ldb_module *module, struct 
ldb_request *req)
                        continue;
                }
                else if (ldb_attr_cmp("unicodePwd", 
req->op.mod.message->elements[i].name) == 0 ||
-                        ldb_attr_cmp("userPassword", 
req->op.mod.message->elements[i].name) == 0 ||
+                        (userPassword&&  ldb_attr_cmp("userPassword", 
req->op.mod.message->elements[i].name) == 0) ||
                         ldb_attr_cmp("clearTextPassword", 
req->op.mod.message->elements[i].name) == 0) {
                        ret = acl_check_password_rights(tmp_ctx,
                                                        module,
                                                        req,
                                                        sd,
                                                        sid,
-                                                       guid);
+                                                       guid,
+                                                       userPassword);
                        if (ret != LDB_SUCCESS) {
                                goto fail;
                        }
@@ -1074,6 +1082,11 @@ static int acl_search_callback(struct ldb_request *req, 
struct ldb_reply *ares)
                if (data&&  data->password_attrs) {
                        if (!ac->am_system) {
                                for (i = 0; data->password_attrs[i]; i++) {
+                                       if ((!ac->userPassword)&&
+                                           
(ldb_attr_cmp(data->password_attrs[i],
+                                                         "userPassword") == 0))
+                                               continue;
+
                                        ldb_msg_remove_attr(ares->message, 
data->password_attrs[i]);
                                }
                        }
@@ -1115,6 +1128,7 @@ static int acl_search(struct ldb_module *module, struct 
ldb_request *req)
        ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, 
"allowedChildClasses");
        ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, 
"allowedChildClassesEffective");
        ac->sDRightsEffective = ldb_attr_in_list(req->op.search.attrs, 
"sDRightsEffective");
+       ac->userPassword = dsdb_user_password_support(module, ac);
        ac->schema = dsdb_get_schema(ldb, ac);

        /* replace any attributes in the parse tree that are private,
@@ -1125,6 +1139,11 @@ static int acl_search(struct ldb_module *module, struct 
ldb_request *req)
                /* remove password attributes */
                if (data&&  data->password_attrs) {
                        for (i = 0; data->password_attrs[i]; i++) {
+                               if ((!ac->userPassword)&&
+                                   (ldb_attr_cmp(data->password_attrs[i],
+                                                 "userPassword") == 0))
+                                               continue;
+
                                ldb_parse_tree_attr_replace(req->op.search.tree,
                                                            
data->password_attrs[i],
                                                            
"kludgeACLredactedattribute");
diff --git a/source4/dsdb/samdb/ldb_modules/local_password.c 
b/source4/dsdb/samdb/ldb_modules/local_password.c
index f544689..c0e1e9a 100644
--- a/source4/dsdb/samdb/ldb_modules/local_password.c
+++ b/source4/dsdb/samdb/ldb_modules/local_password.c
@@ -39,13 +39,15 @@

  #define PASSWORD_GUID_ATTR "masterGUID"

-/* This module maintains a local password database, seperate from the main 
LDAP server.
+/* This module maintains a local password database, separate from the main LDAP
+   server.

-   This allows the password database to be syncronised in a multi-master
+   This allows the password database to be synchronised in a multi-master
     fashion, seperate to the more difficult concerns of the main
-   database.  (With passwords, the last writer always wins)
+   database. (With passwords, the last writer always wins)

-   Each incoming add/modify is split into a remote, and a local request, done 
in that order.
+   Each incoming add/modify is split into a remote, and a local request, done
+   in that order.

     We maintain a list of attributes that are kept locally - perhaps
     this should use the @KLUDGE_ACL list of passwordAttribute
@@ -173,14 +175,6 @@ static int local_password_add(struct ldb_module *module, 
struct ldb_request *req
                return ldb_next_request(module, req);
        }

-       /* TODO: remove this when userPassword will be in schema */
-       if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", 
"person")) {
-               ldb_asprintf_errstring(ldb,
-                                       "Cannot relocate a password on entry: %s, 
does not have objectClass 'person'",
-                                       
ldb_dn_get_linearized(req->op.add.message->dn));
-               return LDB_ERR_OBJECT_CLASS_VIOLATION;
-       }
-
        /* From here, we assume we have password attributes to split off */
        ac = lpdb_init_context(module, req);
        if (!ac) {
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c 
b/source4/dsdb/samdb/ldb_modules/objectclass.c
index 6702b01..2e95eb5 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -334,8 +334,10 @@ static int fix_dn(struct ldb_context *ldb,
                return ldb_operr(ldb);
        }

-
        rdn_val = ldb_dn_get_rdn_val(newdn);
+       if (rdn_val == NULL) {
+               return ldb_operr(ldb);
+       }

  #if 0
        /* the rules for rDN length constraints are more complex than
@@ -468,6 +470,8 @@ static int objectclass_do_add(struct oc_context *ac)
        const struct dsdb_class *objectclass;
        struct ldb_dn *objectcategory;
        int32_t systemFlags = 0;
+       unsigned int i, j;
+       bool found;
        int ret;

        ldb = ldb_module_get_ctx(ac->module);
@@ -561,6 +565,7 @@ static int objectclass_do_add(struct oc_context *ac)
                                talloc_free(mem_ctx);
                                return ldb_oom(ldb);
                        }
+
                        ret = ldb_msg_add_string(msg, "objectClass", value);
                        if (ret != LDB_SUCCESS) {
                                ldb_set_errstring(ldb,
@@ -587,11 +592,25 @@ static int objectclass_do_add(struct oc_context *ac)
                }

                rdn_name = ldb_dn_get_rdn_name(msg->dn);
-               if (objectclass->rDNAttID
-                       &&  ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) 
{
+               if (rdn_name == NULL) {
+                       return ldb_operr(ldb);
+               }
+               found = false;
+               for (i = 0; (!found)&&  (i<  objectclass_element->num_values);
+                    i++) {
+                       const struct dsdb_class *tmp_class =
+                               
dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
+                                                               
&objectclass_element->values[i]);
+
+                       if (tmp_class == NULL) continue;
+
+                       if (ldb_attr_cmp(rdn_name, tmp_class->rDNAttID) == 0)
+                               found = true;
+               }
+               if (!found) {
                        ldb_asprintf_errstring(ldb,
-                                               "RDN %s is not correct for most 
specific structural objectclass %s, should be %s",
-                                               rdn_name, 
objectclass->lDAPDisplayName, objectclass->rDNAttID);
+                                              "objectclass: Invalid RDN '%s' for 
objectclass '%s'!",
+                                              rdn_name, 
objectclass->lDAPDisplayName);
                        return LDB_ERR_NAMING_VIOLATION;
                }

@@ -616,7 +635,6 @@ static int objectclass_do_add(struct oc_context *ac)
                                = ldb_msg_find_element(ac->search_res->message, 
"objectClass");

                        bool allowed_class = false;
-                       unsigned int i, j;
                        for (i=0; allowed_class == false&&  oc_el&&  i<  
oc_el->num_values; i++) {
                                const struct dsdb_class *sclass;

@@ -1256,6 +1274,7 @@ static int objectclass_do_rename2(struct oc_context *ac)
                const char *rdn_name;
                bool allowed_class = false;
                unsigned int i, j;
+               bool found;

                oc_el_entry = ldb_msg_find_element(ac->search_res->message,
                                                   "objectClass");
@@ -1270,13 +1289,24 @@ static int objectclass_do_rename2(struct oc_context *ac)
                }

                rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
-               if ((objectclass->rDNAttID != NULL)&&
-                   (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
+               if (rdn_name == NULL) {
+                       return ldb_operr(ldb);
+               }
+               found = false;
+               for (i = 0; (!found)&&  (i<  oc_el_entry->num_values); i++) {
+                       const struct dsdb_class *tmp_class =
+                               
dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
+                                                               
&oc_el_entry->values[i]);
+
+                       if (tmp_class == NULL) continue;
+
+                       if (ldb_attr_cmp(rdn_name, tmp_class->rDNAttID) == 0)
+                               found = true;
+               }
+               if (!found) {
                        ldb_asprintf_errstring(ldb,
-                                              "objectclass: RDN %s is not correct 
for most specific structural objectclass %s, should be %s",
-                                              rdn_name,
-                                              objectclass->lDAPDisplayName,
-                                              objectclass->rDNAttID);
+                                              "objectclass: Invalid RDN '%s' for 
objectclass '%s'!",
+                                              rdn_name, 
objectclass->lDAPDisplayName);
                        return LDB_ERR_UNWILLING_TO_PERFORM;
                }

diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c 
b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 83bee2f..9b6cf8c 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -33,19 +33,16 @@
   */

  #include "includes.h"
-#include "libcli/ldap/ldap_ndr.h"
  #include "ldb_module.h"
-#include "librpc/gen_ndr/misc.h"
-#include "librpc/gen_ndr/samr.h"
+#include "auth/session.h"
  #include "libcli/auth/libcli_auth.h"
  #include "libcli/security/security.h"
+#include "libcli/security/session.h"
  #include "system/kerberos.h"
  #include "auth/kerberos/kerberos.h"
-#include "system/time.h"
  #include "dsdb/samdb/samdb.h"
-#include "../libds/common/flags.h"
+#include "dsdb/samdb/ldb_modules/util.h"
  #include "dsdb/samdb/ldb_modules/password_modules.h"
-#include "librpc/ndr/libndr.h"
  #include "librpc/gen_ndr/ndr_drsblobs.h"
  #include "../lib/crypto/crypto.h"
  #include "param/param.h"
@@ -1633,6 +1630,68 @@ static int check_password_restrictions(struct 
setup_password_fields_io *io)
        return LDB_SUCCESS;
  }

+/*
+ * This is intended for use by the "password_hash" module since there
+ * password changes can be specified through one message element with the
+ * new password (to set) and another one with the old password (to unset).
+ *
+ * The first which sets a password (new value) can have flags
+ * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
+ * for entries). The latter (old value) has always specified
+ * LDB_FLAG_MOD_DELETE.
+ *
+ * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
+ * matching message elements are malformed in respect to the set/change rules.
+ * Otherwise it returns LDB_SUCCESS.
+ */
+static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
+                                       const char *name,
+                                       enum ldb_request_type operation,
+                                       const struct ldb_val **new_val,
+                                       const struct ldb_val **old_val)
+{
+       unsigned int i;
+
+       *new_val = NULL;
+       *old_val = NULL;
+
+       if (msg == NULL) {
+               return LDB_SUCCESS;
+       }
+
+       for (i = 0; i<  msg->num_elements; i++) {
+               if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
+                       continue;
+               }
+
+               if ((operation == LDB_MODIFY)&&
+                   (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == 
LDB_FLAG_MOD_DELETE)) {
+                       /* 0 values are allowed */
+                       if (msg->elements[i].num_values == 1) {
+                               *old_val =&msg->elements[i].values[0];
+                       } else if (msg->elements[i].num_values>  1) {
+                               return LDB_ERR_CONSTRAINT_VIOLATION;
+                       }
+               } else if ((operation == LDB_MODIFY)&&
+                          (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == 
LDB_FLAG_MOD_REPLACE)) {
+                       if (msg->elements[i].num_values>  0) {
+                               *new_val 
=&msg->elements[i].values[msg->elements[i].num_values - 1];
+                       } else {
+                               return LDB_ERR_UNWILLING_TO_PERFORM;
+                       }
+               } else {
+                       /* Add operations and LDB_FLAG_MOD_ADD */
+                       if (msg->elements[i].num_values>  0) {
+                               *new_val 
=&msg->elements[i].values[msg->elements[i].num_values - 1];
+                       } else {
+                               return LDB_ERR_CONSTRAINT_VIOLATION;
+                       }
+               }
+       }
+
+       return LDB_SUCCESS;
+}
+
  static int setup_io(struct ph_context *ac,
                    const struct ldb_message *orig_msg,
                    const struct ldb_message *searched_msg,
@@ -1687,11 +1746,10 @@ static int setup_io(struct ph_context *ac,
        }

        if (ac->userPassword) {
-               ret = samdb_msg_find_old_and_new_ldb_val(orig_msg,
-                                                        "userPassword",
-                                                        ac->req->operation,
-                                                       &io->n.cleartext_utf8,
-                                                       &io->og.cleartext_utf8);
+               ret = msg_find_old_and_new_pwd_val(orig_msg, "userPassword",
+                                                  ac->req->operation,
+                                               &io->n.cleartext_utf8,
+                                               &io->og.cleartext_utf8);
                if (ret != LDB_SUCCESS) {
                        ldb_asprintf_errstring(ldb,
                                "setup_io: "
@@ -1700,10 +1758,10 @@ static int setup_io(struct ph_context *ac,
                }
        }

-       ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "clearTextPassword",
-                                                ac->req->operation,
-                                               &io->n.cleartext_utf16,
-                                               &io->og.cleartext_utf16);
+       ret = msg_find_old_and_new_pwd_val(orig_msg, "clearTextPassword",
+                                          ac->req->operation,
+                                       &io->n.cleartext_utf16,
+                                       &io->og.cleartext_utf16);
        if (ret != LDB_SUCCESS) {
                ldb_asprintf_errstring(ldb,
                        "setup_io: "
@@ -1724,10 +1782,10 @@ static int setup_io(struct ph_context *ac,
           that would then be treated as a UTF16 password rather than
           a nthash */

-       ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "unicodePwd",
-                                                ac->req->operation,
-                                               &quoted_utf16,
-                                               &old_quoted_utf16);
+       ret = msg_find_old_and_new_pwd_val(orig_msg, "unicodePwd",
+                                          ac->req->operation,
+                                       &quoted_utf16,
+                                       &old_quoted_utf16);
        if (ret != LDB_SUCCESS) {
                ldb_asprintf_errstring(ldb,
                        "setup_io: "
@@ -1841,9 +1899,9 @@ static int setup_io(struct ph_context *ac,

        /* Handles the "dBCSPwd" attribute (LM hash) */
        io->n.lm_hash = NULL; io->og.lm_hash = NULL;
-       ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "dBCSPwd",
-                                                ac->req->operation,
-                                               &lm_hash,&old_lm_hash);
+       ret = msg_find_old_and_new_pwd_val(orig_msg, "dBCSPwd",
+                                          ac->req->operation,
+                                       &lm_hash,&old_lm_hash);
        if (ret != LDB_SUCCESS) {
                ldb_asprintf_errstring(ldb,
                        "setup_io: "
@@ -2232,7 +2290,7 @@ static int password_hash_add(struct ldb_module *module, 
struct ldb_request *req)
                *ntAttr, *lmAttr;
        int ret;
        struct ldb_control *bypass = NULL;
-       bool userPassword = true;
+       bool userPassword = dsdb_user_password_support(module, req);




--
Matthieu Patou
Samba Team        http://samba.org
Private repo      http://git.samba.org/?p=mat/samba.git;a=summary


Reply via email to