summaryrefslogtreecommitdiff
path: root/source4/scripting/bin/upgradeprovision
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-11-26 15:32:49 +1100
committerAndrew Tridgell <tridge@samba.org>2009-11-27 16:05:04 +1100
commitb9f95882f0fd9f453c6b90d1ca023111195d757b (patch)
tree56ee37e9bc3d5502c00e04f12b41de9233979e5b /source4/scripting/bin/upgradeprovision
parent2fd831407d81a53f79fd4d207d086ee9882e7606 (diff)
downloadsamba-b9f95882f0fd9f453c6b90d1ca023111195d757b.tar.gz
samba-b9f95882f0fd9f453c6b90d1ca023111195d757b.tar.bz2
samba-b9f95882f0fd9f453c6b90d1ca023111195d757b.zip
s4:upgradeprovision Rework script, and reset machine account pw
The rework corrects some duplication and errors in the original script, found when preparing an automated test of the script. The code to reset the machine account password avoids issues with AES keys and salting, which may not otherwise be solved by the upgrade. Andrew Bartlett
Diffstat (limited to 'source4/scripting/bin/upgradeprovision')
-rwxr-xr-xsource4/scripting/bin/upgradeprovision85
1 files changed, 58 insertions, 27 deletions
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index 74d9829376..7dd9a95b1e 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -45,9 +45,11 @@ import samba.getopt as options
from samba.samdb import SamDB
from samba import param
from samba.provision import ProvisionNames,provision_paths_from_lp,find_setup_dir,FILL_FULL,provision
+from samba.provisionexceptions import ProvisioningError
from samba.schema import get_dnsyntax_attributes, get_linked_attributes, Schema
from samba.dcerpc import misc, security
from samba.ndr import ndr_pack, ndr_unpack
+from samba.dcerpc.misc import SEC_CHAN_BDC
replace=2^ldb.FLAG_MOD_REPLACE
add=2^ldb.FLAG_MOD_ADD
@@ -171,8 +173,7 @@ def guess_names_from_current_provision(credentials,session_info,paths):
# NT domain, kerberos realm, root dn, domain dn, domain dns name
names.domain = string.upper(lp.get("workgroup"))
names.realm = lp.get("realm")
- rootdn = "DC=" + names.realm.replace(".",",DC=")
- names.domaindn = rootdn
+ basedn = "DC=" + names.realm.replace(".",",DC=")
names.dnsdomain = names.realm
names.realm = string.upper(names.realm)
# netbiosname
@@ -188,16 +189,17 @@ def guess_names_from_current_provision(credentials,session_info,paths):
credentials=credentials, lp=lp, options=["modules:samba_dsdb"])
# That's a bit simplistic but it's ok as long as we have only 3 partitions
- attrs2 = ["schemaNamingContext","configurationNamingContext","rootDomainNamingContext"]
+ attrs2 = ["defaultNamingContext", "schemaNamingContext","configurationNamingContext","rootDomainNamingContext"]
res2 = samdb.search(expression="(objectClass=*)",base="", scope=SCOPE_BASE, attrs=attrs2)
names.configdn = res2[0]["configurationNamingContext"]
configdn = str(names.configdn)
names.schemadn = res2[0]["schemaNamingContext"]
- if not (rootdn == str(res2[0]["rootDomainNamingContext"])):
- message(ERROR, "rootdn in sam.ldb and smb.conf is not the same ...")
- else:
- names.rootdn=res2[0]["rootDomainNamingContext"]
+ if not (ldb.Dn(samdb, basedn) == (ldb.Dn(samdb, res2[0]["defaultNamingContext"][0]))):
+ raise ProvisioningError(("basedn in %s (%s) and from %s (%s) is not the same ..." % (paths.samdb, str(res2[0]["defaultNamingContext"][0]), paths.smbconf, basedn)))
+
+ names.domaindn=res2[0]["defaultNamingContext"]
+ names.rootdn=res2[0]["rootDomainNamingContext"]
# default site name
attrs3 = ["cn"]
res3= samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_ONELEVEL, attrs=attrs3)
@@ -205,43 +207,37 @@ def guess_names_from_current_provision(credentials,session_info,paths):
# dns hostname and server dn
attrs4 = ["dNSHostName"]
- res4= samdb.search(expression="(CN=%s)"%names.netbiosname,base="OU=Domain Controllers,"+rootdn, \
+ res4= samdb.search(expression="(CN=%s)"%names.netbiosname,base="OU=Domain Controllers,"+basedn, \
scope=SCOPE_ONELEVEL, attrs=attrs4)
names.hostname = str(res4[0]["dNSHostName"]).replace("."+names.dnsdomain,"")
- names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (names.netbiosname, names.sitename, configdn)
+ server_res = samdb.search(expression="serverReference=%s"%res4[0].dn, attrs=[], base=configdn)
+ names.serverdn = server_res[0].dn
+
+ # invocation id/objectguid
+ res5 = samdb.search(expression="(objectClass=*)",base="CN=NTDS Settings,%s" % str(names.serverdn), scope=SCOPE_BASE, attrs=["invocationID","objectGUID"])
+ names.invocation = str(ndr_unpack( misc.GUID,res5[0]["invocationId"][0]))
+ names.ntdsguid = str(ndr_unpack( misc.GUID,res5[0]["objectGUID"][0]))
- # invocation id
- attrs5 = ["invocationId"]
- res5 = samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_SUBTREE, attrs=attrs5)
- for i in range(0,len(res5)):
- if ( len(res5[i]) > 0):
- names.invocation = str(ndr_unpack( misc.GUID,res5[i]["invocationId"][0]))
- break
# domain guid/sid
attrs6 = ["objectGUID", "objectSid", ]
- res6 = samdb.search(expression="(objectClass=*)",base=rootdn, scope=SCOPE_BASE, attrs=attrs6)
+ res6 = samdb.search(expression="(objectClass=*)",base=basedn, scope=SCOPE_BASE, attrs=attrs6)
names.domainguid = str(ndr_unpack( misc.GUID,res6[0]["objectGUID"][0]))
names.domainsid = str(ndr_unpack( security.dom_sid,res6[0]["objectSid"][0]))
# policy guid
attrs7 = ["cn","displayName"]
- res7 = samdb.search(expression="(displayName=Default Domain Policy)",base="CN=Policies,CN=System,"+rootdn, \
+ res7 = samdb.search(expression="(displayName=Default Domain Policy)",base="CN=Policies,CN=System,"+basedn, \
scope=SCOPE_ONELEVEL, attrs=attrs7)
names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
# dc policy guid
attrs8 = ["cn","displayName"]
- res8 = samdb.search(expression="(displayName=Default Domain Controllers Policy)",base="CN=Policies,CN=System,"+rootdn, \
+ res8 = samdb.search(expression="(displayName=Default Domain Controllers Policy)",base="CN=Policies,CN=System,"+basedn, \
scope=SCOPE_ONELEVEL, attrs=attrs7)
if len(res8) == 1:
names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
else:
names.policyid_dc = None
- # ntds guid
- attrs9 = ["objectGUID" ]
- exp = "(dn=CN=NTDS Settings,%s)"%(names.serverdn)
- res9 = samdb.search(expression="(dn=CN=NTDS Settings,%s)"%(names.serverdn),base=str(names.configdn), scope=SCOPE_SUBTREE, attrs=attrs9)
- names.ntdsguid = str(ndr_unpack( misc.GUID,res9[0]["objectGUID"][0]))
return names
@@ -251,7 +247,7 @@ def print_names(names):
message(GUESS, "rootdn :"+str(names.rootdn))
message(GUESS, "configdn :"+str(names.configdn))
message(GUESS, "schemadn :"+str(names.schemadn))
- message(GUESS, "serverdn :"+names.serverdn)
+ message(GUESS, "serverdn :"+str(names.serverdn))
message(GUESS, "netbiosname :"+names.netbiosname)
message(GUESS, "defaultsite :"+names.sitename)
message(GUESS, "dnsdomain :"+names.dnsdomain)
@@ -285,7 +281,7 @@ def newprovision(names,setup_dir,creds,session,smbconf):
session, creds, smbconf=smbconf, targetdir=provdir,
samdb_fill=FILL_FULL, realm=names.realm, domain=names.domain,
domainguid=names.domainguid, domainsid=names.domainsid,ntdsguid=names.ntdsguid,
- policyguid=names.policyid,policyguid_dc=names.policyid_dc,hostname=names.hostname,
+ policyguid=names.policyid,policyguid_dc=names.policyid_dc,hostname=names.netbiosname,
hostip=None, hostip6=None,
invocationid=names.invocation, adminpass=None,
krbtgtpass=None, machinepass=None,
@@ -506,7 +502,7 @@ def check_diff_name(newpaths,paths,creds,session,basedn,names,ischema):
# The double ldb open and schema validation is taken from the initial provision script
# it's not certain that it is really needed ....
sam_ldb = Ldb(session_info=session, credentials=creds, lp=lp)
- schema = Schema(setup_path, security.dom_sid(names.domainsid), schemadn=basedn, serverdn=names.serverdn)
+ schema = Schema(setup_path, security.dom_sid(names.domainsid), schemadn=basedn, serverdn=str(names.serverdn))
# Load the schema from the one we computed earlier
sam_ldb.set_schema_from_ldb(schema.ldb)
# And now we can connect to the DB - the schema won't be loaded from the DB
@@ -686,6 +682,40 @@ def update_samdb(newpaths,paths,creds,session,names):
message(SIMPLE,"Done with scanning")
# update_sds(hashdef,hashSD,paths,creds,session,str(names.rootdn),names.domainsid)
+def update_machine_account_password(newpaths,paths,creds,session,names):
+
+ secrets_ldb = Ldb(newpaths.secrets, session_info=session, credentials=creds,lp=lp)
+ secrets_ldb.transaction_start()
+ secrets_msg = secrets_ldb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=["secureChannelType"])
+ sam_ldb = Ldb(paths.samdb, session_info=session, credentials=creds,lp=lp)
+ if secrets_msg[0]["secureChannelType"][0] == SEC_CHAN_BDC:
+ sam_ldb.transaction_start()
+ res = sam_ldb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=[])
+ assert(len(res) == 1)
+
+ msg = ldb.Message(res[0].dn)
+ machinepass = msg["userPassword"] = glue.generate_random_str(12)
+ for el in msg:
+ el.set_flags(ldb.FLAG_MOD_REPLACE)
+ sam_ldb.modify(msg)
+
+ res = sam_ldb.search(expression=("samAccountName=%s$" % names.netbiosname),
+ attrs=["msDs-keyVersionNumber"])
+ assert(len(res) == 1)
+ kvno = res[0]["msDs-keyVersionNumber"]
+
+ secretsdb_self_join(secrets_ldb, domain=names.domain,
+ realm=names.realm,
+ dnsdomain=names.dnsdomain,
+ netbiosname=names.netbiosname,
+ machinepass=machinepass,
+ key_version_number=kvno,
+ secure_channel_type=secrets_msg[0]["secureChannelType"])
+ sam_ldb.transaction_prepare_commit()
+ secrets_ldb.transaction_prepare_commit()
+ sam_ldb.transaction_commit()
+ secrets_ldb.transaction_commit()
+
# From here start the big steps of the program
# First get files paths
paths=get_paths(targetdir=opts.targetdir,smbconf=smbconf)
@@ -708,6 +738,7 @@ update_secrets(newpaths,paths,creds,session)
update_privilege(newpaths,paths)
if opts.full:
update_samdb(newpaths,paths,creds,session,names)
+ update_machine_account_password(newpaths,paths,creds,session,names)
message(SIMPLE,"Upgrade finished !")
# remove reference provision now that everything is done !
rmall(provisiondir)