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
662 * MS-ADTS 3.1.1.5.2.4 */
664 el = ldb_msg_find_element(msg, "systemFlags");
665 if ((el != NULL) && (el->num_values > 1)) {
666 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'systemFlags' attribute multivalued!",
667 ldb_dn_get_linearized(msg->dn));
668 return LDB_ERR_CONSTRAINT_VIOLATION;
671 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
673 ldb_msg_remove_attr(msg, "systemFlags");
675 /* Only these flags may be set by a client, but we can't tell
676 * between a client and our provision at this point
677 * systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE);
680 /* This flag is only allowed on attributeSchema objects */
681 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
682 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
685 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
686 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
687 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
688 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
689 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
690 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
692 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
693 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
694 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
695 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
698 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
700 if (el || systemFlags != 0) {
701 ret = samdb_msg_add_int(ldb, msg, msg, "systemFlags",
703 if (ret != LDB_SUCCESS) {
709 ret = ldb_msg_sanity_check(ldb, msg);
710 if (ret != LDB_SUCCESS) {
714 ret = ldb_build_add_req(&add_req, ldb, ac,
719 if (ret != LDB_SUCCESS) {
723 /* perform the add */
724 return ldb_next_request(ac->module, add_req);
727 static int oc_modify_callback(struct ldb_request *req,
728 struct ldb_reply *ares);
729 static int objectclass_do_mod(struct oc_context *ac);
731 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
733 struct ldb_context *ldb = ldb_module_get_ctx(module);
734 struct ldb_message_element *objectclass_element;
735 struct ldb_message *msg;
736 struct ldb_request *down_req;
737 struct oc_context *ac;
738 bool oc_changes = false;
741 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
743 /* do not manipulate our control entries */
744 if (ldb_dn_is_special(req->op.mod.message->dn)) {
745 return ldb_next_request(module, req);
748 /* As with the "real" AD we don't accept empty messages */
749 if (req->op.mod.message->num_elements == 0) {
750 ldb_set_errstring(ldb, "objectclass: modify message must have "
751 "elements/attributes!");
752 return LDB_ERR_UNWILLING_TO_PERFORM;
755 ac = oc_init_context(module, req);
757 return ldb_operr(ldb);
760 /* Without schema, there isn't much to do here */
761 if (ac->schema == NULL) {
763 return ldb_next_request(module, req);
766 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
768 return ldb_operr(ldb);
771 /* For now change everything except the objectclasses */
773 objectclass_element = ldb_msg_find_element(msg, "objectClass");
774 if (objectclass_element != NULL) {
775 ldb_msg_remove_attr(msg, "objectClass");
779 ret = ldb_build_mod_req(&down_req, ldb, ac,
782 oc_changes ? oc_modify_callback : oc_op_callback,
784 if (ret != LDB_SUCCESS) {
788 return ldb_next_request(module, down_req);
791 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
793 static const char * const attrs[] = { "objectClass", NULL };
794 struct ldb_context *ldb;
795 struct ldb_request *search_req;
796 struct oc_context *ac;
799 ac = talloc_get_type(req->context, struct oc_context);
800 ldb = ldb_module_get_ctx(ac->module);
803 return ldb_module_done(ac->req, NULL, NULL,
804 LDB_ERR_OPERATIONS_ERROR);
807 if (ares->type == LDB_REPLY_REFERRAL) {
808 return ldb_module_send_referral(ac->req, ares->referral);
811 if (ares->error != LDB_SUCCESS) {
812 return ldb_module_done(ac->req, ares->controls,
813 ares->response, ares->error);
816 if (ares->type != LDB_REPLY_DONE) {
818 return ldb_module_done(ac->req, NULL, NULL,
819 LDB_ERR_OPERATIONS_ERROR);
824 /* this looks up the real existing object for fetching some important
825 * informations (objectclasses) */
826 ret = ldb_build_search_req(&search_req, ldb,
827 ac, ac->req->op.mod.message->dn,
831 ac, get_search_callback,
833 if (ret != LDB_SUCCESS) {
834 return ldb_module_done(ac->req, NULL, NULL, ret);
837 ac->step_fn = objectclass_do_mod;
839 ret = ldb_next_request(ac->module, search_req);
840 if (ret != LDB_SUCCESS) {
841 return ldb_module_done(ac->req, NULL, NULL, ret);
847 static int objectclass_do_mod(struct oc_context *ac)
849 struct ldb_context *ldb;
850 struct ldb_request *mod_req;
852 struct ldb_message_element *oc_el_entry, *oc_el_change;
853 struct ldb_val *vals;
854 struct ldb_message *msg;
856 struct class_list *sorted, *current;
857 const struct dsdb_class *objectclass;
859 bool found, replace = false;
862 ldb = ldb_module_get_ctx(ac->module);
864 /* we should always have a valid entry when we enter here */
865 if (ac->search_res == NULL) {
866 return ldb_operr(ldb);
869 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
871 if (oc_el_entry == NULL) {
872 /* existing entry without a valid object class? */
873 return ldb_operr(ldb);
876 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
878 if (oc_el_change == NULL) {
879 /* we should have an objectclass change operation */
880 return ldb_operr(ldb);
883 /* use a new message structure */
884 msg = ldb_msg_new(ac);
889 msg->dn = ac->req->op.mod.message->dn;
891 mem_ctx = talloc_new(ac);
892 if (mem_ctx == NULL) {
896 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
897 case LDB_FLAG_MOD_ADD:
898 /* Merge the two message elements */
899 for (i = 0; i < oc_el_change->num_values; i++) {
900 for (j = 0; j < oc_el_entry->num_values; j++) {
901 if (strcasecmp((char *)oc_el_change->values[i].data,
902 (char *)oc_el_entry->values[j].data) == 0) {
903 /* we cannot add an already existing object class */
904 talloc_free(mem_ctx);
905 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
908 /* append the new object class value - code was copied
909 * from "ldb_msg_add_value" */
910 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
912 oc_el_entry->num_values + 1);
914 talloc_free(mem_ctx);
917 oc_el_entry->values = vals;
918 oc_el_entry->values[oc_el_entry->num_values] =
919 oc_el_change->values[i];
920 ++(oc_el_entry->num_values);
923 objectclass = get_last_structural_class(ac->schema,
925 if (objectclass != NULL) {
926 /* we cannot add a new structural object class */
927 talloc_free(mem_ctx);
928 return LDB_ERR_OBJECT_CLASS_VIOLATION;
931 /* Now do the sorting */
932 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
933 oc_el_entry, &sorted);
934 if (ret != LDB_SUCCESS) {
935 talloc_free(mem_ctx);
941 case LDB_FLAG_MOD_REPLACE:
942 /* Do the sorting for the change message element */
943 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
944 oc_el_change, &sorted);
945 if (ret != LDB_SUCCESS) {
946 talloc_free(mem_ctx);
950 /* this is a replace */
955 case LDB_FLAG_MOD_DELETE:
956 /* get the actual top-most structural objectclass */
957 objectclass = get_last_structural_class(ac->schema,
959 if (objectclass == NULL) {
960 talloc_free(mem_ctx);
961 return ldb_operr(ldb);
964 /* Merge the two message elements */
965 for (i = 0; i < oc_el_change->num_values; i++) {
967 for (j = 0; j < oc_el_entry->num_values; j++) {
968 if (strcasecmp((char *)oc_el_change->values[i].data,
969 (char *)oc_el_entry->values[j].data) == 0) {
971 /* delete the object class value -
972 * code was copied from
973 * "ldb_msg_remove_element" */
974 if (j != oc_el_entry->num_values - 1) {
975 memmove(&oc_el_entry->values[j],
976 &oc_el_entry->values[j+1],
977 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
979 --(oc_el_entry->num_values);
984 /* we cannot delete a not existing object class */
985 talloc_free(mem_ctx);
986 return LDB_ERR_NO_SUCH_ATTRIBUTE;
990 /* Make sure that the top-most structural objectclass wasn't
993 for (i = 0; i < oc_el_entry->num_values; i++) {
994 if (strcasecmp(objectclass->lDAPDisplayName,
995 (char *)oc_el_entry->values[i].data) == 0) {
1000 talloc_free(mem_ctx);
1001 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1005 /* Now do the sorting */
1006 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
1007 oc_el_entry, &sorted);
1008 if (ret != LDB_SUCCESS) {
1009 talloc_free(mem_ctx);
1016 ret = ldb_msg_add_empty(msg, "objectClass",
1017 LDB_FLAG_MOD_REPLACE, &oc_el_change);
1018 if (ret != LDB_SUCCESS) {
1020 talloc_free(mem_ctx);
1024 /* Move from the linked list back into an ldb msg */
1025 for (current = sorted; current; current = current->next) {
1026 value = talloc_strdup(msg,
1027 current->objectclass->lDAPDisplayName);
1028 if (value == NULL) {
1029 talloc_free(mem_ctx);
1030 return ldb_oom(ldb);
1032 ret = ldb_msg_add_string(msg, "objectClass", value);
1033 if (ret != LDB_SUCCESS) {
1034 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
1035 talloc_free(mem_ctx);
1040 talloc_free(mem_ctx);
1043 /* Well, on replace we are nearly done: we have to test if
1044 * the change and entry message element are identically. We
1045 * can use "ldb_msg_element_compare" since now the specified
1046 * objectclasses match for sure in case. */
1047 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
1049 ret = ldb_msg_element_compare(oc_el_change,
1053 /* they are the same so we are done in this case */
1054 return ldb_module_done(ac->req, NULL, NULL,
1057 /* they're not exactly the same */
1058 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1062 /* in the other cases we have the real change left to do */
1064 ret = ldb_msg_sanity_check(ldb, msg);
1065 if (ret != LDB_SUCCESS) {
1069 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1074 if (ret != LDB_SUCCESS) {
1078 return ldb_next_request(ac->module, mod_req);
1081 static int objectclass_do_rename(struct oc_context *ac);
1083 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1085 static const char * const attrs[] = { "objectClass", NULL };
1086 struct ldb_context *ldb;
1087 struct ldb_request *search_req;
1088 struct oc_context *ac;
1089 struct ldb_dn *parent_dn;
1092 ldb = ldb_module_get_ctx(module);
1094 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1096 /* do not manipulate our control entries */
1097 if (ldb_dn_is_special(req->op.rename.newdn)) {
1098 return ldb_next_request(module, req);
1101 ac = oc_init_context(module, req);
1103 return ldb_operr(ldb);
1106 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1107 if (parent_dn == NULL) {
1108 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1109 ldb_dn_get_linearized(req->op.rename.olddn));
1110 return LDB_ERR_NO_SUCH_OBJECT;
1113 /* this looks up the parent object for fetching some important
1114 * informations (objectclasses, DN normalisation...) */
1115 ret = ldb_build_search_req(&search_req, ldb,
1116 ac, parent_dn, LDB_SCOPE_BASE,
1119 ac, get_search_callback,
1121 if (ret != LDB_SUCCESS) {
1125 /* we have to add the show deleted control, as otherwise DRS
1126 deletes will be refused as we will think the target parent
1128 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1130 if (ret != LDB_SUCCESS) {
1134 ac->step_fn = objectclass_do_rename;
1136 return ldb_next_request(ac->module, search_req);
1139 static int objectclass_do_rename2(struct oc_context *ac);
1141 static int objectclass_do_rename(struct oc_context *ac)
1143 static const char * const attrs[] = { "objectClass", NULL };
1144 struct ldb_context *ldb;
1145 struct ldb_request *search_req;
1148 ldb = ldb_module_get_ctx(ac->module);
1150 /* Check if we have a valid parent - this check is needed since
1151 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1152 if (ac->search_res == NULL) {
1153 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1154 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1155 return LDB_ERR_OTHER;
1158 /* now assign "search_res2" to the parent entry to have "search_res"
1159 * free for another lookup */
1160 ac->search_res2 = ac->search_res;
1161 ac->search_res = NULL;
1163 /* this looks up the real existing object for fetching some important
1164 * informations (objectclasses) */
1165 ret = ldb_build_search_req(&search_req, ldb,
1166 ac, ac->req->op.rename.olddn,
1170 ac, get_search_callback,
1172 if (ret != LDB_SUCCESS) {
1176 ac->step_fn = objectclass_do_rename2;
1178 return ldb_next_request(ac->module, search_req);
1181 static int objectclass_do_rename2(struct oc_context *ac)
1183 struct ldb_context *ldb;
1184 struct ldb_request *rename_req;
1185 struct ldb_dn *fixed_dn;
1188 ldb = ldb_module_get_ctx(ac->module);
1190 /* Check if we have a valid entry - this check is needed since
1191 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1192 if (ac->search_res == NULL) {
1193 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1194 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1195 return LDB_ERR_NO_SUCH_OBJECT;
1198 if (ac->schema != NULL) {
1199 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1200 const struct dsdb_class *objectclass;
1201 const char *rdn_name;
1202 bool allowed_class = false;
1205 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1207 if (oc_el_entry == NULL) {
1208 /* existing entry without a valid object class? */
1209 return ldb_operr(ldb);
1211 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1212 if (objectclass == NULL) {
1213 /* existing entry without a valid object class? */
1214 return ldb_operr(ldb);
1217 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1218 if ((objectclass->rDNAttID != NULL) &&
1219 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1220 ldb_asprintf_errstring(ldb,
1221 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1223 objectclass->lDAPDisplayName,
1224 objectclass->rDNAttID);
1225 return LDB_ERR_UNWILLING_TO_PERFORM;
1228 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1230 if (oc_el_parent == NULL) {
1231 /* existing entry without a valid object class? */
1232 return ldb_operr(ldb);
1235 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1236 const struct dsdb_class *sclass;
1238 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1239 &oc_el_parent->values[i]);
1241 /* We don't know this class? what is going on? */
1244 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1245 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1246 allowed_class = true;
1252 if (!allowed_class) {
1253 ldb_asprintf_errstring(ldb,
1254 "objectclass: structural objectClass %s is not a valid child class for %s",
1255 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1256 return LDB_ERR_NAMING_VIOLATION;
1260 /* Ensure we are not trying to rename it to be a child of itself */
1261 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1262 ac->req->op.rename.newdn) == 0) &&
1263 (ldb_dn_compare(ac->req->op.rename.olddn,
1264 ac->req->op.rename.newdn) != 0)) {
1265 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1266 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1267 return LDB_ERR_UNWILLING_TO_PERFORM;
1270 /* Fix up the DN to be in the standard form, taking
1271 * particular care to match the parent DN */
1272 ret = fix_dn(ldb, ac,
1273 ac->req->op.rename.newdn,
1274 ac->search_res2->message->dn,
1276 if (ret != LDB_SUCCESS) {
1277 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1278 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1283 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1284 ac->req->op.rename.olddn, fixed_dn,
1288 if (ret != LDB_SUCCESS) {
1292 /* perform the rename */
1293 return ldb_next_request(ac->module, rename_req);
1296 static int objectclass_do_delete(struct oc_context *ac);
1298 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1300 static const char * const attrs[] = { "nCName", "objectClass",
1301 "systemFlags", NULL };
1302 struct ldb_context *ldb;
1303 struct ldb_request *search_req;
1304 struct oc_context *ac;
1307 ldb = ldb_module_get_ctx(module);
1309 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1311 /* do not manipulate our control entries */
1312 if (ldb_dn_is_special(req->op.del.dn)) {
1313 return ldb_next_request(module, req);
1316 /* Bypass the constraint checks when we do have the "RELAX" control
1318 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1319 return ldb_next_request(module, req);
1322 ac = oc_init_context(module, req);
1324 return ldb_operr(ldb);
1327 /* this looks up the entry object for fetching some important
1328 * informations (object classes, system flags...) */
1329 ret = ldb_build_search_req(&search_req, ldb,
1330 ac, req->op.del.dn, LDB_SCOPE_BASE,
1333 ac, get_search_callback,
1335 if (ret != LDB_SUCCESS) {
1339 ac->step_fn = objectclass_do_delete;
1341 return ldb_next_request(ac->module, search_req);
1344 static int objectclass_do_delete(struct oc_context *ac)
1346 struct ldb_context *ldb;
1348 int32_t systemFlags;
1351 ldb = ldb_module_get_ctx(ac->module);
1353 /* Check if we have a valid entry - this check is needed since
1354 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1355 if (ac->search_res == NULL) {
1356 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1357 ldb_dn_get_linearized(ac->req->op.del.dn));
1358 return LDB_ERR_NO_SUCH_OBJECT;
1361 /* DC's ntDSDSA object */
1362 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1363 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1364 ldb_dn_get_linearized(ac->req->op.del.dn));
1365 return LDB_ERR_UNWILLING_TO_PERFORM;
1368 /* DC's rIDSet object */
1369 /* Perform this check only when it does exist - this is needed in order
1370 * to don't let existing provisions break. */
1371 ret = samdb_rid_set_dn(ldb, ac, &dn);
1372 if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
1375 if (ret == LDB_SUCCESS) {
1376 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1378 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1379 ldb_dn_get_linearized(ac->req->op.del.dn));
1380 return LDB_ERR_UNWILLING_TO_PERFORM;
1385 /* crossRef objects regarding config, schema and default domain NCs */
1386 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1387 "crossRef") != NULL) {
1388 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1390 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1391 (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0) ||
1392 (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0)) {
1395 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the three main partitions!",
1396 ldb_dn_get_linearized(ac->req->op.del.dn));
1397 return LDB_ERR_UNWILLING_TO_PERFORM;
1404 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1406 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1407 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1408 ldb_dn_get_linearized(ac->req->op.del.dn));
1409 return LDB_ERR_UNWILLING_TO_PERFORM;
1412 return ldb_next_request(ac->module, ac->req);
1415 static int objectclass_init(struct ldb_module *module)
1417 struct ldb_context *ldb = ldb_module_get_ctx(module);
1420 /* Init everything else */
1421 ret = ldb_next_init(module);
1422 if (ret != LDB_SUCCESS) {
1426 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1427 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1432 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1433 .name = "objectclass",
1434 .add = objectclass_add,
1435 .modify = objectclass_modify,
1436 .rename = objectclass_rename,
1437 .del = objectclass_delete,
1438 .init_context = objectclass_init