summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsource4/scripting/bin/upgradeprovision222
1 files changed, 137 insertions, 85 deletions
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index f8f1e70ee8..191ac4f88b 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -1176,40 +1176,53 @@ def fix_partition_sd(samdb, names):
:param names: A list of key provision parameters
"""
# First update the SD for the rootdn
- res = samdb.search(expression="objectClass=*", base=str(names.rootdn), scope=SCOPE_BASE,\
- attrs=["dn", "whenCreated"], controls=["search_options:1:2"])
+ res = samdb.search(expression="objectClass=*", base=str(names.rootdn),
+ scope=SCOPE_BASE, attrs=["dn", "whenCreated"],
+ controls=["search_options:1:2"])
delta = Message()
- delta.dn = Dn(samdb,str(res[0]["dn"]))
+ delta.dn = Dn(samdb, str(res[0]["dn"]))
descr = get_domain_descriptor(names.domainsid)
- delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE, "nTSecurityDescriptor")
- samdb.modify(delta,["recalculate_sd:0"])
+ delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE,
+ "nTSecurityDescriptor")
+ samdb.modify(delta, ["recalculate_sd:0"])
# Then the config dn
- res = samdb.search(expression="objectClass=*",base=str(names.configdn), scope=SCOPE_BASE,attrs=["dn","whenCreated"],controls=["search_options:1:2"])
+ res = samdb.search(expression="objectClass=*", base=str(names.configdn),
+ scope=SCOPE_BASE, attrs=["dn", "whenCreated"],
+ controls=["search_options:1:2"])
delta = Message()
- delta.dn = Dn(samdb,str(res[0]["dn"]))
+ delta.dn = Dn(samdb, str(res[0]["dn"]))
descr = get_config_descriptor(names.domainsid)
- delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE, "nTSecurityDescriptor" )
- samdb.modify(delta,["recalculate_sd:0"])
+ delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE,
+ "nTSecurityDescriptor" )
+ samdb.modify(delta, ["recalculate_sd:0"])
# Then the schema dn
- res = samdb.search(expression="objectClass=*",base=str(names.schemadn), scope=SCOPE_BASE,attrs=["dn","whenCreated"],controls=["search_options:1:2"])
+ res = samdb.search(expression="objectClass=*", base=str(names.schemadn),
+ scope=SCOPE_BASE, attrs=["dn", "whenCreated"],
+ controls=["search_options:1:2"])
+
delta = Message()
- delta.dn = Dn(samdb,str(res[0]["dn"]))
+ delta.dn = Dn(samdb, str(res[0]["dn"]))
descr = get_schema_descriptor(names.domainsid)
- delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE, "nTSecurityDescriptor" )
- samdb.modify(delta,["recalculate_sd:0"])
+ delta["nTSecurityDescriptor"] = MessageElement(descr, FLAG_MOD_REPLACE,
+ "nTSecurityDescriptor" )
+ samdb.modify(delta, ["recalculate_sd:0"])
def rebuild_sd(samdb, names):
"""Rebuild security descriptor of the current provision from scratch
- During the different pre release of samba4 security descriptors (SD) were notarly broken (up to alpha11 included)
- This function allow to get them back in order, this function make the assumption that nobody has modified manualy an SD
+ During the different pre release of samba4 security descriptors (SD)
+ were notarly broken (up to alpha11 included)
+ This function allow to get them back in order, this function make the
+ assumption that nobody has modified manualy an SD
and so SD can be safely recalculated from scratch to get them right.
:param names: List of key provision parameters"""
hash = {}
- res = samdb.search(expression="objectClass=*",base=str(names.rootdn), scope=SCOPE_SUBTREE,attrs=["dn","whenCreated"],controls=["search_options:1:2"])
+ res = samdb.search(expression="objectClass=*", base=str(names.rootdn),
+ scope=SCOPE_SUBTREE, attrs=["dn", "whenCreated"],
+ controls=["search_options:1:2"])
for obj in res:
if not (str(obj["dn"]) == str(names.rootdn) or
str(obj["dn"]) == str(names.configdn) or \
@@ -1222,16 +1235,21 @@ def rebuild_sd(samdb, names):
for key in listkeys:
try:
delta = Message()
- delta.dn = Dn(samdb,key)
- delta["whenCreated"] = MessageElement(hash[key], FLAG_MOD_REPLACE, "whenCreated" )
- samdb.modify(delta,["recalculate_sd:0"])
+ delta.dn = Dn(samdb, key)
+ delta["whenCreated"] = MessageElement(hash[key], FLAG_MOD_REPLACE,
+ "whenCreated" )
+ samdb.modify(delta, ["recalculate_sd:0"])
except:
# XXX: We should always catch an explicit exception.
# What could go wrong here?
samdb.transaction_cancel()
- res = samdb.search(expression="objectClass=*", base=str(names.rootdn), scope=SCOPE_SUBTREE,\
- attrs=["dn","nTSecurityDescriptor"], controls=["search_options:1:2"])
- print "bad stuff" +ndr_unpack(security.descriptor,str(res[0]["nTSecurityDescriptor"])).as_sddl(names.domainsid)
+ res = samdb.search(expression="objectClass=*", base=str(names.rootdn),
+ scope=SCOPE_SUBTREE,
+ attrs=["dn", "nTSecurityDescriptor"],
+ controls=["search_options:1:2"])
+ badsd = ndr_unpack(security.descriptor,
+ str(res[0]["nTSecurityDescriptor"]))
+ print "bad stuff %s"%badsd.as_sddl(names.domainsid)
return
def removeProvisionUSN(samdb):
@@ -1251,32 +1269,40 @@ def delta_update_basesamdb(refpaths, paths, creds, session, lp):
"""Update the provision container db: sam.ldb
This function is aimed for alpha9 and newer;
- :param refpaths: An object holding the different importants paths for reference provision object
- :param paths: An object holding the different importants paths for upgraded provision object
+ :param refpaths: An object holding the different importants paths for
+ reference provision object
+ :param paths: An object holding the different importants paths for
+ upgraded provision object
:param creds: Credential used for openning LDB files
:param session: Session to use for openning LDB files
:param lp: A loadparam object"""
- message(SIMPLE,"Update base samdb by searching difference with reference one")
- refsam = Ldb(refpaths.samdb, session_info=session, credentials=creds, lp=lp, options=["modules:"] )
- sam = Ldb(paths.samdb, session_info=session, credentials=creds, lp=lp, options=["modules:"] )
+ message(SIMPLE,
+ "Update base samdb by searching difference with reference one")
+ refsam = Ldb(refpaths.samdb, session_info=session, credentials=creds,
+ lp=lp, options=["modules:"])
+ sam = Ldb(paths.samdb, session_info=session, credentials=creds, lp=lp,
+ options=["modules:"])
empty = Message()
reference = refsam.search(expression="")
for refentry in reference:
- entry = sam.search(expression="dn=%s" % refentry["dn"],scope=SCOPE_SUBTREE)
- if not len(entry[0]):
- message(CHANGE,"Adding %s to sam db" % str(delta.dn))
- delta = sam.msg_diff(empty,refentry)
- if str(refentry.dn) == "@PROVISION" and delta.get(samba.provision.LAST_PROVISION_USN_ATTRIBUTE):
+ entry = sam.search(expression="dn=%s" % refentry["dn"],
+ scope=SCOPE_SUBTREE)
+ if not len(entry):
+ message(CHANGE, "Adding %s to sam db" % str(delta.dn))
+ delta = sam.msg_diff(empty, refentry)
+ if str(refentry.dn) == "@PROVISION" and\
+ delta.get(samba.provision.LAST_PROVISION_USN_ATTRIBUTE):
delta.remove(samba.provision.LAST_PROVISION_USN_ATTRIBUTE)
delta.dn = refentry.dn
sam.add(delta)
else:
- delta = sam.msg_diff(entry[0],refentry)
- if str(refentry.dn) == "@PROVISION" and delta.get(samba.provision.LAST_PROVISION_USN_ATTRIBUTE):
+ delta = sam.msg_diff(entry[0], refentry)
+ if str(refentry.dn) == "@PROVISION" and\
+ delta.get(samba.provision.LAST_PROVISION_USN_ATTRIBUTE):
delta.remove(samba.provision.LAST_PROVISION_USN_ATTRIBUTE)
if len(delta.items()) > 1:
delta.dn = refentry.dn
@@ -1287,12 +1313,14 @@ def simple_update_basesamdb(newpaths, paths, names):
"""Update the provision container db: sam.ldb
This function is aimed at very old provision (before alpha9)
- :param newpaths: List of paths for different provision objects from the reference provision
- :param paths: List of paths for different provision objects from the upgraded provision
+ :param newpaths: List of paths for different provision objects
+ from the reference provision
+ :param paths: List of paths for different provision objects
+ from the upgraded provision
:param names: List of key provision parameters"""
message(SIMPLE, "Copy samdb")
- shutil.copy(newpaths.samdb,paths.samdb)
+ shutil.copy(newpaths.samdb, paths.samdb)
message(SIMPLE, "Update partitions filename if needed")
schemaldb = os.path.join(paths.private_dir, "schema.ldb")
@@ -1302,23 +1330,28 @@ def simple_update_basesamdb(newpaths, paths, names):
if not os.path.isdir(samldbdir):
os.mkdir(samldbdir)
- os.chmod(samldbdir,0700)
+ os.chmod(samldbdir, 0700)
if os.path.isfile(schemaldb):
- shutil.copy(schemaldb, os.path.join(samldbdir, "%s.ldb" % str(names.schemadn).upper()))
+ shutil.copy(schemaldb, os.path.join(samldbdir,
+ "%s.ldb"%str(names.schemadn).upper()))
os.remove(schemaldb)
if os.path.isfile(usersldb):
- shutil.copy(usersldb, os.path.join(samldbdir, "%s.ldb" % str(names.rootdn).upper()))
+ shutil.copy(usersldb, os.path.join(samldbdir,
+ "%s.ldb"%str(names.rootdn).upper()))
os.remove(usersldb)
if os.path.isfile(configldb):
- shutil.copy(configldb, os.path.join(samldbdir, "%s.ldb" % str(names.configdn).upper()))
+ shutil.copy(configldb, os.path.join(samldbdir,
+ "%s.ldb"%str(names.configdn).upper()))
os.remove(configldb)
def update_privilege(ref_private_path, cur_private_path):
"""Update the privilege database
- :param ref_private_path: Path to the private directory of the reference provision.
- :param cur_private_path: Path to the private directory of the current (and to be updated) provision."""
+ :param ref_private_path: Path to the private directory of the reference
+ provision.
+ :param cur_private_path: Path to the private directory of the current
+ (and to be updated) provision."""
message(SIMPLE, "Copy privilege")
shutil.copy(os.path.join(ref_private_path, "privilege.ldb"),
os.path.join(cur_private_path, "privilege.ldb"))
@@ -1327,44 +1360,54 @@ def update_privilege(ref_private_path, cur_private_path):
def update_samdb(ref_samdb, samdb, names, highestUSN, schema):
"""Upgrade the SAM DB contents for all the provision partitions
- :param ref_sambdb: An LDB object conntected to the sam.ldb of the reference provision
- :param samdb: An LDB object connected to the sam.ldb of the update provision
+ :param ref_sambdb: An LDB object conntected to the sam.ldb of the reference
+ provision
+ :param samdb: An LDB object connected to the sam.ldb of the update
+ provision
:param names: List of key provision parameters
- :param highestUSN: The highest USN modified by provision/upgradeprovision last time
+ :param highestUSN: The highest USN modified by provision/upgradeprovision
+ last time
:param schema: A Schema object that represent the schema of the provision"""
message(SIMPLE, "Starting update of samdb")
- ret = update_partition(ref_samdb, samdb, str(names.rootdn), names, schema, highestUSN)
+ ret = update_partition(ref_samdb, samdb, str(names.rootdn), names,
+ schema, highestUSN)
if ret:
- message(SIMPLE,"Update of samdb finished")
+ message(SIMPLE, "Update of samdb finished")
return 1
else:
- message(SIMPLE,"Update failed")
+ message(SIMPLE, "Update failed")
return 0
def update_machine_account_password(samdb, secrets_ldb, names):
- """Update (change) the password of the current DC both in the SAM db and in secret one
+ """Update (change) the password of the current DC both in the SAM db and in
+ secret one
:param samdb: An LDB object related to the sam.ldb file of a given provision
- :param secrets_ldb: An LDB object related to the secrets.ldb file of a given provision
+ :param secrets_ldb: An LDB object related to the secrets.ldb file of a given
+ provision
:param names: List of key provision parameters"""
- message(SIMPLE,"Update machine account")
- secrets_msg = secrets_ldb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=["secureChannelType"])
+ message(SIMPLE, "Update machine account")
+ expression = "samAccountName=%s$" % names.netbiosname
+ secrets_msg = secrets_ldb.search(expression=expression,
+ attrs=["secureChannelType"])
if int(secrets_msg[0]["secureChannelType"][0]) == SEC_CHAN_BDC:
- res = samdb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=[])
+ res = samdb.search(expression=expression, attrs=[])
assert(len(res) == 1)
msg = Message(res[0].dn)
machinepass = samba.generate_random_password(128, 255)
- msg["userPassword"] = MessageElement(machinepass, FLAG_MOD_REPLACE, "userPassword")
+ msg["userPassword"] = MessageElement(machinepass, FLAG_MOD_REPLACE,
+ "userPassword")
samdb.modify(msg)
res = samdb.search(expression=("samAccountName=%s$" % names.netbiosname),
attrs=["msDs-keyVersionNumber"])
assert(len(res) == 1)
kvno = int(str(res[0]["msDs-keyVersionNumber"]))
+ secChanType = int(secrets_msg[0]["secureChannelType"][0])
secretsdb_self_join(secrets_ldb, domain=names.domain,
realm=names.realm or sambaopts._lp.get('realm'),
@@ -1373,24 +1416,25 @@ def update_machine_account_password(samdb, secrets_ldb, names):
netbiosname=names.netbiosname,
machinepass=machinepass,
key_version_number=kvno,
- secure_channel_type=int(secrets_msg[0]["secureChannelType"][0]))
+ secure_channel_type=secChanType)
else:
- raise ProvisioningError("Unable to find a Secure Channel of type SEC_CHAN_BDC")
+ raise ProvisioningError("Unable to find a Secure Channel" \
+ "of type SEC_CHAN_BDC")
-def update_gpo(paths,creds,session,names):
+def update_gpo(paths, creds, session, names):
"""Create missing GPO file object if needed
Set ACL correctly also.
"""
- dir = getpolicypath(paths.sysvol,names.dnsdomain,names.policyid)
+ dir = getpolicypath(paths.sysvol, names.dnsdomain, names.policyid)
if not os.path.isdir(dir):
create_gpo_struct(dir)
- dir = getpolicypath(paths.sysvol,names.dnsdomain,names.policyid_dc)
+ dir = getpolicypath(paths.sysvol, names.dnsdomain, names.policyid_dc)
if not os.path.isdir(dir):
create_gpo_struct(dir)
- samdb = Ldb(paths.samdb, session_info=session, credentials=creds,lp=lp)
+ samdb = Ldb(paths.samdb, session_info=session, credentials=creds, lp=lp)
set_gpo_acl(paths.sysvol, names.dnsdomain, names.domainsid,
names.domaindn, samdb, lp)
@@ -1434,7 +1478,8 @@ if __name__ == '__main__':
# First get files paths
paths = get_paths(param, smbconf=smbconf)
paths.setup = setup_dir
- # Get ldbs with the system session, it is needed for searching provision parameters
+ # Get ldbs with the system session, it is needed for searching
+ # provision parameters
session = system_session()
# This variable will hold the last provision USN once if it exists.
@@ -1445,19 +1490,22 @@ if __name__ == '__main__':
# Guess all the needed names (variables in fact) from the current
# provision.
- names = find_provision_key_parameters(ldbs.sam, ldbs.secrets, paths, smbconf, lp)
+ names = find_provision_key_parameters(ldbs.sam, ldbs.secrets, paths,
+ smbconf, lp)
lastProvisionUSNs = getLastProvisionUSN(ldbs.sam)
if lastProvisionUSNs != None:
message(CHANGE,
"Find a last provision USN, %d range(s)" % len(lastProvisionUSNs))
- # Objects will be created with the admin session (not anymore system session)
+ # Objects will be created with the admin session
+ # (not anymore system session)
adm_session = admin_session(lp, str(names.domainsid))
# So we reget handle on objects
# ldbs = get_ldbs(paths, creds, adm_session, lp)
if not sanitychecks(ldbs.sam, names):
- message(SIMPLE,"Sanity checks for the upgrade fails, checks messages and correct them before rerunning upgradeprovision")
+ message(SIMPLE, "Sanity checks for the upgrade fails, checks messages" \
+ " and correct them before rerunning upgradeprovision")
sys.exit(1)
# Let's see provision parameters
@@ -1487,12 +1535,13 @@ if __name__ == '__main__':
# List of attribute with ASN DN synthax)
populate_dnsyntax(new_ldbs.sam, names.schemadn)
- update_privilege(newpaths.private_dir,paths.private_dir)
+ update_privilege(newpaths.private_dir, paths.private_dir)
oem = getOEMInfo(ldbs.sam, names.rootdn)
# Do some modification on sam.ldb
ldbs.groupedCommit()
- if re.match(".*alpha((9)|(\d\d+)).*",str(oem)):
- # Starting from alpha9 we can consider that the structure is quite ok and that we should do only dela
+ if re.match(".*alpha((9)|(\d\d+)).*", str(oem)):
+ # Starting from alpha9 we can consider that the structure is quite ok
+ # and that we should do only dela
new_ldbs.groupedCommit()
delta_update_basesamdb(newpaths, paths, creds, session, lp)
ldbs.startTransactions()
@@ -1510,24 +1559,25 @@ if __name__ == '__main__':
if opts.full:
if not update_samdb(new_ldbs.sam, ldbs.sam, names, lastProvisionUSNs,
schema):
- message(SIMPLE, "Rollbacking every changes. Check the reason\
- of the problem")
- message(SIMPLE, "In any case your system as it was before\
- the upgrade")
+ message(SIMPLE, "Rollbacking every changes. Check the reason" \
+ " of the problem")
+ message(SIMPLE, "In any case your system as it was before" \
+ " the upgrade")
ldbs.groupedRollback()
new_ldbs.groupedRollback()
shutil.rmtree(provisiondir)
sys.exit(1)
- update_secrets(new_ldbs.secrets,ldbs.secrets)
- update_machine_account_password(ldbs.sam,ldbs.secrets, names)
+ update_secrets(new_ldbs.secrets, ldbs.secrets)
+ update_machine_account_password(ldbs.sam, ldbs.secrets, names)
- # SD should be created with admin but as some previous acl were so wrong that admin can't modify them we have first
- # to recreate them with the good form but with system account and then give the ownership to admin ...
- if not re.match(r'.*alpha(9|\d\d+)',str(oem)):
+ # SD should be created with admin but as some previous acl were so wrong
+ # that admin can't modify them we have first to recreate them with the good
+ # form but with system account and then give the ownership to admin ...
+ if not re.match(r'.*alpha(9|\d\d+)', str(oem)):
message(SIMPLE, "Fixing old povision SD")
- fix_partition_sd(ldbs.sam,names)
- rebuild_sd(ldbs.sam,names)
+ fix_partition_sd(ldbs.sam, names)
+ rebuild_sd(ldbs.sam, names)
# We calculate the max USN before recalculating the SD because we might
# touch object that have been modified after a provision and we do not
@@ -1543,16 +1593,18 @@ if __name__ == '__main__':
message(SIMPLE, "Updating SD")
ldbs.sam.set_session_info(adm_session)
# Alpha10 was a bit broken still
- if re.match(r'.*alpha(\d|10)',str(oem)):
- fix_partition_sd(ldbs.sam,names)
+ if re.match(r'.*alpha(\d|10)', str(oem)):
+ fix_partition_sd(ldbs.sam, names)
rebuild_sd(ldbs.sam, names)
- # Now we are quite confident in the recalculate process of the SD, we make it optional
- # Also the check must be done in a clever way as for the moment we just compare SDDL
+ # Now we are quite confident in the recalculate process of the SD, we make
+ # it optional.
+ # Also the check must be done in a clever way as for the moment we just
+ # compare SDDL
if opts.debugchangesd:
- check_updated_sd(new_ldbs.sam,ldbs.sam, names)
+ check_updated_sd(new_ldbs.sam, ldbs.sam, names)
- updateOEMInfo(ldbs.sam,names)
+ updateOEMInfo(ldbs.sam, names)
check_for_DNS(newpaths.private_dir, paths.private_dir)
if lastProvisionUSNs != None:
updateProvisionUSN(ldbs.sam, minUSN, maxUSN)