[SCM] Samba Shared Repository - branch master updated
Andrew Tridgell
tridge at samba.org
Thu Jun 16 21:44:03 MDT 2011
The branch, master has been updated
via 0c3075c s4-pysamdb: fixed the normalisation of grouptype in group add
via a826979 samba-tool: report total error count and suggest --fix if needed
via 08dc1aa samba-tool: added attribute normalisation checks
via 4905725 s4-dsdb: if we don't have a remote schema, then use the local one
via 665ef94 s4-pydsdb: added dsdb_normalise_attributes() call
from 5961852 s3:wb_lookupsids: add some paranoia checks to wb_lookupsids_recv()
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 0c3075cb57134f6171c332158c3052e05dace595
Author: Andrew Tridgell <tridge at samba.org>
Date: Fri Jun 17 12:02:23 2011 +1000
s4-pysamdb: fixed the normalisation of grouptype in group add
ldap integers are signed
Autobuild-User: Andrew Tridgell <tridge at samba.org>
Autobuild-Date: Fri Jun 17 05:43:18 CEST 2011 on sn-devel-104
commit a8269792aa7c75b82b5ccab0e3b819601f7a4ef4
Author: Andrew Tridgell <tridge at samba.org>
Date: Fri Jun 17 11:34:19 2011 +1000
samba-tool: report total error count and suggest --fix if needed
commit 08dc1aa4cc1a697dd72db6a09a32d1929421fc09
Author: Andrew Tridgell <tridge at samba.org>
Date: Fri Jun 17 11:31:25 2011 +1000
samba-tool: added attribute normalisation checks
this checks that all attributes have the right normalisation, and
offers to fix the ones that don't
commit 49057255999fce2e4aa93de60dc80d40a655e61a
Author: Andrew Tridgell <tridge at samba.org>
Date: Fri Jun 17 11:30:41 2011 +1000
s4-dsdb: if we don't have a remote schema, then use the local one
this allows the use of drsuapi_to_ldb() on all attributes for the
local database
commit 665ef94d3c15ba59811143bb3d3e395ffd306a58
Author: Andrew Tridgell <tridge at samba.org>
Date: Fri Jun 17 11:29:44 2011 +1000
s4-pydsdb: added dsdb_normalise_attributes() call
this call converts a set of attributes to DRSUAPI format and back to
ldb format. This has the effect of normalising the attributes using
the schema syntax rules
-----------------------------------------------------------------------
Summary of changes:
source4/dsdb/pydsdb.c | 104 ++++++++++++++++++++++
source4/dsdb/schema/schema_syntax.c | 10 ++-
source4/scripting/python/samba/netcmd/dbcheck.py | 69 +++++++++++++--
source4/scripting/python/samba/samdb.py | 13 +++-
4 files changed, 187 insertions(+), 9 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 895bd9a..62f33bb 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -423,6 +423,109 @@ static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
return ret;
}
+
+/*
+ normalise a ldb attribute list
+ */
+static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
+{
+ PyObject *py_ldb, *el_list, *ret;
+ struct ldb_context *ldb;
+ char *ldap_display_name;
+ const struct dsdb_attribute *a;
+ struct dsdb_schema *schema;
+ struct dsdb_syntax_ctx syntax_ctx;
+ struct ldb_message_element *el;
+ struct drsuapi_DsReplicaAttribute *attr;
+ TALLOC_CTX *tmp_ctx;
+ WERROR werr;
+ Py_ssize_t i;
+
+ if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
+ return NULL;
+ }
+
+ PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+ if (!PyList_Check(el_list)) {
+ PyErr_Format(PyExc_TypeError, "ldif_elements must be a list");
+ return NULL;
+ }
+
+ schema = dsdb_get_schema(ldb, NULL);
+ if (!schema) {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
+ return NULL;
+ }
+
+ a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
+ if (a == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name);
+ return NULL;
+ }
+
+ dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
+ syntax_ctx.is_schema_nc = false;
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ el = talloc_zero(tmp_ctx, struct ldb_message_element);
+ if (el == NULL) {
+ PyErr_NoMemory();
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ el->name = ldap_display_name;
+ el->num_values = PyList_Size(el_list);
+
+ el->values = talloc_array(el, struct ldb_val, el->num_values);
+ if (el->values == NULL) {
+ PyErr_NoMemory();
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ for (i = 0; i < el->num_values; i++) {
+ PyObject *item = PyList_GetItem(el_list, i);
+ if (!PyString_Check(item)) {
+ PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
+ return NULL;
+ }
+ el->values[i].data = (uint8_t *)PyString_AsString(item);
+ el->values[i].length = PyString_Size(item);
+ }
+
+ /* first run ldb_to_drsuapi, then convert back again. This has
+ * the effect of normalising the attributes
+ */
+
+ attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
+ if (attr == NULL) {
+ PyErr_NoMemory();
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
+ PyErr_WERROR_IS_ERR_RAISE(werr);
+
+ /* now convert back again */
+ werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, el, el);
+ PyErr_WERROR_IS_ERR_RAISE(werr);
+
+ ret = py_return_ndr_struct("ldb", "MessageElement", el, el);
+
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
+
+
static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
{
PyObject *py_ldb, *py_guid;
@@ -723,6 +826,7 @@ static PyMethodDef py_dsdb_methods[] = {
NULL },
{ "_dsdb_get_partitions_dn", (PyCFunction)py_dsdb_get_partitions_dn, METH_VARARGS, NULL },
{ "_dsdb_DsReplicaAttribute", (PyCFunction)py_dsdb_DsReplicaAttribute, METH_VARARGS, NULL },
+ { "_dsdb_normalise_attributes", (PyCFunction)py_dsdb_normalise_attributes, METH_VARARGS, NULL },
{ NULL }
};
diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c
index ea582db..75dc162 100644
--- a/source4/dsdb/schema/schema_syntax.c
+++ b/source4/dsdb/schema/schema_syntax.c
@@ -1069,8 +1069,14 @@ static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *
struct ldb_message_element *out)
{
unsigned int i;
+ const struct dsdb_schema_prefixmap *prefixmap;
- SMB_ASSERT(ctx->pfm_remote);
+ if (ctx->pfm_remote != NULL) {
+ prefixmap = ctx->pfm_remote;
+ } else {
+ prefixmap = ctx->schema->prefixmap;
+ }
+ SMB_ASSERT(prefixmap);
out->flags = 0;
out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
@@ -1095,7 +1101,7 @@ static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *
attid = IVAL(in->value_ctr.values[i].blob->data, 0);
- status = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, attid,
+ status = dsdb_schema_pfm_oid_from_attid(prefixmap, attid,
out->values, &oid);
if (!W_ERROR_IS_OK(status)) {
DEBUG(0,(__location__ ": Error: Unknown ATTID 0x%08X\n",
diff --git a/source4/scripting/python/samba/netcmd/dbcheck.py b/source4/scripting/python/samba/netcmd/dbcheck.py
index 7af2101..9f12136 100644
--- a/source4/scripting/python/samba/netcmd/dbcheck.py
+++ b/source4/scripting/python/samba/netcmd/dbcheck.py
@@ -58,24 +58,71 @@ 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
+ return 1
obj = res[0]
+ error_count = 0
for attrname in obj:
if attrname == 'dn':
continue
+
+ # check for empty attributes
for val in obj[attrname]:
if val == '':
empty_attribute(self, dn, attrname)
+ error_count += 1
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])
+ error_count += 1
+ break
+ return error_count
+
class cmd_dbcheck(Command):
"""check local AD database for errors"""
@@ -96,11 +143,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 +166,15 @@ 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))
+ error_count = 0
for object in res:
- check_object(self, object.dn)
- print('Checked %u objects' % len(res))
+ error_count += check_object(self, object.dn)
+ if error_count != 0 and not self.fix:
+ print("Please use --fix to fix these errors")
+ print('Checked %u objects (%u errors)' % (len(res), error_count))
diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py
index 55f3536..53346e8 100644
--- a/source4/scripting/python/samba/samdb.py
+++ b/source4/scripting/python/samba/samdb.py
@@ -142,7 +142,7 @@ pwdLastSet: 0
"objectClass": "group"}
if grouptype is not None:
- ldbmessage["groupType"] = "%d" % grouptype
+ ldbmessage["groupType"] = self.normalise_int32(grouptype)
if description is not None:
ldbmessage["description"] = description
@@ -507,8 +507,13 @@ accountExpires: %u
dsdb._dsdb_set_schema_from_ldb(self, ldb_conn)
def dsdb_DsReplicaAttribute(self, ldb, ldap_display_name, ldif_elements):
+ '''convert a list of attribute values to a DRSUAPI DsReplicaAttribute'''
return dsdb._dsdb_DsReplicaAttribute(ldb, ldap_display_name, ldif_elements)
+ def dsdb_normalise_attributes(self, ldb, ldap_display_name, ldif_elements):
+ '''normalise a list of attribute values'''
+ return dsdb._dsdb_normalise_attributes(ldb, ldap_display_name, ldif_elements)
+
def get_attribute_from_attid(self, attid):
""" Get from an attid the associated attribute
@@ -717,3 +722,9 @@ accountExpires: %u
if sd:
m["nTSecurityDescriptor"] = ndr_pack(sd)
self.add(m)
+
+ def normalise_int32(self, ivalue):
+ '''normalise a ldap integer to signed 32 bit'''
+ if int(ivalue) & 0x80000000:
+ return str(int(ivalue) - 0x100000000)
+ return str(ivalue)
--
Samba Shared Repository
More information about the samba-cvs
mailing list