[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Sun Nov 7 16:33:01 MST 2010


The branch, master has been updated
       via  e59bf5e s4-join: modify join behaviour according to domain level
       via  fc5fecb s4-drs: allow override of the replica_flags
       via  18085b1 s4-dsdb: give the DN on a shema attribute failure
      from  9ba7ce6 s4:ldap.py - add more "objectGUID" related tests

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


- Log -----------------------------------------------------------------
commit e59bf5efb5cf23ff21f2a2ac7dff8d211070a916
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sun Nov 7 13:55:20 2010 +1100

    s4-join: modify join behaviour according to domain level
    
    Autobuild-User: Andrew Tridgell <tridge at samba.org>
    Autobuild-Date: Sun Nov  7 23:32:16 UTC 2010 on sn-devel-104

commit fc5fecb0b7d6bbbcf3613df302785176e4582b52
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sun Nov 7 13:53:13 2010 +1100

    s4-drs: allow override of the replica_flags

commit 18085b12360b5314730e0e82eee2204d44cb0939
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sun Nov 7 11:25:00 2010 +1100

    s4-dsdb: give the DN on a shema attribute failure

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

Summary of changes:
 source4/dsdb/schema/schema_init.c           |    2 +-
 source4/scripting/bin/samba_spnupdate       |    2 +-
 source4/scripting/devel/pfm_verify.py       |    2 +-
 source4/scripting/python/samba/drs_utils.py |   30 +++++--
 source4/scripting/python/samba/join.py      |  130 +++++++++++++++++++--------
 5 files changed, 120 insertions(+), 46 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index c1032f9..bcb51f6 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -450,7 +450,7 @@ static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
 	const struct ldb_val *get_string_val = ldb_msg_find_ldb_val(msg, attr); \
 	if (get_string_val == NULL) { \
 		if (strict) {					  \
-			d_printf("%s: %s == NULL\n", __location__, attr); \
+			d_printf("%s: %s == NULL in %s\n", __location__, attr, ldb_dn_get_linearized(msg->dn)); \
 			return WERR_INVALID_PARAM;			\
 		} else {						\
 			(p)->elem = NULL;				\
diff --git a/source4/scripting/bin/samba_spnupdate b/source4/scripting/bin/samba_spnupdate
index c6af81f..7a4de7a 100755
--- a/source4/scripting/bin/samba_spnupdate
+++ b/source4/scripting/bin/samba_spnupdate
@@ -196,7 +196,7 @@ def call_rodc_update(d):
     server = cldap_ret.pdc_dns_name
     try:
         drs = drsuapi.drsuapi('ncacn_ip_tcp:%s[seal,print]' % server, lp, creds)
-        drs_handle = drs_utils.drs_DsBind(drs)
+        (drs_handle, supported_extensions) = drs_utils.drs_DsBind(drs)
     except Exception, reason:
         print("Unable to connect to DC '%s' for domain '%s' : %s" % (server, domain, reason))
         sys.exit(1)
diff --git a/source4/scripting/devel/pfm_verify.py b/source4/scripting/devel/pfm_verify.py
index 76fb8e4..dbd3d88 100755
--- a/source4/scripting/devel/pfm_verify.py
+++ b/source4/scripting/devel/pfm_verify.py
@@ -49,7 +49,7 @@ def _drs_fetch_pfm(server, samdb, creds, lp):
     binding_str = "ncacn_ip_tcp:%s[print,seal]" % server
 
     drs = drsuapi.drsuapi(binding_str, lp, creds)
-    drs_handle = drs_DsBind(drs)
+    (drs_handle, supported_extensions) = drs_DsBind(drs)
     print "DRS Handle: %s" % drs_handle
 
     req8 = drsuapi.DsGetNCChangesRequest8()
diff --git a/source4/scripting/python/samba/drs_utils.py b/source4/scripting/python/samba/drs_utils.py
index a600c23..00efd78 100644
--- a/source4/scripting/python/samba/drs_utils.py
+++ b/source4/scripting/python/samba/drs_utils.py
@@ -58,14 +58,15 @@ def drs_DsBind(drs):
     bind_info.info.supported_extensions	|= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7
     bind_info.info.supported_extensions	|= drsuapi.DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT
     (info, handle) = drs.DsBind(misc.GUID(drsuapi.DRSUAPI_DS_BIND_GUID), bind_info)
-    return handle
+
+    return (handle, info.info.supported_extensions)
 
 class drs_Replicate:
     '''DRS replication calls'''
 
     def __init__(self, binding_string, lp, creds, samdb):
         self.drs = drsuapi.drsuapi(binding_string, lp, creds)
-        self.drs_handle = drs_DsBind(self.drs)
+        (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs)
         self.net = Net(creds=creds, lp=lp)
         self.samdb = samdb
         self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs)
@@ -111,7 +112,8 @@ class drs_Replicate:
 
 
     def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid,
-                  schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False):
+                  schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False,
+                  replica_flags=None):
         '''replicate a single DN'''
 
         # setup for a GetNCChanges call
@@ -126,7 +128,9 @@ class drs_Replicate:
         req8.highwatermark.reserved_usn	    = 0
         req8.highwatermark.highest_usn	    = 0
         req8.uptodateness_vector	    = None
-        if exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET:
+        if replica_flags is not None:
+            req8.replica_flags = replica_flags
+        elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET:
             req8.replica_flags		    = 0
         else:
             req8.replica_flags		    =  (drsuapi.DRSUAPI_DRS_INIT_SYNC |
@@ -135,6 +139,8 @@ class drs_Replicate:
                                                 drsuapi.DRSUAPI_DRS_NEVER_SYNCED)
             if rodc:
                 req8.replica_flags |= drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING
+            else:
+                req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP
         req8.max_object_count		     = 402
         req8.max_ndr_size		     = 402116
         req8.extended_op		     = exop
@@ -147,9 +153,21 @@ class drs_Replicate:
         if not schema and rodc:
             req8.partial_attribute_set = self.drs_get_rodc_partial_attribute_set()
 
+        if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8:
+            req_level = 8
+            req = req8
+        else:
+            req_level = 5
+            req5 = drsuapi.DsGetNCChangesRequest5()
+            for a in dir(req5):
+                if a[0] != '_':
+                    setattr(req5, a, getattr(req8, a))
+            req = req5
+
+
         while True:
-            (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, 8, req8)
+            (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req)
             self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema)
             if ctr.more_data == 0:
                 break
-            req8.highwatermark.tmp_highest_usn = ctr.new_highwatermark.tmp_highest_usn
+            req.highwatermark.tmp_highest_usn = ctr.new_highwatermark.tmp_highest_usn
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index 7d3b6f2..5f11f66 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -21,7 +21,7 @@
 import samba.getopt as options
 from samba.auth import system_session
 from samba.samdb import SamDB
-from samba import gensec, Ldb, drs_utils
+from samba import gensec, Ldb, drs_utils, dsdb
 import ldb, samba, sys, os, uuid
 from samba.ndr import ndr_pack, ndr_unpack, ndr_print
 from samba.dcerpc import security, drsuapi, misc, netlogon, nbt
@@ -30,7 +30,6 @@ from samba.provision import secretsdb_self_join, provision, FILL_DRS, find_setup
 from samba.schema import Schema
 from samba.net import Net
 import logging
-from samba.dsdb import DS_DOMAIN_FUNCTION_2008_R2
 import talloc
 
 # this makes debugging easier
@@ -70,21 +69,31 @@ class dc_join:
         ctx.domsid = ctx.samdb.get_domain_sid()
         ctx.domain_name = ctx.get_domain_name()
 
-        lp.set("realm", ctx.domain_name)
+        lp.set("workgroup", ctx.domain_name)
+        print("workgroup is %s" % ctx.domain_name)
 
         ctx.dc_ntds_dn = ctx.get_dsServiceName()
         ctx.dc_dnsHostName = ctx.get_dnsHostName()
+        ctx.behavior_version = ctx.get_behavior_version()
+
         ctx.acct_pass = samba.generate_random_password(12, 32)
-        ctx.mysid = ctx.get_mysid()
 
         # work out the DNs of all the objects we will be adding
-        ctx.admin_dn = "<SID=%s>" % ctx.mysid
         ctx.server_dn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (ctx.myname, ctx.site, ctx.config_dn)
         ctx.ntds_dn = "CN=NTDS Settings,%s" % ctx.server_dn
-        ctx.topology_dn = "CN=%s,CN=Topology,CN=Domain System Volume,CN=DFSR-GlobalSettings,CN=System,%s" % (ctx.myname, ctx.base_dn)
+        topology_base = "CN=Topology,CN=Domain System Volume,CN=DFSR-GlobalSettings,CN=System,%s" % ctx.base_dn
+        if ctx.dn_exists(topology_base):
+            ctx.topology_dn = "CN=%s,%s" % (ctx.myname, topology_base)
+        else:
+            ctx.topology_dn = None
 
         ctx.dnsdomain = ldb.Dn(ctx.samdb, ctx.base_dn).canonical_str().split('/')[0]
+
         ctx.realm = ctx.dnsdomain
+        lp.set("realm", ctx.realm)
+
+        print("realm is %s" % ctx.realm)
+
         ctx.dnshostname = "%s.%s" % (ctx.myname.lower(), ctx.dnsdomain)
 
         ctx.acct_dn = "CN=%s,OU=Domain Controllers,%s" % (ctx.myname, ctx.base_dn)
@@ -136,7 +145,8 @@ class dc_join:
                 ctx.del_noerror(ctx.krbtgt_dn)
             ctx.del_noerror(ctx.ntds_dn)
             ctx.del_noerror(ctx.server_dn, recursive=True)
-            ctx.del_noerror(ctx.topology_dn)
+            if ctx.topology_dn:
+                ctx.del_noerror(ctx.topology_dn)
             if res:
                 ctx.new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0]
                 ctx.del_noerror(ctx.new_krbtgt_dn)
@@ -159,6 +169,13 @@ class dc_join:
         res = ctx.samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
         return res[0]["dsServiceName"][0]
 
+    def get_behavior_version(ctx):
+        res = ctx.samdb.search(base=ctx.base_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-Behavior-Version"])
+        if "msDS-Behavior-Version" in res[0]:
+            return int(res[0]["msDS-Behavior-Version"][0])
+        else:
+            return samba.dsdb.DS_DOMAIN_FUNCTION_2000
+
     def get_dnsHostName(ctx):
         res = ctx.samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dnsHostName"])
         return res[0]["dnsHostName"][0]
@@ -171,10 +188,20 @@ class dc_join:
         return res[0]["nETBIOSName"][0]
 
     def get_mysid(ctx):
+        '''get the SID of the connected user. Only works with w2k8 and later,
+           so only used for RODC join'''
         res = ctx.samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"])
         binsid = res[0]["tokenGroups"][0]
         return ctx.samdb.schema_format_value("objectSID", binsid)
 
+    def dn_exists(ctx, dn):
+        '''check if a DN exists'''
+        try:
+            res = ctx.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=[])
+        except ldb.LdbError, (ERR_NO_SUCH_OBJECT, _):
+            return False
+        return True
+
     def add_krbtgt_account(ctx):
         '''RODCs need a special krbtgt account'''
         print "Adding %s" % ctx.krbtgt_dn
@@ -208,7 +235,7 @@ class dc_join:
         '''make a DRSUAPI connection to the server'''
         binding_string = "ncacn_ip_tcp:%s[seal]" % ctx.server
         ctx.drsuapi = drsuapi.drsuapi(binding_string, ctx.lp, ctx.creds)
-        ctx.drsuapi_handle = drs_utils.drs_DsBind(ctx.drsuapi)
+        (ctx.drsuapi_handle, ctx.bind_supported_extensions) = drs_utils.drs_DsBind(ctx.drsuapi)
 
     def create_tmp_samdb(ctx):
         '''create a temporary samdb object for schema queries'''
@@ -263,7 +290,6 @@ class dc_join:
         req2 = drsuapi.DsAddEntryRequest2()
         req2.first_object = first_object
 
-        # this dies
         (level, ctr) = ctx.drsuapi.DsAddEntry(ctx.drsuapi_handle, 2, req2)
 
 
@@ -276,8 +302,9 @@ class dc_join:
             "displayname": ctx.samname,
             "samaccountname" : ctx.samname,
             "userAccountControl" : str(ctx.userAccountControl),
-            "dnshostname" : ctx.dnshostname,
-            "msDS-SupportedEncryptionTypes" : str(samba.dsdb.ENC_ALL_TYPES)}
+            "dnshostname" : ctx.dnshostname}
+        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+            rec['msDS-SupportedEncryptionTypes'] = str(samba.dsdb.ENC_ALL_TYPES)
         if ctx.managedby:
             rec["managedby"] = ctx.managedby
         if ctx.never_reveal_sid:
@@ -306,9 +333,11 @@ class dc_join:
             "dn" : ctx.ntds_dn,
             "objectclass" : "nTDSDSA",
             "systemFlags" : str(samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
-            "dMDLocation" : ctx.schema_dn,
-            "msDS-Behavior-Version" : str(DS_DOMAIN_FUNCTION_2008_R2),
-            "msDS-HasDomainNCs" : ctx.base_dn }
+            "dMDLocation" : ctx.schema_dn}
+
+        if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+            rec["msDS-Behavior-Version"] = str(ctx.behavior_version)
+            rec["msDS-HasDomainNCs"] = ctx.base_dn
 
         if ctx.RODC:
             rec["objectCategory"] = "CN=NTDS-DSA-RO,%s" % ctx.schema_dn
@@ -318,7 +347,8 @@ class dc_join:
         else:
             rec["objectCategory"] = "CN=NTDS-DSA,%s" % ctx.schema_dn
             rec["HasMasterNCs"]      = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
-            rec["msDS-HasMasterNCs"] = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
+            if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2003:
+                rec["msDS-HasMasterNCs"] = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
             rec["options"] = "1"
             rec["invocationId"] = ndr_pack(misc.GUID(str(uuid.uuid4())))
             ctx.DsAddEntry(rec)
@@ -337,13 +367,14 @@ class dc_join:
                 "fromServer" : ctx.dc_ntds_dn}
             ctx.samdb.add(rec)
 
-        print "Adding %s" % ctx.topology_dn
-        rec = {
-            "dn" : ctx.topology_dn,
-            "objectclass" : "msDFSR-Member",
-            "msDFSR-ComputerReference" : ctx.acct_dn,
-            "serverReference" : ctx.ntds_dn}
-        ctx.samdb.add(rec)
+        if ctx.topology_dn:
+            print "Adding %s" % ctx.topology_dn
+            rec = {
+                "dn" : ctx.topology_dn,
+                "objectclass" : "msDFSR-Member",
+                "msDFSR-ComputerReference" : ctx.acct_dn,
+                "serverReference" : ctx.ntds_dn}
+            ctx.samdb.add(rec)
 
         print "Adding SPNs to %s" % ctx.acct_dn
         m = ldb.Message()
@@ -361,7 +392,7 @@ class dc_join:
                               force_change_at_next_login=False,
                               username=ctx.samname)
         res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-keyVersionNumber"])
-        ctx.key_version_number = res[0]["msDS-keyVersionNumber"]
+        ctx.key_version_number = int(res[0]["msDS-keyVersionNumber"][0])
 
 
     def join_provision(ctx):
@@ -379,7 +410,7 @@ class dc_join:
                             schemadn=ctx.schema_dn,
                             configdn=ctx.config_dn,
                             serverdn=ctx.server_dn, domain=ctx.domain_name,
-                            hostname=ctx.myname, hostip="127.0.0.1", domainsid=ctx.domsid,
+                            hostname=ctx.myname, domainsid=ctx.domsid,
                             machinepass=ctx.acct_pass, serverrole="domain controller",
                             sitename=ctx.site)
         print "Provision OK for domain DN %s" % presult.domaindn
@@ -395,21 +426,31 @@ class dc_join:
         ctx.local_samdb.transaction_start()
 
         source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id())
+        destination_dsa_guid = ctx.ntds_guid
 
-        acct_creds = Credentials()
-        acct_creds.guess(ctx.lp)
-        acct_creds.set_kerberos_state(DONT_USE_KERBEROS)
-        acct_creds.set_username(ctx.samname)
-        acct_creds.set_password(ctx.acct_pass)
+        if ctx.RODC:
+            repl_creds = Credentials()
+            repl_creds.guess(ctx.lp)
+            repl_creds.set_kerberos_state(DONT_USE_KERBEROS)
+            repl_creds.set_username(ctx.samname)
+            repl_creds.set_password(ctx.acct_pass)
+        else:
+            repl_creds = ctx.creds
 
-        repl = drs_utils.drs_Replicate("ncacn_ip_tcp:%s[seal]" % ctx.server, ctx.lp, acct_creds, ctx.local_samdb)
+        repl = drs_utils.drs_Replicate("ncacn_ip_tcp:%s[seal]" % ctx.server, ctx.lp, repl_creds, ctx.local_samdb)
 
-        repl.replicate(ctx.schema_dn, source_dsa_invocation_id, ctx.ntds_guid, schema=True, rodc=ctx.RODC)
-        repl.replicate(ctx.config_dn, source_dsa_invocation_id, ctx.ntds_guid, rodc=ctx.RODC)
-        repl.replicate(ctx.base_dn, source_dsa_invocation_id, ctx.ntds_guid, rodc=ctx.RODC)
+        repl.replicate(ctx.schema_dn, source_dsa_invocation_id, destination_dsa_guid,
+                       schema=True, rodc=ctx.RODC,
+                       replica_flags=ctx.replica_flags)
+        repl.replicate(ctx.config_dn, source_dsa_invocation_id, destination_dsa_guid,
+                       rodc=ctx.RODC, replica_flags=ctx.replica_flags)
+        repl.replicate(ctx.base_dn, source_dsa_invocation_id, destination_dsa_guid,
+                       rodc=ctx.RODC, replica_flags=ctx.replica_flags)
         if ctx.RODC:
-            repl.replicate(ctx.acct_dn, source_dsa_invocation_id, ctx.ntds_guid, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True)
-            repl.replicate(ctx.new_krbtgt_dn, source_dsa_invocation_id, ctx.ntds_guid, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True)
+            repl.replicate(ctx.acct_dn, source_dsa_invocation_id, destination_dsa_guid,
+                           exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True)
+            repl.replicate(ctx.new_krbtgt_dn, source_dsa_invocation_id, destination_dsa_guid,
+                           exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True)
 
         print "Committing SAM database"
         ctx.local_samdb.transaction_commit()
@@ -465,7 +506,9 @@ def join_RODC(server=None, creds=None, lp=None, site=None, netbios_name=None,
                              "<SID=%s>" % security.SID_BUILTIN_ACCOUNT_OPERATORS ]
     ctx.reveal_sid = "<SID=%s-%s>" % (ctx.domsid, security.DOMAIN_RID_RODC_ALLOW)
 
-    ctx.managedby = ctx.admin_dn
+    mysid = ctx.get_mysid()
+    admin_dn = "<SID=%s>" % mysid
+    ctx.managedby = admin_dn
 
     ctx.userAccountControl = (samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT |
                               samba.dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |
@@ -477,7 +520,14 @@ def join_RODC(server=None, creds=None, lp=None, site=None, netbios_name=None,
     ctx.connection_dn = "CN=RODC Connection (FRS),%s" % ctx.ntds_dn
     ctx.secure_channel_type = misc.SEC_CHAN_RODC
     ctx.RODC = True
+    ctx.replica_flags  =  (drsuapi.DRSUAPI_DRS_INIT_SYNC |
+                           drsuapi.DRSUAPI_DRS_PER_SYNC |
+                           drsuapi.DRSUAPI_DRS_GET_ANC |
+                           drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
+                           drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
     ctx.do_join()
+
+
     print "Joined domain %s (SID %s) as an RODC" % (ctx.domain_name, ctx.domsid)
 
 
@@ -491,5 +541,11 @@ def join_DC(server=None, creds=None, lp=None, site=None, netbios_name=None,
     ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain)
     ctx.secure_channel_type = misc.SEC_CHAN_BDC
 
+    ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP |
+                         drsuapi.DRSUAPI_DRS_INIT_SYNC |
+                         drsuapi.DRSUAPI_DRS_PER_SYNC |
+                         drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS |
+                         drsuapi.DRSUAPI_DRS_NEVER_SYNCED)
+
     ctx.do_join()
-    print "Joined domain %s (SID %s) as an DC" % (ctx.domain_name, ctx.domsid)
+    print "Joined domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list