[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Fri Jun 11 08:29:01 UTC 2021


The branch, master has been updated
       via  18394daf1e6 dbcheck: formatting
       via  5bf75d01c79 dbcheck: Refactor RID Set check to use free_rid_bounds()
       via  739d7e54e78 netcmd: Avoid conflicting SIDs when creating an offline backup
       via  2a3b82ae237 ridalloc: Don't skip the first RID of a pool
       via  59d293b6060 netcmd: Use next_free_rid() function to calculate a SID for restoring a backup
       via  7c7cad81844 python/tests/dsdb: Add tests for RID allocation functions
       via  cc98e03e7a0 dsdb: Add next_free_rid() function to allocate a RID without modifying the database
       via  b7e6a1c5da7 netcmd: Add tests for performing an offline backup immediately after joining a domain
       via  4feb353f705 dbcheck: check correct RID set attributes when looking for SID conflicts
       via  9bfba62c484 netcmd: Refactor seizing DNS roles while restoring from a backup
       via  fb0d71b3587 netcmd: Use correct path for state directory during offline backup
       via  11dae9cf367 tests: Specify additional modules for 'vfs objects' parameter
       via  658e5a6cc20 netcmd: Ignore rIDUsedPool attribute in offline domain backup test
       via  e8c242bed19 netcmd: Fix error-checking condition
       via  9f1e5637bc5 provision: Refactor another usage of create_dns_dir_keytab_link
       via  ae5964be424 sambadns: Create BINDDNS_DIR/dns.keytab link to PRIVATE_DIR/dns.keytab on DC join
       via  f5c26f7231e samba_upgradedns: Create binddns_dir if it doesn't already exist
       via  c6b2846c9d6 testprogs: Test that dns.keytab is created after a dns upgrade
       via  3e4ec0a90a2 pyldb: Fix Message.items() for a message containing elements
       via  79a898e2b71 pyldb: Add test for Message.items()
       via  bb4d06e15e4 sambadns: Fix docstring for create_dns_dir()
       via  e7754b56a1d pytest: Fix typo in docstring
       via  fec996ff277 samldb: Fix function name typo in error message
       via  51afb64d68f selftest: Remove duplicate variable assignment
      from  e165dcc770e selftest: Only set netbios aliases for the ad_member env

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


- Log -----------------------------------------------------------------
commit 18394daf1e6e7b71fe903d8061dc30e1b58ca3dd
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Fri Jun 4 11:37:56 2021 +1200

    dbcheck: formatting
    
    Reduce the length of some lines to 79 characters or less.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Fri Jun 11 08:28:28 UTC 2021 on sn-devel-184

commit 5bf75d01c792793ef60219250b7e22ea0846ab03
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Fri Jun 4 11:32:00 2021 +1200

    dbcheck: Refactor RID Set check to use free_rid_bounds()
    
    This function provides a simpler method of getting the bounds of the
    range of RIDs we want to check. We also now check that the low bound is
    less than the high bound for both rIDAllocationPool and
    rIDPreviousAllocationPool.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 739d7e54e78046dc77385b882fbba38ab5e7bd60
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Jun 2 17:00:33 2021 +1200

    netcmd: Avoid conflicting SIDs when creating an offline backup
    
    To allow the new DC object to be created in a restored domain while
    avoiding conflicts with existing SIDS, we fetch a SID that is available
    at the time of backing up and store it in the backed-up database.
    However, if a new security principal is created on this DC during the
    backup process, the stored SID may be reused for that object, resulting
    in an error on restoration.
    
    By getting the SID for restore only after all the database files have
    been backed up, we ensure that the chosen SID does not conflict with any
    objects in the backed-up database.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 2a3b82ae2373c39a0a113d75a27a196b5233fe32
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Tue Jun 1 12:03:38 2021 +1200

    ridalloc: Don't skip the first RID of a pool
    
    Previously, if either of the rIDPreviousAllocation and rIDNextRID
    attributes were not present in a RID Set, the first RID in
    rIDAllocationPool was skipped over when determining their values.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 59d293b60608172ae61551c642d13d3b215924e4
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 27 15:35:35 2021 +1200

    netcmd: Use next_free_rid() function to calculate a SID for restoring a backup
    
    This means we won't get errors if the DC doesn't have a rIDNextRID
    attribute, but we will still error if there is no RID Set or if all its
    pools are exhausted.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14669
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 7c7cad81844950c3efe9a540a47b9d4e1ce1b2a1
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon May 24 16:46:28 2021 +1200

    python/tests/dsdb: Add tests for RID allocation functions
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14669
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit cc98e03e7a0f2bf7a1ace2950fe6500f53640c1b
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon May 24 12:59:59 2021 +1200

    dsdb: Add next_free_rid() function to allocate a RID without modifying the database
    
    If used to generate SIDs for objects, care should be taken, as the
    possibility for having duplicate objectSIDs can arise.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14669
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit b7e6a1c5da7283c49586dc29f85ab19e0e57b0f6
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon May 24 14:58:40 2021 +1200

    netcmd: Add tests for performing an offline backup immediately after joining a domain
    
    This currently fails due to the DC not having a rIDNextRID attribute,
    which is required for the restore process.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14669
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 4feb353f7050a81e723906e61a3873c5973e512b
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 27 20:28:26 2018 +1200

    dbcheck: check correct RID set attributes when looking for SID conflicts
    
    The previous code would only work for the first rid set ever given to a DC
    because the names are so misleading.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13632
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 9bfba62c4843cad3443a1855f3be1c70dd1c1653
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 27 15:38:03 2021 +1200

    netcmd: Refactor seizing DNS roles while restoring from a backup
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit fb0d71b358702f1d57568fd016251587c2050386
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 27 11:47:36 2021 +1200

    netcmd: Use correct path for state directory during offline backup
    
    During the restore process, we use make_smbconf() to create a new
    smb.conf file with the default paths. The default location for 'state
    directory' is 'state', but we currently rename this directory to
    'statedir' on backing up, so it will end up pointing to a non-existent
    directory. This commit ensures the names are consistent.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 11dae9cf36781eb62b4f747988c21baa7e4ba06a
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 27 11:48:52 2021 +1200

    tests: Specify additional modules for 'vfs objects' parameter
    
    This helps to avoid a warning 'vfs objects specified without required AD
    DC module'.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 658e5a6cc20b57f48477affd370fe25458178b92
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 26 13:40:30 2021 +1200

    netcmd: Ignore rIDUsedPool attribute in offline domain backup test
    
    The RID Set of the newly created DC account has all its values
    initialised to zero. If the rIDUsedPool attribute was previously
    non-zero, then the restore process will cause its value to change.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14669
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit e8c242bed19432d96e78dc345ab5f06422c5b104
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon May 24 16:40:55 2021 +1200

    netcmd: Fix error-checking condition
    
    This condition probably meant to check the argument of the most recently
    thrown exception, rather than the previous one again.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14669
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 9f1e5637bc5fe51c56ad996dd881779e6ef3c0aa
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 6 15:08:19 2021 +1200

    provision: Refactor another usage of create_dns_dir_keytab_link
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14181
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14535
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit ae5964be42459beed8c174b8e2dd4d4167623158
Author: Derek Lambert <dlambert at dereklambert.com>
Date:   Wed Apr 22 15:30:53 2020 -0500

    sambadns: Create BINDDNS_DIR/dns.keytab link to PRIVATE_DIR/dns.keytab on DC join
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14181
    
    Signed-off-by: Derek Lambert <dlambert at dereklambert.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit f5c26f7231e9c5558e40ef70529693a35a8442f2
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 26 13:44:15 2021 +1200

    samba_upgradedns: Create binddns_dir if it doesn't already exist
    
    Without doing this, the upgrade process can fail if the directory is not
    present, e.g. after restoring from an offline backup (which specifically
    ignores this directory).
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit c6b2846c9d6d235cd833c5425723260368cef101
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 6 16:51:26 2021 +1200

    testprogs: Test that dns.keytab is created after a dns upgrade
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 3e4ec0a90a222c1cff4a91912afc703ca4cbbb0e
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Fri May 28 14:15:43 2021 +1200

    pyldb: Fix Message.items() for a message containing elements
    
    Previously, message elements were being freed before the call to
    Py_BuildValue(), resulting in an exception being raised. Additionally,
    only the first element of the returned list was ever assigned to.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 79a898e2b717a75004f5c64dfb5adcf28372760b
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Fri May 28 14:15:27 2021 +1200

    pyldb: Add test for Message.items()
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit bb4d06e15e427a69193cc11c2819d2c769cb73de
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 26 13:38:22 2021 +1200

    sambadns: Fix docstring for create_dns_dir()
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit e7754b56a1d4f1e4a9a5cb858420ec712385e828
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 6 15:40:44 2021 +1200

    pytest: Fix typo in docstring
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit fec996ff277479e5bac2159e2aab78d838d86b4c
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon May 24 13:01:39 2021 +1200

    samldb: Fix function name typo in error message
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 51afb64d68f7fafb475a71596b3a58a71772adad
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 26 15:21:02 2021 +1200

    selftest: Remove duplicate variable assignment
    
    This line currently produces a warning.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

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

Summary of changes:
 lib/ldb/pyldb.c                                  |   4 +-
 lib/ldb/tests/python/api.py                      |  21 ++
 python/samba/dbchecker.py                        |  88 ++++---
 python/samba/netcmd/domain_backup.py             |  86 ++-----
 python/samba/provision/__init__.py               |  37 +--
 python/samba/provision/sambadns.py               |  45 +++-
 python/samba/samdb.py                            | 105 ++++++++
 python/samba/tests/blackbox/downgradedatabase.py |   2 +-
 python/samba/tests/domain_backup_offline.py      |  65 ++++-
 python/samba/tests/dsdb.py                       | 304 ++++++++++++++++++++++-
 python/samba/tests/samba_tool/join.py            |   2 +-
 selftest/target/Samba3.pm                        |   1 -
 source4/dsdb/samdb/ldb_modules/ridalloc.c        |   3 +-
 source4/dsdb/samdb/ldb_modules/samldb.c          |   2 +-
 source4/scripting/bin/samba_upgradedns           |  39 +--
 source4/selftest/tests.py                        |   2 +-
 testprogs/blackbox/test_samba_upgradedns.sh      |   1 +
 17 files changed, 631 insertions(+), 176 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c
index be01b24325b..dadea2a7d6e 100644
--- a/lib/ldb/pyldb.c
+++ b/lib/ldb/pyldb.c
@@ -3509,13 +3509,13 @@ static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
 		PyObject *value = NULL;
 		PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
 		int res = 0;
-		Py_CLEAR(py_el);
 		value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
+		Py_CLEAR(py_el);
 		if (value == NULL ) {
 			Py_CLEAR(l);
 			return NULL;
 		}
-		res = PyList_SetItem(l, 0, value);
+		res = PyList_SetItem(l, j, value);
 		if (res == -1) {
 			Py_CLEAR(l);
 			return NULL;
diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py
index 940c9051932..16b71e2e650 100755
--- a/lib/ldb/tests/python/api.py
+++ b/lib/ldb/tests/python/api.py
@@ -3043,6 +3043,27 @@ class LdbMsgTests(TestCase):
         self.msg.dn = ldb.Dn(ldb.Ldb(), "dc=foo28")
         self.assertEqual(1, len(self.msg.items()))
 
+    def test_items(self):
+        self.msg["foo"] = ["foo"]
+        self.msg["bar"] = ["bar"]
+        try:
+            items = self.msg.items()
+        except:
+            self.fail()
+        self.assertEqual([("foo", ldb.MessageElement(["foo"])),
+                          ("bar", ldb.MessageElement(["bar"]))],
+                         items)
+
+        self.msg.dn = ldb.Dn(ldb.Ldb(), "dc=test")
+        try:
+            items = self.msg.items()
+        except:
+            self.fail()
+        self.assertEqual([("dn", ldb.Dn(ldb.Ldb(), "dc=test")),
+                          ("foo", ldb.MessageElement(["foo"])),
+                          ("bar", ldb.MessageElement(["bar"]))],
+                         items)
+
     def test_repr(self):
         self.msg.dn = ldb.Dn(ldb.Ldb(), "dc=foo29")
         self.msg["dc"] = b"foo"
diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index b2d029db9f2..d133b2aa55e 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -2697,7 +2697,8 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
 
                     if self.is_rid_master:
                         # Allocate a RID Set
-                        if self.confirm_all('Allocate the missing RID set for RID master?',
+                        if self.confirm_all('Allocate the missing RID set for '
+                                            'RID master?',
                                             'fix_missing_rid_set_master'):
 
                             # We don't have auto-transaction logic on
@@ -2716,45 +2717,73 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
                             self.samdb.transaction_commit()
 
                     elif not self.samdb.am_rodc():
-                        self.report("No RID Set found for this server: %s, and we are not the RID Master (so can not self-allocate)" % dn)
+                        self.report("No RID Set found for this server: %s, "
+                                    "and we are not the RID Master (so can "
+                                    "not self-allocate)" % dn)
 
         # Check some details of our own RID Set
+        #
+        # Note that the attributes have very bad names.  From ridalloc.c:
+        #
+        #   Note: the RID allocation attributes in AD are very badly named.
+        #     Here is what we think they really do:
+        #
+        #     in RID Set object:
+        #       - rIDPreviousAllocationPool: the pool which a DC is currently
+        #         pulling RIDs from. Managed by client DC
+        #
+        #       - rIDAllocationPool: the pool that the DC will switch to next,
+        #         when rIDPreviousAllocationPool is exhausted. Managed by RID
+        #         Manager.
+        #
+        #       - rIDNextRID: the last RID allocated by this DC. Managed by
+        #         client DC
+        #
+        #     in RID Manager object:
+        #       - rIDAvailablePool: the pool where the RID Manager gets new rID
+        #         pools from when it gets a EXOP_RID_ALLOC getncchanges call
+        #         (or locally when the DC is the RID Manager)
+
         if dn == self.rid_set_dn:
+            pool_attrs = ["rIDAllocationPool", "rIDPreviousAllocationPool"]
+
             res = self.samdb.search(base=self.rid_set_dn, scope=ldb.SCOPE_BASE,
-                                    attrs=["rIDAllocationPool",
-                                           "rIDPreviousAllocationPool",
-                                           "rIDUsedPool",
-                                           "rIDNextRID"])
-            if "rIDAllocationPool" not in res[0]:
-                self.report("No rIDAllocationPool found in %s" % dn)
-                error_count += 1
-            else:
-                next_pool = int(res[0]["rIDAllocationPool"][0])
+                                    attrs=pool_attrs)
 
-                high = (0xFFFFFFFF00000000 & next_pool) >> 32
-                low = 0x00000000FFFFFFFF & next_pool
+            for pool_attr in pool_attrs:
+                if pool_attr not in res[0]:
+                    continue
 
-                if high <= low:
-                    self.report("Invalid RID set %d-%s, %d > %d!" % (low, high, low, high))
-                    error_count += 1
+                pool = int(res[0][pool_attr][0])
 
-                if "rIDNextRID" in res[0]:
-                    next_free_rid = int(res[0]["rIDNextRID"][0])
-                else:
-                    next_free_rid = 0
+                high = pool >> 32
+                low = 0xFFFFFFFF & pool
 
-                if next_free_rid == 0:
-                    next_free_rid = low
-                else:
-                    next_free_rid += 1
+                if pool != 0 and low >= high:
+                    self.report("Invalid RID pool %d-%d, %d >= %d!" %
+                                (low, high, low, high))
+                    error_count += 1
+
+            if "rIDAllocationPool" not in res[0]:
+                self.report("No rIDAllocationPool found in %s" % dn)
+                error_count += 1
 
+            try:
+                next_free_rid, high = self.samdb.free_rid_bounds()
+            except ldb.LdbError as err:
+                enum, estr = err.args
+                self.report("Couldn't get available RIDs: %s" % estr)
+                error_count += 1
+            else:
                 # Check the remainder of this pool for conflicts.  If
                 # ridalloc_allocate_rid() moves to a new pool, this
                 # will be above high, so we will stop.
+                domain_sid = self.samdb.get_domain_sid()
                 while next_free_rid <= high:
-                    sid = "%s-%d" % (self.samdb.get_domain_sid(), next_free_rid)
+                    sid = "%s-%d" % (domain_sid, next_free_rid)
                     try:
-                        res = self.samdb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE,
+                        res = self.samdb.search(base="<SID=%s>" % sid,
+                                                scope=ldb.SCOPE_BASE,
                                                 attrs=[])
                     except ldb.LdbError as e:
                         (enum, estr) = e.args
@@ -2762,10 +2791,13 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
                             raise
                         res = None
                     if res is not None:
-                        self.report("SID %s for %s conflicts with our current RID set in %s" % (sid, res[0].dn, dn))
+                        self.report("SID %s for %s conflicts with our current "
+                                    "RID set in %s" % (sid, res[0].dn, dn))
                         error_count += 1
 
-                        if self.confirm_all('Fix conflict between SID %s and RID pool in %s by allocating a new RID?'
+                        if self.confirm_all('Fix conflict between SID %s and '
+                                            'RID pool in %s by allocating a '
+                                            'new RID?'
                                             % (sid, dn),
                                             'fix_sid_rid_set_conflict'):
                             self.samdb.transaction_start()
diff --git a/python/samba/netcmd/domain_backup.py b/python/samba/netcmd/domain_backup.py
index f00fd41d95a..5cccccd40ec 100644
--- a/python/samba/netcmd/domain_backup.py
+++ b/python/samba/netcmd/domain_backup.py
@@ -62,50 +62,21 @@ from samba.credentials import SMB_SIGNING_REQUIRED
 # This ensures that the restored DC's SID won't clash with any other RIDs
 # already in use in the domain
 def get_sid_for_restore(samdb, logger):
-    # Find the DN of the RID set of the server
-    res = samdb.search(base=ldb.Dn(samdb, samdb.get_serverName()),
-                       scope=ldb.SCOPE_BASE, attrs=["serverReference"])
-    server_ref_dn = ldb.Dn(samdb, str(res[0]['serverReference'][0]))
-    res = samdb.search(base=server_ref_dn,
-                       scope=ldb.SCOPE_BASE,
-                       attrs=['rIDSetReferences'])
-    rid_set_dn = ldb.Dn(samdb, str(res[0]['rIDSetReferences'][0]))
-
-    # Get the alloc pools and next RID of the RID set
-    res = samdb.search(base=rid_set_dn,
-                       scope=ldb.SCOPE_SUBTREE,
-                       expression="(rIDNextRID=*)",
-                       attrs=['rIDAllocationPool',
-                              'rIDPreviousAllocationPool',
-                              'rIDNextRID'])
-
-    # Decode the bounds of the RID allocation pools
+    # Allocate a new RID without modifying the database. This should be safe,
+    # because we acquire the RID master role after creating an account using
+    # this RID during the restore process. Acquiring the RID master role
+    # creates a new RID pool which we will fetch RIDs from, so we shouldn't get
+    # duplicates.
     try:
-        rid = int(res[0].get('rIDNextRID')[0])
-    except IndexError:
-        logger.info("The RID pool for this DC is not initalized "
-                    "(e.g. it may be a fairly new DC).")
-        logger.info("To initialize it, create a temporary user on this DC "
-                    "(you can delete it later).")
-        raise CommandError("Cannot create backup - "
-                           "please initialize this DC's RID pool first.")
-
-    def split_val(num):
-        high = (0xFFFFFFFF00000000 & int(num)) >> 32
-        low = 0x00000000FFFFFFFF & int(num)
-        return low, high
-    pool_l, pool_h = split_val(res[0].get('rIDPreviousAllocationPool')[0])
-    npool_l, npool_h = split_val(res[0].get('rIDAllocationPool')[0])
-
-    # Calculate next RID based on pool bounds
-    if rid == npool_h:
-        raise CommandError('Out of RIDs, finished AllocPool')
-    if rid == pool_h:
-        if pool_h == npool_h:
-            raise CommandError('Out of RIDs, finished PrevAllocPool.')
-        rid = npool_l
-    else:
-        rid += 1
+        rid = samdb.next_free_rid()
+    except LdbError as err:
+        logger.info("A SID could not be allocated for restoring the domain. "
+                    "Either no RID Set was found on this DC, "
+                    "or the RID Set was not usable.")
+        logger.info("To initialise this DC's RID pools, obtain a RID Set from "
+                    "this domain's RID master, or run samba-tool dbcheck "
+                    "to fix the existing RID Set.")
+        raise CommandError("Cannot create backup", err)
 
     # Construct full SID
     sid = dom_sid(samdb.get_domain_sid())
@@ -602,11 +573,12 @@ class cmd_domain_backup_restore(cmd_fsmo_seize):
                                        controls=["show_deleted:0",
                                                  "show_recycled:0"])
             except LdbError as dup_e:
-                if enum != ldb.ERR_NO_SUCH_OBJECT:
-                    raise e
+                (dup_enum, _) = dup_e.args
+                if dup_enum != ldb.ERR_NO_SUCH_OBJECT:
+                    raise
 
             if (len(dup_res) != 1):
-                raise e
+                raise
 
             objectguid = samdb.schema_format_value("objectGUID",
                                                        dup_res[0]["objectGUID"][0])
@@ -659,18 +631,11 @@ class cmd_domain_backup_restore(cmd_fsmo_seize):
         # Seize DNS roles
         domain_dn = samdb.domain_dn()
         forest_dn = samba.dn_from_dns_name(samdb.forest_dns_name())
-        domaindns_dn = ("CN=Infrastructure,DC=DomainDnsZones,", domain_dn)
-        forestdns_dn = ("CN=Infrastructure,DC=ForestDnsZones,", forest_dn)
-        for dn_prefix, dns_dn in [forestdns_dn, domaindns_dn]:
-            if dns_dn not in ncs:
-                continue
-            full_dn = dn_prefix + dns_dn
-            m = ldb.Message()
-            m.dn = ldb.Dn(samdb, full_dn)
-            m["fSMORoleOwner"] = ldb.MessageElement(samdb.get_dsServiceName(),
-                                                    ldb.FLAG_MOD_REPLACE,
-                                                    "fSMORoleOwner")
-            samdb.modify(m)
+        dns_roles = [("domaindns", domain_dn),
+                     ("forestdns", forest_dn)]
+        for role, dn in dns_roles:
+            if dn in ncs:
+                self.seize_dns_role(role, samdb, None, None, None, force=True)
 
         # Seize other roles
         for role in ['rid', 'pdc', 'naming', 'infrastructure', 'schema']:
@@ -1076,7 +1041,7 @@ class cmd_domain_backup_offline(samba.netcmd.Command):
     # Find where a path should go in the fixed backup archive structure.
     def get_arc_path(self, path, conf_paths):
         backup_dirs = {"private": conf_paths.private_dir,
-                       "statedir": conf_paths.state_dir,
+                       "state": conf_paths.state_dir,
                        "etc": os.path.dirname(conf_paths.smbconf)}
         matching_dirs = [(_, p) for (_, p) in backup_dirs.items() if
                          path.startswith(p)]
@@ -1109,7 +1074,6 @@ class cmd_domain_backup_offline(samba.netcmd.Command):
 
         samdb = SamDB(url=paths.samdb, session_info=system_session(), lp=lp,
                       flags=ldb.FLG_RDONLY)
-        sid = get_sid_for_restore(samdb, logger)
 
         # Iterating over the directories in this specific order ensures that
         # when the private directory contains hardlinks that are also contained
@@ -1161,6 +1125,8 @@ class cmd_domain_backup_offline(samba.netcmd.Command):
         dom_sid_str = samdb.get_domain_sid()
         dom_sid = security.dom_sid(dom_sid_str)
 
+        sid = get_sid_for_restore(samdb, logger)
+
         # Close the original samdb
         samdb = None
 
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index 2531f51ffc8..1723d9935d4 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -111,6 +111,7 @@ from samba.provision.common import (
 from samba.provision.sambadns import (
     get_dnsadmins_sid,
     setup_ad_dns,
+    create_dns_dir_keytab_link,
     create_dns_update_list
 )
 
@@ -2361,41 +2362,7 @@ def provision(logger, session_info, smbconf=None,
     secrets_ldb.transaction_commit()
 
     # the commit creates the dns.keytab in the private directory
-    private_dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
-    bind_dns_keytab_path = os.path.join(paths.binddns_dir, paths.dns_keytab)
-
-    if os.path.isfile(private_dns_keytab_path):
-        if os.path.isfile(bind_dns_keytab_path):
-            try:
-                os.unlink(bind_dns_keytab_path)
-            except OSError as e:
-                logger.error("Failed to remove %s: %s" %
-                             (bind_dns_keytab_path, e.strerror))
-
-        # link the dns.keytab to the bind-dns directory
-        try:
-            os.link(private_dns_keytab_path, bind_dns_keytab_path)
-        except OSError as e:
-            logger.error("Failed to create link %s -> %s: %s" %
-                         (private_dns_keytab_path, bind_dns_keytab_path, e.strerror))
-
-        # chown the dns.keytab in the bind-dns directory
-        if paths.bind_gid is not None:
-            try:
-                os.chmod(paths.binddns_dir, 0o770)
-                os.chown(paths.binddns_dir, -1, paths.bind_gid)
-            except OSError:
-                if 'SAMBA_SELFTEST' not in os.environ:
-                    logger.info("Failed to chown %s to bind gid %u",
-                                paths.binddns_dir, paths.bind_gid)
-
-            try:
-                os.chmod(bind_dns_keytab_path, 0o640)
-                os.chown(bind_dns_keytab_path, -1, paths.bind_gid)
-            except OSError:
-                if 'SAMBA_SELFTEST' not in os.environ:
-                    logger.info("Failed to chown %s to bind gid %u",
-                                bind_dns_keytab_path, paths.bind_gid)
+    create_dns_dir_keytab_link(logger, paths)
 
     result = ProvisionResult()
     result.server_role = serverrole
diff --git a/python/samba/provision/sambadns.py b/python/samba/provision/sambadns.py
index 4ddde36b4cb..cd8df680749 100644
--- a/python/samba/provision/sambadns.py
+++ b/python/samba/provision/sambadns.py
@@ -698,7 +698,7 @@ def secretsdb_setup_dns(secretsdb, names, private_dir, binddns_dir, realm,
 
 
 def create_dns_dir(logger, paths):
-    """Write out a DNS zone file, from the info in the current database.
+    """(Re)create the DNS directory and chown it to bind.
 
     :param logger: Logger object
     :param paths: paths object
@@ -723,6 +723,48 @@ def create_dns_dir(logger, paths):
                     dns_dir, paths.bind_gid))
 
 
+def create_dns_dir_keytab_link(logger, paths):
+    """Create link for BIND to DNS keytab
+
+    :param logger: Logger object
+    :param paths: paths object
+    """
+    private_dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
+    bind_dns_keytab_path = os.path.join(paths.binddns_dir, paths.dns_keytab)
+
+    if os.path.isfile(private_dns_keytab_path):
+        if os.path.isfile(bind_dns_keytab_path):
+            try:
+                os.unlink(bind_dns_keytab_path)
+            except OSError as e:
+                logger.error("Failed to remove %s: %s" %
+                             (bind_dns_keytab_path, e.strerror))
+
+        # link the dns.keytab to the bind-dns directory
+        try:
+            os.link(private_dns_keytab_path, bind_dns_keytab_path)
+        except OSError as e:
+            logger.error("Failed to create link %s -> %s: %s" %
+                         (private_dns_keytab_path, bind_dns_keytab_path, e.strerror))
+
+        # chown the dns.keytab in the bind-dns directory
+        if paths.bind_gid is not None:
+            try:
+                os.chmod(paths.binddns_dir, 0o770)
+                os.chown(paths.binddns_dir, -1, paths.bind_gid)
+            except OSError:
+                if 'SAMBA_SELFTEST' not in os.environ:
+                    logger.info("Failed to chown %s to bind gid %u",
+                                paths.binddns_dir, paths.bind_gid)
+            try:
+                os.chmod(bind_dns_keytab_path, 0o640)
+                os.chown(bind_dns_keytab_path, -1, paths.bind_gid)
+            except OSError:
+                if 'SAMBA_SELFTEST' not in os.environ:
+                    logger.info("Failed to chown %s to bind gid %u",
+                                bind_dns_keytab_path, paths.bind_gid)
+
+
 def create_zone_file(lp, logger, paths, targetdir, dnsdomain,
                      hostip, hostip6, hostname, realm, domainguid,
                      ntdsguid, site):
@@ -1261,6 +1303,7 @@ def setup_bind9_dns(samdb, secretsdb, names, paths, lp, logger,
                         key_version_number=key_version_number)
 
     create_dns_dir(logger, paths)
+    create_dns_dir_keytab_link(logger, paths)
 
     if dns_backend == "BIND9_FLATFILE":
         create_zone_file(lp, logger, paths, targetdir, site=site,
diff --git a/python/samba/samdb.py b/python/samba/samdb.py
index 292bee14da3..424d6d2e88a 100644
--- a/python/samba/samdb.py
+++ b/python/samba/samdb.py
@@ -1390,6 +1390,111 @@ schemaUpdateNow: 1
         '''return a new RID from the RID Pool on this DSA'''
         return dsdb._dsdb_allocate_rid(self)
 
+    def next_free_rid(self):
+        '''return the next free RID from the RID Pool on this DSA.
+
+        :note: This function is not intended for general use, and care must be
+            taken if it is used to generate objectSIDs. The returned RID is not
+            formally reserved for use, creating the possibility of duplicate
+            objectSIDs.
+        '''
+        rid, _ = self.free_rid_bounds()
+        return rid
+
+    def free_rid_bounds(self):
+        '''return the low and high bounds (inclusive) of RIDs that are
+            available for use in this DSA's current RID pool.
+
+        :note: This function is not intended for general use, and care must be
+            taken if it is used to generate objectSIDs. The returned range of
+            RIDs is not formally reserved for use, creating the possibility of
+            duplicate objectSIDs.
+        '''
+        # Get DN of this server's RID Set
+        server_name_dn = ldb.Dn(self, self.get_serverName())
+        res = self.search(base=server_name_dn,
+                          scope=ldb.SCOPE_BASE,
+                          attrs=["serverReference"])
+        try:
+            server_ref = res[0]["serverReference"]
+        except KeyError:
+            raise ldb.LdbError(
+                ldb.ERR_NO_SUCH_ATTRIBUTE,
+                "No RID Set DN - "
+                "Cannot find attribute serverReference of %s "
+                "to calculate reference dn" % server_name_dn) from None
+        server_ref_dn = ldb.Dn(self, server_ref[0].decode("utf-8"))
+
+        res = self.search(base=server_ref_dn,
+                          scope=ldb.SCOPE_BASE,
+                          attrs=["rIDSetReferences"])
+        try:
+            rid_set_refs = res[0]["rIDSetReferences"]
+        except KeyError:
+            raise ldb.LdbError(
+                ldb.ERR_NO_SUCH_ATTRIBUTE,
+                "No RID Set DN - "
+                "Cannot find attribute rIDSetReferences of %s "
+                "to calculate reference dn" % server_ref_dn) from None
+        rid_set_dn = ldb.Dn(self, rid_set_refs[0].decode("utf-8"))
+
+        # Get the alloc pools and next RID of this RID Set
+        res = self.search(base=rid_set_dn,
+                          scope=ldb.SCOPE_BASE,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list