The branch, master has been updated via 12fdfc9... s4:ldap.py - add another test about linked attributes via 53afe4e... s4:ldif-handlers Add a custom handler for DNs that knows about deleted values via 5779c21... s4:provision.py - we do now support the "Windows 2000 Native" domain function level via 233ce18... s4:linked attributes LDB module - strip trailing whitespaces via e190683... s4:linked_attributes LDB module - cosmetics from b4364ad... s3-auth: in make_user_info_for_reply_enc make sure to check length and data pointer of nt and lm hash.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 12fdfc94307b5f1b7982fc82c525b260806c8323 Author: Matthias Dieter Wallnöfer <m...@samba.org> Date: Wed Jun 16 14:51:05 2010 +0200 s4:ldap.py - add another test about linked attributes In addition this test makes sure that the bug regarding the search with deleted linked attributes in the filter has been fixed. commit 53afe4e018cb3bd8728e68699910ec4501fd658d Author: Andrew Bartlett <abart...@samba.org> Date: Mon Jun 14 15:52:01 2010 +1000 s4:ldif-handlers Add a custom handler for DNs that knows about deleted values In Samba we my store a deleted DN for a linked attribute. We must ensure that we can't match on it, or else searches for member= will still reveal it. Andrew Bartlett commit 5779c21e41c6da9eabaaaf373d6a45311b234e90 Author: Matthias Dieter Wallnöfer <m...@samba.org> Date: Wed Jun 16 15:18:34 2010 +0200 s4:provision.py - we do now support the "Windows 2000 Native" domain function level commit 233ce18a176fc8c7c8b6b6dbf2eadd30a225405d Author: Matthias Dieter Wallnöfer <m...@samba.org> Date: Wed Jun 16 15:15:39 2010 +0200 s4:linked attributes LDB module - strip trailing whitespaces commit e190683b59db4d22c89644a72d0dd3779ac3d706 Author: Matthias Dieter Wallnöfer <m...@samba.org> Date: Wed Jun 16 14:49:08 2010 +0200 s4:linked_attributes LDB module - cosmetics - unsigned counters for LDB objects - we tend to have the "ret" variable always as the last declaration to see which type of error a function returns ----------------------------------------------------------------------- Summary of changes: source4/dsdb/samdb/ldb_modules/linked_attributes.c | 92 ++++++++++---------- source4/lib/ldb-samba/ldif_handlers.c | 78 +++++++++++++++++ source4/lib/ldb/tests/python/ldap.py | 91 +++++++++++++++++++- source4/scripting/python/samba/provision.py | 3 - 4 files changed, 213 insertions(+), 51 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index c21fda5..c204571 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -1,4 +1,4 @@ -/* +/* ldb database library Copyright (C) Andrew Bartlett <abart...@samba.org> 2007 @@ -8,12 +8,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -93,8 +93,8 @@ static struct la_context *linked_attributes_init(struct ldb_module *module, */ static int la_guid_from_dn(struct la_context *ac, struct ldb_dn *dn, struct GUID *guid) { - int ret; NTSTATUS status; + int ret; status = dsdb_get_extended_dn_guid(dn, guid, "GUID"); if (NT_STATUS_IS_OK(status)) { @@ -131,7 +131,7 @@ static int la_store_op(struct la_context *ac, op_dn = ldb_dn_from_ldb_val(ac, ldb, dn); if (!op_dn) { - ldb_asprintf_errstring(ldb, + ldb_asprintf_errstring(ldb, "could not parse attribute as a DN"); return LDB_ERR_INVALID_DN_SYNTAX; } @@ -191,8 +191,8 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * struct la_context *ac; const char *attr_name; struct ldb_control *ctrl; + unsigned int i, j; int ret; - int i, j; ldb = ldb_module_get_ctx(module); @@ -224,9 +224,9 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * const struct dsdb_attribute *schema_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, el->name); if (!schema_attr) { - ldb_asprintf_errstring(ldb, + ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", el->name); - return LDB_ERR_OBJECT_CLASS_VIOLATION; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* We have a valid attribute, now find out if it is a forward link */ if ((schema_attr->linkID == 0)) { @@ -235,11 +235,11 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * if ((schema_attr->linkID & 1) == 1) { unsigned int functional_level; - + functional_level = dsdb_functional_level(ldb); SMB_ASSERT(functional_level > DS_DOMAIN_FUNCTION_2000); } - + /* Even link IDs are for the originating attribute */ target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID + 1); if (!target_attr) { @@ -289,7 +289,7 @@ static int la_mod_search_callback(struct ldb_request *req, struct ldb_reply *are struct replace_context *rc; struct la_context *ac; const char *attr_name; - int i, j; + unsigned int i, j; int ret = LDB_SUCCESS; ac = talloc_get_type(req->context, struct la_context); @@ -310,8 +310,8 @@ static int la_mod_search_callback(struct ldb_request *req, struct ldb_reply *are case LDB_REPLY_ENTRY: if (ldb_dn_compare(ares->message->dn, ac->req->op.mod.message->dn) != 0) { - ldb_asprintf_errstring(ldb, - "linked_attributes: %s is not the DN we were looking for", + ldb_asprintf_errstring(ldb, + "linked_attributes: %s is not the DN we were looking for", ldb_dn_get_linearized(ares->message->dn)); /* Guh? We only asked for this DN */ talloc_free(ares); @@ -412,12 +412,11 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques /* Apply the modify to the linked entry */ struct ldb_context *ldb; - int i, j; + unsigned int i, j; struct la_context *ac; struct ldb_request *search_req; const char **attrs; struct ldb_control *ctrl; - int ret; ldb = ldb_module_get_ctx(module); @@ -457,9 +456,9 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques const struct dsdb_attribute *schema_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, el->name); if (!schema_attr) { - ldb_asprintf_errstring(ldb, + ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", el->name); - return LDB_ERR_OBJECT_CLASS_VIOLATION; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* We have a valid attribute, now find out if it is a forward link (Even link IDs are for the originating attribute) */ @@ -469,7 +468,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques if ((schema_attr->linkID & 1) == 1) { unsigned int functional_level; - + functional_level = dsdb_functional_level(ldb); SMB_ASSERT(functional_level > DS_DOMAIN_FUNCTION_2000); } @@ -487,7 +486,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques } attr_name = target_attr->lDAPDisplayName; - + switch (el->flags & LDB_FLAG_MOD_MASK) { case LDB_FLAG_MOD_REPLACE: /* treat as just a normal add the delete part is handled by the callback */ @@ -546,11 +545,11 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques ac->rc->num_elements++; } } - + if (ac->ops || ac->rc->el) { /* both replace and delete without values are handled in the callback * after the search on the entry to be modified is performed */ - + attrs = talloc_array(ac->rc, const char *, ac->rc->num_elements + 1); if (!attrs) { ldb_oom(ldb); @@ -560,7 +559,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques attrs[i] = ac->rc->el[i].name; } attrs[i] = NULL; - + /* The callback does all the hard work here */ ret = ldb_build_search_req(&search_req, ldb, ac, req->op.mod.message->dn, @@ -578,7 +577,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques } if (ret == LDB_SUCCESS) { talloc_steal(search_req, attrs); - + ret = ldb_next_request(module, search_req); } @@ -596,11 +595,12 @@ static int linked_attributes_fix_links(struct ldb_module *module, struct ldb_message_element *el, struct dsdb_schema *schema, const struct dsdb_attribute *schema_attr) { - unsigned int i; + unsigned int i, j; TALLOC_CTX *tmp_ctx = talloc_new(module); struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_attribute *target; const char *attrs[2]; + int ret; target = dsdb_attribute_by_linkID(schema, schema_attr->linkID ^ 1); if (target == NULL) { @@ -613,8 +613,6 @@ static int linked_attributes_fix_links(struct ldb_module *module, for (i=0; i<el->num_values; i++) { struct dsdb_dn *dsdb_dn; - unsigned int j; - int ret; struct ldb_result *res; struct ldb_message *msg; struct ldb_message_element *el2; @@ -645,7 +643,7 @@ static int linked_attributes_fix_links(struct ldb_module *module, /* Forward link without backlink remaining - nothing to do here */ continue; } else if (msg->num_elements != 1) { - ldb_asprintf_errstring(ldb, "Bad msg elements - got %u elements, expected one element to be returned in linked_attributes_fix_links for %s", + ldb_asprintf_errstring(ldb, "Bad msg elements - got %u elements, expected one element to be returned in linked_attributes_fix_links for %s", msg->num_elements, ldb_dn_get_linearized(msg->dn)); talloc_free(tmp_ctx); return LDB_ERR_OPERATIONS_ERROR; @@ -709,9 +707,9 @@ static int linked_attributes_rename(struct ldb_module *module, struct ldb_reques struct ldb_result *res; struct ldb_message *msg; unsigned int i; - int ret; struct ldb_context *ldb = ldb_module_get_ctx(module); struct dsdb_schema *schema; + int ret; /* - load the current msg - find any linked attributes @@ -757,7 +755,7 @@ static int linked_attributes_rename(struct ldb_module *module, struct ldb_reques structure */ static int la_queue_mod_request(struct la_context *ac) { - struct la_private *la_private = + struct la_private *la_private = talloc_get_type(ldb_module_get_private(ac->module), struct la_private); if (la_private == NULL) { @@ -775,9 +773,9 @@ static int la_queue_mod_request(struct la_context *ac) /* Having done the original operation, then try to fix up all the linked attributes for modify and delete */ static int la_mod_del_callback(struct ldb_request *req, struct ldb_reply *ares) { - int ret; struct la_context *ac; struct ldb_context *ldb; + int ret; ac = talloc_get_type(req->context, struct la_context); ldb = ldb_module_get_ctx(ac->module); @@ -798,13 +796,13 @@ static int la_mod_del_callback(struct ldb_request *req, struct ldb_reply *ares) return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); } - + ac->op_controls = talloc_steal(ac, ares->controls); ac->op_response = talloc_steal(ac, ares->response); /* If we have modfies to make, this is the time to do them for modify and delete */ ret = la_queue_mod_request(ac); - + if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } @@ -821,9 +819,9 @@ static int la_mod_del_callback(struct ldb_request *req, struct ldb_reply *ares) */ static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares) { - int ret; struct la_context *ac; struct ldb_context *ldb; + int ret; ac = talloc_get_type(req->context, struct la_context); ldb = ldb_module_get_ctx(ac->module); @@ -844,11 +842,11 @@ static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares) return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); } - + if (ac->ops) { struct ldb_request *search_req; static const char *attrs[] = { NULL }; - + /* The callback does all the hard work here - we need * the objectGUID and SID of the added record */ ret = ldb_build_search_req(&search_req, ldb, ac, @@ -858,7 +856,7 @@ static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares) NULL, ac, la_mod_search_callback, ac->req); - + if (ret == LDB_SUCCESS) { ret = ldb_request_add_control(search_req, LDB_CONTROL_EXTENDED_DN_OID, @@ -873,7 +871,7 @@ static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares) ac->op_response = talloc_steal(ac, ares->response); return ldb_next_request(ac->module, search_req); - + } else { return ldb_module_done(ac->req, ares->controls, ares->response, ares->error); @@ -884,8 +882,8 @@ static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares) static int la_down_req(struct la_context *ac) { struct ldb_request *down_req; - int ret; struct ldb_context *ldb; + int ret; ldb = ldb_module_get_ctx(ac->module); @@ -918,7 +916,7 @@ static int la_down_req(struct la_context *ac) use the GUID part of an extended DN to find the target DN, in case it has moved */ -static int la_find_dn_target(struct ldb_module *module, struct la_context *ac, +static int la_find_dn_target(struct ldb_module *module, struct la_context *ac, struct GUID *guid, struct ldb_dn **dn) { return dsdb_find_dn_by_guid(ldb_module_get_ctx(ac->module), ac, guid, dn); @@ -970,10 +968,10 @@ static int la_do_op_request(struct ldb_module *module, struct la_context *ac, st #if 0 ldb_debug(ldb, LDB_DEBUG_WARNING, - "link on %s %s: %s %s\n", - ldb_dn_get_linearized(new_msg->dn), ret_el->name, + "link on %s %s: %s %s\n", + ldb_dn_get_linearized(new_msg->dn), ret_el->name, ret_el->values[0].data, ac->ops->op == LA_OP_ADD ? "added" : "deleted"); -#endif +#endif if (DEBUGLVL(4)) { DEBUG(4,("Applying linked attribute change:\n%s\n", @@ -1009,7 +1007,7 @@ static int la_do_mod_request(struct ldb_module *module, struct la_context *ac) /* - we hook into the transaction operations to allow us to + we hook into the transaction operations to allow us to perform the linked attribute updates at the end of the whole transaction. This allows a forward linked attribute to be created before the target is created, as long as the target is created @@ -1036,7 +1034,7 @@ static int linked_attributes_start_transaction(struct ldb_module *module) */ static int linked_attributes_prepare_commit(struct ldb_module *module) { - struct la_private *la_private = + struct la_private *la_private = talloc_get_type(ldb_module_get_private(module), struct la_private); struct la_context *ac; @@ -1060,20 +1058,20 @@ static int linked_attributes_prepare_commit(struct ldb_module *module) if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed mod request ret=%d\n", ret)); talloc_free(la_private); - ldb_module_set_private(module, NULL); + ldb_module_set_private(module, NULL); return ret; } } talloc_free(la_private); - ldb_module_set_private(module, NULL); + ldb_module_set_private(module, NULL); return ldb_next_prepare_commit(module); } static int linked_attributes_del_transaction(struct ldb_module *module) { - struct la_private *la_private = + struct la_private *la_private = talloc_get_type(ldb_module_get_private(module), struct la_private); talloc_free(la_private); ldb_module_set_private(module, NULL); diff --git a/source4/lib/ldb-samba/ldif_handlers.c b/source4/lib/ldb-samba/ldif_handlers.c index 480335f..2ce1055 100644 --- a/source4/lib/ldb-samba/ldif_handlers.c +++ b/source4/lib/ldb-samba/ldif_handlers.c @@ -878,6 +878,78 @@ static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx, return 0; } +/* + compare two dns +*/ +static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + struct ldb_dn *dn1 = NULL, *dn2 = NULL; + int ret; + + if (dsdb_dn_is_deleted_val(v1)) { + /* If the DN is deleted, then we can't search for it */ + return -1; + } + + if (dsdb_dn_is_deleted_val(v2)) { + /* If the DN is deleted, then we can't search for it */ + return -1; + } + + dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1); + if ( ! ldb_dn_validate(dn1)) return -1; + + dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2); + if ( ! ldb_dn_validate(dn2)) { + talloc_free(dn1); + return -1; + } + + ret = ldb_dn_compare(dn1, dn2); + + talloc_free(dn1); + talloc_free(dn2); + return ret; +} + +static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + struct ldb_dn *dn; + int ret = -1; + + out->length = 0; + out->data = NULL; + + dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in); + if ( ! ldb_dn_validate(dn)) { + return LDB_ERR_INVALID_DN_SYNTAX; + } + + /* By including the RMD_FLAGS of a deleted DN, we ensure it + * does not casually match a not deleted DN */ + if (dsdb_dn_is_deleted_val(in)) { + out->data = talloc_asprintf(mem_ctx, "<RMD_FLAGS=%u>%s", + dsdb_dn_val_rmd_flags(in), + ldb_dn_get_casefold(dn)); + } else { + out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn); + } + + if (out->data == NULL) { + goto done; + } + out->length = strlen((char *)out->data); + + ret = 0; + +done: + talloc_free(dn); + + return ret; +} + /* write a 64 bit 2-part range @@ -1010,6 +1082,12 @@ static const struct ldb_schema_syntax samba_syntaxes[] = { .canonicalise_fn = dsdb_dn_string_canonicalise, .comparison_fn = dsdb_dn_string_comparison },{ + .name = LDB_SYNTAX_DN, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = samba_ldb_dn_link_canonicalise, + .comparison_fn = samba_ldb_dn_link_comparison, + },{ .name = LDB_SYNTAX_SAMBA_RANGE64, .ldif_read_fn = ldif_read_range64, .ldif_write_fn = ldif_write_range64, diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py index ddf0254..40cbb9f 100755 --- a/source4/lib/ldb/tests/python/ldap.py +++ b/source4/lib/ldb/tests/python/ldap.py @@ -969,6 +969,95 @@ objectClass: container self.assertEquals(res1[0]["groupType"][0], "-2147483643") + def test_linked_attributes(self): + """This tests the linked attribute behaviour""" + print "Testing linked attribute behaviour\n" + + ldb.add({ + "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, + "objectclass": "group"}) + + # This should not work since "memberOf" is linked to "member" + try: + ldb.add({ + "dn": "cn=ldaptestuser,cn=users," + self.base_dn, + "objectclass": ["user", "person"], + "memberOf": "cn=ldaptestgroup,cn=users," + self.base_dn}) + except LdbError, (num, _): + self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + + ldb.add({ + "dn": "cn=ldaptestuser,cn=users," + self.base_dn, + "objectclass": ["user", "person"]}) + + m = Message() + m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) -- Samba Shared Repository