summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2011-06-17 11:31:25 +1000
committerAndrew Tridgell <tridge@samba.org>2011-06-17 12:32:55 +1000
commit08dc1aa4cc1a697dd72db6a09a32d1929421fc09 (patch)
treeda3e574ce958d7daf5fc5a0328603b2cc8b0022c
parent49057255999fce2e4aa93de60dc80d40a655e61a (diff)
downloadsamba-08dc1aa4cc1a697dd72db6a09a32d1929421fc09.tar.gz
samba-08dc1aa4cc1a697dd72db6a09a32d1929421fc09.tar.bz2
samba-08dc1aa4cc1a697dd72db6a09a32d1929421fc09.zip
samba-tool: added attribute normalisation checks
this checks that all attributes have the right normalisation, and offers to fix the ones that don't
-rw-r--r--source4/scripting/python/samba/netcmd/dbcheck.py56
1 files changed, 53 insertions, 3 deletions
diff --git a/source4/scripting/python/samba/netcmd/dbcheck.py b/source4/scripting/python/samba/netcmd/dbcheck.py
index 7af210104c..4eebca3503 100644
--- a/source4/scripting/python/samba/netcmd/dbcheck.py
+++ b/source4/scripting/python/samba/netcmd/dbcheck.py
@@ -58,12 +58,46 @@ def empty_attribute(self, dn, attrname):
print("Removed empty attribute %s" % attrname)
+def normalise_mismatch(self, dn, attrname, values):
+ '''fix attribute normalisation errors'''
+ print("ERROR: Normalisation error for attribute %s in %s" % (attrname, dn))
+ mod_list = []
+ for val in values:
+ normalised = self.samdb.dsdb_normalise_attributes(self.samdb, attrname, [val])
+ if len(normalised) != 1:
+ print("Unable to normalise value '%s'" % val)
+ mod_list.append((val, ''))
+ elif (normalised[0] != val):
+ print("value '%s' should be '%s'" % (val, normalised[0]))
+ mod_list.append((val, normalised[0]))
+ if not self.fix:
+ return
+ if not confirm(self, 'Fix normalisation for %s from %s?' % (attrname, dn)):
+ print("Not fixing attribute %s" % attrname)
+ return
+
+ m = ldb.Message()
+ m.dn = dn
+ for i in range(0, len(mod_list)):
+ (val, nval) = mod_list[i]
+ m['value_%u' % i] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname)
+ if nval != '':
+ m['normv_%u' % i] = ldb.MessageElement(nval, ldb.FLAG_MOD_ADD, attrname)
+
+ try:
+ self.samdb.modify(m, controls=["relax:0"], validate=False)
+ except Exception, msg:
+ print("Failed to normalise attribute %s : %s" % (attrname, msg))
+ return
+ print("Normalised attribute %s" % attrname)
+
+
def check_object(self, dn):
'''check one object'''
if self.verbose:
print("Checking object %s" % dn)
- res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE)
+ res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, controls=["extended_dn:1:1"], attrs=['*', 'ntSecurityDescriptor'])
if len(res) != 1:
print("Object %s disappeared during check" % dn)
return
@@ -71,11 +105,20 @@ def check_object(self, dn):
for attrname in obj:
if attrname == 'dn':
continue
+
+ # check for empty attributes
for val in obj[attrname]:
if val == '':
empty_attribute(self, dn, attrname)
continue
+ # check for incorrectly normalised attributes
+ for val in obj[attrname]:
+ normalised = self.samdb.dsdb_normalise_attributes(self.samdb, attrname, [val])
+ if len(normalised) != 1 or normalised[0] != val:
+ normalise_mismatch(self, dn, attrname, obj[attrname])
+ break
+
class cmd_dbcheck(Command):
"""check local AD database for errors"""
@@ -96,11 +139,13 @@ class cmd_dbcheck(Command):
help='Fix any errors found'),
Option("--yes", dest="yes", default=False, action='store_true',
help="don't confirm changes, just do them all"),
+ Option("--cross-ncs", dest="cross_ncs", default=False, action='store_true',
+ help="cross naming context boundaries"),
Option("-v", "--verbose", dest="verbose", action="store_true", default=False,
help="Print more details of checking"),
]
- def run(self, DN=None, verbose=False, fix=False, yes=False,
+ def run(self, DN=None, verbose=False, fix=False, yes=False, cross_ncs=False,
scope="SUB", credopts=None, sambaopts=None, versionopts=None):
self.lp = sambaopts.get_loadparm()
self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
@@ -117,7 +162,12 @@ class cmd_dbcheck(Command):
raise CommandError("Unknown scope %s" % scope)
self.search_scope = scope_map[scope]
- res = self.samdb.search(base=DN, scope=self.search_scope, attrs=['dn'])
+ controls = []
+ if cross_ncs:
+ controls.append("search_options:1:2")
+
+ res = self.samdb.search(base=DN, scope=self.search_scope, attrs=['dn'], controls=controls)
+ print('Checking %u objects' % len(res))
for object in res:
check_object(self, object.dn)
print('Checked %u objects' % len(res))