[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Sun Sep 18 20:32:03 MDT 2011


The branch, master has been updated
       via  9d98461 s4-dsdb: cope with out of sync replication attributes in partition module
       via  2e76b79 ldb:"ldb_extended" -make the call more similar to "ldb_search"
       via  966b5d5 pyldb: fixed places where we try to concatenate a Dn with a string
       via  f79d6ee s4-provision: use get_config_basedn() in DNS setup
       via  579fd43 samba-tool: use get_config_basedn() to get configuration NC DN
       via  ee7cfca s4-kdc: default kvno for inter-domain trusts to zero
       via  4577ee1 s4-dsdb: use get_config_basedn() in python tests
       via  cea37b0 s4-drs: cope with REPL_OBJ getncchanges call for new object
       via  aa960d8 s4-provision Add initial support for joining as a new subdomain
      from  4e05847 Fix a typo. This is not an electromagnet pulse daemon I guess :-)

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


- Log -----------------------------------------------------------------
commit 9d9846115068cfb328a18a0a2eddb5698a21edb8
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Sep 19 10:55:17 2011 +1000

    s4-dsdb: cope with out of sync replication attributes in partition module
    
    if the @ATTRIBUTES or other objects which are replicated between
    partions become out of sync, then the ldb would fail to open. This
    changes ensures that we can always fix those records, by running the
    operation in the top level partition, and replicating the result to
    the other partitions
    
    Pair-Programmed-With: Amitay Isaacs <amitay at gmail.com>
    
    Autobuild-User: Andrew Tridgell <tridge at samba.org>
    Autobuild-Date: Mon Sep 19 04:31:48 CEST 2011 on sn-devel-104

commit 2e76b798fe9732284a50b43cf10a0f3802ea6e4f
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Tue Jun 21 22:25:22 2011 +0200

    ldb:"ldb_extended" -make the call more similar to "ldb_search"
    
    For example NULL out the LDB result pointer on failures.
    
    Signed-off-by: Andrew Tridgell <tridge at samba.org>

commit 966b5d5de2fc40ff77e2b947c61a2419795a2282
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 16 15:15:35 2011 +1000

    pyldb: fixed places where we try to concatenate a Dn with a string
    
    you need to either use str(dn) or use %s in a format string

commit f79d6ee929884ad76f2a88fc67c660fec31b8ed7
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 16 11:18:26 2011 +1000

    s4-provision: use get_config_basedn() in DNS setup
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 579fd43057e5d838ef24a72af20203eda8199204
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 16 11:18:05 2011 +1000

    samba-tool: use get_config_basedn() to get configuration NC DN
    
    this allows these commands to work for subdomains
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit ee7cfcadc60eac34bf646f765798ca5a01d311ed
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 16 11:15:27 2011 +1000

    s4-kdc: default kvno for inter-domain trusts to zero
    
    the exact value doesn't matter, as both Samba and windows check
    against the latest password, but the old default of -1 caused ASN.1
    parsing errors on windows, which prevented it answering TGS requests
    
    thanks to Hongwei Sun for finding this from a ttt trace
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 4577ee1f957e08d19b2c849b9b698b31474040ff
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 16 11:14:12 2011 +1000

    s4-dsdb: use get_config_basedn() in python tests
    
    we can't just append CN=Configuration to the basedn, as that won't
    give the right configuration DN for a subdomain of a forest
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit cea37b0d6d0f5f32fdfafd160dfbcf2c5dccdb12
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 16 11:13:05 2011 +1000

    s4-drs: cope with REPL_OBJ getncchanges call for new object
    
    when we do a subdomain join we create a new object using a REPL_OBJ
    getncchanges call for the partitions DN. This has a side effect of
    creating that object. We need to skip the UDV update in that case
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit aa960d8fa70ab243e97eed5d7bb7a47f4386487c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Aug 24 15:39:51 2011 +1000

    s4-provision Add initial support for joining as a new subdomain
    
    To do this we need to reorganise a lot of the provision code, so that
    we can create the framework for the inbound replicaton of the config
    and schema partitions and then add in the new subdomain locally.
    
    Andrew Bartlett

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

Summary of changes:
 lib/ldb/common/ldb.c                               |    8 +-
 source4/dsdb/samdb/ldb_modules/partition.c         |   69 +++++++++-
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    |   15 ++-
 source4/dsdb/tests/python/acl.py                   |    4 +-
 source4/dsdb/tests/python/dirsync.py               |    2 +-
 source4/dsdb/tests/python/ldap.py                  |   30 ++--
 source4/dsdb/tests/python/urgent_replication.py    |    2 +-
 source4/kdc/db-glue.c                              |   10 ++-
 source4/scripting/python/samba/join.py             |  150 +++++++++++---------
 source4/scripting/python/samba/netcmd/domain.py    |   12 +-
 source4/scripting/python/samba/netcmd/fsmo.py      |    4 +-
 .../scripting/python/samba/provision/__init__.py   |  137 +++++++++---------
 .../scripting/python/samba/provision/sambadns.py   |    2 +-
 13 files changed, 274 insertions(+), 171 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index 433f30b..a4c04ce 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -1417,6 +1417,7 @@ int ldb_extended(struct ldb_context *ldb,
 	struct ldb_result *res;
 
 	*_res = NULL;
+	req = NULL;
 
 	res = talloc_zero(ldb, struct ldb_result);
 	if (!res) {
@@ -1427,6 +1428,8 @@ int ldb_extended(struct ldb_context *ldb,
 				     oid, data, NULL,
 				     res, ldb_extended_default_callback,
 				     NULL);
+	ldb_req_set_location(req, "ldb_extended");
+
 	if (ret != LDB_SUCCESS) goto done;
 
 	ldb_set_timeout(ldb, req, 0); /* use default timeout */
@@ -1437,13 +1440,14 @@ int ldb_extended(struct ldb_context *ldb,
 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
 	}
 
-	talloc_free(req);
-
 done:
 	if (ret != LDB_SUCCESS) {
 		talloc_free(res);
+		res = NULL;
 	}
 
+	talloc_free(req);
+
 	*_res = res;
 	return ret;
 }
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index b286548..93f2d6b 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -398,6 +398,73 @@ static int partition_send_all(struct ldb_module *module,
 	return partition_call_first(ac);
 }
 
+
+/**
+ * send an operation to the top partition, then copy the resulting
+ * object to all other partitions
+ */
+static int partition_copy_all(struct ldb_module *module,
+			      struct partition_context *ac,
+			      struct ldb_request *req,
+			      struct ldb_dn *dn)
+{
+	unsigned int i;
+	struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
+							      struct partition_private_data);
+	int ret, search_ret;
+	struct ldb_result *res;
+
+	/* do the request on the top level sam.ldb synchronously */
+	ret = ldb_next_request(module, req);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	/* now fetch the resulting object, and then copy it to all the
+	 * other partitions. We need this approach to cope with the
+	 * partitions getting out of sync. If for example the
+	 * @ATTRIBUTES object exists on one partition but not the
+	 * others then just doing each of the partitions in turn will
+	 * lead to an error
+	 */
+	search_ret = dsdb_module_search_dn(module, ac, &res, dn, NULL, DSDB_FLAG_NEXT_MODULE, req);
+	if (search_ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
+		return search_ret;
+	}
+
+	/* now delete the object in the other partitions. Once that is
+	   done we will re-add the object, if search_ret was not
+	   LDB_ERR_NO_SUCH_OBJECT
+	*/
+	for (i=0; data->partitions && data->partitions[i]; i++) {
+		int pret;
+		pret = dsdb_module_del(data->partitions[i]->module, dn, DSDB_FLAG_NEXT_MODULE, req);
+		if (pret != LDB_SUCCESS && pret != LDB_ERR_NO_SUCH_OBJECT) {
+			/* we should only get success or no
+			   such object from the other partitions */
+			return pret;
+		}
+	}
+
+
+	if (search_ret != LDB_ERR_NO_SUCH_OBJECT) {
+		/* now re-add in the other partitions */
+		for (i=0; data->partitions && data->partitions[i]; i++) {
+			int pret;
+			pret = dsdb_module_add(data->partitions[i]->module, res->msgs[0], DSDB_FLAG_NEXT_MODULE, req);
+			if (pret != LDB_SUCCESS) {
+				return pret;
+			}
+		}
+	}
+
+	return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+}
+
 /**
  * Figure out which backend a request needs to be aimed at.  Some
  * requests must be replicated to all backends
@@ -427,7 +494,7 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re
 					return ldb_operr(ldb_module_get_ctx(module));
 				}
 				
-				return partition_send_all(module, ac, req);
+				return partition_copy_all(module, ac, req, dn);
 			}
 		}
 	}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index e50e2a0..3b4e280 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -3972,6 +3972,15 @@ static int replmd_replicated_uptodate_modify(struct replmd_replicated_request *a
 
 	unix_to_nt_time(&now, t);
 
+	if (ar->search_msg == NULL) {
+		/* this happens for a REPL_OBJ call where we are
+		   creating the target object by replicating it. The
+		   subdomain join code does this for the partition DN
+		*/
+		DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as no target DN\n"));
+		return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
+	}
+
 	instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0);
 	if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
 		DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as not NC root: %s\n",
@@ -4251,11 +4260,7 @@ static int replmd_replicated_uptodate_search_callback(struct ldb_request *req,
 		break;
 
 	case LDB_REPLY_DONE:
-		if (ar->search_msg == NULL) {
-			ret = replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
-		} else {
-			ret = replmd_replicated_uptodate_modify(ar);
-		}
+		ret = replmd_replicated_uptodate_modify(ar);
 		if (ret != LDB_SUCCESS) {
 			return ldb_module_done(ar->req, NULL, NULL, ret);
 		}
diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py
index 22080a3..238889a 100755
--- a/source4/dsdb/tests/python/acl.py
+++ b/source4/dsdb/tests/python/acl.py
@@ -698,7 +698,7 @@ class AclSearchTests(AclTests):
         else:
             self.fail()
         try:
-            res = anonymous.search("CN=Configuration," + self.base_dn, expression="(objectClass=*)",
+            res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)",
                                         scope=SCOPE_SUBTREE)
         except LdbError, (num, _):
             self.assertEquals(num, ERR_OPERATIONS_ERROR)
@@ -719,7 +719,7 @@ class AclSearchTests(AclTests):
         self.assertTrue("dn" in res[0])
         self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin,
                                            "OU=test_search_ou2,OU=test_search_ou1," + self.base_dn))
-        res = anonymous.search("CN=Configuration," + self.base_dn, expression="(objectClass=*)",
+        res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)",
                                scope=SCOPE_SUBTREE)
         self.assertEquals(len(res), 1)
         self.assertTrue("dn" in res[0])
diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py
index 96c6950..dcb10a8 100755
--- a/source4/dsdb/tests/python/dirsync.py
+++ b/source4/dsdb/tests/python/dirsync.py
@@ -166,7 +166,7 @@ class SimpleDirsyncTests(DirsyncBaseTests):
     def test_ok_not_rootdc(self):
         """Test if it's ok to do dirsync on another NC that is not the root DC"""
         try:
-            res = self.ldb_admin.search("CN=Configuration, %s" % self.base_dn,
+            res = self.ldb_admin.search(self.ldb_admin.get_config_basedn(),
                                         expression="samaccountname=*",
                                         controls=["dirsync:1:0:1"])
         except:
diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py
index 4f2044b..9f5b82f 100755
--- a/source4/dsdb/tests/python/ldap.py
+++ b/source4/dsdb/tests/python/ldap.py
@@ -1574,7 +1574,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d
         self.assertEquals(res[0]["objectClass"][4], "computer");
         self.assertTrue("objectGUID" in res[0])
         self.assertTrue("whenCreated" in res[0])
-        self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
+        self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,%s" % ldb.get_schema_basedn()))
         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT);
         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE);
@@ -1883,7 +1883,7 @@ servicePrincipalName: host/ldaptest2computer29
         except LdbError, (num, _):
             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
         try:
-            ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
+            ldb.rename("cn=ldaptestuser3,cn=users,%s" % self.base_dn, "cn=ldaptestuser3,%s" % ldb.get_config_basedn())
             self.fail()
         except LdbError, (num, _):
             self.assertTrue(num in (71, 64))
@@ -2014,15 +2014,15 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
         self.assertTrue("objectGUID" in res[0])
         self.assertTrue("whenCreated" in res[0])
-        self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
+        self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,%s" % ldb.get_schema_basedn()))
         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
         self.assertEquals(len(res[0]["memberOf"]), 1)
 
-        print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
-        res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
-        self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
+        print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()
+        res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn())
+        self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn())
 
         self.assertEquals(res[0].dn, res2[0].dn)
 
@@ -2059,23 +2059,23 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
         self.assertTrue("objectGUID" in res[0])
         self.assertTrue("whenCreated" in res[0])
-        self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
+        self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,%s" % ldb.get_schema_basedn()))
         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
         self.assertEquals(len(res[0]["memberOf"]), 1)
 
-        print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
-        res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
-        self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
+        print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()
+        res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn())
+        self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn())
 
         self.assertEquals(res[0].dn, res2[0].dn)
 
         if gc_ldb is not None:
-            print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
-            res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
-            self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
+            print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) in Global Catalog" % gc_ldb.get_schema_basedn()
+            res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % gc_ldb.get_schema_basedn())
+            self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) In Global Catalog" % gc_ldb.get_schema_basedn())
 
             self.assertEquals(res[0].dn, res2gc[0].dn)
 
@@ -2122,7 +2122,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
         self.assertTrue("objectGUID" in res[0])
         self.assertTrue("whenCreated" in res[0])
-        self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
+        self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,%s" % ldb.get_schema_basedn())
         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
 
@@ -2761,7 +2761,7 @@ class BaseDnTests(unittest.TestCase):
         self.assertEquals(len(res4[0]["msDS-Behavior-Version"]), 1)
         self.assertEquals(int(res[0]["domainFunctionality"][0]), int(res4[0]["msDS-Behavior-Version"][0]))
 
-        res5 = self.ldb.search("cn=partitions," + str(ldb.get_config_basedn()), scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"])
+        res5 = self.ldb.search("cn=partitions,%s" % ldb.get_config_basedn(), scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"])
         self.assertEquals(len(res5), 1)
         self.assertEquals(len(res5[0]["msDS-Behavior-Version"]), 1)
         self.assertEquals(int(res[0]["forestFunctionality"][0]), int(res5[0]["msDS-Behavior-Version"][0]))
diff --git a/source4/dsdb/tests/python/urgent_replication.py b/source4/dsdb/tests/python/urgent_replication.py
index 3759c82..2a07a58 100755
--- a/source4/dsdb/tests/python/urgent_replication.py
+++ b/source4/dsdb/tests/python/urgent_replication.py
@@ -87,7 +87,7 @@ class UrgentReplicationTests(samba.tests.TestCase):
         '''Test if the urgent replication is activated
            when handling a nTDSDSA object'''
         self.ldb.add({
-            "dn": "cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration," + self.base_dn,
+            "dn": "cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,%s" % self.ldb.get_config_basedn(),
             "objectclass":"server",
             "cn":"test server",
             "name":"test server",
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c
index cdc318a..52bacd0 100644
--- a/source4/kdc/db-glue.c
+++ b/source4/kdc/db-glue.c
@@ -896,7 +896,15 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
 		goto out;
 	}
 
-	entry_ex->entry.kvno = -1;
+	entry_ex->entry.kvno = 0;
+	/*
+	  we usually don't have a TRUST_AUTH_TYPE_VERSION field, as
+	  windows doesn't create one, so we rely on the fact that both
+	  windows and Samba don't actually check the kvno and instead
+	  just check against the latest password blob. If we do have a
+	  TRUST_AUTH_TYPE_VERSION field then we do use it, otherwise
+	  we just use 0.
+	 */
 	for (i=0; i < password_blob.count; i++) {
 		if (password_blob.current.array[i].AuthType == TRUST_AUTH_TYPE_VERSION) {
 			entry_ex->entry.kvno = password_blob.current.array[i].AuthInfo.version.version;
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index ccb9f06..195dfc2 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -304,40 +304,47 @@ class dc_join(object):
         r.value_ctr = 1
 
 
-    def DsAddEntry(ctx, rec):
+    def DsAddEntry(ctx, recs):
         '''add a record via the DRSUAPI DsAddEntry call'''
         if ctx.drsuapi is None:
             ctx.drsuapi_connect()
         if ctx.tmp_samdb is None:
             ctx.create_tmp_samdb()
 
-        id = drsuapi.DsReplicaObjectIdentifier()
-        id.dn = rec['dn']
-
-        attrs = []
-        for a in rec:
-            if a == 'dn':
-                continue
-            if not isinstance(rec[a], list):
-                v = [rec[a]]
-            else:
-                v = rec[a]
-            rattr = ctx.tmp_samdb.dsdb_DsReplicaAttribute(ctx.tmp_samdb, a, v)
-            attrs.append(rattr)
-
-        attribute_ctr = drsuapi.DsReplicaAttributeCtr()
-        attribute_ctr.num_attributes = len(attrs)
-        attribute_ctr.attributes = attrs
-
-        object = drsuapi.DsReplicaObject()
-        object.identifier = id
-        object.attribute_ctr = attribute_ctr
-
-        first_object = drsuapi.DsReplicaObjectListItem()
-        first_object.object = object
+        objects = []
+        for rec in recs:
+            id = drsuapi.DsReplicaObjectIdentifier()
+            id.dn = rec['dn']
+
+            attrs = []
+            for a in rec:
+                if a == 'dn':
+                    continue
+                if not isinstance(rec[a], list):
+                    v = [rec[a]]
+                else:
+                    v = rec[a]
+                rattr = ctx.tmp_samdb.dsdb_DsReplicaAttribute(ctx.tmp_samdb, a, v)
+                attrs.append(rattr)
+
+            attribute_ctr = drsuapi.DsReplicaAttributeCtr()
+            attribute_ctr.num_attributes = len(attrs)
+            attribute_ctr.attributes = attrs
+
+            object = drsuapi.DsReplicaObject()
+            object.identifier = id
+            object.attribute_ctr = attribute_ctr
+
+            list_object = drsuapi.DsReplicaObjectListItem()
+            list_object.object = object
+            objects.append(list_object)
 
         req2 = drsuapi.DsAddEntryRequest2()
-        req2.first_object = first_object
+        req2.first_object = objects[0]
+        prev = req2.first_object
+        for o in objects[1:]:
+            prev.next_object = o
+            prev = o
 
         (level, ctr) = ctx.drsuapi.DsAddEntry(ctx.drsuapi_handle, 2, req2)
         if ctr.err_ver != 1:
@@ -349,6 +356,7 @@ class dc_join(object):
         if ctr.err_data.dir_err != drsuapi.DRSUAPI_DIRERR_OK:
             print("DsAddEntry failed with dir_err %u" % ctr.err_data.dir_err)
             raise RuntimeError("DsAddEntry failed")
+        return ctr.objects
 
 
     def join_add_ntdsdsa(ctx):
@@ -361,17 +369,12 @@ class dc_join(object):
             "systemFlags" : str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
             "dMDLocation" : ctx.schema_dn}
 
-        if ctx.subdomain:
-            # the local subdomain NC doesn't exist at this time
-            # so we have to add the base_dn NC later
-            nc_list = [ ctx.config_dn, ctx.schema_dn ]
-        else:
-            nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
+        nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
 
         if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
             rec["msDS-Behavior-Version"] = str(ctx.behavior_version)
 
-        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003 and not ctx.subdomain:
+        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
             rec["msDS-HasDomainNCs"] = ctx.base_dn
 
         if ctx.RODC:
@@ -386,32 +389,13 @@ class dc_join(object):
                 rec["msDS-HasMasterNCs"] = nc_list
             rec["options"] = "1"
             rec["invocationId"] = ndr_pack(ctx.invocation_id)
-            if ctx.subdomain:
-                ctx.samdb.add(rec, ['relax:0'])
-            else:
-                ctx.DsAddEntry(rec)
+            ctx.DsAddEntry([rec])
 
         # find the GUID of our NTDS DN
         res = ctx.samdb.search(base=ctx.ntds_dn, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
         ctx.ntds_guid = misc.GUID(ctx.samdb.schema_format_value("objectGUID", res[0]["objectGUID"][0]))
 
 
-    def join_modify_ntdsdsa(ctx):
-        '''modify the ntdsdsa object to add local partitions'''
-        print "Modifying %s using system privileges" % ctx.ntds_dn
-
-        # this works around the Enterprise Admins ACL on the NTDSDSA object
-        system_session_info = system_session()
-        ctx.samdb.set_session_info(system_session_info)
-
-        m = ldb.Message()
-        m.dn = ldb.Dn(ctx.samdb, ctx.ntds_dn)
-        m["HasMasterNCs"] = ldb.MessageElement(ctx.base_dn, ldb.FLAG_MOD_ADD, "HasMasterNCs")
-        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
-            m["msDS-HasDomainNCs"] = ldb.MessageElement(ctx.base_dn, ldb.FLAG_MOD_ADD, "msDS-HasDomainNCs")
-            m["msDS-HasMasterNCs"] = ldb.MessageElement(ctx.base_dn, ldb.FLAG_MOD_ADD, "msDS-HasMasterNCs")
-        ctx.samdb.modify(m, controls=['relax:0'])
-
     def join_add_objects(ctx):
         '''add the various objects needed for the join'''
         if ctx.acct_dn:
@@ -440,9 +424,11 @@ class dc_join(object):
         rec = {
             "dn": ctx.server_dn,
             "objectclass" : "server",
+            # windows uses 50000000 decimal for systemFlags. A windows hex/decimal mixup bug?
             "systemFlags" : str(samba.dsdb.SYSTEM_FLAG_CONFIG_ALLOW_RENAME |
                                 samba.dsdb.SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE |
                                 samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
+            # windows seems to add the dnsHostName later
             "dnsHostName" : ctx.dnshostname}
 
         if ctx.acct_dn:
@@ -507,9 +493,6 @@ class dc_join(object):
     def join_add_objects2(ctx):
         '''add the various objects needed for the join, for subdomains post replication'''
 
-        if not ctx.subdomain:
-            return
-
         print "Adding %s" % ctx.partition_dn
         # NOTE: windows sends a ntSecurityDescriptor here, we
         # let it default
@@ -524,8 +507,47 @@ class dc_join(object):
             "systemFlags" : str(samba.dsdb.SYSTEM_FLAG_CR_NTDS_NC|samba.dsdb.SYSTEM_FLAG_CR_NTDS_DOMAIN)}
         if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
             rec["msDS-Behavior-Version"] = str(ctx.behavior_version)
-        ctx.DsAddEntry(rec)
 
+        rec2 = {
+            "dn" : ctx.ntds_dn,
+            "objectclass" : "nTDSDSA",
+            "systemFlags" : str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
+            "dMDLocation" : ctx.schema_dn}
+
+        nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
+
+        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+            rec2["msDS-Behavior-Version"] = str(ctx.behavior_version)
+
+        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+            rec2["msDS-HasDomainNCs"] = ctx.base_dn
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list