The branch, master has been updated via 3dae323 s4-dsdb: fixed the defaultObjectCategory to have a full GUID via 18995cd s4-fault: changed to use %d for PID, instead of %PID% via 80c8f42 s4-dsdb: another special case for the "member" attribute via 43c0a92 s4-dsdb Don't process deletion of member attributes here. via 014fca1 dsdb: fixed special case of zero NTTIME via fc476ec dbcheck: use samdb_schema for getting the backlink via 23b6af1 ldb: added ldb_val_string_cmp() via 2087eb1 ldb: use base searches for @ special DNs via c60a489 ldb: don't return special DNs on non-base searches via 58e8944 ldb: don't shortcut dn comparison for mismatched special DNs via eb7c2af dbcheck: only do the provision dbcheck if there are objects to check via 1ee67df s4-test: fixed usage message on renamedc.sh via 182fd31 s4-provision: fixed the GUIDs in the provision using dbcheck via afe4b77 s4-dsdb: fixed modify of ACLs on deleted objects via 303b57c dbcheck: only fix replPropertyMetaData if we included it in the search via 5064d73 dbcheck: added checks for missing and orphansed backlinks via b66c577 s4-dsdb: raise debug level for backlink errors via 534c1ca dbcheck: fixed ldap check with no database specified via 0ab3086 dbcheck: added --reindex option via 6bc1957 samba-tool: fixed ldapcmp to run as non-root via d9e2317 dbcheck: added checking of backlinks via 94b820a pydsdb: added get_backlink_from_lDAPDisplayName() via 0214b7f s4-dsdb: moved checking of duplicate member entries to repl_meta_data.c from e858ec6 s3-rpc_server: Removed no longer used functions.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 3dae32397a87534ff1cf764260e7fcadd6665a49 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 19:36:59 2011 +1000 s4-dsdb: fixed the defaultObjectCategory to have a full GUID this fixes the DN to have a full GUID for new objects Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> Autobuild-User: Andrew Tridgell <tri...@samba.org> Autobuild-Date: Wed Jul 13 14:03:30 CEST 2011 on sn-devel-104 commit 18995cde5c5d2e647d94f9dcde4ba9261464c217 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 17:26:31 2011 +1000 s4-fault: changed to use %d for PID, instead of %PID% this matches the s3 behaviour Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 80c8f42f058bdcdf639037927c5941190f019a67 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 15:58:45 2011 +1000 s4-dsdb: another special case for the "member" attribute thanks to Matthias for his great test suite work! Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 43c0a92d23c2be446a9568b9d937e525d676f85e Author: Andrew Bartlett <abart...@samba.org> Date: Wed Jul 13 15:31:19 2011 +1000 s4-dsdb Don't process deletion of member attributes here. We don't need to compare the delete against the primaryGroupID check here - that test is for adds. Andrew Bartlett commit 014fca10697c80d49d2c3438089935c63f445644 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 13:26:48 2011 +1000 dsdb: fixed special case of zero NTTIME we can't convert 0 NTTIME via a unix time_t Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit fc476ec8ac3357c81b805e0634624f183a6f7b49 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 13:26:19 2011 +1000 dbcheck: use samdb_schema for getting the backlink this is not available on an ldap samdb Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 23b6af10f6ab3852ca28338b8d58342be816f0a2 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 13:25:34 2011 +1000 ldb: added ldb_val_string_cmp() this should help fix some places where we run past the end of a string Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 2087eb1602d647a7b14523820834231f50dea79d Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 13:05:19 2011 +1000 ldb: use base searches for @ special DNs subtree searches on these DNs don't work any more Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit c60a48948a75a6d300e31c2a2629daa4a48cbeb1 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 12:25:09 2011 +1000 ldb: don't return special DNs on non-base searches to look at a special DN, give the full DN Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 58e89443e2e1722dec85ec426a63449b53b19ea3 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 12:24:25 2011 +1000 ldb: don't shortcut dn comparison for mismatched special DNs DNs that start with @ can't be compared via string comparison with normal DNs Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit eb7c2af83bbebd9e32fdfd459cfef7db15918911 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 10:54:50 2011 +1000 dbcheck: only do the provision dbcheck if there are objects to check when in FILL_DRS mode, there are no objects to check yet Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 1ee67df307f27f2787793b7304a333a563f247c3 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 10:49:45 2011 +1000 s4-test: fixed usage message on renamedc.sh commit 182fd31be57907e252c86506b1c2dac5c40fe244 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 10:31:15 2011 +1000 s4-provision: fixed the GUIDs in the provision using dbcheck some DNs are are not setup with GUIDs during the provision because of circular dependencies between objects. This adds a dbcheck pass to the provision to fix those DNs Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit afe4b77d35a95d2338094b8cbc96ca421a023413 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 10:28:07 2011 +1000 s4-dsdb: fixed modify of ACLs on deleted objects this is needed for the dbcheck code Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 303b57c295c4712c0bd606e893e39dff1cbe3e65 Author: Andrew Tridgell <tri...@samba.org> Date: Wed Jul 13 10:12:48 2011 +1000 dbcheck: only fix replPropertyMetaData if we included it in the search if we didn't find a replPropertyMetaData attribute at all then don't try fixing it Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> commit 5064d73672eecb2750d64f84c126f82781b0191b Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 12 11:26:29 2011 +1000 dbcheck: added checks for missing and orphansed backlinks this checks for missing backlinks or backlinks without a forward link and optionally fixes them Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit b66c57751a0f217b5dbd7b3b75cf13c3ae465855 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 12 11:25:39 2011 +1000 s4-dsdb: raise debug level for backlink errors when dbcheck is fixing missing backlinks we don't want a DEBUG 0 message Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> commit 534c1ca00ef1d658c4cefe72fcc3acb101635ae9 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 12 11:12:21 2011 +1000 dbcheck: fixed ldap check with no database specified Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> commit 0ab3086b46259a4627eabab93ebda41fd21408b0 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 12 11:05:43 2011 +1000 dbcheck: added --reindex option this allows you to force a reindex of the database Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 6bc1957a54ba2e3c73b0cf580c94e8055d451b03 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Jul 12 10:41:52 2011 +1000 samba-tool: fixed ldapcmp to run as non-root this avoids the need for access to the secrets database Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> commit d9e2317f491cbf532c7bc186d91c6d270a2f583e Author: Andrew Tridgell <tri...@samba.org> Date: Mon Jul 11 16:55:36 2011 +1000 dbcheck: added checking of backlinks Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit 94b820af56f841ae755822a421a5c7066b7921d0 Author: Andrew Tridgell <tri...@samba.org> Date: Mon Jul 11 16:55:11 2011 +1000 pydsdb: added get_backlink_from_lDAPDisplayName() Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> commit 0214b7f20cfcecd3d51aa12ae4e31cc4e095d73b Author: Andrew Tridgell <tri...@samba.org> Date: Mon Jul 11 15:32:12 2011 +1000 s4-dsdb: moved checking of duplicate member entries to repl_meta_data.c the samldb checks failed to account for the possibility of a member being removed and added in the same modify operation. This happens (for example) when dbcheck is fixing a SID in a DN. The repl_meta_data.c code already has this check, it just wasn't giving the right specialised error code for the 'member' attribute Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> Pair-Programmed-With: Amitay Isaacs <ami...@gmail.com> ----------------------------------------------------------------------- Summary of changes: lib/ldb/ABI/{ldb-1.1.0.sigs => ldb-1.1.1.sigs} | 1 + lib/ldb/common/ldb_dn.c | 2 +- lib/ldb/common/ldb_match.c | 5 + lib/ldb/common/ldb_msg.c | 12 ++ lib/ldb/include/ldb.h | 5 + lib/ldb/wscript | 2 +- lib/util/fault.c | 2 +- selftest/selftest.pl | 2 +- selftest/target/Samba4.pm | 2 +- source4/dsdb/pydsdb.c | 45 +++++ source4/dsdb/samdb/ldb_modules/acl.c | 6 +- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 29 +++- source4/dsdb/samdb/ldb_modules/samldb.c | 68 ++++---- source4/dsdb/schema/schema_syntax.c | 20 +++ source4/scripting/bin/upgradeprovision | 2 +- source4/scripting/python/samba/dbchecker.py | 180 +++++++++++++------- source4/scripting/python/samba/netcmd/dbcheck.py | 15 ++- source4/scripting/python/samba/netcmd/ldapcmp.py | 11 +- .../scripting/python/samba/provision/__init__.py | 42 ++++-- source4/scripting/python/samba/samdb.py | 5 + .../python/samba/tests/upgradeprovision.py | 8 +- source4/scripting/python/samba/upgradehelpers.py | 6 +- testprogs/blackbox/renamedc.sh | 2 +- wintest/test-s4-howto.py | 2 +- 24 files changed, 336 insertions(+), 138 deletions(-) copy lib/ldb/ABI/{ldb-1.1.0.sigs => ldb-1.1.1.sigs} (99%) Changeset truncated at 500 lines: diff --git a/lib/ldb/ABI/ldb-1.1.0.sigs b/lib/ldb/ABI/ldb-1.1.1.sigs similarity index 99% copy from lib/ldb/ABI/ldb-1.1.0.sigs copy to lib/ldb/ABI/ldb-1.1.1.sigs index 149d4bc..2fe215c 100644 --- a/lib/ldb/ABI/ldb-1.1.0.sigs +++ b/lib/ldb/ABI/ldb-1.1.1.sigs @@ -248,6 +248,7 @@ ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *) ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *) ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_string_cmp: int (const struct ldb_val *, const char *) ldb_val_to_time: int (const struct ldb_val *, time_t *) ldb_valid_attr_name: int (const char *) ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index cd9055d..6b1ef03 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -1034,7 +1034,7 @@ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn) if ( ! dn || dn->invalid) return -1; if (( ! base->valid_case) || ( ! dn->valid_case)) { - if (base->linearized && dn->linearized) { + if (base->linearized && dn->linearized && dn->special == base->special) { /* try with a normal compare first, if we are lucky * we will avoid exploding and casfolding */ int dif; diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c index a42cf94..c23e804 100644 --- a/lib/ldb/common/ldb_match.c +++ b/lib/ldb/common/ldb_match.c @@ -463,6 +463,11 @@ static int ldb_match_message(struct ldb_context *ldb, *matched = false; + if (scope != LDB_SCOPE_BASE && ldb_dn_is_special(msg->dn)) { + /* don't match special records except on base searches */ + return LDB_SUCCESS; + } + switch (tree->operation) { case LDB_OP_AND: for (i=0;i<tree->u.list.num_elements;i++) { diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c index 28c414e..1a2bebc 100644 --- a/lib/ldb/common/ldb_msg.c +++ b/lib/ldb/common/ldb_msg.c @@ -1185,3 +1185,15 @@ int ldb_msg_check_string_attribute(const struct ldb_message *msg, return 0; } + +/* + compare a ldb_val to a string +*/ +int ldb_val_string_cmp(const struct ldb_val *v, const char *str) +{ + size_t len = strlen(str); + if (len != v->length) { + return len - v->length; + } + return strncmp((const char *)v->data, str, len); +} diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h index d745f37..1305d8e 100644 --- a/lib/ldb/include/ldb.h +++ b/lib/ldb/include/ldb.h @@ -2251,4 +2251,9 @@ const char *ldb_req_location(struct ldb_request *req); */ bool ldb_dn_minimise(struct ldb_dn *dn); +/* + compare a ldb_val to a string +*/ +int ldb_val_string_cmp(const struct ldb_val *v, const char *str); + #endif diff --git a/lib/ldb/wscript b/lib/ldb/wscript index a8d9bf7..d05453e 100755 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'ldb' -VERSION = '1.1.0' +VERSION = '1.1.1' blddir = 'bin' diff --git a/lib/util/fault.c b/lib/util/fault.c index 708dc67..ed7684a 100644 --- a/lib/util/fault.c +++ b/lib/util/fault.c @@ -121,7 +121,7 @@ static void smb_panic_default(const char *why) char cmdstring[200]; strlcpy(cmdstring, panic_action, sizeof(cmdstring)); snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid()); - all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring)); + all_string_sub(cmdstring, "%d", pidstr, sizeof(cmdstring)); DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring)); result = system(cmdstring); diff --git a/selftest/selftest.pl b/selftest/selftest.pl index 808be22..218f83b 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -643,7 +643,7 @@ sub write_clientconf($$$) cache dir = $clientdir/cachedir ncalrpc dir = $clientdir/ncalrpcdir name resolve order = file bcast - panic action = $RealBin/gdb_backtrace \%PID\% + panic action = $RealBin/gdb_backtrace \%d max xmit = 32K notify:inotify = false ldb:nosync = true diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 2bb74ca..2610232 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -606,7 +606,7 @@ sub provision_raw_step1($$) name resolve order = file bcast interfaces = $ctx->{interfaces} tls dh params file = $ctx->{tlsdir}/dhparms.pem - panic action = $RealBin/gdb_backtrace \%PID% + panic action = $RealBin/gdb_backtrace \%d wins support = yes server role = $ctx->{server_role} server services = +echo diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index 463a2f9..e74f2bb 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -394,6 +394,49 @@ static PyObject *py_dsdb_get_linkId_from_lDAPDisplayName(PyObject *self, PyObjec return PyInt_FromLong(attribute->linkID); } +/* + return the backlink attribute name (if any) for an attribute + */ +static PyObject *py_dsdb_get_backlink_from_lDAPDisplayName(PyObject *self, PyObject *args) +{ + PyObject *py_ldb; + struct ldb_context *ldb; + struct dsdb_schema *schema; + const char *ldap_display_name; + const struct dsdb_attribute *attribute, *target_attr; + + if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name)) + return NULL; + + PyErr_LDB_OR_RAISE(py_ldb, ldb); + + schema = dsdb_get_schema(ldb, NULL); + + if (!schema) { + PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb"); + return NULL; + } + + attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name); + if (attribute == NULL) { + PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name); + return NULL; + } + + if (attribute->linkID == 0) { + Py_RETURN_NONE; + } + + target_attr = dsdb_attribute_by_linkID(schema, attribute->linkID ^ 1); + if (target_attr == NULL) { + /* when we add pseudo-backlinks we'll need to handle + them here */ + Py_RETURN_NONE; + } + + return PyString_FromString(target_attr->lDAPDisplayName); +} + static PyObject *py_dsdb_get_lDAPDisplayName_by_attid(PyObject *self, PyObject *args) { @@ -937,6 +980,8 @@ static PyMethodDef py_dsdb_methods[] = { METH_VARARGS, NULL }, { "_dsdb_get_lDAPDisplayName_by_attid", (PyCFunction)py_dsdb_get_lDAPDisplayName_by_attid, METH_VARARGS, NULL }, + { "_dsdb_get_backlink_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_backlink_from_lDAPDisplayName, + METH_VARARGS, NULL }, { "_dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS, NULL }, diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 49152d4..12a4028 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -902,7 +902,8 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) } ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res, req->op.mod.message->dn, acl_attrs, - DSDB_FLAG_NEXT_MODULE, req); + DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, + req); if (ret != LDB_SUCCESS) { goto fail; @@ -1337,7 +1338,8 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) || ac->sDRightsEffective) { ret = dsdb_module_search_dn(ac->module, ac, &acl_res, ares->message->dn, acl_attrs, - DSDB_FLAG_NEXT_MODULE, req); + DSDB_FLAG_NEXT_MODULE | + DSDB_SEARCH_SHOW_DELETED, req); if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index a76b88e..706ca33 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -258,7 +258,7 @@ static int replmd_process_backlink(struct ldb_module *module, struct la_backlink /* we allow LDB_ERR_NO_SUCH_ATTRIBUTE as success to cope with possible corruption where the backlink has already been removed */ - DEBUG(0,("WARNING: backlink from %s already removed from %s - %s\n", + DEBUG(3,("WARNING: backlink from %s already removed from %s - %s\n", ldb_dn_get_linearized(target_dn), ldb_dn_get_linearized(source_dn), ldb_errstring(ldb))); @@ -395,7 +395,7 @@ static int replmd_op_callback(struct ldb_request *req, struct ldb_reply *ares) } if (ares->error != LDB_SUCCESS) { - DEBUG(0,("%s failure. Error is: %s\n", __FUNCTION__, ldb_strerror(ares->error))); + DEBUG(5,("%s failure. Error is: %s\n", __FUNCTION__, ldb_strerror(ares->error))); return ldb_module_done(ac->req, controls, ares->response, ares->error); } @@ -1457,6 +1457,11 @@ static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx, if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Unable to find GUID for DN %s\n", ldb_dn_get_linearized(dn)); + if (ret == LDB_ERR_NO_SUCH_OBJECT && + LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE && + ldb_attr_cmp(el->name, "member") == 0) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } return ret; } ret = dsdb_set_extended_dn_guid(dn, p->guid, "GUID"); @@ -1774,7 +1779,13 @@ static int replmd_modify_la_add(struct ldb_module *module, ldb_asprintf_errstring(ldb, "Attribute %s already exists for target GUID %s", el->name, GUID_string(tmp_ctx, p->guid)); talloc_free(tmp_ctx); - return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + /* error codes for 'member' need to be + special cased */ + if (ldb_attr_cmp(el->name, "member") == 0) { + return LDB_ERR_ENTRY_ALREADY_EXISTS; + } else { + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } } ret = replmd_update_la_val(old_el->values, p->v, dns[i].dsdb_dn, p->dsdb_dn, invocation_id, seq_num, seq_num, now, 0, false); @@ -1886,13 +1897,21 @@ static int replmd_modify_la_delete(struct ldb_module *module, if (!p2) { ldb_asprintf_errstring(ldb, "Attribute %s doesn't exist for target GUID %s", el->name, GUID_string(tmp_ctx, p->guid)); - return LDB_ERR_NO_SUCH_ATTRIBUTE; + if (ldb_attr_cmp(el->name, "member") == 0) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } else { + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } } rmd_flags = dsdb_dn_rmd_flags(p2->dsdb_dn->dn); if (rmd_flags & DSDB_RMD_FLAG_DELETED) { ldb_asprintf_errstring(ldb, "Attribute %s already deleted for target GUID %s", el->name, GUID_string(tmp_ctx, p->guid)); - return LDB_ERR_NO_SUCH_ATTRIBUTE; + if (ldb_attr_cmp(el->name, "member") == 0) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } else { + return LDB_ERR_NO_SUCH_ATTRIBUTE; + } } } diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index a61920f..5c94099 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -379,6 +379,30 @@ static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac) return ret; } + if (ret == LDB_SUCCESS) { + /* ensure the defaultObjectCategory has a full GUID */ + struct ldb_message *m; + m = ldb_msg_new(ac->msg); + if (m == NULL) { + return ldb_oom(ldb); + } + m->dn = ac->msg->dn; + if (ldb_msg_add_string(m, "defaultObjectCategory", + ldb_dn_get_extended_linearized(m, res->msgs[0]->dn, 1)) != + LDB_SUCCESS) { + return ldb_oom(ldb); + } + m->elements[0].flags = LDB_FLAG_MOD_REPLACE; + + ret = dsdb_module_modify(ac->module, m, + DSDB_FLAG_NEXT_MODULE, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + ac->res_dn = ac->dn; return samldb_next_step(ac); @@ -1568,7 +1592,6 @@ static int samldb_member_check(struct samldb_ctx *ac) struct ldb_result *res; struct dom_sid *group_sid; unsigned int i, j; - int cnt; int ret; /* Fetch information from the existing object */ @@ -1596,47 +1619,25 @@ static int samldb_member_check(struct samldb_ctx *ac) el = &ac->msg->elements[i]; for (j = 0; j < el->num_values; j++) { - struct ldb_message_element *mo; struct ldb_result *group_res; const char *group_attrs[] = { "primaryGroupID" , NULL }; uint32_t prim_group_rid; + if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) { + /* Deletes will be handled in + * repl_meta_data, and deletes not + * matching a member will return + * LDB_ERR_UNWILLING_TO_PERFORM + * there */ + continue; + } + member_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[j]); if (!ldb_dn_validate(member_dn)) { return ldb_operr(ldb); } - /* The "member" attribute can be modified with the - * following restrictions (beside a valid DN): - * - * - "add" operations can only be performed when the - * member still doesn't exist - if not then return - * ERR_ENTRY_ALREADY_EXISTS (not - * ERR_ATTRIBUTE_OR_VALUE_EXISTS!) - * - "delete" operations can only be performed when the - * member does exist - if not then return - * ERR_UNWILLING_TO_PERFORM (not - * ERR_NO_SUCH_ATTRIBUTE!) - * - primary group check - */ - mo = samdb_find_attribute(ldb, res->msgs[0], "member", - ldb_dn_get_linearized(member_dn)); - if (mo == NULL) { - cnt = 0; - } else { - cnt = 1; - } - - if ((cnt > 0) && (LDB_FLAG_MOD_TYPE(el->flags) - == LDB_FLAG_MOD_ADD)) { - return LDB_ERR_ENTRY_ALREADY_EXISTS; - } - if ((cnt == 0) && LDB_FLAG_MOD_TYPE(el->flags) - == LDB_FLAG_MOD_DELETE) { - return LDB_ERR_UNWILLING_TO_PERFORM; - } - /* Denies to add "member"s to groups which are primary * ones for them - in this case return * ERR_ENTRY_ALREADY_EXISTS. */ @@ -1665,6 +1666,9 @@ static int samldb_member_check(struct samldb_ctx *ac) } if (dom_sid_equal(group_sid, sid)) { + ldb_asprintf_errstring(ldb, + "samldb: member %s already set via primaryGroupID %u", + ldb_dn_get_linearized(member_dn), prim_group_rid); return LDB_ERR_ENTRY_ALREADY_EXISTS; } } diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c index a93cdfa..d443c00 100644 --- a/source4/dsdb/schema/schema_syntax.c +++ b/source4/dsdb/schema/schema_syntax.c @@ -554,6 +554,11 @@ static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_syntax_ctx } v = BVAL(in->value_ctr.values[i].blob->data, 0); + if (v == 0) { + /* special case for 1601 zero timestamp */ + out->values[i] = data_blob_string_const("16010101000000.0Z"); + continue; + } v *= 10000000; t = nt_time_to_unix(v); @@ -607,6 +612,11 @@ static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_syntax_ctx blobs[i] = data_blob_talloc(blobs, NULL, 8); W_ERROR_HAVE_NO_MEMORY(blobs[i].data); + if (ldb_val_string_cmp("16010101000000.0Z", &in->values[i]) == 0) { + SBVALS(blobs[i].data, 0, 0); + continue; + } + t = ldb_string_utc_to_time((const char *)in->values[i].data); unix_to_nt_time(&v, t); v /= 10000000; @@ -693,6 +703,11 @@ static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ct } v = BVAL(in->value_ctr.values[i].blob->data, 0); + if (v == 0) { + /* special case for 1601 zero timestamp */ + out->values[i] = data_blob_string_const("16010101000000.0Z"); + continue; + } v *= 10000000; t = nt_time_to_unix(v); @@ -739,6 +754,11 @@ static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ct blobs[i] = data_blob_talloc(blobs, NULL, 8); W_ERROR_HAVE_NO_MEMORY(blobs[i].data); + if (ldb_val_string_cmp("16010101000000.0Z", &in->values[i]) == 0) { + SBVALS(blobs[i].data, 0, 0); + continue; + } + ret = ldb_val_to_time(&in->values[i], &t); if (ret != LDB_SUCCESS) { return WERR_DS_INVALID_ATTRIBUTE_SYNTAX; diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision index d2a645a..54f3cf1 100755 --- a/source4/scripting/bin/upgradeprovision +++ b/source4/scripting/bin/upgradeprovision @@ -1349,7 +1349,7 @@ def rebuild_sd(samdb, names): def removeProvisionUSN(samdb): attrs = [samba.provision.LAST_PROVISION_USN_ATTRIBUTE, "dn"] entry = samdb.search(expression="dn=@PROVISION", base = "", - scope=SCOPE_SUBTREE, + scope=SCOPE_BASE, attrs=attrs) empty = Message() empty.dn = entry[0].dn diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py index f914bbb..a1836cf 100644 --- a/source4/scripting/python/samba/dbchecker.py +++ b/source4/scripting/python/samba/dbchecker.py @@ -68,6 +68,8 @@ class dbcheck(object): self.remove_all_deleted_DN_links = False self.fix_all_target_mismatch = False self.fix_all_metadata = False + self.fix_all_missing_backlinks = False + self.fix_all_orphaned_backlinks = False def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']): '''perform a database check, returning the number of errors found''' @@ -126,6 +128,18 @@ class dbcheck(object): return c + def do_modify(self, m, controls, msg, validate=True): + '''perform a modify with optional verbose output''' + if self.verbose: + self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY)) + try: + self.samdb.modify(m, controls=controls, validate=validate) + except Exception, err: + self.report("%s : %s" % (msg, err)) + return False + return True + + ################################################################ # handle empty attributes def err_empty_attribute(self, dn, attrname): @@ -138,14 +152,9 @@ class dbcheck(object): m = ldb.Message() m.dn = dn -- Samba Shared Repository