summaryrefslogtreecommitdiff
path: root/source4/scripting/bin/upgradeprovision
diff options
context:
space:
mode:
authorMatthieu Patou <mat@matws.net>2010-01-19 01:53:01 +0300
committerAndrew Bartlett <abartlet@samba.org>2010-01-21 07:11:20 +1300
commit929dbf8ef817cb1646a5f82b9a0f0eece4ab84ee (patch)
treeac70fa88ec2f6083d6d8d08aa65a786b7334dd13 /source4/scripting/bin/upgradeprovision
parent4d6cda75e3f0536c71741051ae4c643d11ab95d8 (diff)
downloadsamba-929dbf8ef817cb1646a5f82b9a0f0eece4ab84ee.tar.gz
samba-929dbf8ef817cb1646a5f82b9a0f0eece4ab84ee.tar.bz2
samba-929dbf8ef817cb1646a5f82b9a0f0eece4ab84ee.zip
upgradeprovision: mark rIDAvailablePool never upgraded
handle properly the fact that missing object might depend on some other in order to be correctly created debug change also if we are in debugall mode
Diffstat (limited to 'source4/scripting/bin/upgradeprovision')
-rwxr-xr-xsource4/scripting/bin/upgradeprovision137
1 files changed, 121 insertions, 16 deletions
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index 0c33ee358e..1c70e377ae 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -54,6 +54,7 @@ from samba.dcerpc import misc, security
from samba.ndr import ndr_pack, ndr_unpack
from samba.dcerpc.misc import SEC_CHAN_BDC
+never=0
replace=2^ldb.FLAG_MOD_REPLACE
add=2^ldb.FLAG_MOD_ADD
delete=2^ldb.FLAG_MOD_DELETE
@@ -85,11 +86,12 @@ hashAttrNotCopied = { "dn": 1,"whenCreated": 1,"whenChanged": 1,"objectGUID": 1
hashOverwrittenAtt = { "prefixMap": replace, "systemMayContain": replace,"systemOnly":replace, "searchFlags":replace,
"mayContain":replace, "systemFlags":replace,"description":replace,
"oEMInformation":replace, "operatingSystemVersion":replace, "adminPropertyPages":replace,
- "defaultSecurityDescriptor": replace,"wellKnownObjects":replace,"privilege":delete,"groupType":replace}
+ "defaultSecurityDescriptor": replace,"wellKnownObjects":replace,"privilege":delete,"groupType":replace,
+ "rIDAvailablePool": never}
backlinked = []
-
+dn_syntax_att = []
def define_what_to_log(opts):
what = 0
if opts.debugchange:
@@ -156,7 +158,15 @@ def identic_rename(ldbobj,dn):
# Create an array of backlinked attributes
def populate_backlink(newpaths,creds,session,schemadn):
newsam_ldb = Ldb(newpaths.samdb, session_info=session, credentials=creds,lp=lp)
- backlinked.extend(get_linked_attributes(ldb.Dn(newsam_ldb,str(schemadn)),newsam_ldb).values())
+ linkedAttHash = get_linked_attributes(ldb.Dn(newsam_ldb,str(schemadn)),newsam_ldb)
+ backlinked.extend(linkedAttHash.values())
+
+# Create an array of attributes with a dn synthax (2.5.5.1)
+def populate_dnsyntax(newpaths,creds,session,schemadn):
+ newsam_ldb = Ldb(newpaths.samdb, session_info=session, credentials=creds,lp=lp)
+ res = newsam_ldb.search(expression="(attributeSyntax=2.5.5.1)",base=ldb.Dn(newsam_ldb,str(schemadn)), scope=SCOPE_SUBTREE, attrs=["lDAPDisplayName"])
+ for elem in res:
+ dn_syntax_att.append(elem["lDAPDisplayName"])
# Get Paths for important objects (ldb, keytabs ...)
def get_paths(targetdir=None,smbconf=None):
@@ -497,6 +507,107 @@ def update_secrets(newpaths,paths,creds,session):
delta.dn = current[0].dn
secrets_ldb.modify(delta)
+def dump_denied_change(dn,att,flagtxt,current,reference):
+ message(CHANGE, "dn= "+str(dn)+" "+att+" with flag "+flagtxt+" is not allowed to be changed/removed, I discard this change ...")
+ if att != "objectSid" :
+ i = 0
+ for e in range(0,len(current)):
+ message(CHANGE,"old %d : %s"%(i,str(current[e])))
+ i=i+1
+ if reference != None:
+ i = 0
+ for e in range(0,len(reference)):
+ message(CHANGE,"new %d : %s"%(i,str(reference[e])))
+ i=i+1
+ else:
+ message(CHANGE,"old : %s"%str(ndr_unpack( security.dom_sid,current[0])))
+ message(CHANGE,"new : %s"%str(ndr_unpack( security.dom_sid,reference[0])))
+
+#This function is for doing case by case treatment on special object
+
+def handle_special_add(sam_ldb,dn,names):
+ dntoremove=None
+ if str(dn).lower() == ("CN=Certificate Service DCOM Access,CN=Builtin,%s"%names.rootdn).lower():
+ #This entry was misplaced lets remove it if it exists
+ dntoremove="CN=Certificate Service DCOM Access,CN=Users,%s"%names.rootdn
+
+ if str(dn).lower() == ("CN=Cryptographic Operators,CN=Builtin,%s"%names.rootdn).lower():
+ #This entry was misplaced lets remove it if it exists
+ dntoremove="CN=Cryptographic Operators,CN=Users,%s"%names.rootdn
+
+ if str(dn).lower() == ("CN=Event Log Readers,CN=Builtin,%s"%names.rootdn).lower():
+ #This entry was misplaced lets remove it if it exists
+ dntoremove="CN=Event Log Readers,CN=Users,%s"%names.rootdn
+
+ if dntoremove != None:
+ res = sam_ldb.search(expression="objectClass=*",base=dntoremove, scope=SCOPE_BASE,attrs=["dn"],controls=["search_options:1:2"])
+ if len(res) > 0:
+ message(CHANGE,"Existing object %s must be replaced by %s, removing old object"%(dntoremove,str(dn)))
+ sam_ldb.delete(res[0]["dn"])
+
+#Check if the one of the dn in the listdn will be created after the current dn
+#hash is indexed by dn to be created, with each key is associated the creation order
+#First dn to be created has the creation order 0, second has 1, ...
+#Index contain the current creation order
+def check_dn_nottobecreated(hash,index,listdn):
+ if listdn == None:
+ return None
+ for dn in listdn:
+ key = str(dn).lower()
+ if hash.has_key(key) and hash[key] > index:
+ return str(dn)
+ return None
+
+#This function tries to add the missing object "dn" if this object depends on some others
+# the function returns 0, if the object was created 1 is returned
+def add_missing_object(newsam_ldb,sam_ldb,dn,names,basedn,hash,index):
+ handle_special_add(sam_ldb,dn,names)
+ reference = newsam_ldb.search(expression="dn=%s"%(str(dn)),base=basedn,
+ scope=SCOPE_SUBTREE,controls=["search_options:1:2"])
+ empty = ldb.Message()
+ delta = sam_ldb.msg_diff(empty,reference[0])
+ for att in hashAttrNotCopied.keys():
+ delta.remove(att)
+ for att in backlinked:
+ delta.remove(att)
+ depend_on_yettobecreated = None
+ for att in dn_syntax_att:
+ depend_on_yet_tobecreated = check_dn_nottobecreated(hash,index,delta.get(str(att)))
+ if depend_on_yet_tobecreated != None:
+ message(CHANGE,"Object %s depends on %s in attribute %s, delaying the creation"
+ %(str(dn),depend_on_yet_tobecreated,str(att)))
+ return 0
+ delta.dn = dn
+ message(CHANGE,"Object %s will be added"%dn)
+ sam_ldb.add(delta,["relax:0"])
+ return 1
+
+def gen_dn_index_hash(listMissing):
+ hash = {}
+ for i in range(0,len(listMissing)):
+ hash[str(listMissing[i]).lower()] = i
+ return hash
+
+def add_missing_entries(newsam_ldb,sam_ldb,names,basedn,list):
+ listMissing = []
+ listDefered = list
+
+ while(len(listDefered) != len(listMissing) and len(listDefered) > 0):
+ index = 0
+ listMissing = listDefered
+ listDefered = []
+ hashMissing = gen_dn_index_hash(listMissing)
+ for dn in listMissing:
+ ret = add_missing_object(newsam_ldb,sam_ldb,dn,names,basedn,hashMissing,index)
+ index = index + 1
+ if ret == 0:
+ #DN can't be created because it depends on some other DN in the list
+ listDefered.append(dn)
+ if len(listDefered) != 0:
+ raise ProvisioningError("Unable to insert missing elements: circular references")
+
+
+
# Check difference between the current provision and the reference provision.
# It looks for all objects which base DN is name. If ischema is "false" then
@@ -534,6 +645,7 @@ def check_diff_name(newpaths,paths,creds,session,basedn,names,ischema):
for k in hash_new.keys():
if not hash.has_key(k):
+ print hash_new[k]
listMissing.append(hash_new[k])
else:
listPresent.append(hash_new[k])
@@ -564,19 +676,8 @@ def check_diff_name(newpaths,paths,creds,session,basedn,names,ischema):
sam_ldb.transaction_start()
- empty = ldb.Message()
message(SIMPLE,"There are %d missing objects"%(len(listMissing)))
- for dn in listMissing:
- reference = newsam_ldb.search(expression="dn=%s"%(str(dn)),base=basedn, scope=SCOPE_SUBTREE,controls=["search_options:1:2"])
- delta = sam_ldb.msg_diff(empty,reference[0])
- for att in hashAttrNotCopied.keys():
- delta.remove(att)
- for att in backlinked:
- delta.remove(att)
- delta.dn = dn
-
- sam_ldb.add(delta,["relax:0"])
-
+ add_missing_entries(newsam_ldb,sam_ldb,names,basedn,listMissing)
changed = 0
for dn in listPresent:
reference = newsam_ldb.search(expression="dn=%s"%(str(dn)),base=basedn, scope=SCOPE_SUBTREE,controls=["search_options:1:2"])
@@ -605,9 +706,12 @@ def check_diff_name(newpaths,paths,creds,session,basedn,names,ischema):
delta.remove(att)
continue
if (not hashOverwrittenAtt.has_key(att) or not (hashOverwrittenAtt.get(att)&2^msgElt.flags())):
+ if hashOverwrittenAtt.has_key(att) and hashOverwrittenAtt.get(att)==never:
+ delta.remove(att)
+ continue
if handle_special_case(att,delta,reference,current,ischema)==0 and msgElt.flags()!=ldb.FLAG_MOD_ADD:
i = 0
- if opts.debugchange:
+ if opts.debugchange or opts.debugall:
try:
dump_denied_change(dn,att,messageEltFlagToString(msgElt.flags()),current[0][att],reference[0][att])
except:
@@ -794,6 +898,7 @@ provisiondir = newprovision(names,setup_dir,creds,session,smbconf)
# Get file paths of this new provision
newpaths = get_paths(targetdir=provisiondir)
populate_backlink(newpaths,creds,session,names.schemadn)
+populate_dnsyntax(newpaths,creds,session,names.schemadn)
# Check the difference
update_basesamdb(newpaths,paths,names)