1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-20 16:23:51 +03:00

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@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
This commit is contained in:
Joseph Sutton
2021-05-27 15:35:35 +12:00
committed by Andrew Bartlett
parent 7c7cad8184
commit 59d293b606
2 changed files with 14 additions and 44 deletions

View File

@@ -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())