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 /* the various objectclasses must be specified on add operations */
405 if (ldb_msg_find_element(req->op.add.message, "objectClass") == NULL) {
406 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
407 ldb_dn_get_linearized(req->op.add.message->dn));
408 return LDB_ERR_OBJECT_CLASS_VIOLATION;
411 ac = oc_init_context(module, req);
413 return ldb_operr(ldb);
416 /* If there isn't a parent, just go on to the add processing */
417 if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
418 return objectclass_do_add(ac);
421 /* get copy of parent DN */
422 parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
423 if (parent_dn == NULL) {
427 ret = ldb_build_search_req(&search_req, ldb,
428 ac, parent_dn, LDB_SCOPE_BASE,
429 "(objectClass=*)", parent_attrs,
431 ac, get_search_callback,
433 if (ret != LDB_SUCCESS) {
437 ac->step_fn = objectclass_do_add;
439 return ldb_next_request(ac->module, search_req);
442 static int objectclass_do_add(struct oc_context *ac)
444 struct ldb_context *ldb;
445 struct ldb_request *add_req;
446 struct ldb_message_element *objectclass_element, *el;
447 struct ldb_message *msg;
449 struct class_list *sorted, *current;
450 const char *rdn_name = NULL;
452 const struct dsdb_class *objectclass;
453 int32_t systemFlags = 0;
456 ldb = ldb_module_get_ctx(ac->module);
458 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
460 /* Check if we have a valid parent - this check is needed since
461 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
462 if (ac->search_res == NULL) {
463 unsigned int instanceType;
465 /* An add operation on partition DNs without "NC-add" operation
467 instanceType = ldb_msg_find_attr_as_uint(ac->req->op.add.message,
469 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
470 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
471 ldb_dn_get_linearized(msg->dn));
472 return LDB_ERR_NO_SUCH_OBJECT;
475 /* Don't keep any error messages - we've to add a partition */
476 ldb_set_errstring(ldb, NULL);
478 /* Fix up the DN to be in the standard form, taking
479 * particular care to match the parent DN */
480 ret = fix_dn(ldb, msg,
481 ac->req->op.add.message->dn,
482 ac->search_res->message->dn,
484 if (ret != LDB_SUCCESS) {
485 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
486 ldb_dn_get_linearized(ac->req->op.add.message->dn));
491 mem_ctx = talloc_new(ac);
492 if (mem_ctx == NULL) {
496 if (ac->schema != NULL) {
497 /* This is now the objectClass list from the database */
498 objectclass_element = ldb_msg_find_element(msg, "objectClass");
500 if (!objectclass_element) {
501 /* Where did it go? bail now... */
502 talloc_free(mem_ctx);
503 return ldb_operr(ldb);
505 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
506 objectclass_element, &sorted);
507 if (ret != LDB_SUCCESS) {
508 talloc_free(mem_ctx);
512 ldb_msg_remove_attr(msg, "objectClass");
513 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
515 if (ret != LDB_SUCCESS) {
516 talloc_free(mem_ctx);
520 /* We must completely replace the existing objectClass entry,
521 * because we need it sorted */
523 /* Move from the linked list back into an ldb msg */
524 for (current = sorted; current; current = current->next) {
525 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
527 talloc_free(mem_ctx);
530 ret = ldb_msg_add_string(msg, "objectClass", value);
531 if (ret != LDB_SUCCESS) {
532 ldb_set_errstring(ldb,
533 "objectclass: could not re-add sorted "
534 "objectclass to modify msg");
535 talloc_free(mem_ctx);
540 talloc_free(mem_ctx);
542 /* Retrive the message again so get_last_structural_class works */
543 objectclass_element = ldb_msg_find_element(msg, "objectClass");
545 /* Make sure its valid to add an object of this type */
546 objectclass = get_last_structural_class(ac->schema,
547 objectclass_element);
548 if(objectclass == NULL) {
549 ldb_asprintf_errstring(ldb,
550 "Failed to find a structural class for %s",
551 ldb_dn_get_linearized(msg->dn));
552 return LDB_ERR_UNWILLING_TO_PERFORM;
555 rdn_name = ldb_dn_get_rdn_name(msg->dn);
556 if (objectclass->rDNAttID
557 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
558 ldb_asprintf_errstring(ldb,
559 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
560 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
561 return LDB_ERR_NAMING_VIOLATION;
564 if (ac->search_res && ac->search_res->message) {
565 struct ldb_message_element *oc_el
566 = ldb_msg_find_element(ac->search_res->message, "objectClass");
568 bool allowed_class = false;
570 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
571 const struct dsdb_class *sclass;
573 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
576 /* We don't know this class? what is going on? */
579 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
580 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
581 allowed_class = true;
587 if (!allowed_class) {
588 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
589 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
590 return LDB_ERR_NAMING_VIOLATION;
594 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
595 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
596 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
597 return LDB_ERR_UNWILLING_TO_PERFORM;
600 if (!ldb_msg_find_element(msg, "objectCategory")) {
601 struct dsdb_extended_dn_store_format *dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct dsdb_extended_dn_store_format);
602 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
603 /* Strip off extended components */
604 struct ldb_dn *dn = ldb_dn_new(msg, ldb, objectclass->defaultObjectCategory);
605 value = ldb_dn_alloc_linearized(msg, dn);
608 value = talloc_strdup(msg, objectclass->defaultObjectCategory);
613 ldb_msg_add_string(msg, "objectCategory", value);
615 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
616 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
620 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
621 el = ldb_msg_find_element(msg, "systemFlags");
623 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
626 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
627 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
628 ldb_msg_remove_element(msg, el);
631 /* This flag is only allowed on attributeSchema objects */
632 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
633 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
636 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
637 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
638 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
639 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
640 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
641 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
643 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
644 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
645 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
646 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
649 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
651 if (el || systemFlags != 0) {
652 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
655 ret = ldb_msg_sanity_check(ldb, msg);
657 if (ret != LDB_SUCCESS) {
661 ret = ldb_build_add_req(&add_req, ldb, ac,
666 if (ret != LDB_SUCCESS) {
670 /* perform the add */
671 return ldb_next_request(ac->module, add_req);
674 static int oc_modify_callback(struct ldb_request *req,
675 struct ldb_reply *ares);
676 static int objectclass_do_mod(struct oc_context *ac);
678 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
680 struct ldb_context *ldb = ldb_module_get_ctx(module);
681 struct ldb_message_element *objectclass_element;
682 struct ldb_message *msg;
683 struct ldb_request *down_req;
684 struct oc_context *ac;
685 bool oc_changes = false;
688 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
690 /* do not manipulate our control entries */
691 if (ldb_dn_is_special(req->op.mod.message->dn)) {
692 return ldb_next_request(module, req);
695 /* As with the "real" AD we don't accept empty messages */
696 if (req->op.mod.message->num_elements == 0) {
697 ldb_set_errstring(ldb, "objectclass: modify message must have "
698 "elements/attributes!");
699 return LDB_ERR_UNWILLING_TO_PERFORM;
702 ac = oc_init_context(module, req);
704 return ldb_operr(ldb);
707 /* Without schema, there isn't much to do here */
708 if (ac->schema == NULL) {
710 return ldb_next_request(module, req);
713 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
715 return ldb_operr(ldb);
718 /* For now change everything except the objectclasses */
720 objectclass_element = ldb_msg_find_element(msg, "objectClass");
721 if (objectclass_element != NULL) {
722 ldb_msg_remove_attr(msg, "objectClass");
726 ret = ldb_build_mod_req(&down_req, ldb, ac,
729 oc_changes ? oc_modify_callback : oc_op_callback,
731 if (ret != LDB_SUCCESS) {
735 return ldb_next_request(module, down_req);
738 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
740 static const char * const attrs[] = { "objectClass", NULL };
741 struct ldb_context *ldb;
742 struct ldb_request *search_req;
743 struct oc_context *ac;
746 ac = talloc_get_type(req->context, struct oc_context);
747 ldb = ldb_module_get_ctx(ac->module);
750 return ldb_module_done(ac->req, NULL, NULL,
751 LDB_ERR_OPERATIONS_ERROR);
754 if (ares->type == LDB_REPLY_REFERRAL) {
755 return ldb_module_send_referral(ac->req, ares->referral);
758 if (ares->error != LDB_SUCCESS) {
759 return ldb_module_done(ac->req, ares->controls,
760 ares->response, ares->error);
763 if (ares->type != LDB_REPLY_DONE) {
765 return ldb_module_done(ac->req, NULL, NULL,
766 LDB_ERR_OPERATIONS_ERROR);
771 /* this looks up the real existing object for fetching some important
772 * informations (objectclasses) */
773 ret = ldb_build_search_req(&search_req, ldb,
774 ac, ac->req->op.mod.message->dn,
778 ac, get_search_callback,
780 if (ret != LDB_SUCCESS) {
781 return ldb_module_done(ac->req, NULL, NULL, ret);
784 ac->step_fn = objectclass_do_mod;
786 ret = ldb_next_request(ac->module, search_req);
787 if (ret != LDB_SUCCESS) {
788 return ldb_module_done(ac->req, NULL, NULL, ret);
794 static int objectclass_do_mod(struct oc_context *ac)
796 struct ldb_context *ldb;
797 struct ldb_request *mod_req;
799 struct ldb_message_element *oc_el_entry, *oc_el_change;
800 struct ldb_val *vals;
801 struct ldb_message *msg;
803 struct class_list *sorted, *current;
804 const struct dsdb_class *objectclass;
806 bool found, replace = false;
809 ldb = ldb_module_get_ctx(ac->module);
811 /* we should always have a valid entry when we enter here */
812 if (ac->search_res == NULL) {
813 return ldb_operr(ldb);
816 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
818 if (oc_el_entry == NULL) {
819 /* existing entry without a valid object class? */
820 return ldb_operr(ldb);
823 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
825 if (oc_el_change == NULL) {
826 /* we should have an objectclass change operation */
827 return ldb_operr(ldb);
830 /* use a new message structure */
831 msg = ldb_msg_new(ac);
836 msg->dn = ac->req->op.mod.message->dn;
838 mem_ctx = talloc_new(ac);
839 if (mem_ctx == NULL) {
843 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
844 case LDB_FLAG_MOD_ADD:
845 /* Merge the two message elements */
846 for (i = 0; i < oc_el_change->num_values; i++) {
847 for (j = 0; j < oc_el_entry->num_values; j++) {
848 if (strcasecmp((char *)oc_el_change->values[i].data,
849 (char *)oc_el_entry->values[j].data) == 0) {
850 /* we cannot add an already existing object class */
851 talloc_free(mem_ctx);
852 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
855 /* append the new object class value - code was copied
856 * from "ldb_msg_add_value" */
857 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
859 oc_el_entry->num_values + 1);
861 talloc_free(mem_ctx);
864 oc_el_entry->values = vals;
865 oc_el_entry->values[oc_el_entry->num_values] =
866 oc_el_change->values[i];
867 ++(oc_el_entry->num_values);
870 objectclass = get_last_structural_class(ac->schema,
872 if (objectclass != NULL) {
873 /* we cannot add a new structural object class */
874 talloc_free(mem_ctx);
875 return LDB_ERR_OBJECT_CLASS_VIOLATION;
878 /* Now do the sorting */
879 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
880 oc_el_entry, &sorted);
881 if (ret != LDB_SUCCESS) {
882 talloc_free(mem_ctx);
888 case LDB_FLAG_MOD_REPLACE:
889 /* Do the sorting for the change message element */
890 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
891 oc_el_change, &sorted);
892 if (ret != LDB_SUCCESS) {
893 talloc_free(mem_ctx);
897 /* this is a replace */
902 case LDB_FLAG_MOD_DELETE:
903 /* get the actual top-most structural objectclass */
904 objectclass = get_last_structural_class(ac->schema,
906 if (objectclass == NULL) {
907 talloc_free(mem_ctx);
908 return ldb_operr(ldb);
911 /* Merge the two message elements */
912 for (i = 0; i < oc_el_change->num_values; i++) {
914 for (j = 0; j < oc_el_entry->num_values; j++) {
915 if (strcasecmp((char *)oc_el_change->values[i].data,
916 (char *)oc_el_entry->values[j].data) == 0) {
918 /* delete the object class value -
919 * code was copied from
920 * "ldb_msg_remove_element" */
921 if (j != oc_el_entry->num_values - 1) {
922 memmove(&oc_el_entry->values[j],
923 &oc_el_entry->values[j+1],
924 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
926 --(oc_el_entry->num_values);
931 /* we cannot delete a not existing object class */
932 talloc_free(mem_ctx);
933 return LDB_ERR_NO_SUCH_ATTRIBUTE;
937 /* Make sure that the top-most structural objectclass wasn't
940 for (i = 0; i < oc_el_entry->num_values; i++) {
941 if (strcasecmp(objectclass->lDAPDisplayName,
942 (char *)oc_el_entry->values[i].data) == 0) {
947 talloc_free(mem_ctx);
948 return LDB_ERR_OBJECT_CLASS_VIOLATION;
952 /* Now do the sorting */
953 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
954 oc_el_entry, &sorted);
955 if (ret != LDB_SUCCESS) {
956 talloc_free(mem_ctx);
963 ret = ldb_msg_add_empty(msg, "objectClass",
964 LDB_FLAG_MOD_REPLACE, &oc_el_change);
965 if (ret != LDB_SUCCESS) {
967 talloc_free(mem_ctx);
971 /* Move from the linked list back into an ldb msg */
972 for (current = sorted; current; current = current->next) {
973 value = talloc_strdup(msg,
974 current->objectclass->lDAPDisplayName);
976 talloc_free(mem_ctx);
979 ret = ldb_msg_add_string(msg, "objectClass", value);
980 if (ret != LDB_SUCCESS) {
981 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
982 talloc_free(mem_ctx);
987 talloc_free(mem_ctx);
990 /* Well, on replace we are nearly done: we have to test if
991 * the change and entry message element are identically. We
992 * can use "ldb_msg_element_compare" since now the specified
993 * objectclasses match for sure in case. */
994 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
996 ret = ldb_msg_element_compare(oc_el_change,
1000 /* they are the same so we are done in this case */
1001 return ldb_module_done(ac->req, NULL, NULL,
1004 /* they're not exactly the same */
1005 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1009 /* in the other cases we have the real change left to do */
1011 ret = ldb_msg_sanity_check(ldb, msg);
1012 if (ret != LDB_SUCCESS) {
1016 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1021 if (ret != LDB_SUCCESS) {
1025 return ldb_next_request(ac->module, mod_req);
1028 static int objectclass_do_rename(struct oc_context *ac);
1030 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1032 static const char * const attrs[] = { "objectClass", NULL };
1033 struct ldb_context *ldb;
1034 struct ldb_request *search_req;
1035 struct oc_context *ac;
1036 struct ldb_dn *parent_dn;
1039 ldb = ldb_module_get_ctx(module);
1041 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1043 /* do not manipulate our control entries */
1044 if (ldb_dn_is_special(req->op.rename.newdn)) {
1045 return ldb_next_request(module, req);
1048 ac = oc_init_context(module, req);
1050 return ldb_operr(ldb);
1053 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1054 if (parent_dn == NULL) {
1055 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1056 ldb_dn_get_linearized(req->op.rename.olddn));
1057 return LDB_ERR_NO_SUCH_OBJECT;
1060 /* this looks up the parent object for fetching some important
1061 * informations (objectclasses, DN normalisation...) */
1062 ret = ldb_build_search_req(&search_req, ldb,
1063 ac, parent_dn, LDB_SCOPE_BASE,
1066 ac, get_search_callback,
1068 if (ret != LDB_SUCCESS) {
1072 /* we have to add the show deleted control, as otherwise DRS
1073 deletes will be refused as we will think the target parent
1075 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1077 if (ret != LDB_SUCCESS) {
1081 ac->step_fn = objectclass_do_rename;
1083 return ldb_next_request(ac->module, search_req);
1086 static int objectclass_do_rename2(struct oc_context *ac);
1088 static int objectclass_do_rename(struct oc_context *ac)
1090 static const char * const attrs[] = { "objectClass", NULL };
1091 struct ldb_context *ldb;
1092 struct ldb_request *search_req;
1095 ldb = ldb_module_get_ctx(ac->module);
1097 /* Check if we have a valid parent - this check is needed since
1098 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1099 if (ac->search_res == NULL) {
1100 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1101 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1102 return LDB_ERR_OTHER;
1105 /* now assign "search_res2" to the parent entry to have "search_res"
1106 * free for another lookup */
1107 ac->search_res2 = ac->search_res;
1108 ac->search_res = NULL;
1110 /* this looks up the real existing object for fetching some important
1111 * informations (objectclasses) */
1112 ret = ldb_build_search_req(&search_req, ldb,
1113 ac, ac->req->op.rename.olddn,
1117 ac, get_search_callback,
1119 if (ret != LDB_SUCCESS) {
1123 ac->step_fn = objectclass_do_rename2;
1125 return ldb_next_request(ac->module, search_req);
1128 static int objectclass_do_rename2(struct oc_context *ac)
1130 struct ldb_context *ldb;
1131 struct ldb_request *rename_req;
1132 struct ldb_dn *fixed_dn;
1135 ldb = ldb_module_get_ctx(ac->module);
1137 /* Check if we have a valid entry - this check is needed since
1138 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1139 if (ac->search_res == NULL) {
1140 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1141 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1142 return LDB_ERR_NO_SUCH_OBJECT;
1145 if (ac->schema != NULL) {
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_operr(ldb);
1158 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1159 if (objectclass == NULL) {
1160 /* existing entry without a valid object class? */
1161 return ldb_operr(ldb);
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_operr(ldb);
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(ac->schema,
1186 &oc_el_parent->values[i]);
1188 /* We don't know this class? what is going on? */
1191 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1192 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1193 allowed_class = true;
1199 if (!allowed_class) {
1200 ldb_asprintf_errstring(ldb,
1201 "objectclass: structural objectClass %s is not a valid child class for %s",
1202 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1203 return LDB_ERR_NAMING_VIOLATION;
1207 /* Ensure we are not trying to rename it to be a child of itself */
1208 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1209 ac->req->op.rename.newdn) == 0) &&
1210 (ldb_dn_compare(ac->req->op.rename.olddn,
1211 ac->req->op.rename.newdn) != 0)) {
1212 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1213 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1214 return LDB_ERR_UNWILLING_TO_PERFORM;
1217 /* Fix up the DN to be in the standard form, taking
1218 * particular care to match the parent DN */
1219 ret = fix_dn(ldb, ac,
1220 ac->req->op.rename.newdn,
1221 ac->search_res2->message->dn,
1223 if (ret != LDB_SUCCESS) {
1224 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1225 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1230 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1231 ac->req->op.rename.olddn, fixed_dn,
1235 if (ret != LDB_SUCCESS) {
1239 /* perform the rename */
1240 return ldb_next_request(ac->module, rename_req);
1243 static int objectclass_do_delete(struct oc_context *ac);
1245 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1247 static const char * const attrs[] = { "nCName", "objectClass",
1248 "systemFlags", NULL };
1249 struct ldb_context *ldb;
1250 struct ldb_request *search_req;
1251 struct oc_context *ac;
1254 ldb = ldb_module_get_ctx(module);
1256 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1258 /* do not manipulate our control entries */
1259 if (ldb_dn_is_special(req->op.del.dn)) {
1260 return ldb_next_request(module, req);
1263 /* Bypass the constraint checks when we do have the "RELAX" control
1265 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1266 return ldb_next_request(module, req);
1269 ac = oc_init_context(module, req);
1271 return ldb_operr(ldb);
1274 /* this looks up the entry object for fetching some important
1275 * informations (object classes, system flags...) */
1276 ret = ldb_build_search_req(&search_req, ldb,
1277 ac, req->op.del.dn, LDB_SCOPE_BASE,
1280 ac, get_search_callback,
1282 if (ret != LDB_SUCCESS) {
1286 ac->step_fn = objectclass_do_delete;
1288 return ldb_next_request(ac->module, search_req);
1291 static int objectclass_do_delete(struct oc_context *ac)
1293 struct ldb_context *ldb;
1295 int32_t systemFlags;
1298 ldb = ldb_module_get_ctx(ac->module);
1300 /* Check if we have a valid entry - this check is needed since
1301 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1302 if (ac->search_res == NULL) {
1303 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1304 ldb_dn_get_linearized(ac->req->op.del.dn));
1305 return LDB_ERR_NO_SUCH_OBJECT;
1308 /* DC's ntDSDSA object */
1309 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1310 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1311 ldb_dn_get_linearized(ac->req->op.del.dn));
1312 return LDB_ERR_UNWILLING_TO_PERFORM;
1315 /* DC's rIDSet object */
1316 ret = samdb_rid_set_dn(ldb, ac, &dn);
1317 if (ret != LDB_SUCCESS) {
1321 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1323 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1324 ldb_dn_get_linearized(ac->req->op.del.dn));
1325 return LDB_ERR_UNWILLING_TO_PERFORM;
1330 /* crossRef objects regarding config, schema and default domain NCs */
1331 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1332 "crossRef") != NULL) {
1333 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1335 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1336 (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0) ||
1337 (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0)) {
1340 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the three main partitions!",
1341 ldb_dn_get_linearized(ac->req->op.del.dn));
1342 return LDB_ERR_UNWILLING_TO_PERFORM;
1349 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1351 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1352 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1353 ldb_dn_get_linearized(ac->req->op.del.dn));
1354 return LDB_ERR_UNWILLING_TO_PERFORM;
1357 return ldb_next_request(ac->module, ac->req);
1360 static int objectclass_init(struct ldb_module *module)
1362 struct ldb_context *ldb = ldb_module_get_ctx(module);
1365 /* Init everything else */
1366 ret = ldb_next_init(module);
1367 if (ret != LDB_SUCCESS) {
1371 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1372 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1377 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1378 .name = "objectclass",
1379 .add = objectclass_add,
1380 .modify = objectclass_modify,
1381 .rename = objectclass_rename,
1382 .del = objectclass_delete,
1383 .init_context = objectclass_init