[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Sat Nov 13 07:09:51 MST 2010


Sure, Jelmer!

Consider this modify request message - doesn't make much sense but was 
needed for a test. There's obviously a bug that the previous message 
element is overwritten by the second one. Only with "modify_ldif" it 
works correctly.

Greets,
Matthias
> -        m = Message()
> -        m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
> -        m["objectClass"] = MessageElement("bootableDevice", 
> FLAG_MOD_DELETE,
> -          "objectClass")
> -        m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
> -          "objectClass")
> -        try:
> -            ldb.modify(m)
> -            self.fail()
> -        except LdbError, (num, _):
> -            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
>
> +        # More than one change operation is allowed
> +        ldb.modify_ldif("""
> +dn: cn=ldaptestuser,cn=users, """ + self.base_dn + """
> +changetype: modify
> +delete: objectClass
> +objectClass: bootableDevice
> +add: objectClass
> +objectClass: bootableDevice
> +""")


Jelmer Vernooij wrote:
> On Sat, 2010-11-13 at 11:50 +0100, Matthias Dieter Wallnöfer wrote:
>    
>> Well basically yes, ekacnet.
>>
>> But I don't see any problem to use "modify_ldif"/"add_ldif" when sending
>> very special requests as password changes and others. Sometimes it's
>> really needed due to encoding constraints.
>>      
> Can you give an example of this? E.g. in this situation below it would
> be simpler without the ldif. Since LDIFs are always converted to ldb
> Message anyway before they are processed I don't see how they could be
> used in a larger number of situations.
>
> Cheers,
>
> Jelmer
>
>    
>> u Patou wrote:
>>      
>>> 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<mdw at 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<mdw at samba.org>
>>>>       Autobuild-Date: Thu Nov 11 09:47:55 UTC 2010 on sn-devel-104
>>>>
>>>> commit f0367905d9a6db76712f1dcf9734f64fe5c5e1b3
>>>> Author: Matthias Dieter Wallnöfer<mdw at 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<mdw at 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.zahariev at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at 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<mdw at samba.org>
>>>> Date:   Wed Nov 10 13:28:22 2010 +0100
>>>>
>>>>       s4:speedtest.py - remove duplicated code
>>>>
>>>> commit 0a29e552cb29cadbb75e64d8cc1278891132a7b0
>>>> Author: Matthias Dieter Wallnöfer<mdw at 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<mdw at samba.org>
>>>> Date:   Wed Nov 10 13:29:14 2010 +0100
>>>>
>>>>       s4:speedtest.py - make it executable
>>>>
>>>> commit cc7f390bf940a2f009e16c3811e38424d62ca2dd
>>>> Author: Matthias Dieter Wallnöfer<mdw at 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);
>>>>
>>>>
>>>>          
>>>
>>>        
>>      
>    



More information about the samba-technical mailing list