[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Sun Jul 10 23:44:02 MDT 2011


The branch, master has been updated
       via  330c00a dbcheck: use get_lDAPDisplayName_by_attid()
       via  02562a0 dsdb: added get_lDAPDisplayName_by_attid
       via  082a9cc dbcheck: improved error checking in fixup of missing metdata
       via  396beee s4-provision: use samba.unix2nttime() instead of hard coding NTTIME offsets
       via  723fc5f s4-drs: do not return links pointed to unexistant objects
       via  4a4c748 s4-dirsync: do not return linked attribute if the target object is no more
       via  74530d6 s4-dsdb: allow objectsid to be specified in a modification operation
       via  61fc7f2 s4-samba-tool: dbcheck, check and fix broken metadata
       via  bbd4e27 s4-python: Add functions to get linkid and systemflags of an attribute
       via  ab77df8 s4-dsdb: if the provision control is specified, update replication metadata even if the data hasn't change
       via  e3fef4d upgradeprovision: reduce the number of attribute that we skip
       via  c3106a6 s4-provision: fix the value of creation timestamp to be a MS timestamp
       via  6ec4630 s4-dsdb: when replacing linked attribute take always the new dn as the old dn might be broken
       via  3764b93 s4-dsdb: check for single valued attribute in repl_meta_data module
       via  e14725c dbcheck: check all objects, including deleted objects
       via  6f6cda7 s4-dsdb: deleted objects are expected to be missing mandatory attributes
       via  da75e03 s4-dsdb: fixed crash bug in extended_dn_in
       via  faec258 dbcheck: added confirm_all support for remaining checks
       via  059941b dbcheck: use specified DB schema for non-LDAP URLs
      from  86b7b5c socket_wrapper: make sure interfaces are in the valid range on bind()

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


- Log -----------------------------------------------------------------
commit 330c00a14d0d903b5f1accf5a17c226ca3413dc4
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 14:28:19 2011 +1000

    dbcheck: use get_lDAPDisplayName_by_attid()
    
    this is better than doing a schema search inside the dbcheck code
    
    Autobuild-User: Andrew Tridgell <tridge at samba.org>
    Autobuild-Date: Mon Jul 11 07:43:18 CEST 2011 on sn-devel-104

commit 02562a0ca988b5b1e0796a445aabc96dddb408d2
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 14:27:21 2011 +1000

    dsdb: added get_lDAPDisplayName_by_attid
    
    this allows conversion from a DRS attribute ID to a LDAP display name
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 082a9cc72815a3873b1cea2779dff6bc41a9773c
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 14:05:30 2011 +1000

    dbcheck: improved error checking in fixup of missing metdata
    
    when fixing missing attributes in replPropertyMetaData, allow user to
    confirm changes, and check for exceptions
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

commit 396beee776778af7c9b7d48d7c977b32b3ee4654
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 13:45:50 2011 +1000

    s4-provision: use samba.unix2nttime() instead of hard coding NTTIME offsets
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

commit 723fc5fadd55987d38641508a3c50314147588c3
Author: Matthieu Patou <mat at matws.net>
Date:   Fri Jul 8 02:06:04 2011 +0400

    s4-drs: do not return links pointed to unexistant objects
    
    When an object is deleted, link pointed to it are marked as inactive.
    When the same object is purged we do not remmove the link pointed to it
    (we can't know them) so they stay in the database, it turns to be a
    problem for Windows 2008.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 4a4c748d2b3071ad7cd06b96cb0279a89c3ec6d0
Author: Matthieu Patou <mat at matws.net>
Date:   Fri Jul 8 02:04:52 2011 +0400

    s4-dirsync: do not return linked attribute if the target object is no more
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 74530d6453451d7a7ad08a11e37ea8b4672fc4ab
Author: Matthieu Patou <mat at matws.net>
Date:   Thu Jul 7 00:32:32 2011 +0400

    s4-dsdb: allow objectsid to be specified in a modification operation
    
    if we have the provision control, it's used by dbcheck
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 61fc7f285eee888e3603afd7beafba83cca4e378
Author: Matthieu Patou <mat at matws.net>
Date:   Thu Jul 7 00:31:21 2011 +0400

    s4-samba-tool: dbcheck, check and fix broken metadata
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit bbd4e27745352cc1069d7070620fe21f46702743
Author: Matthieu Patou <mat at matws.net>
Date:   Thu Jul 7 00:29:58 2011 +0400

    s4-python: Add functions to get linkid and systemflags of an attribute
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit ab77df800eb5e4af83d3a9e1079c369e00903fac
Author: Matthieu Patou <mat at matws.net>
Date:   Thu Jul 7 00:27:44 2011 +0400

    s4-dsdb: if the provision control is specified, update replication metadata even if the data hasn't change
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit e3fef4db0fe3f92ad0c12b9b85dccbea64d38193
Author: Matthieu Patou <mat at matws.net>
Date:   Tue Jul 5 21:56:30 2011 +0400

    upgradeprovision: reduce the number of attribute that we skip
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit c3106a6091090212a45b1ef02ddb0272c8f51d73
Author: Matthieu Patou <mat at matws.net>
Date:   Sun Jul 3 11:15:05 2011 +0400

    s4-provision: fix the value of creation timestamp to be a MS timestamp
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 6ec46309c3b1b766a23cd0327bcf7ff9f661fdf2
Author: Matthieu Patou <mat at matws.net>
Date:   Sun Jul 3 22:21:29 2011 +0400

    s4-dsdb: when replacing linked attribute take always the new dn as the old dn might be broken
    
    The usual use case is that you have a not complete linked attribute (ie.
    without the SID) if we keep using the old dn, then the SID will never be
    added.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 3764b93b7c9df4bcc03e4fbf2e1acb5f7a3d268d
Author: Matthieu Patou <mat at matws.net>
Date:   Sun Jul 3 22:06:34 2011 +0400

    s4-dsdb: check for single valued attribute in repl_meta_data module
    
    This is needed because we can have more than 1 value in a single valued
    attribute as we store also deleted values. So we do the check in repl_meta_data
    and then indicate LDB to do the check.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit e14725c8fe4c257d9951d48d3093ecb9916abfae
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 12:23:01 2011 +1000

    dbcheck: check all objects, including deleted objects
    
    this makes dbcheck search over all objects, deleted or not. This
    matters because when another DC replicates from this DC it replicates
    the deleted objects as well, so invalid attributes in deleted objects
    can cause problems on the new DC (for example, windows can get stuck
    or even crash during the replication)
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

commit 6f6cda72fc6d737060dd1f747b0e3b0f497b8d57
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 12:20:27 2011 +1000

    s4-dsdb: deleted objects are expected to be missing mandatory attributes
    
    the objectclass_attrs validation that an object contains all mandatory
    attributes is incorrect for deleted objects, as they get stripped of
    some mandatory attributes when deleted (for example, objectCategory
    gets stripped)
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

commit da75e031c3cff54d23d47f54459addf3d00236af
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 12:01:18 2011 +1000

    s4-dsdb: fixed crash bug in extended_dn_in
    
    when extended_dn_in fails to resolve a GUID extended DN component, the
    debug code assumed that it was a search operation, and accessed
    ac->req->op.search.base, which is not valid for non-search DN
    expansions.
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

commit faec2588f51e97e7421b9b092e53d88c88f6abd9
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 11:09:00 2011 +1000

    dbcheck: added confirm_all support for remaining checks
    
    this allows the user to choose all/none for all the remaining database
    checks
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

commit 059941b6e76589d76773b66643b2ec6826a17800
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Jul 11 10:53:52 2011 +1000

    dbcheck: use specified DB schema for non-LDAP URLs
    
    when connecting to a local database with -H we can use that databases
    schema
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>

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

Summary of changes:
 source4/dsdb/pydsdb.c                              |  101 +++++++++++++++++
 source4/dsdb/samdb/ldb_modules/dirsync.c           |   29 +++++
 source4/dsdb/samdb/ldb_modules/extended_dn_in.c    |    6 +-
 source4/dsdb/samdb/ldb_modules/objectclass_attrs.c |    3 +-
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    |   21 ++++-
 source4/dsdb/samdb/ldb_modules/samldb.c            |    8 +-
 source4/rpc_server/drsuapi/getncchanges.c          |   24 ++++
 source4/scripting/bin/upgradeprovision             |    3 +-
 source4/scripting/python/samba/dbchecker.py        |  115 ++++++++++++++++----
 source4/scripting/python/samba/netcmd/dbcheck.py   |   13 ++-
 .../scripting/python/samba/provision/__init__.py   |    4 +-
 source4/scripting/python/samba/samdb.py            |   12 ++
 12 files changed, 303 insertions(+), 36 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 5ca6b02..463a2f9 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -331,6 +331,101 @@ static PyObject *py_dsdb_get_attid_from_lDAPDisplayName(PyObject *self, PyObject
 }
 
 /*
+  return the systemFlags as int from the attribute name
+ */
+static PyObject *py_dsdb_get_systemFlags_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;
+
+	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;
+	}
+
+	return PyInt_FromLong(attribute->systemFlags);
+}
+
+/*
+  return the linkID from the attribute name
+ */
+static PyObject *py_dsdb_get_linkId_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;
+
+	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;
+	}
+
+	return PyInt_FromLong(attribute->linkID);
+}
+
+
+static PyObject *py_dsdb_get_lDAPDisplayName_by_attid(PyObject *self, PyObject *args)
+{
+	PyObject *py_ldb;
+	struct ldb_context *ldb;
+	struct dsdb_schema *schema;
+	const struct dsdb_attribute *a;
+	uint32_t attid;
+
+	if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &attid))
+		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;
+	}
+
+	a = dsdb_attribute_by_attributeID_id(schema, attid);
+	if (a == NULL) {
+		PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '0x%08x'", attid);
+		return NULL;
+	}
+
+	return PyString_FromString(a->lDAPDisplayName);
+}
+
+
+/*
   return the attribute syntax oid as a string from the attribute name
  */
 static PyObject *py_dsdb_get_syntax_oid_from_lDAPDisplayName(PyObject *self, PyObject *args)
@@ -836,6 +931,12 @@ static PyMethodDef py_dsdb_methods[] = {
 		METH_VARARGS, NULL },
 	{ "_dsdb_get_syntax_oid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_syntax_oid_from_lDAPDisplayName,
 		METH_VARARGS, NULL },
+	{ "_dsdb_get_systemFlags_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_systemFlags_from_lDAPDisplayName,
+		METH_VARARGS, NULL },
+	{ "_dsdb_get_linkId_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_linkId_from_lDAPDisplayName,
+		METH_VARARGS, NULL },
+	{ "_dsdb_get_lDAPDisplayName_by_attid", (PyCFunction)py_dsdb_get_lDAPDisplayName_by_attid,
+		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/dirsync.c b/source4/dsdb/samdb/ldb_modules/dirsync.c
index 64c5047..7ed1ed3 100644
--- a/source4/dsdb/samdb/ldb_modules/dirsync.c
+++ b/source4/dsdb/samdb/ldb_modules/dirsync.c
@@ -428,10 +428,17 @@ skip:
 				uint32_t tmp_usn2 = 0;
 				struct GUID invocation_id = GUID_zero();
 				struct dsdb_dn *dn = dsdb_dn_parse(msg, ldb, &el->values[k], attr->syntax->ldap_oid);
+				struct ldb_dn *copydn;
 				if (dn == NULL) {
 					ldb_set_errstring(ldb, "Cannot parse DN");
 					return ldb_module_done(dsc->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
 				}
+
+				copydn = ldb_dn_copy(msg, dn->dn);
+				if (copydn == NULL) {
+					ldb_oom(ldb);
+				}
+
 				status = dsdb_get_extended_dn_uint32(dn->dn, &tmp_usn, "RMD_LOCAL_USN");
 				if (!NT_STATUS_IS_OK(status)) {
 					talloc_free(dn);
@@ -504,6 +511,28 @@ skip:
 					if (dsc->linkIncrVal == true) {
 						struct ldb_message_element *tmpel;
 						if (flags & DSDB_RMD_FLAG_DELETED) {
+							/* We have to check that the inactive link still point to an existing object */
+							struct GUID guid;
+							struct ldb_dn *tdn;
+							int ret;
+
+							status = dsdb_get_extended_dn_guid(copydn, &guid, "GUID");
+							if (!NT_STATUS_IS_OK(status)) {
+								DEBUG(0,(__location__ " Unable to extract GUID in linked attribute '%s' in '%s'\n",
+									el->name, ldb_dn_get_linearized(copydn)));
+								return ldb_operr(ldb);
+							}
+							ret = dsdb_find_dn_by_guid(ldb, newmsg, &guid, &tdn);
+							if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+								DEBUG(2, (" Search of guid %s returned 0 objects, skipping it !\n",
+											GUID_string(newmsg, &guid)));
+								continue;
+							} else if (ret != LDB_SUCCESS) {
+								DEBUG(0, (__location__ " Search of guid %s failed with error code %d\n",
+											GUID_string(newmsg, &guid),
+											ret));
+								continue;
+							}
 							tmpel = el_incr_del;
 						} else {
 							tmpel = el_incr_add;
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_in.c b/source4/dsdb/samdb/ldb_modules/extended_dn_in.c
index 9a70d9a..4944137 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_in.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_in.c
@@ -44,6 +44,7 @@ struct extended_search_context {
 	struct ldb_module *module;
 	struct ldb_request *req;
 	struct ldb_dn *basedn;
+	struct ldb_dn *dn;
 	char *wellknown_object;
 	int extended_type;
 };
@@ -109,7 +110,7 @@ static int extended_base_callback(struct ldb_request *req, struct ldb_reply *are
 			   normal provision. We need to return
 			   NO_SUCH_OBJECT */
 			const char *str = talloc_asprintf(req, "Duplicate base-DN matches found for '%s'",
-							  ldb_dn_get_extended_linearized(req, ac->req->op.search.base, 1));
+							  ldb_dn_get_extended_linearized(req, ac->dn, 1));
 			ldb_set_errstring(ldb_module_get_ctx(ac->module), str);
 			return ldb_module_done(ac->req, NULL, NULL,
 					       LDB_ERR_NO_SUCH_OBJECT);
@@ -168,7 +169,7 @@ static int extended_base_callback(struct ldb_request *req, struct ldb_reply *are
 
 		if (!ac->basedn) {
 			const char *str = talloc_asprintf(req, "Base-DN '%s' not found",
-							  ldb_dn_get_extended_linearized(req, ac->req->op.search.base, 1));
+							  ldb_dn_get_extended_linearized(req, ac->dn, 1));
 			ldb_set_errstring(ldb_module_get_ctx(ac->module), str);
 			return ldb_module_done(ac->req, NULL, NULL,
 					       LDB_ERR_NO_SUCH_OBJECT);
@@ -388,6 +389,7 @@ static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req
 		
 		ac->module = module;
 		ac->req = req;
+		ac->dn = dn;
 		ac->basedn = NULL;  /* Filled in if the search finds the DN by SID/GUID etc */
 		ac->wellknown_object = wellknown_object;
 		
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
index 302904a..4525cf3 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
@@ -332,7 +332,8 @@ static int attr_handler2(struct oc_context *ac)
 		}
 	}
 
-	if (found_must_contain[0] != NULL) {
+	if (found_must_contain[0] != NULL &&
+	    ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE") == 0) {
 		ldb_asprintf_errstring(ldb, "objectclass_attrs: at least one mandatory attribute ('%s') on entry '%s' wasn't specified!",
 				       found_must_contain[0],
 				       ldb_dn_get_linearized(msg->dn));
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 830c118..a76b88e 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -1068,7 +1068,13 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb,
 
 	/* if the attribute's value haven't changed then return LDB_SUCCESS	*/
 	if (old_el != NULL && ldb_msg_element_compare(el, old_el) == 0) {
-		return LDB_SUCCESS;
+		if (!ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID)) {
+			/*
+			 * allow this to make it possible for dbcheck
+			 * to rebuild broken metadata
+			 */
+			return LDB_SUCCESS;
+		}
 	}
 
 	for (i=0; i<omd->ctr.ctr1.count; i++) {
@@ -2024,7 +2030,7 @@ static int replmd_modify_la_replace(struct ldb_module *module,
 		    (old_p = parsed_dn_find(old_dns,
 					    old_num_values, p->guid, NULL)) != NULL) {
 			/* update in place */
-			ret = replmd_update_la_val(old_el->values, old_p->v, old_p->dsdb_dn,
+			ret = replmd_update_la_val(old_el->values, old_p->v, p->dsdb_dn,
 						   old_p->dsdb_dn, invocation_id,
 						   seq_num, seq_num, now, 0, false);
 			if (ret != LDB_SUCCESS) {
@@ -2168,6 +2174,17 @@ static int replmd_modify_handle_linked_attribs(struct ldb_module *module,
 					       el->flags, el->name);
 			return LDB_ERR_UNWILLING_TO_PERFORM;
 		}
+		if (dsdb_check_single_valued_link(schema_attr, el) != LDB_SUCCESS) {
+			ldb_asprintf_errstring(ldb,
+					       "Attribute %s is single valued but more than one value has been supplied",
+					       el->name);
+			return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+		} else {
+			el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
+		}
+
+
+
 		if (ret != LDB_SUCCESS) {
 			return ret;
 		}
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 6533d10..a61920f 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -2035,9 +2035,11 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 	/* make sure that "objectSid" is not specified */
 	el = ldb_msg_find_element(req->op.mod.message, "objectSid");
 	if (el != NULL) {
-		ldb_set_errstring(ldb,
-				  "samldb: objectSid must not be specified!");
-		return LDB_ERR_UNWILLING_TO_PERFORM;
+		if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) {
+			ldb_set_errstring(ldb,
+					  "samldb: objectSid must not be specified!");
+			return LDB_ERR_UNWILLING_TO_PERFORM;
+		}
 	}
 	/* make sure that "sAMAccountType" is not specified */
 	el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType");
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index c57fec2..dc50fc0 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -357,6 +357,30 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx,
 
 	active = (dsdb_dn_rmd_flags(dsdb_dn->dn) & DSDB_RMD_FLAG_DELETED) == 0;
 
+	if (!active) {
+		/* We have to check that the inactive link still point to an existing object */
+		struct GUID guid;
+		struct ldb_dn *tdn;
+		int ret;
+
+		status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid, "GUID");
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0,(__location__ " Unable to extract GUID in linked attribute '%s' in '%s'\n",
+				sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn)));
+			return ntstatus_to_werror(status);
+		}
+		ret = dsdb_find_dn_by_guid(sam_ctx, mem_ctx, &guid, &tdn);
+		if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+			DEBUG(2, (" Search of guid %s returned 0 objects, skipping it !\n",
+						GUID_string(mem_ctx, &guid)));
+			return WERR_OK;
+		} else if (ret != LDB_SUCCESS) {
+			DEBUG(0, (__location__ " Search of guid %s failed with error code %d\n",
+						GUID_string(mem_ctx, &guid),
+						ret));
+			return WERR_OK;
+		}
+	}
 	la->attid = sa->attributeID_id;
 	la->flags = active?DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE:0;
 
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index e98b642..d2a645a 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -84,8 +84,7 @@ __docformat__ = "restructuredText"
 # This also apply to imported object from reference provision
 replAttrNotCopied = [   "dn", "whenCreated", "whenChanged", "objectGUID",
                         "parentGUID", "objectCategory", "distinguishedName",
-                        "nTMixedDomain", "showInAdvancedViewOnly",
-                        "instanceType", "msDS-Behavior-Version", "cn",
+                        "instanceType", "cn",
                         "lmPwdHistory", "pwdLastSet", "ntPwdHistory",
                         "unicodePwd", "dBCSPwd", "supplementalCredentials",
                         "gPCUserExtensionNames", "gPCMachineExtensionNames",
diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py
index 4209a3b..f914bbb 100644
--- a/source4/scripting/python/samba/dbchecker.py
+++ b/source4/scripting/python/samba/dbchecker.py
@@ -3,6 +3,7 @@
 # Samba4 AD database checker
 #
 # Copyright (C) Andrew Tridgell 2011
+# Copyright (C) Matthieu Patou <mat at matws.net> 2011
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,6 +23,8 @@ import ldb
 from samba import dsdb
 from samba import common
 from samba.dcerpc import misc
+from samba.ndr import ndr_unpack
+from samba.dcerpc import drsblobs
 
 
 class dsdb_DN(object):
@@ -52,12 +55,19 @@ class dbcheck(object):
 
     def __init__(self, samdb, samdb_schema=None, verbose=False, fix=False, yes=False, quiet=False):
         self.samdb = samdb
+        self.dict_oid_name = None
         self.samdb_schema = (samdb_schema or samdb)
         self.verbose = verbose
         self.fix = fix
         self.yes = yes
         self.quiet = quiet
         self.remove_all_unknown_attributes = False
+        self.remove_all_empty_attributes = False
+        self.fix_all_normalisation = False
+        self.fix_all_DN_GUIDs = False
+        self.remove_all_deleted_DN_links = False
+        self.fix_all_target_mismatch = False
+        self.fix_all_metadata = False
 
     def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']):
         '''perform a database check, returning the number of errors found'''
@@ -121,7 +131,7 @@ class dbcheck(object):
     def err_empty_attribute(self, dn, attrname):
         '''fix empty attributes'''
         self.report("ERROR: Empty attribute %s in %s" % (attrname, dn))
-        if not self.confirm('Remove empty attribute %s from %s?' % (attrname, dn)):
+        if not self.confirm_all('Remove empty attribute %s from %s?' % (attrname, dn), 'remove_all_empty_attributes'):
             self.report("Not fixing empty attribute %s" % attrname)
             return
 
@@ -131,7 +141,7 @@ class dbcheck(object):
         if self.verbose:
             self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
         try:
-            self.samdb.modify(m, controls=["relax:0"], validate=False)
+            self.samdb.modify(m, controls=["relax:0", "show_deleted:1"], validate=False)
         except Exception, msg:
             self.report("Failed to remove empty attribute %s : %s" % (attrname, msg))
             return
@@ -152,7 +162,7 @@ class dbcheck(object):
             elif (normalised[0] != val):
                 self.report("value '%s' should be '%s'" % (val, normalised[0]))
                 mod_list.append((val, normalised[0]))
-        if not self.confirm('Fix normalisation for %s from %s?' % (attrname, dn)):
+        if not self.confirm_all('Fix normalisation for %s from %s?' % (attrname, dn), 'fix_all_normalisation'):
             self.report("Not fixing attribute %s" % attrname)
             return
 
@@ -167,7 +177,7 @@ class dbcheck(object):
         if self.verbose:
             self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
         try:
-            self.samdb.modify(m, controls=["relax:0"], validate=False)
+            self.samdb.modify(m, controls=["relax:0", "show_deleted:1"], validate=False)
         except Exception, msg:
             self.report("Failed to normalise attribute %s : %s" % (attrname, msg))
             return
@@ -182,9 +192,7 @@ class dbcheck(object):
     # handle a missing GUID extended DN component
     def err_incorrect_dn_GUID(self, dn, attrname, val, dsdb_dn, errstr):
         self.report("ERROR: %s component for %s in object %s - %s" % (errstr, attrname, dn, val))
-        controls=["extended_dn:1:1"]
-        if self.is_deleted_objects_dn(dsdb_dn):
-            controls.append("show_deleted:1")
+        controls=["extended_dn:1:1", "show_deleted:1"]
         try:
             res = self.samdb.search(base=str(dsdb_dn.dn), scope=ldb.SCOPE_BASE,
                                     attrs=[], controls=controls)
@@ -193,7 +201,7 @@ class dbcheck(object):
             return
         dsdb_dn.dn = res[0].dn
 
-        if not self.confirm('Change DN to %s?' % str(dsdb_dn)):
+        if not self.confirm_all('Change DN to %s?' % str(dsdb_dn), 'fix_all_DN_GUIDs'):
             self.report("Not fixing %s" % errstr)
             return
         m = ldb.Message()
@@ -203,7 +211,7 @@ class dbcheck(object):
         if self.verbose:
             self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
         try:
-            self.samdb.modify(m)
+            self.samdb.modify(m, controls=["show_deleted:1"])
         except Exception, msg:
             self.report("Failed to fix %s on attribute %s : %s" % (errstr, attrname, msg))
             return
@@ -215,7 +223,7 @@ class dbcheck(object):
     def err_deleted_dn(self, dn, attrname, val, dsdb_dn, correct_dn):
         self.report("ERROR: target DN is deleted for %s in object %s - %s" % (attrname, dn, val))
         self.report("Target GUID points at deleted DN %s" % correct_dn)
-        if not self.confirm('Remove DN?'):
+        if not self.confirm_all('Remove DN?', 'remove_all_deleted_DN_links'):
             self.report("Not removing")
             return
         m = ldb.Message()
@@ -224,7 +232,7 @@ class dbcheck(object):
         if self.verbose:
             self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
         try:
-            self.samdb.modify(m)
+            self.samdb.modify(m, controls=["show_deleted:1"])
         except Exception, msg:
             self.report("Failed to remove deleted DN attribute %s : %s" % (attrname, msg))
             return
@@ -237,7 +245,7 @@ class dbcheck(object):
         self.report("ERROR: incorrect DN string component for %s in object %s - %s" % (attrname, dn, val))
         dsdb_dn.dn = correct_dn
 
-        if not self.confirm('Change DN to %s?' % str(dsdb_dn)):
+        if not self.confirm_all('Change DN to %s?' % str(dsdb_dn), 'fix_all_target_mismatch'):
             self.report("Not fixing %s" % errstr)
             return
         m = ldb.Message()
@@ -247,7 +255,7 @@ class dbcheck(object):
         if self.verbose:
             self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
         try:
-            self.samdb.modify(m)
+            self.samdb.modify(m, controls=["show_deleted:1"])
         except Exception, msg:
             self.report("Failed to fix incorrect DN string on attribute %s : %s" % (attrname, msg))
             return
@@ -267,7 +275,7 @@ class dbcheck(object):
         if self.verbose:
             self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY))
         try:
-            self.samdb.modify(m, controls=["relax:0"])
+            self.samdb.modify(m, controls=["relax:0", "show_deleted:1"])
         except Exception, msg:
             self.report("Failed to remove unknown attribute %s : %s" % (attrname, msg))
             return
@@ -300,12 +308,13 @@ class dbcheck(object):
                 self.err_incorrect_dn_GUID(obj.dn, attrname, val, dsdb_dn, "incorrect GUID")
                 continue
 
-            # the target DN might be deleted
-            if ((not self.is_deleted_objects_dn(dsdb_dn)) and
-                'isDeleted' in res[0] and
-                res[0]['isDeleted'][0].upper() == "TRUE"):
-                # note that we don't check this for the special wellKnownObjects prefix
-                # for Deleted Objects, as we expect that to be deleted
+            # now we have two cases - the source object might or might not be deleted
+            is_deleted = 'isDeleted' in obj and obj['isDeleted'][0].upper() == 'TRUE'
+            target_is_deleted = 'isDeleted' in res[0] and res[0]['isDeleted'][0].upper() == 'TRUE'


-- 
Samba Shared Repository


More information about the samba-cvs mailing list