4 Copyright (C) Simo Sorce 2006-2008
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
6 Copyright (C) Matthias Dieter Wallnöfer 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * Component: objectClass sorting and constraint checking module
28 * - sort the objectClass attribute into the class
29 * hierarchy and perform constraint checks (correct RDN name,
31 * - fix DNs into 'standard' case
32 * - Add objectCategory and some other attribute defaults
34 * Author: Andrew Bartlett
39 #include "ldb_module.h"
40 #include "util/dlinklist.h"
41 #include "dsdb/samdb/samdb.h"
42 #include "librpc/ndr/libndr.h"
43 #include "librpc/gen_ndr/ndr_security.h"
44 #include "libcli/security/security.h"
45 #include "auth/auth.h"
46 #include "param/param.h"
47 #include "../libds/common/flags.h"
52 struct ldb_module *module;
53 struct ldb_request *req;
54 const struct dsdb_schema *schema;
56 struct ldb_reply *search_res;
57 struct ldb_reply *search_res2;
59 int (*step_fn)(struct oc_context *);
63 struct class_list *prev, *next;
64 const struct dsdb_class *objectclass;
67 static struct oc_context *oc_init_context(struct ldb_module *module,
68 struct ldb_request *req)
70 struct ldb_context *ldb;
71 struct oc_context *ac;
73 ldb = ldb_module_get_ctx(module);
75 ac = talloc_zero(req, struct oc_context);
83 ac->schema = dsdb_get_schema(ldb, ac);
88 static int objectclass_do_add(struct oc_context *ac);
90 /* Sort objectClasses into correct order, and validate that all
91 * objectClasses specified actually exist in the schema
94 static int objectclass_sort(struct ldb_module *module,
95 const struct dsdb_schema *schema,
97 struct ldb_message_element *objectclass_element,
98 struct class_list **sorted_out)
100 struct ldb_context *ldb;
101 unsigned int i, lowest;
102 struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL, *poss_parent = NULL, *new_parent = NULL, *current_lowest = NULL;
104 ldb = ldb_module_get_ctx(module);
108 * We work on 4 different 'bins' (implemented here as linked lists):
110 * * sorted: the eventual list, in the order we wish to push
111 * into the database. This is the only ordered list.
113 * * parent_class: The current parent class 'bin' we are
114 * trying to find subclasses for
116 * * subclass: The subclasses we have found so far
118 * * unsorted: The remaining objectClasses
120 * The process is a matter of filtering objectClasses up from
121 * unsorted into sorted. Order is irrelevent in the later 3 'bins'.
123 * We start with 'top' (found and promoted to parent_class
124 * initially). Then we find (in unsorted) all the direct
125 * subclasses of 'top'. parent_classes is concatenated onto
126 * the end of 'sorted', and subclass becomes the list in
129 * We then repeat, until we find no more subclasses. Any left
130 * over classes are added to the end.
134 /* Firstly, dump all the objectClass elements into the
135 * unsorted bin, except for 'top', which is special */
136 for (i=0; i < objectclass_element->num_values; i++) {
137 current = talloc(mem_ctx, struct class_list);
141 current->objectclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &objectclass_element->values[i]);
142 if (!current->objectclass) {
143 ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema",
144 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
145 /* This looks weird, but windows apparently returns this for invalid objectClass values */
146 return LDB_ERR_NO_SUCH_ATTRIBUTE;
147 } else if (current->objectclass->isDefunct) {
148 ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects",
149 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
150 /* This looks weird, but windows apparently returns this for invalid objectClass values */
151 return LDB_ERR_NO_SUCH_ATTRIBUTE;
154 /* Don't add top to list, we will do that later */
155 if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) != 0) {
156 DLIST_ADD_END(unsorted, current, struct class_list *);
160 /* Add top here, to prevent duplicates */
161 current = talloc(mem_ctx, struct class_list);
162 current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
163 DLIST_ADD_END(sorted, current, struct class_list *);
166 /* For each object: find parent chain */
167 for (current = unsorted; schema && current; current = current->next) {
168 for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) {
169 if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) {
173 /* If we didn't get to the end of the list, we need to add this parent */
174 if (poss_parent || (ldb_attr_cmp("top", current->objectclass->subClassOf) == 0)) {
178 new_parent = talloc(mem_ctx, struct class_list);
179 new_parent->objectclass = dsdb_class_by_lDAPDisplayName(schema, current->objectclass->subClassOf);
180 DLIST_ADD_END(unsorted, new_parent, struct class_list *);
186 current_lowest = NULL;
187 for (current = unsorted; schema && current; current = current->next) {
188 if(current->objectclass->subClass_order < lowest) {
189 current_lowest = current;
190 lowest = current->objectclass->subClass_order;
194 if(current_lowest != NULL) {
195 DLIST_REMOVE(unsorted,current_lowest);
196 DLIST_ADD_END(sorted,current_lowest, struct class_list *);
202 *sorted_out = sorted;
207 /* If we don't have schema yet, then just merge the lists again */
208 DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
209 *sorted_out = sorted;
213 /* This shouldn't happen, and would break MMC, perhaps there
214 * was no 'top', a conflict in the objectClasses or some other
217 ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName);
218 return LDB_ERR_OBJECT_CLASS_VIOLATION;
221 static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares)
223 struct ldb_context *ldb;
224 struct oc_context *ac;
227 ac = talloc_get_type(req->context, struct oc_context);
228 ldb = ldb_module_get_ctx(ac->module);
231 return ldb_module_done(ac->req, NULL, NULL,
232 LDB_ERR_OPERATIONS_ERROR);
234 if (ares->error != LDB_SUCCESS &&
235 ares->error != LDB_ERR_NO_SUCH_OBJECT) {
236 return ldb_module_done(ac->req, ares->controls,
237 ares->response, ares->error);
240 ldb_reset_err_string(ldb);
242 switch (ares->type) {
243 case LDB_REPLY_ENTRY:
244 if (ac->search_res != NULL) {
245 ldb_set_errstring(ldb, "Too many results");
247 return ldb_module_done(ac->req, NULL, NULL,
248 LDB_ERR_OPERATIONS_ERROR);
251 ac->search_res = talloc_steal(ac, ares);
254 case LDB_REPLY_REFERRAL:
261 ret = ac->step_fn(ac);
262 if (ret != LDB_SUCCESS) {
263 return ldb_module_done(ac->req, NULL, NULL, ret);
271 static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)
273 struct oc_context *ac;
275 ac = talloc_get_type(req->context, struct oc_context);
278 return ldb_module_done(ac->req, NULL, NULL,
279 LDB_ERR_OPERATIONS_ERROR);
282 if (ares->type == LDB_REPLY_REFERRAL) {
283 return ldb_module_send_referral(ac->req, ares->referral);
286 if (ares->error != LDB_SUCCESS) {
287 return ldb_module_done(ac->req, ares->controls,
288 ares->response, ares->error);
291 if (ares->type != LDB_REPLY_DONE) {
293 return ldb_module_done(ac->req, NULL, NULL,
294 LDB_ERR_OPERATIONS_ERROR);
297 return ldb_module_done(ac->req, ares->controls,
298 ares->response, ares->error);
301 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN
303 This should mean that if the parent is:
304 CN=Users,DC=samba,DC=example,DC=com
305 and a proposed child is
306 cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM
308 The resulting DN should be:
310 CN=Admins,CN=Users,DC=samba,DC=example,DC=com
313 static int fix_dn(struct ldb_context *ldb,
315 struct ldb_dn *newdn, struct ldb_dn *parent_dn,
316 struct ldb_dn **fixed_dn)
318 char *upper_rdn_attr;
319 const struct ldb_val *rdn_val;
321 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
322 *fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
324 /* We need the attribute name in upper case */
325 upper_rdn_attr = strupper_talloc(*fixed_dn,
326 ldb_dn_get_rdn_name(newdn));
327 if (!upper_rdn_attr) {
328 return ldb_operr(ldb);
331 /* Create a new child */
332 if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
333 return ldb_operr(ldb);
337 rdn_val = ldb_dn_get_rdn_val(newdn);
340 /* the rules for rDN length constraints are more complex than
341 this. Until we understand them we need to leave this
342 constraint out. Otherwise we break replication, as windows
343 does sometimes send us rDNs longer than 64 */
344 if (!rdn_val || rdn_val->length > 64) {
345 DEBUG(2,(__location__ ": WARNING: rDN longer than 64 limit for '%s'\n", ldb_dn_get_linearized(newdn)));
350 /* And replace it with CN=foo (we need the attribute in upper case */
351 return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
355 static int objectclass_do_add(struct oc_context *ac);
357 static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
359 struct ldb_context *ldb;
360 struct ldb_request *search_req;
361 struct oc_context *ac;
362 struct ldb_dn *parent_dn;
363 const struct ldb_val *val;
366 static const char * const parent_attrs[] = { "objectGUID", "objectClass", NULL };
368 ldb = ldb_module_get_ctx(module);
370 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
372 /* do not manipulate our control entries */
373 if (ldb_dn_is_special(req->op.add.message->dn)) {
374 return ldb_next_request(module, req);
377 /* An add operation on the basedn without "NC-add" operation isn't
379 if (ldb_dn_compare(ldb_get_default_basedn(ldb), req->op.add.message->dn) == 0) {
380 unsigned int instanceType;
382 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message,
384 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
385 /* When we are trying to readd the root basedn then
386 * this is denied, but with an interesting mechanism:
387 * there is generated a referral with the last
388 * component value as hostname. */
389 val = ldb_dn_get_component_val(req->op.add.message->dn,
390 ldb_dn_get_comp_num(req->op.add.message->dn) - 1);
392 return ldb_operr(ldb);
394 value = talloc_asprintf(req, "ldap://%s/%s", val->data,
395 ldb_dn_get_linearized(req->op.add.message->dn));
400 return ldb_module_send_referral(req, value);
404 ac = oc_init_context(module, req);
406 return ldb_operr(ldb);
409 /* If there isn't a parent, just go on to the add processing */
410 if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
411 return objectclass_do_add(ac);
414 /* get copy of parent DN */
415 parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
416 if (parent_dn == NULL) {
420 ret = ldb_build_search_req(&search_req, ldb,
421 ac, parent_dn, LDB_SCOPE_BASE,
422 "(objectClass=*)", parent_attrs,
424 ac, get_search_callback,
426 if (ret != LDB_SUCCESS) {
430 ac->step_fn = objectclass_do_add;
432 return ldb_next_request(ac->module, search_req);
435 static int objectclass_do_add(struct oc_context *ac)
437 struct ldb_context *ldb;
438 struct ldb_request *add_req;
439 struct ldb_message_element *objectclass_element, *el;
440 struct ldb_message *msg;
442 struct class_list *sorted, *current;
443 const char *rdn_name = NULL;
445 const struct dsdb_class *objectclass;
446 struct ldb_dn *objectcategory;
447 int32_t systemFlags = 0;
450 ldb = ldb_module_get_ctx(ac->module);
452 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
454 /* Check if we have a valid parent - this check is needed since
455 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
456 if (ac->search_res == NULL) {
457 unsigned int instanceType;
459 /* An add operation on partition DNs without "NC-add" operation
461 instanceType = ldb_msg_find_attr_as_uint(ac->req->op.add.message,
463 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
464 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
465 ldb_dn_get_linearized(msg->dn));
466 return LDB_ERR_NO_SUCH_OBJECT;
469 /* Don't keep any error messages - we've to add a partition */
470 ldb_set_errstring(ldb, NULL);
472 /* Fix up the DN to be in the standard form, taking
473 * particular care to match the parent DN */
474 ret = fix_dn(ldb, msg,
475 ac->req->op.add.message->dn,
476 ac->search_res->message->dn,
478 if (ret != LDB_SUCCESS) {
479 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
480 ldb_dn_get_linearized(ac->req->op.add.message->dn));
485 mem_ctx = talloc_new(ac);
486 if (mem_ctx == NULL) {
490 if (ac->schema != NULL) {
491 objectclass_element = ldb_msg_find_element(msg, "objectClass");
492 if (!objectclass_element) {
493 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
494 ldb_dn_get_linearized(msg->dn));
495 talloc_free(mem_ctx);
496 return LDB_ERR_OBJECT_CLASS_VIOLATION;
499 /* Here we do now get the "objectClass" list from the
501 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
502 objectclass_element, &sorted);
503 if (ret != LDB_SUCCESS) {
504 talloc_free(mem_ctx);
508 ldb_msg_remove_element(msg, objectclass_element);
510 /* Well, now we shouldn't find any additional "objectClass"
511 * message element (required by the AD specification). */
512 objectclass_element = ldb_msg_find_element(msg, "objectClass");
513 if (objectclass_element != NULL) {
514 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, only one 'objectclass' attribute specification is allowed!",
515 ldb_dn_get_linearized(msg->dn));
516 talloc_free(mem_ctx);
517 return LDB_ERR_OBJECT_CLASS_VIOLATION;
520 /* We must completely replace the existing objectClass entry,
521 * because we need it sorted. */
522 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
523 if (ret != LDB_SUCCESS) {
524 talloc_free(mem_ctx);
528 /* Move from the linked list back into an ldb msg */
529 for (current = sorted; current; current = current->next) {
530 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
532 talloc_free(mem_ctx);
535 ret = ldb_msg_add_string(msg, "objectClass", value);
536 if (ret != LDB_SUCCESS) {
537 ldb_set_errstring(ldb,
538 "objectclass: could not re-add sorted "
539 "objectclass to modify msg");
540 talloc_free(mem_ctx);
545 talloc_free(mem_ctx);
547 /* Retrive the message again so get_last_structural_class works */
548 objectclass_element = ldb_msg_find_element(msg, "objectClass");
550 /* Make sure its valid to add an object of this type */
551 objectclass = get_last_structural_class(ac->schema,
552 objectclass_element);
553 if(objectclass == NULL) {
554 ldb_asprintf_errstring(ldb,
555 "Failed to find a structural class for %s",
556 ldb_dn_get_linearized(msg->dn));
557 return LDB_ERR_UNWILLING_TO_PERFORM;
560 rdn_name = ldb_dn_get_rdn_name(msg->dn);
561 if (objectclass->rDNAttID
562 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
563 ldb_asprintf_errstring(ldb,
564 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
565 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
566 return LDB_ERR_NAMING_VIOLATION;
569 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
570 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
571 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
572 return LDB_ERR_UNWILLING_TO_PERFORM;
575 if (((strcmp(objectclass->lDAPDisplayName, "secret") == 0) ||
576 (strcmp(objectclass->lDAPDisplayName, "trustedDomain") == 0)) &&
577 !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
578 ldb_asprintf_errstring(ldb, "objectClass %s is LSA-specific, rejecting creation of %s",
579 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
580 return LDB_ERR_UNWILLING_TO_PERFORM;
583 if (ac->search_res && ac->search_res->message) {
584 struct ldb_message_element *oc_el
585 = ldb_msg_find_element(ac->search_res->message, "objectClass");
587 bool allowed_class = false;
589 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
590 const struct dsdb_class *sclass;
592 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
595 /* We don't know this class? what is going on? */
598 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
599 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
600 allowed_class = true;
606 if (!allowed_class) {
607 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
608 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
609 return LDB_ERR_NAMING_VIOLATION;
613 objectcategory = ldb_msg_find_attr_as_dn(ldb, ac, msg,
615 if (objectcategory == NULL) {
616 struct dsdb_extended_dn_store_format *dn_format =
617 talloc_get_type(ldb_module_get_private(ac->module),
618 struct dsdb_extended_dn_store_format);
619 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
620 /* Strip off extended components */
621 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
622 objectclass->defaultObjectCategory);
623 value = ldb_dn_alloc_linearized(msg, dn);
626 value = talloc_strdup(msg,
627 objectclass->defaultObjectCategory);
633 ret = ldb_msg_add_string(msg, "objectCategory", value);
634 if (ret != LDB_SUCCESS) {
638 const struct dsdb_class *ocClass =
639 dsdb_class_by_cn_ldb_val(ac->schema,
640 ldb_dn_get_rdn_val(objectcategory));
641 if (ocClass != NULL) {
642 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
643 ocClass->defaultObjectCategory);
644 if (ldb_dn_compare(objectcategory, dn) != 0) {
648 talloc_free(objectcategory);
649 if (ocClass == NULL) {
650 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'objectCategory' attribute invalid!",
651 ldb_dn_get_linearized(msg->dn));
652 return LDB_ERR_OBJECT_CLASS_VIOLATION;
656 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
657 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
661 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
662 el = ldb_msg_find_element(msg, "systemFlags");
664 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
667 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
668 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
669 ldb_msg_remove_element(msg, el);
672 /* This flag is only allowed on attributeSchema objects */
673 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
674 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
677 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
678 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
679 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
680 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
681 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
682 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
684 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
685 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
686 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
687 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
690 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
692 if (el || systemFlags != 0) {
693 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
696 ret = ldb_msg_sanity_check(ldb, msg);
698 if (ret != LDB_SUCCESS) {
702 ret = ldb_build_add_req(&add_req, ldb, ac,
707 if (ret != LDB_SUCCESS) {
711 /* perform the add */
712 return ldb_next_request(ac->module, add_req);
715 static int oc_modify_callback(struct ldb_request *req,
716 struct ldb_reply *ares);
717 static int objectclass_do_mod(struct oc_context *ac);
719 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
721 struct ldb_context *ldb = ldb_module_get_ctx(module);
722 struct ldb_message_element *objectclass_element;
723 struct ldb_message *msg;
724 struct ldb_request *down_req;
725 struct oc_context *ac;
726 bool oc_changes = false;
729 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
731 /* do not manipulate our control entries */
732 if (ldb_dn_is_special(req->op.mod.message->dn)) {
733 return ldb_next_request(module, req);
736 /* As with the "real" AD we don't accept empty messages */
737 if (req->op.mod.message->num_elements == 0) {
738 ldb_set_errstring(ldb, "objectclass: modify message must have "
739 "elements/attributes!");
740 return LDB_ERR_UNWILLING_TO_PERFORM;
743 ac = oc_init_context(module, req);
745 return ldb_operr(ldb);
748 /* Without schema, there isn't much to do here */
749 if (ac->schema == NULL) {
751 return ldb_next_request(module, req);
754 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
756 return ldb_operr(ldb);
759 /* For now change everything except the objectclasses */
761 objectclass_element = ldb_msg_find_element(msg, "objectClass");
762 if (objectclass_element != NULL) {
763 ldb_msg_remove_attr(msg, "objectClass");
767 ret = ldb_build_mod_req(&down_req, ldb, ac,
770 oc_changes ? oc_modify_callback : oc_op_callback,
772 if (ret != LDB_SUCCESS) {
776 return ldb_next_request(module, down_req);
779 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
781 static const char * const attrs[] = { "objectClass", NULL };
782 struct ldb_context *ldb;
783 struct ldb_request *search_req;
784 struct oc_context *ac;
787 ac = talloc_get_type(req->context, struct oc_context);
788 ldb = ldb_module_get_ctx(ac->module);
791 return ldb_module_done(ac->req, NULL, NULL,
792 LDB_ERR_OPERATIONS_ERROR);
795 if (ares->type == LDB_REPLY_REFERRAL) {
796 return ldb_module_send_referral(ac->req, ares->referral);
799 if (ares->error != LDB_SUCCESS) {
800 return ldb_module_done(ac->req, ares->controls,
801 ares->response, ares->error);
804 if (ares->type != LDB_REPLY_DONE) {
806 return ldb_module_done(ac->req, NULL, NULL,
807 LDB_ERR_OPERATIONS_ERROR);
812 /* this looks up the real existing object for fetching some important
813 * informations (objectclasses) */
814 ret = ldb_build_search_req(&search_req, ldb,
815 ac, ac->req->op.mod.message->dn,
819 ac, get_search_callback,
821 if (ret != LDB_SUCCESS) {
822 return ldb_module_done(ac->req, NULL, NULL, ret);
825 ac->step_fn = objectclass_do_mod;
827 ret = ldb_next_request(ac->module, search_req);
828 if (ret != LDB_SUCCESS) {
829 return ldb_module_done(ac->req, NULL, NULL, ret);
835 static int objectclass_do_mod(struct oc_context *ac)
837 struct ldb_context *ldb;
838 struct ldb_request *mod_req;
840 struct ldb_message_element *oc_el_entry, *oc_el_change;
841 struct ldb_val *vals;
842 struct ldb_message *msg;
844 struct class_list *sorted, *current;
845 const struct dsdb_class *objectclass;
847 bool found, replace = false;
850 ldb = ldb_module_get_ctx(ac->module);
852 /* we should always have a valid entry when we enter here */
853 if (ac->search_res == NULL) {
854 return ldb_operr(ldb);
857 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
859 if (oc_el_entry == NULL) {
860 /* existing entry without a valid object class? */
861 return ldb_operr(ldb);
864 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
866 if (oc_el_change == NULL) {
867 /* we should have an objectclass change operation */
868 return ldb_operr(ldb);
871 /* use a new message structure */
872 msg = ldb_msg_new(ac);
877 msg->dn = ac->req->op.mod.message->dn;
879 mem_ctx = talloc_new(ac);
880 if (mem_ctx == NULL) {
884 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
885 case LDB_FLAG_MOD_ADD:
886 /* Merge the two message elements */
887 for (i = 0; i < oc_el_change->num_values; i++) {
888 for (j = 0; j < oc_el_entry->num_values; j++) {
889 if (strcasecmp((char *)oc_el_change->values[i].data,
890 (char *)oc_el_entry->values[j].data) == 0) {
891 /* we cannot add an already existing object class */
892 talloc_free(mem_ctx);
893 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
896 /* append the new object class value - code was copied
897 * from "ldb_msg_add_value" */
898 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
900 oc_el_entry->num_values + 1);
902 talloc_free(mem_ctx);
905 oc_el_entry->values = vals;
906 oc_el_entry->values[oc_el_entry->num_values] =
907 oc_el_change->values[i];
908 ++(oc_el_entry->num_values);
911 objectclass = get_last_structural_class(ac->schema,
913 if (objectclass != NULL) {
914 /* we cannot add a new structural object class */
915 talloc_free(mem_ctx);
916 return LDB_ERR_OBJECT_CLASS_VIOLATION;
919 /* Now do the sorting */
920 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
921 oc_el_entry, &sorted);
922 if (ret != LDB_SUCCESS) {
923 talloc_free(mem_ctx);
929 case LDB_FLAG_MOD_REPLACE:
930 /* Do the sorting for the change message element */
931 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
932 oc_el_change, &sorted);
933 if (ret != LDB_SUCCESS) {
934 talloc_free(mem_ctx);
938 /* this is a replace */
943 case LDB_FLAG_MOD_DELETE:
944 /* get the actual top-most structural objectclass */
945 objectclass = get_last_structural_class(ac->schema,
947 if (objectclass == NULL) {
948 talloc_free(mem_ctx);
949 return ldb_operr(ldb);
952 /* Merge the two message elements */
953 for (i = 0; i < oc_el_change->num_values; i++) {
955 for (j = 0; j < oc_el_entry->num_values; j++) {
956 if (strcasecmp((char *)oc_el_change->values[i].data,
957 (char *)oc_el_entry->values[j].data) == 0) {
959 /* delete the object class value -
960 * code was copied from
961 * "ldb_msg_remove_element" */
962 if (j != oc_el_entry->num_values - 1) {
963 memmove(&oc_el_entry->values[j],
964 &oc_el_entry->values[j+1],
965 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
967 --(oc_el_entry->num_values);
972 /* we cannot delete a not existing object class */
973 talloc_free(mem_ctx);
974 return LDB_ERR_NO_SUCH_ATTRIBUTE;
978 /* Make sure that the top-most structural objectclass wasn't
981 for (i = 0; i < oc_el_entry->num_values; i++) {
982 if (strcasecmp(objectclass->lDAPDisplayName,
983 (char *)oc_el_entry->values[i].data) == 0) {
988 talloc_free(mem_ctx);
989 return LDB_ERR_OBJECT_CLASS_VIOLATION;
993 /* Now do the sorting */
994 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
995 oc_el_entry, &sorted);
996 if (ret != LDB_SUCCESS) {
997 talloc_free(mem_ctx);
1004 ret = ldb_msg_add_empty(msg, "objectClass",
1005 LDB_FLAG_MOD_REPLACE, &oc_el_change);
1006 if (ret != LDB_SUCCESS) {
1008 talloc_free(mem_ctx);
1012 /* Move from the linked list back into an ldb msg */
1013 for (current = sorted; current; current = current->next) {
1014 value = talloc_strdup(msg,
1015 current->objectclass->lDAPDisplayName);
1016 if (value == NULL) {
1017 talloc_free(mem_ctx);
1018 return ldb_oom(ldb);
1020 ret = ldb_msg_add_string(msg, "objectClass", value);
1021 if (ret != LDB_SUCCESS) {
1022 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
1023 talloc_free(mem_ctx);
1028 talloc_free(mem_ctx);
1031 /* Well, on replace we are nearly done: we have to test if
1032 * the change and entry message element are identically. We
1033 * can use "ldb_msg_element_compare" since now the specified
1034 * objectclasses match for sure in case. */
1035 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
1037 ret = ldb_msg_element_compare(oc_el_change,
1041 /* they are the same so we are done in this case */
1042 return ldb_module_done(ac->req, NULL, NULL,
1045 /* they're not exactly the same */
1046 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1050 /* in the other cases we have the real change left to do */
1052 ret = ldb_msg_sanity_check(ldb, msg);
1053 if (ret != LDB_SUCCESS) {
1057 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1062 if (ret != LDB_SUCCESS) {
1066 return ldb_next_request(ac->module, mod_req);
1069 static int objectclass_do_rename(struct oc_context *ac);
1071 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1073 static const char * const attrs[] = { "objectClass", NULL };
1074 struct ldb_context *ldb;
1075 struct ldb_request *search_req;
1076 struct oc_context *ac;
1077 struct ldb_dn *parent_dn;
1080 ldb = ldb_module_get_ctx(module);
1082 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1084 /* do not manipulate our control entries */
1085 if (ldb_dn_is_special(req->op.rename.newdn)) {
1086 return ldb_next_request(module, req);
1089 ac = oc_init_context(module, req);
1091 return ldb_operr(ldb);
1094 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1095 if (parent_dn == NULL) {
1096 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1097 ldb_dn_get_linearized(req->op.rename.olddn));
1098 return LDB_ERR_NO_SUCH_OBJECT;
1101 /* this looks up the parent object for fetching some important
1102 * informations (objectclasses, DN normalisation...) */
1103 ret = ldb_build_search_req(&search_req, ldb,
1104 ac, parent_dn, LDB_SCOPE_BASE,
1107 ac, get_search_callback,
1109 if (ret != LDB_SUCCESS) {
1113 /* we have to add the show deleted control, as otherwise DRS
1114 deletes will be refused as we will think the target parent
1116 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1118 if (ret != LDB_SUCCESS) {
1122 ac->step_fn = objectclass_do_rename;
1124 return ldb_next_request(ac->module, search_req);
1127 static int objectclass_do_rename2(struct oc_context *ac);
1129 static int objectclass_do_rename(struct oc_context *ac)
1131 static const char * const attrs[] = { "objectClass", NULL };
1132 struct ldb_context *ldb;
1133 struct ldb_request *search_req;
1136 ldb = ldb_module_get_ctx(ac->module);
1138 /* Check if we have a valid parent - this check is needed since
1139 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1140 if (ac->search_res == NULL) {
1141 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1142 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1143 return LDB_ERR_OTHER;
1146 /* now assign "search_res2" to the parent entry to have "search_res"
1147 * free for another lookup */
1148 ac->search_res2 = ac->search_res;
1149 ac->search_res = NULL;
1151 /* this looks up the real existing object for fetching some important
1152 * informations (objectclasses) */
1153 ret = ldb_build_search_req(&search_req, ldb,
1154 ac, ac->req->op.rename.olddn,
1158 ac, get_search_callback,
1160 if (ret != LDB_SUCCESS) {
1164 ac->step_fn = objectclass_do_rename2;
1166 return ldb_next_request(ac->module, search_req);
1169 static int objectclass_do_rename2(struct oc_context *ac)
1171 struct ldb_context *ldb;
1172 struct ldb_request *rename_req;
1173 struct ldb_dn *fixed_dn;
1176 ldb = ldb_module_get_ctx(ac->module);
1178 /* Check if we have a valid entry - this check is needed since
1179 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1180 if (ac->search_res == NULL) {
1181 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1182 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1183 return LDB_ERR_NO_SUCH_OBJECT;
1186 if (ac->schema != NULL) {
1187 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1188 const struct dsdb_class *objectclass;
1189 const char *rdn_name;
1190 bool allowed_class = false;
1193 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1195 if (oc_el_entry == NULL) {
1196 /* existing entry without a valid object class? */
1197 return ldb_operr(ldb);
1199 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1200 if (objectclass == NULL) {
1201 /* existing entry without a valid object class? */
1202 return ldb_operr(ldb);
1205 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1206 if ((objectclass->rDNAttID != NULL) &&
1207 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1208 ldb_asprintf_errstring(ldb,
1209 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1211 objectclass->lDAPDisplayName,
1212 objectclass->rDNAttID);
1213 return LDB_ERR_UNWILLING_TO_PERFORM;
1216 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1218 if (oc_el_parent == NULL) {
1219 /* existing entry without a valid object class? */
1220 return ldb_operr(ldb);
1223 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1224 const struct dsdb_class *sclass;
1226 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1227 &oc_el_parent->values[i]);
1229 /* We don't know this class? what is going on? */
1232 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1233 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1234 allowed_class = true;
1240 if (!allowed_class) {
1241 ldb_asprintf_errstring(ldb,
1242 "objectclass: structural objectClass %s is not a valid child class for %s",
1243 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1244 return LDB_ERR_NAMING_VIOLATION;
1248 /* Ensure we are not trying to rename it to be a child of itself */
1249 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1250 ac->req->op.rename.newdn) == 0) &&
1251 (ldb_dn_compare(ac->req->op.rename.olddn,
1252 ac->req->op.rename.newdn) != 0)) {
1253 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1254 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1255 return LDB_ERR_UNWILLING_TO_PERFORM;
1258 /* Fix up the DN to be in the standard form, taking
1259 * particular care to match the parent DN */
1260 ret = fix_dn(ldb, ac,
1261 ac->req->op.rename.newdn,
1262 ac->search_res2->message->dn,
1264 if (ret != LDB_SUCCESS) {
1265 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1266 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1271 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1272 ac->req->op.rename.olddn, fixed_dn,
1276 if (ret != LDB_SUCCESS) {
1280 /* perform the rename */
1281 return ldb_next_request(ac->module, rename_req);
1284 static int objectclass_do_delete(struct oc_context *ac);
1286 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1288 static const char * const attrs[] = { "nCName", "objectClass",
1289 "systemFlags", NULL };
1290 struct ldb_context *ldb;
1291 struct ldb_request *search_req;
1292 struct oc_context *ac;
1295 ldb = ldb_module_get_ctx(module);
1297 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1299 /* do not manipulate our control entries */
1300 if (ldb_dn_is_special(req->op.del.dn)) {
1301 return ldb_next_request(module, req);
1304 /* Bypass the constraint checks when we do have the "RELAX" control
1306 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1307 return ldb_next_request(module, req);
1310 ac = oc_init_context(module, req);
1312 return ldb_operr(ldb);
1315 /* this looks up the entry object for fetching some important
1316 * informations (object classes, system flags...) */
1317 ret = ldb_build_search_req(&search_req, ldb,
1318 ac, req->op.del.dn, LDB_SCOPE_BASE,
1321 ac, get_search_callback,
1323 if (ret != LDB_SUCCESS) {
1327 ac->step_fn = objectclass_do_delete;
1329 return ldb_next_request(ac->module, search_req);
1332 static int objectclass_do_delete(struct oc_context *ac)
1334 struct ldb_context *ldb;
1336 int32_t systemFlags;
1339 ldb = ldb_module_get_ctx(ac->module);
1341 /* Check if we have a valid entry - this check is needed since
1342 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1343 if (ac->search_res == NULL) {
1344 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1345 ldb_dn_get_linearized(ac->req->op.del.dn));
1346 return LDB_ERR_NO_SUCH_OBJECT;
1349 /* DC's ntDSDSA object */
1350 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1351 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1352 ldb_dn_get_linearized(ac->req->op.del.dn));
1353 return LDB_ERR_UNWILLING_TO_PERFORM;
1356 /* DC's rIDSet object */
1357 ret = samdb_rid_set_dn(ldb, ac, &dn);
1358 if (ret != LDB_SUCCESS) {
1362 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1364 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1365 ldb_dn_get_linearized(ac->req->op.del.dn));
1366 return LDB_ERR_UNWILLING_TO_PERFORM;
1371 /* crossRef objects regarding config, schema and default domain NCs */
1372 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1373 "crossRef") != NULL) {
1374 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1376 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1377 (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0) ||
1378 (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0)) {
1381 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the three main partitions!",
1382 ldb_dn_get_linearized(ac->req->op.del.dn));
1383 return LDB_ERR_UNWILLING_TO_PERFORM;
1390 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1392 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1393 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1394 ldb_dn_get_linearized(ac->req->op.del.dn));
1395 return LDB_ERR_UNWILLING_TO_PERFORM;
1398 return ldb_next_request(ac->module, ac->req);
1401 static int objectclass_init(struct ldb_module *module)
1403 struct ldb_context *ldb = ldb_module_get_ctx(module);
1406 /* Init everything else */
1407 ret = ldb_next_init(module);
1408 if (ret != LDB_SUCCESS) {
1412 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1413 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1418 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1419 .name = "objectclass",
1420 .add = objectclass_add,
1421 .modify = objectclass_modify,
1422 .rename = objectclass_rename,
1423 .del = objectclass_delete,
1424 .init_context = objectclass_init