summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)