1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-05 21:57:51 +03:00

s4:objectclass LDB module - multiple "objectClass" change elements are unfortunately still allowed

The test message has been compressed - therefore I've now used "modify_ldif".
This commit is contained in:
Matthias Dieter Wallnöfer 2010-11-13 12:25:40 +01:00
parent b9cfe10945
commit 113a9c1806
2 changed files with 189 additions and 184 deletions

View File

@ -921,7 +921,7 @@ static int objectclass_do_mod(struct oc_context *ac)
TALLOC_CTX *mem_ctx;
struct class_list *sorted, *current;
const struct dsdb_class *objectclass;
unsigned int i, j;
unsigned int i, j, k;
bool found, replace = false;
int ret;
@ -939,13 +939,6 @@ static int objectclass_do_mod(struct oc_context *ac)
return ldb_operr(ldb);
}
oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
"objectClass");
if (oc_el_change == NULL) {
/* we should have an objectclass change operation */
return ldb_operr(ldb);
}
/* use a new message structure */
msg = ldb_msg_new(ac);
if (msg == NULL) {
@ -959,20 +952,32 @@ static int objectclass_do_mod(struct oc_context *ac)
return ldb_oom(ldb);
}
/* We've to walk over all "objectClass" message elements */
for (k = 0; k < ac->req->op.mod.message->num_elements; k++) {
if (ldb_attr_cmp(ac->req->op.mod.message->elements[k].name,
"objectClass") != 0) {
continue;
}
oc_el_change = &ac->req->op.mod.message->elements[k];
switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
case LDB_FLAG_MOD_ADD:
/* Merge the two message elements */
for (i = 0; i < oc_el_change->num_values; i++) {
for (j = 0; j < oc_el_entry->num_values; j++) {
if (strcasecmp((char *)oc_el_change->values[i].data,
if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
(char *)oc_el_entry->values[j].data) == 0) {
/* we cannot add an already existing object class */
ldb_asprintf_errstring(ldb,
"objectclass: cannot re-add an existing objectclass: '%.*s'!",
(int)oc_el_change->values[i].length,
(const char *)oc_el_change->values[i].data);
talloc_free(mem_ctx);
return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
}
}
/* append the new object class value - code was copied
* from "ldb_msg_add_value" */
/* append the new object class value - code was
* copied from "ldb_msg_add_value" */
vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
struct ldb_val,
oc_el_entry->num_values + 1);
@ -989,7 +994,9 @@ static int objectclass_do_mod(struct oc_context *ac)
objectclass = get_last_structural_class(ac->schema,
oc_el_change);
if (objectclass != NULL) {
/* we cannot add a new structural object class */
ldb_asprintf_errstring(ldb,
"objectclass: cannot add a new top-most structural objectclass '%s'!",
objectclass->lDAPDisplayName);
talloc_free(mem_ctx);
return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
@ -1031,11 +1038,11 @@ static int objectclass_do_mod(struct oc_context *ac)
for (i = 0; i < oc_el_change->num_values; i++) {
found = false;
for (j = 0; j < oc_el_entry->num_values; j++) {
if (strcasecmp((char *)oc_el_change->values[i].data,
if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
(char *)oc_el_entry->values[j].data) == 0) {
found = true;
/* delete the object class value -
* code was copied from
/* delete the object class value
* - code was copied from
* "ldb_msg_remove_element" */
if (j != oc_el_entry->num_values - 1) {
memmove(&oc_el_entry->values[j],
@ -1047,30 +1054,35 @@ static int objectclass_do_mod(struct oc_context *ac)
}
}
if (!found) {
/* we cannot delete a not existing object class */
ldb_asprintf_errstring(ldb, "Cannot delete this %.*s ",
(int)oc_el_change->values[i].length, (const char *)oc_el_change->values[i].data);
/* we cannot delete a not existing
* object class */
ldb_asprintf_errstring(ldb,
"objectclass: cannot delete this objectclass: '%.*s'!",
(int)oc_el_change->values[i].length,
(const char *)oc_el_change->values[i].data);
talloc_free(mem_ctx);
return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
}
/* Make sure that the top-most structural objectclass wasn't
* deleted */
/* Make sure that the top-most structural object class
* hasn't been deleted */
found = false;
for (i = 0; i < oc_el_entry->num_values; i++) {
if (strcasecmp(objectclass->lDAPDisplayName,
if (ldb_attr_cmp(objectclass->lDAPDisplayName,
(char *)oc_el_entry->values[i].data) == 0) {
found = true; break;
found = true;
break;
}
}
if (!found) {
ldb_asprintf_errstring(ldb,
"objectclass: cannot delete the top-most structural objectclass '%s'!",
objectclass->lDAPDisplayName);
talloc_free(mem_ctx);
return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
/* Now do the sorting */
ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
oc_el_entry, &sorted);
@ -1082,21 +1094,9 @@ static int objectclass_do_mod(struct oc_context *ac)
break;
}
/* Only one "objectclass" attribute change element per modify request
* allowed! */
for (i = 0; i < ac->req->op.mod.message->num_elements; i++) {
if (ldb_attr_cmp(ac->req->op.mod.message->elements[i].name,
"objectClass") != 0) continue;
if (ldb_msg_element_compare(&ac->req->op.mod.message->elements[i],
oc_el_change) != 0) {
ldb_set_errstring(ldb,
"objectclass: only one 'objectClass' attribute change per modify request allowed!");
talloc_free(mem_ctx);
return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
}
}
/* (Re)-add an empty "objectClass" attribute on the object
* classes change message "msg". */
ldb_msg_remove_attr(msg, "objectClass");
ret = ldb_msg_add_empty(msg, "objectClass",
LDB_FLAG_MOD_REPLACE, &oc_el_change);
if (ret != LDB_SUCCESS) {
@ -1114,41 +1114,49 @@ static int objectclass_do_mod(struct oc_context *ac)
}
ret = ldb_msg_add_string(msg, "objectClass", value);
if (ret != LDB_SUCCESS) {
ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
ldb_set_errstring(ldb,
"objectclass: could not re-add sorted objectclasses!");
talloc_free(mem_ctx);
return ret;
}
}
talloc_free(mem_ctx);
if (replace) {
/* Well, on replace we are nearly done: we have to test if
* the change and entry message element are identically. We
* can use "ldb_msg_element_compare" since now the specified
* objectclasses match for sure in case. */
ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
/* Well, on replace we are nearly done: we have to test
* if the change and entry message element are identical
* ly. We can use "ldb_msg_element_compare" since now
* the specified objectclasses match for sure in case.
*/
ret = ldb_msg_element_compare(oc_el_entry,
oc_el_change);
if (ret == 0) {
ret = ldb_msg_element_compare(oc_el_change,
oc_el_entry);
}
if (ret == 0) {
/* they are the same so we are done in this case */
/* they are the same so we are done in this
* case */
talloc_free(mem_ctx);
return ldb_module_done(ac->req, NULL, NULL,
LDB_SUCCESS);
} else {
/* they're not exactly the same */
ldb_set_errstring(ldb,
"objectclass: the specified objectclasses are not exactly the same as on the entry!");
talloc_free(mem_ctx);
return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
}
/* in the other cases we have the real change left to do */
ret = ldb_msg_sanity_check(ldb, msg);
if (ret != LDB_SUCCESS) {
return ret;
/* Now we've applied all changes from "oc_el_change" to
* "oc_el_entry" therefore the new "oc_el_entry" will be
* "oc_el_change". */
oc_el_entry = oc_el_change;
}
talloc_free(mem_ctx);
/* Now we have the real and definitive change left to do */
ret = ldb_build_mod_req(&mod_req, ldb, ac,
msg,
ac->req->controls,

View File

@ -310,18 +310,15 @@ class BasicTests(unittest.TestCase):
except LdbError, (num, _):
self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
# More than one change operation is not allowed
m = Message()
m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
"objectClass")
m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
"objectClass")
try:
ldb.modify(m)
self.fail()
except LdbError, (num, _):
self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
# More than one change operation is allowed
ldb.modify_ldif("""
dn: cn=ldaptestuser,cn=users, """ + self.base_dn + """
changetype: modify
delete: objectClass
objectClass: bootableDevice
add: objectClass
objectClass: bootableDevice
""")
# We cannot remove all object classes by an empty replace
m = Message()