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 "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;
55 struct ldb_reply *search_res;
56 struct ldb_reply *search_res2;
58 int (*step_fn)(struct oc_context *);
62 struct class_list *prev, *next;
63 const struct dsdb_class *objectclass;
66 static struct oc_context *oc_init_context(struct ldb_module *module,
67 struct ldb_request *req)
69 struct ldb_context *ldb;
70 struct oc_context *ac;
72 ldb = ldb_module_get_ctx(module);
74 ac = talloc_zero(req, struct oc_context);
86 static int objectclass_do_add(struct oc_context *ac);
88 /* Sort objectClasses into correct order, and validate that all
89 * objectClasses specified actually exist in the schema
92 static int objectclass_sort(struct ldb_module *module,
93 const struct dsdb_schema *schema,
95 struct ldb_message_element *objectclass_element,
96 struct class_list **sorted_out)
98 struct ldb_context *ldb;
99 unsigned int i, lowest;
100 struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL, *poss_parent = NULL, *new_parent = NULL, *current_lowest = NULL;
102 ldb = ldb_module_get_ctx(module);
106 * We work on 4 different 'bins' (implemented here as linked lists):
108 * * sorted: the eventual list, in the order we wish to push
109 * into the database. This is the only ordered list.
111 * * parent_class: The current parent class 'bin' we are
112 * trying to find subclasses for
114 * * subclass: The subclasses we have found so far
116 * * unsorted: The remaining objectClasses
118 * The process is a matter of filtering objectClasses up from
119 * unsorted into sorted. Order is irrelevent in the later 3 'bins'.
121 * We start with 'top' (found and promoted to parent_class
122 * initially). Then we find (in unsorted) all the direct
123 * subclasses of 'top'. parent_classes is concatenated onto
124 * the end of 'sorted', and subclass becomes the list in
127 * We then repeat, until we find no more subclasses. Any left
128 * over classes are added to the end.
132 /* Firstly, dump all the objectClass elements into the
133 * unsorted bin, except for 'top', which is special */
134 for (i=0; i < objectclass_element->num_values; i++) {
135 current = talloc(mem_ctx, struct class_list);
138 return LDB_ERR_OPERATIONS_ERROR;
140 current->objectclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &objectclass_element->values[i]);
141 if (!current->objectclass) {
142 ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema",
143 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
144 /* This looks weird, but windows apparently returns this for invalid objectClass values */
145 return LDB_ERR_NO_SUCH_ATTRIBUTE;
146 } else if (current->objectclass->isDefunct) {
147 ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects",
148 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
149 /* This looks weird, but windows apparently returns this for invalid objectClass values */
150 return LDB_ERR_NO_SUCH_ATTRIBUTE;
153 /* Don't add top to list, we will do that later */
154 if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) != 0) {
155 DLIST_ADD_END(unsorted, current, struct class_list *);
159 /* Add top here, to prevent duplicates */
160 current = talloc(mem_ctx, struct class_list);
161 current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
162 DLIST_ADD_END(sorted, current, struct class_list *);
165 /* For each object: find parent chain */
166 for (current = unsorted; schema && current; current = current->next) {
167 for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) {
168 if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) {
172 /* If we didn't get to the end of the list, we need to add this parent */
173 if (poss_parent || (ldb_attr_cmp("top", current->objectclass->subClassOf) == 0)) {
177 new_parent = talloc(mem_ctx, struct class_list);
178 new_parent->objectclass = dsdb_class_by_lDAPDisplayName(schema, current->objectclass->subClassOf);
179 DLIST_ADD_END(unsorted, new_parent, struct class_list *);
185 current_lowest = NULL;
186 for (current = unsorted; schema && current; current = current->next) {
187 if(current->objectclass->subClass_order < lowest) {
188 current_lowest = current;
189 lowest = current->objectclass->subClass_order;
193 if(current_lowest != NULL) {
194 DLIST_REMOVE(unsorted,current_lowest);
195 DLIST_ADD_END(sorted,current_lowest, struct class_list *);
201 *sorted_out = sorted;
206 /* If we don't have schema yet, then just merge the lists again */
207 DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
208 *sorted_out = sorted;
212 /* This shouldn't happen, and would break MMC, perhaps there
213 * was no 'top', a conflict in the objectClasses or some other
216 ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName);
217 return LDB_ERR_OBJECT_CLASS_VIOLATION;
220 static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares)
222 struct ldb_context *ldb;
223 struct oc_context *ac;
226 ac = talloc_get_type(req->context, struct oc_context);
227 ldb = ldb_module_get_ctx(ac->module);
230 return ldb_module_done(ac->req, NULL, NULL,
231 LDB_ERR_OPERATIONS_ERROR);
233 if (ares->error != LDB_SUCCESS &&
234 ares->error != LDB_ERR_NO_SUCH_OBJECT) {
235 return ldb_module_done(ac->req, ares->controls,
236 ares->response, ares->error);
239 ldb_reset_err_string(ldb);
241 switch (ares->type) {
242 case LDB_REPLY_ENTRY:
243 if (ac->search_res != NULL) {
244 ldb_set_errstring(ldb, "Too many results");
246 return ldb_module_done(ac->req, NULL, NULL,
247 LDB_ERR_OPERATIONS_ERROR);
250 ac->search_res = talloc_steal(ac, ares);
253 case LDB_REPLY_REFERRAL:
260 ret = ac->step_fn(ac);
261 if (ret != LDB_SUCCESS) {
262 return ldb_module_done(ac->req, NULL, NULL, ret);
270 static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)
272 struct oc_context *ac;
274 ac = talloc_get_type(req->context, struct oc_context);
277 return ldb_module_done(ac->req, NULL, NULL,
278 LDB_ERR_OPERATIONS_ERROR);
281 if (ares->type == LDB_REPLY_REFERRAL) {
282 return ldb_module_send_referral(ac->req, ares->referral);
285 if (ares->error != LDB_SUCCESS) {
286 return ldb_module_done(ac->req, ares->controls,
287 ares->response, ares->error);
290 if (ares->type != LDB_REPLY_DONE) {
292 return ldb_module_done(ac->req, NULL, NULL,
293 LDB_ERR_OPERATIONS_ERROR);
296 return ldb_module_done(ac->req, ares->controls,
297 ares->response, ares->error);
300 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN
302 This should mean that if the parent is:
303 CN=Users,DC=samba,DC=example,DC=com
304 and a proposed child is
305 cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM
307 The resulting DN should be:
309 CN=Admins,CN=Users,DC=samba,DC=example,DC=com
312 static int fix_dn(TALLOC_CTX *mem_ctx,
313 struct ldb_dn *newdn, struct ldb_dn *parent_dn,
314 struct ldb_dn **fixed_dn)
316 char *upper_rdn_attr;
317 const struct ldb_val *rdn_val;
319 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
320 *fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
322 /* We need the attribute name in upper case */
323 upper_rdn_attr = strupper_talloc(*fixed_dn,
324 ldb_dn_get_rdn_name(newdn));
325 if (!upper_rdn_attr) {
326 return LDB_ERR_OPERATIONS_ERROR;
329 /* Create a new child */
330 if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
331 return LDB_ERR_OPERATIONS_ERROR;
335 rdn_val = ldb_dn_get_rdn_val(newdn);
338 /* the rules for rDN length constraints are more complex than
339 this. Until we understand them we need to leave this
340 constraint out. Otherwise we break replication, as windows
341 does sometimes send us rDNs longer than 64 */
342 if (!rdn_val || rdn_val->length > 64) {
343 DEBUG(2,(__location__ ": WARNING: rDN longer than 64 limit for '%s'\n", ldb_dn_get_linearized(newdn)));
348 /* And replace it with CN=foo (we need the attribute in upper case */
349 return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
352 /* Fix all attribute names to be in the correct case, and check they are all valid per the schema */
353 static int fix_check_attributes(struct ldb_context *ldb,
354 const struct dsdb_schema *schema,
355 struct ldb_message *msg,
356 enum ldb_request_type op)
359 for (i=0; i < msg->num_elements; i++) {
360 const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(schema, msg->elements[i].name);
361 /* Add in a very special case for 'clearTextPassword',
362 * which is used for internal processing only, and is
363 * not presented in the schema */
365 if (strcasecmp(msg->elements[i].name, "clearTextPassword") != 0) {
366 ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
367 /* Apparently Windows sends exactly this behaviour */
368 return LDB_ERR_NO_SUCH_ATTRIBUTE;
371 msg->elements[i].name = attribute->lDAPDisplayName;
373 /* We have to deny write operations on constructed attributes */
374 if ((attribute->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED) != 0) {
375 ldb_asprintf_errstring(ldb, "attribute %s is constructed", msg->elements[i].name);
377 return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
379 return LDB_ERR_CONSTRAINT_VIOLATION;
389 static int objectclass_do_add(struct oc_context *ac);
391 static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
393 struct ldb_context *ldb;
394 struct ldb_request *search_req;
395 struct oc_context *ac;
396 struct ldb_dn *parent_dn;
398 static const char * const parent_attrs[] = { "objectGUID", "objectClass", NULL };
400 ldb = ldb_module_get_ctx(module);
402 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
404 /* do not manipulate our control entries */
405 if (ldb_dn_is_special(req->op.add.message->dn)) {
406 return ldb_next_request(module, req);
409 /* the objectClass must be specified on add */
410 if (ldb_msg_find_element(req->op.add.message,
411 "objectClass") == NULL) {
412 return LDB_ERR_OBJECT_CLASS_VIOLATION;
415 ac = oc_init_context(module, req);
417 return LDB_ERR_OPERATIONS_ERROR;
420 /* If there isn't a parent, just go on to the add processing */
421 if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
422 return objectclass_do_add(ac);
425 /* get copy of parent DN */
426 parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
427 if (parent_dn == NULL) {
429 return LDB_ERR_OPERATIONS_ERROR;
432 ret = ldb_build_search_req(&search_req, ldb,
433 ac, parent_dn, LDB_SCOPE_BASE,
434 "(objectClass=*)", parent_attrs,
436 ac, get_search_callback,
438 if (ret != LDB_SUCCESS) {
442 ac->step_fn = objectclass_do_add;
444 return ldb_next_request(ac->module, search_req);
447 static int objectclass_do_add(struct oc_context *ac)
449 struct ldb_context *ldb;
450 const struct dsdb_schema *schema;
451 struct ldb_request *add_req;
453 struct ldb_message_element *objectclass_element, *el;
454 struct ldb_message *msg;
456 struct class_list *sorted, *current;
458 const struct dsdb_class *objectclass;
459 int32_t systemFlags = 0;
460 const char *rdn_name = NULL;
462 ldb = ldb_module_get_ctx(ac->module);
463 schema = dsdb_get_schema(ldb, ac);
465 mem_ctx = talloc_new(ac);
466 if (mem_ctx == NULL) {
468 return LDB_ERR_OPERATIONS_ERROR;
471 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
473 /* Check if we have a valid parent - this check is needed since
474 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
475 if (ac->search_res == NULL) {
476 if (ldb_dn_compare(ldb_get_root_basedn(ldb), msg->dn) == 0) {
477 /* Allow the tree to be started */
479 /* but don't keep any error string, it's meaningless */
480 ldb_set_errstring(ldb, NULL);
482 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
483 ldb_dn_get_linearized(msg->dn));
484 talloc_free(mem_ctx);
485 return LDB_ERR_NO_SUCH_OBJECT;
489 /* Fix up the DN to be in the standard form, taking
490 * particular care to match the parent DN */
492 ac->req->op.add.message->dn,
493 ac->search_res->message->dn,
496 if (ret != LDB_SUCCESS) {
497 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
498 ldb_dn_get_linearized(ac->req->op.add.message->dn));
499 talloc_free(mem_ctx);
505 ret = fix_check_attributes(ldb, schema, msg, ac->req->operation);
506 if (ret != LDB_SUCCESS) {
507 talloc_free(mem_ctx);
511 /* This is now the objectClass list from the database */
512 objectclass_element = ldb_msg_find_element(msg, "objectClass");
514 if (!objectclass_element) {
515 /* Where did it go? bail now... */
516 talloc_free(mem_ctx);
517 return LDB_ERR_OPERATIONS_ERROR;
519 ret = objectclass_sort(ac->module, schema, mem_ctx, objectclass_element, &sorted);
520 if (ret != LDB_SUCCESS) {
521 talloc_free(mem_ctx);
525 ldb_msg_remove_attr(msg, "objectClass");
526 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
528 if (ret != LDB_SUCCESS) {
529 talloc_free(mem_ctx);
533 /* We must completely replace the existing objectClass entry,
534 * because we need it sorted */
536 /* Move from the linked list back into an ldb msg */
537 for (current = sorted; current; current = current->next) {
538 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
541 talloc_free(mem_ctx);
542 return LDB_ERR_OPERATIONS_ERROR;
544 ret = ldb_msg_add_string(msg, "objectClass", value);
545 if (ret != LDB_SUCCESS) {
546 ldb_set_errstring(ldb,
547 "objectclass: could not re-add sorted "
548 "objectclass to modify msg");
549 talloc_free(mem_ctx);
554 /* Retrive the message again so get_last_structural_class works */
555 objectclass_element = ldb_msg_find_element(msg, "objectClass");
557 /* Make sure its valid to add an object of this type */
558 objectclass = get_last_structural_class(schema,objectclass_element);
559 if(objectclass == NULL) {
560 ldb_asprintf_errstring(ldb,
561 "Failed to find a structural class for %s",
562 ldb_dn_get_linearized(msg->dn));
563 return LDB_ERR_UNWILLING_TO_PERFORM;
566 rdn_name = ldb_dn_get_rdn_name(msg->dn);
567 if (objectclass->rDNAttID
568 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
569 ldb_asprintf_errstring(ldb,
570 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
571 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
572 return LDB_ERR_NAMING_VIOLATION;
575 if (ac->search_res && ac->search_res->message) {
576 struct ldb_message_element *oc_el
577 = ldb_msg_find_element(ac->search_res->message, "objectClass");
579 bool allowed_class = false;
581 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
582 const struct dsdb_class *sclass;
584 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
586 /* We don't know this class? what is going on? */
589 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
590 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
591 allowed_class = true;
597 if (!allowed_class) {
598 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
599 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
600 return LDB_ERR_NAMING_VIOLATION;
604 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
605 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
606 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
607 return LDB_ERR_UNWILLING_TO_PERFORM;
610 if (!ldb_msg_find_element(msg, "objectCategory")) {
611 struct dsdb_extended_dn_store_format *dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct dsdb_extended_dn_store_format);
612 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
613 /* Strip off extended components */
614 struct ldb_dn *dn = ldb_dn_new(msg, ldb, objectclass->defaultObjectCategory);
615 value = ldb_dn_alloc_linearized(msg, dn);
618 value = talloc_strdup(msg, objectclass->defaultObjectCategory);
622 talloc_free(mem_ctx);
623 return LDB_ERR_OPERATIONS_ERROR;
625 ldb_msg_add_string(msg, "objectCategory", value);
627 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
628 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
632 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
633 el = ldb_msg_find_element(msg, "systemFlags");
635 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
638 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
639 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
640 ldb_msg_remove_element(msg, el);
643 /* This flag is only allowed on attributeSchema objects */
644 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
645 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
648 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
649 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
650 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
651 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
652 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
653 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
655 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
656 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
657 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
658 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
661 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
663 if (el || systemFlags != 0) {
664 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
668 talloc_free(mem_ctx);
669 ret = ldb_msg_sanity_check(ldb, msg);
672 if (ret != LDB_SUCCESS) {
676 ret = ldb_build_add_req(&add_req, ldb, ac,
681 if (ret != LDB_SUCCESS) {
685 /* perform the add */
686 return ldb_next_request(ac->module, add_req);
689 static int oc_modify_callback(struct ldb_request *req,
690 struct ldb_reply *ares);
691 static int objectclass_do_mod(struct oc_context *ac);
693 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
695 struct ldb_context *ldb = ldb_module_get_ctx(module);
696 struct ldb_message_element *objectclass_element;
697 struct ldb_message *msg;
698 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
699 struct class_list *sorted, *current;
700 struct ldb_request *down_req;
701 struct oc_context *ac;
706 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
708 /* do not manipulate our control entries */
709 if (ldb_dn_is_special(req->op.mod.message->dn)) {
710 return ldb_next_request(module, req);
713 /* Without schema, there isn't much to do here */
715 return ldb_next_request(module, req);
718 /* As with the "real" AD we don't accept empty messages */
719 if (req->op.mod.message->num_elements == 0) {
720 ldb_set_errstring(ldb, "objectclass: modify message must have "
721 "elements/attributes!");
722 return LDB_ERR_UNWILLING_TO_PERFORM;
725 ac = oc_init_context(module, req);
727 return LDB_ERR_OPERATIONS_ERROR;
730 if (!talloc_reference(ac, schema)) {
732 return LDB_ERR_OPERATIONS_ERROR;
735 /* If no part of this touches the objectClass, then we don't
736 * need to make any changes. */
737 objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
739 /* If the only operation is the deletion of the objectClass
740 * then go on with just fixing the attribute case */
741 if (!objectclass_element) {
742 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
744 return LDB_ERR_OPERATIONS_ERROR;
747 ret = fix_check_attributes(ldb, schema, msg, req->operation);
748 if (ret != LDB_SUCCESS) {
752 ret = ldb_build_mod_req(&down_req, ldb, ac,
757 if (ret != LDB_SUCCESS) {
761 /* go on with the call chain */
762 return ldb_next_request(module, down_req);
765 switch (objectclass_element->flags & LDB_FLAG_MOD_MASK) {
766 case LDB_FLAG_MOD_DELETE:
767 if (objectclass_element->num_values == 0) {
768 return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
772 case LDB_FLAG_MOD_REPLACE:
773 mem_ctx = talloc_new(ac);
774 if (mem_ctx == NULL) {
775 return LDB_ERR_OPERATIONS_ERROR;
778 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
780 talloc_free(mem_ctx);
781 return LDB_ERR_OPERATIONS_ERROR;
784 ret = fix_check_attributes(ldb, schema, msg, req->operation);
785 if (ret != LDB_SUCCESS) {
786 talloc_free(mem_ctx);
790 ret = objectclass_sort(module, schema, mem_ctx, objectclass_element, &sorted);
791 if (ret != LDB_SUCCESS) {
792 talloc_free(mem_ctx);
796 /* We must completely replace the existing objectClass entry,
797 * because we need it sorted */
799 ldb_msg_remove_attr(msg, "objectClass");
800 ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
802 if (ret != LDB_SUCCESS) {
803 talloc_free(mem_ctx);
807 /* Move from the linked list back into an ldb msg */
808 for (current = sorted; current; current = current->next) {
809 /* copy the value as this string is on the schema
810 * context and we can't rely on it not changing
811 * before the operation is over */
812 value = talloc_strdup(msg,
813 current->objectclass->lDAPDisplayName);
816 talloc_free(mem_ctx);
817 return LDB_ERR_OPERATIONS_ERROR;
819 ret = ldb_msg_add_string(msg, "objectClass", value);
820 if (ret != LDB_SUCCESS) {
821 ldb_set_errstring(ldb,
822 "objectclass: could not re-add sorted "
823 "objectclass to modify msg");
824 talloc_free(mem_ctx);
829 talloc_free(mem_ctx);
831 ret = ldb_msg_sanity_check(ldb, msg);
832 if (ret != LDB_SUCCESS) {
836 ret = ldb_build_mod_req(&down_req, ldb, ac,
841 if (ret != LDB_SUCCESS) {
845 /* go on with the call chain */
846 return ldb_next_request(module, down_req);
849 /* This isn't the default branch of the switch, but a 'in any
850 * other case'. When a delete isn't for all objectClasses for
854 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
857 return LDB_ERR_OPERATIONS_ERROR;
860 ret = fix_check_attributes(ldb, schema, msg, req->operation);
861 if (ret != LDB_SUCCESS) {
866 ret = ldb_build_mod_req(&down_req, ldb, ac,
869 ac, oc_modify_callback,
871 if (ret != LDB_SUCCESS) {
875 return ldb_next_request(module, down_req);
878 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
880 struct ldb_context *ldb;
881 static const char * const attrs[] = { "objectClass", NULL };
882 struct ldb_request *search_req;
883 struct oc_context *ac;
886 ac = talloc_get_type(req->context, struct oc_context);
887 ldb = ldb_module_get_ctx(ac->module);
890 return ldb_module_done(ac->req, NULL, NULL,
891 LDB_ERR_OPERATIONS_ERROR);
894 if (ares->type == LDB_REPLY_REFERRAL) {
895 return ldb_module_send_referral(ac->req, ares->referral);
898 if (ares->error != LDB_SUCCESS) {
899 return ldb_module_done(ac->req, ares->controls,
900 ares->response, ares->error);
903 if (ares->type != LDB_REPLY_DONE) {
905 return ldb_module_done(ac->req, NULL, NULL,
906 LDB_ERR_OPERATIONS_ERROR);
911 ret = ldb_build_search_req(&search_req, ldb, ac,
912 ac->req->op.mod.message->dn, LDB_SCOPE_BASE,
915 ac, get_search_callback,
917 if (ret != LDB_SUCCESS) {
918 return ldb_module_done(ac->req, NULL, NULL, ret);
921 ac->step_fn = objectclass_do_mod;
923 ret = ldb_next_request(ac->module, search_req);
924 if (ret != LDB_SUCCESS) {
925 return ldb_module_done(ac->req, NULL, NULL, ret);
930 static int objectclass_do_mod(struct oc_context *ac)
932 struct ldb_context *ldb;
933 const struct dsdb_schema *schema;
934 struct ldb_request *mod_req;
936 struct ldb_message_element *objectclass_element;
937 struct ldb_message *msg;
939 struct class_list *sorted, *current;
942 ldb = ldb_module_get_ctx(ac->module);
944 if (ac->search_res == NULL) {
945 return LDB_ERR_OPERATIONS_ERROR;
947 schema = dsdb_get_schema(ldb, ac);
949 mem_ctx = talloc_new(ac);
950 if (mem_ctx == NULL) {
951 return LDB_ERR_OPERATIONS_ERROR;
954 /* use a new message structure */
955 msg = ldb_msg_new(ac);
957 ldb_set_errstring(ldb,
958 "objectclass: could not create new modify msg");
959 talloc_free(mem_ctx);
960 return LDB_ERR_OPERATIONS_ERROR;
963 /* This is now the objectClass list from the database */
964 objectclass_element = ldb_msg_find_element(ac->search_res->message,
966 if (!objectclass_element) {
967 /* Where did it go? bail now... */
968 talloc_free(mem_ctx);
969 return LDB_ERR_OPERATIONS_ERROR;
973 msg->dn = ac->req->op.mod.message->dn;
975 ret = objectclass_sort(ac->module, schema, mem_ctx, objectclass_element, &sorted);
976 if (ret != LDB_SUCCESS) {
980 /* We must completely replace the existing objectClass entry.
981 * We could do a constrained add/del, but we are meant to be
982 * in a transaction... */
984 ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
985 if (ret != LDB_SUCCESS) {
986 ldb_set_errstring(ldb, "objectclass: could not clear objectclass in modify msg");
987 talloc_free(mem_ctx);
991 /* Move from the linked list back into an ldb msg */
992 for (current = sorted; current; current = current->next) {
993 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
996 return LDB_ERR_OPERATIONS_ERROR;
998 ret = ldb_msg_add_string(msg, "objectClass", value);
999 if (ret != LDB_SUCCESS) {
1000 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
1001 talloc_free(mem_ctx);
1006 ret = ldb_msg_sanity_check(ldb, msg);
1007 if (ret != LDB_SUCCESS) {
1008 talloc_free(mem_ctx);
1012 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1017 if (ret != LDB_SUCCESS) {
1018 talloc_free(mem_ctx);
1022 talloc_free(mem_ctx);
1023 /* perform the modify */
1024 return ldb_next_request(ac->module, mod_req);
1027 static int objectclass_do_rename(struct oc_context *ac);
1029 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1031 static const char * const attrs[] = { "objectClass", NULL };
1032 struct ldb_context *ldb;
1033 struct ldb_request *search_req;
1034 struct oc_context *ac;
1035 struct ldb_dn *parent_dn;
1038 ldb = ldb_module_get_ctx(module);
1040 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1042 /* do not manipulate our control entries */
1043 if (ldb_dn_is_special(req->op.rename.newdn)) {
1044 return ldb_next_request(module, req);
1047 ac = oc_init_context(module, req);
1049 return LDB_ERR_OPERATIONS_ERROR;
1052 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1053 if (parent_dn == NULL) {
1055 return LDB_ERR_OPERATIONS_ERROR;
1058 /* this looks up the parent object for fetching some important
1059 * informations (objectclasses, DN normalisation...) */
1060 ret = ldb_build_search_req(&search_req, ldb,
1061 ac, parent_dn, LDB_SCOPE_BASE,
1064 ac, get_search_callback,
1066 if (ret != LDB_SUCCESS) {
1070 /* we have to add the show deleted control, as otherwise DRS
1071 deletes will be refused as we will think the target parent
1073 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1075 if (ret != LDB_SUCCESS) {
1079 ac->step_fn = objectclass_do_rename;
1081 return ldb_next_request(ac->module, search_req);
1084 static int objectclass_do_rename2(struct oc_context *ac);
1086 static int objectclass_do_rename(struct oc_context *ac)
1088 static const char * const attrs[] = { "objectClass", NULL };
1089 struct ldb_context *ldb;
1090 struct ldb_request *search_req;
1093 ldb = ldb_module_get_ctx(ac->module);
1095 /* Check if we have a valid parent - this check is needed since
1096 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1097 if (ac->search_res == NULL) {
1098 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1099 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1100 return LDB_ERR_OTHER;
1103 /* now assign "search_res2" to the parent entry to have "search_res"
1104 * free for another lookup */
1105 ac->search_res2 = ac->search_res;
1106 ac->search_res = NULL;
1108 /* this looks up the real existing object for fetching some important
1109 * informations (objectclasses) */
1110 ret = ldb_build_search_req(&search_req, ldb,
1111 ac, ac->req->op.rename.olddn,
1115 ac, get_search_callback,
1117 if (ret != LDB_SUCCESS) {
1121 ac->step_fn = objectclass_do_rename2;
1123 return ldb_next_request(ac->module, search_req);
1126 static int objectclass_do_rename2(struct oc_context *ac)
1128 struct ldb_context *ldb;
1129 const struct dsdb_schema *schema;
1130 struct ldb_request *rename_req;
1131 struct ldb_dn *fixed_dn;
1134 ldb = ldb_module_get_ctx(ac->module);
1136 /* Check if we have a valid entry - this check is needed since
1137 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1138 if (ac->search_res == NULL) {
1139 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1140 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1141 return LDB_ERR_NO_SUCH_OBJECT;
1144 schema = dsdb_get_schema(ldb, ac);
1146 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1147 const struct dsdb_class *objectclass;
1148 const char *rdn_name;
1149 bool allowed_class = false;
1152 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1154 if (oc_el_entry == NULL) {
1155 /* existing entry without a valid object class? */
1156 return LDB_ERR_OPERATIONS_ERROR;
1158 objectclass = get_last_structural_class(schema, oc_el_entry);
1159 if (objectclass == NULL) {
1160 /* existing entry without a valid object class? */
1161 return LDB_ERR_OPERATIONS_ERROR;
1164 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1165 if ((objectclass->rDNAttID != NULL) &&
1166 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1167 ldb_asprintf_errstring(ldb,
1168 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1170 objectclass->lDAPDisplayName,
1171 objectclass->rDNAttID);
1172 return LDB_ERR_UNWILLING_TO_PERFORM;
1175 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1177 if (oc_el_parent == NULL) {
1178 /* existing entry without a valid object class? */
1179 return LDB_ERR_OPERATIONS_ERROR;
1182 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1183 const struct dsdb_class *sclass;
1185 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el_parent->values[i]);
1187 /* We don't know this class? what is going on? */
1190 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1191 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1192 allowed_class = true;
1198 if (!allowed_class) {
1199 ldb_asprintf_errstring(ldb,
1200 "objectclass: structural objectClass %s is not a valid child class for %s",
1201 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1202 return LDB_ERR_NAMING_VIOLATION;
1206 /* Ensure we are not trying to rename it to be a child of itself */
1207 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1208 ac->req->op.rename.newdn) == 0) &&
1209 (ldb_dn_compare(ac->req->op.rename.olddn,
1210 ac->req->op.rename.newdn) != 0)) {
1211 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1212 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1213 return LDB_ERR_UNWILLING_TO_PERFORM;
1216 /* Fix up the DN to be in the standard form, taking
1217 * particular care to match the parent DN */
1219 ac->req->op.rename.newdn,
1220 ac->search_res2->message->dn,
1222 if (ret != LDB_SUCCESS) {
1223 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1224 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1229 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1230 ac->req->op.rename.olddn, fixed_dn,
1234 if (ret != LDB_SUCCESS) {
1238 /* perform the rename */
1239 return ldb_next_request(ac->module, rename_req);
1242 static int objectclass_init(struct ldb_module *module)
1244 struct ldb_context *ldb = ldb_module_get_ctx(module);
1246 /* Init everything else */
1247 ret = ldb_next_init(module);
1248 if (ret != LDB_SUCCESS) {
1252 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1253 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1258 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1259 .name = "objectclass",
1260 .add = objectclass_add,
1261 .modify = objectclass_modify,
1262 .rename = objectclass_rename,
1263 .init_context = objectclass_init