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:
committed by
Andrew Bartlett
parent
7c7cad8184
commit
59d293b606
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user