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 LDB_REQ_SET_LOCATION(search_req);
427 if (ret != LDB_SUCCESS) {
431 ac->step_fn = objectclass_do_add;
433 return ldb_next_request(ac->module, search_req);
438 check if this is a special RODC nTDSDSA add
440 static bool check_rodc_ntdsdsa_add(struct oc_context *ac,
441 const struct dsdb_class *objectclass)
443 struct ldb_control *rodc_control;
445 if (strcasecmp(objectclass->lDAPDisplayName, "nTDSDSA") != 0) {
448 rodc_control = ldb_request_get_control(ac->req, LDB_CONTROL_RODC_DCPROMO_OID);
453 rodc_control->critical = false;
457 static int objectclass_do_add(struct oc_context *ac)
459 struct ldb_context *ldb;
460 struct ldb_request *add_req;
461 struct ldb_message_element *objectclass_element, *el;
462 struct ldb_message *msg;
464 struct class_list *sorted, *current;
465 const char *rdn_name = NULL;
467 const struct dsdb_class *objectclass;
468 struct ldb_dn *objectcategory;
469 int32_t systemFlags = 0;
472 ldb = ldb_module_get_ctx(ac->module);
474 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
476 /* Check if we have a valid parent - this check is needed since
477 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
478 if (ac->search_res == NULL) {
479 unsigned int instanceType;
481 /* An add operation on partition DNs without "NC-add" operation
483 instanceType = ldb_msg_find_attr_as_uint(ac->req->op.add.message,
485 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
486 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
487 ldb_dn_get_linearized(msg->dn));
488 return LDB_ERR_NO_SUCH_OBJECT;
491 /* Don't keep any error messages - we've to add a partition */
492 ldb_set_errstring(ldb, NULL);
494 /* Fix up the DN to be in the standard form, taking
495 * particular care to match the parent DN */
496 ret = fix_dn(ldb, msg,
497 ac->req->op.add.message->dn,
498 ac->search_res->message->dn,
500 if (ret != LDB_SUCCESS) {
501 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
502 ldb_dn_get_linearized(ac->req->op.add.message->dn));
507 mem_ctx = talloc_new(ac);
508 if (mem_ctx == NULL) {
512 if (ac->schema != NULL) {
513 objectclass_element = ldb_msg_find_element(msg, "objectClass");
514 if (!objectclass_element) {
515 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
516 ldb_dn_get_linearized(msg->dn));
517 talloc_free(mem_ctx);
518 return LDB_ERR_OBJECT_CLASS_VIOLATION;
521 /* Here we do now get the "objectClass" list from the
523 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
524 objectclass_element, &sorted);
525 if (ret != LDB_SUCCESS) {
526 talloc_free(mem_ctx);
530 ldb_msg_remove_element(msg, objectclass_element);
532 /* Well, now we shouldn't find any additional "objectClass"
533 * message element (required by the AD specification). */
534 objectclass_element = ldb_msg_find_element(msg, "objectClass");
535 if (objectclass_element != NULL) {
536 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, only one 'objectclass' attribute specification is allowed!",
537 ldb_dn_get_linearized(msg->dn));
538 talloc_free(mem_ctx);
539 return LDB_ERR_OBJECT_CLASS_VIOLATION;
542 /* We must completely replace the existing objectClass entry,
543 * because we need it sorted. */
544 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
545 if (ret != LDB_SUCCESS) {
546 talloc_free(mem_ctx);
550 /* Move from the linked list back into an ldb msg */
551 for (current = sorted; current; current = current->next) {
552 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
554 talloc_free(mem_ctx);
557 ret = ldb_msg_add_string(msg, "objectClass", value);
558 if (ret != LDB_SUCCESS) {
559 ldb_set_errstring(ldb,
560 "objectclass: could not re-add sorted "
561 "objectclass to modify msg");
562 talloc_free(mem_ctx);
567 talloc_free(mem_ctx);
569 /* Retrive the message again so get_last_structural_class works */
570 objectclass_element = ldb_msg_find_element(msg, "objectClass");
572 /* Make sure its valid to add an object of this type */
573 objectclass = get_last_structural_class(ac->schema,
574 objectclass_element);
575 if(objectclass == NULL) {
576 ldb_asprintf_errstring(ldb,
577 "Failed to find a structural class for %s",
578 ldb_dn_get_linearized(msg->dn));
579 return LDB_ERR_UNWILLING_TO_PERFORM;
582 rdn_name = ldb_dn_get_rdn_name(msg->dn);
583 if (objectclass->rDNAttID
584 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
585 ldb_asprintf_errstring(ldb,
586 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
587 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
588 return LDB_ERR_NAMING_VIOLATION;
591 if (objectclass->systemOnly &&
592 !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
593 !check_rodc_ntdsdsa_add(ac, objectclass)) {
594 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
595 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
596 return LDB_ERR_UNWILLING_TO_PERFORM;
599 if (((strcmp(objectclass->lDAPDisplayName, "secret") == 0) ||
600 (strcmp(objectclass->lDAPDisplayName, "trustedDomain") == 0)) &&
601 !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
602 ldb_asprintf_errstring(ldb, "objectClass %s is LSA-specific, rejecting creation of %s",
603 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
604 return LDB_ERR_UNWILLING_TO_PERFORM;
607 if (ac->search_res && ac->search_res->message) {
608 struct ldb_message_element *oc_el
609 = ldb_msg_find_element(ac->search_res->message, "objectClass");
611 bool allowed_class = false;
613 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
614 const struct dsdb_class *sclass;
616 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
619 /* We don't know this class? what is going on? */
622 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
623 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
624 allowed_class = true;
630 if (!allowed_class) {
631 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
632 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
633 return LDB_ERR_NAMING_VIOLATION;
637 objectcategory = ldb_msg_find_attr_as_dn(ldb, ac, msg,
639 if (objectcategory == NULL) {
640 struct dsdb_extended_dn_store_format *dn_format =
641 talloc_get_type(ldb_module_get_private(ac->module),
642 struct dsdb_extended_dn_store_format);
643 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
644 /* Strip off extended components */
645 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
646 objectclass->defaultObjectCategory);
647 value = ldb_dn_alloc_linearized(msg, dn);
650 value = talloc_strdup(msg,
651 objectclass->defaultObjectCategory);
657 ret = ldb_msg_add_string(msg, "objectCategory", value);
658 if (ret != LDB_SUCCESS) {
662 const struct dsdb_class *ocClass =
663 dsdb_class_by_cn_ldb_val(ac->schema,
664 ldb_dn_get_rdn_val(objectcategory));
665 if (ocClass != NULL) {
666 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
667 ocClass->defaultObjectCategory);
668 if (ldb_dn_compare(objectcategory, dn) != 0) {
672 talloc_free(objectcategory);
673 if (ocClass == NULL) {
674 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'objectCategory' attribute invalid!",
675 ldb_dn_get_linearized(msg->dn));
676 return LDB_ERR_OBJECT_CLASS_VIOLATION;
680 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
681 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
685 /* There are very special rules for systemFlags, see MS-ADTS
686 * MS-ADTS 3.1.1.5.2.4 */
688 el = ldb_msg_find_element(msg, "systemFlags");
689 if ((el != NULL) && (el->num_values > 1)) {
690 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'systemFlags' attribute multivalued!",
691 ldb_dn_get_linearized(msg->dn));
692 return LDB_ERR_CONSTRAINT_VIOLATION;
695 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
697 ldb_msg_remove_attr(msg, "systemFlags");
699 /* Only these flags may be set by a client, but we can't tell
700 * between a client and our provision at this point
701 * systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE);
704 /* This flag is only allowed on attributeSchema objects */
705 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
706 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
709 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
710 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
711 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
712 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serversContainer") == 0
713 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") == 0) {
714 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
716 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
717 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
718 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
719 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
722 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
724 if (el || systemFlags != 0) {
725 ret = samdb_msg_add_int(ldb, msg, msg, "systemFlags",
727 if (ret != LDB_SUCCESS) {
733 ret = ldb_msg_sanity_check(ldb, msg);
734 if (ret != LDB_SUCCESS) {
738 ret = ldb_build_add_req(&add_req, ldb, ac,
743 LDB_REQ_SET_LOCATION(add_req);
744 if (ret != LDB_SUCCESS) {
748 /* perform the add */
749 return ldb_next_request(ac->module, add_req);
752 static int oc_modify_callback(struct ldb_request *req,
753 struct ldb_reply *ares);
754 static int objectclass_do_mod(struct oc_context *ac);
756 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
758 struct ldb_context *ldb = ldb_module_get_ctx(module);
759 struct ldb_message_element *objectclass_element;
760 struct ldb_message *msg;
761 struct ldb_request *down_req;
762 struct oc_context *ac;
763 bool oc_changes = false;
766 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
768 /* do not manipulate our control entries */
769 if (ldb_dn_is_special(req->op.mod.message->dn)) {
770 return ldb_next_request(module, req);
773 /* As with the "real" AD we don't accept empty messages */
774 if (req->op.mod.message->num_elements == 0) {
775 ldb_set_errstring(ldb, "objectclass: modify message must have "
776 "elements/attributes!");
777 return LDB_ERR_UNWILLING_TO_PERFORM;
780 ac = oc_init_context(module, req);
782 return ldb_operr(ldb);
785 /* Without schema, there isn't much to do here */
786 if (ac->schema == NULL) {
788 return ldb_next_request(module, req);
791 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
793 return ldb_operr(ldb);
796 /* For now change everything except the objectclasses */
798 objectclass_element = ldb_msg_find_element(msg, "objectClass");
799 if (objectclass_element != NULL) {
800 ldb_msg_remove_attr(msg, "objectClass");
804 ret = ldb_build_mod_req(&down_req, ldb, ac,
807 oc_changes ? oc_modify_callback : oc_op_callback,
809 LDB_REQ_SET_LOCATION(down_req);
810 if (ret != LDB_SUCCESS) {
814 return ldb_next_request(module, down_req);
817 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
819 static const char * const attrs[] = { "objectClass", NULL };
820 struct ldb_context *ldb;
821 struct ldb_request *search_req;
822 struct oc_context *ac;
825 ac = talloc_get_type(req->context, struct oc_context);
826 ldb = ldb_module_get_ctx(ac->module);
829 return ldb_module_done(ac->req, NULL, NULL,
830 LDB_ERR_OPERATIONS_ERROR);
833 if (ares->type == LDB_REPLY_REFERRAL) {
834 return ldb_module_send_referral(ac->req, ares->referral);
837 if (ares->error != LDB_SUCCESS) {
838 return ldb_module_done(ac->req, ares->controls,
839 ares->response, ares->error);
842 if (ares->type != LDB_REPLY_DONE) {
844 return ldb_module_done(ac->req, NULL, NULL,
845 LDB_ERR_OPERATIONS_ERROR);
850 /* this looks up the real existing object for fetching some important
851 * informations (objectclasses) */
852 ret = ldb_build_search_req(&search_req, ldb,
853 ac, ac->req->op.mod.message->dn,
857 ac, get_search_callback,
859 LDB_REQ_SET_LOCATION(search_req);
860 if (ret != LDB_SUCCESS) {
861 return ldb_module_done(ac->req, NULL, NULL, ret);
864 ac->step_fn = objectclass_do_mod;
866 ret = ldb_next_request(ac->module, search_req);
867 if (ret != LDB_SUCCESS) {
868 return ldb_module_done(ac->req, NULL, NULL, ret);
874 static int objectclass_do_mod(struct oc_context *ac)
876 struct ldb_context *ldb;
877 struct ldb_request *mod_req;
879 struct ldb_message_element *oc_el_entry, *oc_el_change;
880 struct ldb_val *vals;
881 struct ldb_message *msg;
883 struct class_list *sorted, *current;
884 const struct dsdb_class *objectclass;
886 bool found, replace = false;
889 ldb = ldb_module_get_ctx(ac->module);
891 /* we should always have a valid entry when we enter here */
892 if (ac->search_res == NULL) {
893 return ldb_operr(ldb);
896 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
898 if (oc_el_entry == NULL) {
899 /* existing entry without a valid object class? */
900 return ldb_operr(ldb);
903 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
905 if (oc_el_change == NULL) {
906 /* we should have an objectclass change operation */
907 return ldb_operr(ldb);
910 /* use a new message structure */
911 msg = ldb_msg_new(ac);
916 msg->dn = ac->req->op.mod.message->dn;
918 mem_ctx = talloc_new(ac);
919 if (mem_ctx == NULL) {
923 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
924 case LDB_FLAG_MOD_ADD:
925 /* Merge the two message elements */
926 for (i = 0; i < oc_el_change->num_values; i++) {
927 for (j = 0; j < oc_el_entry->num_values; j++) {
928 if (strcasecmp((char *)oc_el_change->values[i].data,
929 (char *)oc_el_entry->values[j].data) == 0) {
930 /* we cannot add an already existing object class */
931 talloc_free(mem_ctx);
932 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
935 /* append the new object class value - code was copied
936 * from "ldb_msg_add_value" */
937 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
939 oc_el_entry->num_values + 1);
941 talloc_free(mem_ctx);
944 oc_el_entry->values = vals;
945 oc_el_entry->values[oc_el_entry->num_values] =
946 oc_el_change->values[i];
947 ++(oc_el_entry->num_values);
950 objectclass = get_last_structural_class(ac->schema,
952 if (objectclass != NULL) {
953 /* we cannot add a new structural object class */
954 talloc_free(mem_ctx);
955 return LDB_ERR_OBJECT_CLASS_VIOLATION;
958 /* Now do the sorting */
959 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
960 oc_el_entry, &sorted);
961 if (ret != LDB_SUCCESS) {
962 talloc_free(mem_ctx);
968 case LDB_FLAG_MOD_REPLACE:
969 /* Do the sorting for the change message element */
970 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
971 oc_el_change, &sorted);
972 if (ret != LDB_SUCCESS) {
973 talloc_free(mem_ctx);
977 /* this is a replace */
982 case LDB_FLAG_MOD_DELETE:
983 /* get the actual top-most structural objectclass */
984 objectclass = get_last_structural_class(ac->schema,
986 if (objectclass == NULL) {
987 talloc_free(mem_ctx);
988 return ldb_operr(ldb);
991 /* Merge the two message elements */
992 for (i = 0; i < oc_el_change->num_values; i++) {
994 for (j = 0; j < oc_el_entry->num_values; j++) {
995 if (strcasecmp((char *)oc_el_change->values[i].data,
996 (char *)oc_el_entry->values[j].data) == 0) {
998 /* delete the object class value -
999 * code was copied from
1000 * "ldb_msg_remove_element" */
1001 if (j != oc_el_entry->num_values - 1) {
1002 memmove(&oc_el_entry->values[j],
1003 &oc_el_entry->values[j+1],
1004 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
1006 --(oc_el_entry->num_values);
1011 /* we cannot delete a not existing object class */
1012 ldb_asprintf_errstring(ldb, "Cannot delete this %.*s ",
1013 (int)oc_el_change->values[i].length, (const char *)oc_el_change->values[i].data);
1015 talloc_free(mem_ctx);
1016 return LDB_ERR_NO_SUCH_ATTRIBUTE;
1020 /* Make sure that the top-most structural objectclass wasn't
1023 for (i = 0; i < oc_el_entry->num_values; i++) {
1024 if (strcasecmp(objectclass->lDAPDisplayName,
1025 (char *)oc_el_entry->values[i].data) == 0) {
1026 found = true; break;
1030 talloc_free(mem_ctx);
1031 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1035 /* Now do the sorting */
1036 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
1037 oc_el_entry, &sorted);
1038 if (ret != LDB_SUCCESS) {
1039 talloc_free(mem_ctx);
1046 ret = ldb_msg_add_empty(msg, "objectClass",
1047 LDB_FLAG_MOD_REPLACE, &oc_el_change);
1048 if (ret != LDB_SUCCESS) {
1050 talloc_free(mem_ctx);
1054 /* Move from the linked list back into an ldb msg */
1055 for (current = sorted; current; current = current->next) {
1056 value = talloc_strdup(msg,
1057 current->objectclass->lDAPDisplayName);
1058 if (value == NULL) {
1059 talloc_free(mem_ctx);
1060 return ldb_oom(ldb);
1062 ret = ldb_msg_add_string(msg, "objectClass", value);
1063 if (ret != LDB_SUCCESS) {
1064 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
1065 talloc_free(mem_ctx);
1070 talloc_free(mem_ctx);
1073 /* Well, on replace we are nearly done: we have to test if
1074 * the change and entry message element are identically. We
1075 * can use "ldb_msg_element_compare" since now the specified
1076 * objectclasses match for sure in case. */
1077 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
1079 ret = ldb_msg_element_compare(oc_el_change,
1083 /* they are the same so we are done in this case */
1084 return ldb_module_done(ac->req, NULL, NULL,
1087 /* they're not exactly the same */
1088 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1092 /* in the other cases we have the real change left to do */
1094 ret = ldb_msg_sanity_check(ldb, msg);
1095 if (ret != LDB_SUCCESS) {
1099 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1104 LDB_REQ_SET_LOCATION(mod_req);
1105 if (ret != LDB_SUCCESS) {
1109 return ldb_next_request(ac->module, mod_req);
1112 static int objectclass_do_rename(struct oc_context *ac);
1114 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1116 static const char * const attrs[] = { "objectClass", NULL };
1117 struct ldb_context *ldb;
1118 struct ldb_request *search_req;
1119 struct oc_context *ac;
1120 struct ldb_dn *parent_dn;
1123 ldb = ldb_module_get_ctx(module);
1125 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1127 /* do not manipulate our control entries */
1128 if (ldb_dn_is_special(req->op.rename.newdn)) {
1129 return ldb_next_request(module, req);
1132 ac = oc_init_context(module, req);
1134 return ldb_operr(ldb);
1137 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1138 if (parent_dn == NULL) {
1139 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1140 ldb_dn_get_linearized(req->op.rename.olddn));
1141 return LDB_ERR_NO_SUCH_OBJECT;
1144 /* this looks up the parent object for fetching some important
1145 * informations (objectclasses, DN normalisation...) */
1146 ret = ldb_build_search_req(&search_req, ldb,
1147 ac, parent_dn, LDB_SCOPE_BASE,
1150 ac, get_search_callback,
1152 LDB_REQ_SET_LOCATION(search_req);
1153 if (ret != LDB_SUCCESS) {
1157 /* we have to add the show recycled control, as otherwise DRS
1158 deletes will be refused as we will think the target parent
1160 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
1163 if (ret != LDB_SUCCESS) {
1167 ac->step_fn = objectclass_do_rename;
1169 return ldb_next_request(ac->module, search_req);
1172 static int objectclass_do_rename2(struct oc_context *ac);
1174 static int objectclass_do_rename(struct oc_context *ac)
1176 static const char * const attrs[] = { "objectClass", NULL };
1177 struct ldb_context *ldb;
1178 struct ldb_request *search_req;
1181 ldb = ldb_module_get_ctx(ac->module);
1183 /* Check if we have a valid parent - this check is needed since
1184 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1185 if (ac->search_res == NULL) {
1186 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1187 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1188 return LDB_ERR_OTHER;
1191 /* now assign "search_res2" to the parent entry to have "search_res"
1192 * free for another lookup */
1193 ac->search_res2 = ac->search_res;
1194 ac->search_res = NULL;
1196 /* this looks up the real existing object for fetching some important
1197 * informations (objectclasses) */
1198 ret = ldb_build_search_req(&search_req, ldb,
1199 ac, ac->req->op.rename.olddn,
1203 ac, get_search_callback,
1205 LDB_REQ_SET_LOCATION(search_req);
1206 if (ret != LDB_SUCCESS) {
1210 ac->step_fn = objectclass_do_rename2;
1212 return ldb_next_request(ac->module, search_req);
1215 static int objectclass_do_rename2(struct oc_context *ac)
1217 struct ldb_context *ldb;
1218 struct ldb_request *rename_req;
1219 struct ldb_dn *fixed_dn;
1222 ldb = ldb_module_get_ctx(ac->module);
1224 /* Check if we have a valid entry - this check is needed since
1225 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1226 if (ac->search_res == NULL) {
1227 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1228 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1229 return LDB_ERR_NO_SUCH_OBJECT;
1232 if (ac->schema != NULL) {
1233 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1234 const struct dsdb_class *objectclass;
1235 const char *rdn_name;
1236 bool allowed_class = false;
1239 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1241 if (oc_el_entry == NULL) {
1242 /* existing entry without a valid object class? */
1243 return ldb_operr(ldb);
1245 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1246 if (objectclass == NULL) {
1247 /* existing entry without a valid object class? */
1248 return ldb_operr(ldb);
1251 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1252 if ((objectclass->rDNAttID != NULL) &&
1253 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1254 ldb_asprintf_errstring(ldb,
1255 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1257 objectclass->lDAPDisplayName,
1258 objectclass->rDNAttID);
1259 return LDB_ERR_UNWILLING_TO_PERFORM;
1262 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1264 if (oc_el_parent == NULL) {
1265 /* existing entry without a valid object class? */
1266 return ldb_operr(ldb);
1269 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1270 const struct dsdb_class *sclass;
1272 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1273 &oc_el_parent->values[i]);
1275 /* We don't know this class? what is going on? */
1278 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1279 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1280 allowed_class = true;
1286 if (!allowed_class) {
1287 ldb_asprintf_errstring(ldb,
1288 "objectclass: structural objectClass %s is not a valid child class for %s",
1289 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1290 return LDB_ERR_NAMING_VIOLATION;
1294 /* Ensure we are not trying to rename it to be a child of itself */
1295 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1296 ac->req->op.rename.newdn) == 0) &&
1297 (ldb_dn_compare(ac->req->op.rename.olddn,
1298 ac->req->op.rename.newdn) != 0)) {
1299 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1300 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1301 return LDB_ERR_UNWILLING_TO_PERFORM;
1304 /* Fix up the DN to be in the standard form, taking
1305 * particular care to match the parent DN */
1306 ret = fix_dn(ldb, ac,
1307 ac->req->op.rename.newdn,
1308 ac->search_res2->message->dn,
1310 if (ret != LDB_SUCCESS) {
1311 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1312 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1317 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1318 ac->req->op.rename.olddn, fixed_dn,
1322 LDB_REQ_SET_LOCATION(rename_req);
1323 if (ret != LDB_SUCCESS) {
1327 /* perform the rename */
1328 return ldb_next_request(ac->module, rename_req);
1331 static int objectclass_do_delete(struct oc_context *ac);
1333 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1335 static const char * const attrs[] = { "nCName", "objectClass",
1336 "systemFlags", NULL };
1337 struct ldb_context *ldb;
1338 struct ldb_request *search_req;
1339 struct oc_context *ac;
1342 ldb = ldb_module_get_ctx(module);
1344 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1346 /* do not manipulate our control entries */
1347 if (ldb_dn_is_special(req->op.del.dn)) {
1348 return ldb_next_request(module, req);
1351 /* Bypass the constraint checks when we do have the "RELAX" control
1353 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1354 return ldb_next_request(module, req);
1357 ac = oc_init_context(module, req);
1359 return ldb_operr(ldb);
1362 /* this looks up the entry object for fetching some important
1363 * informations (object classes, system flags...) */
1364 ret = ldb_build_search_req(&search_req, ldb,
1365 ac, req->op.del.dn, LDB_SCOPE_BASE,
1368 ac, get_search_callback,
1370 LDB_REQ_SET_LOCATION(search_req);
1371 if (ret != LDB_SUCCESS) {
1375 ac->step_fn = objectclass_do_delete;
1377 return ldb_next_request(ac->module, search_req);
1380 static int objectclass_do_delete(struct oc_context *ac)
1382 struct ldb_context *ldb;
1384 int32_t systemFlags;
1387 ldb = ldb_module_get_ctx(ac->module);
1389 /* Check if we have a valid entry - this check is needed since
1390 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1391 if (ac->search_res == NULL) {
1392 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1393 ldb_dn_get_linearized(ac->req->op.del.dn));
1394 return LDB_ERR_NO_SUCH_OBJECT;
1397 /* DC's ntDSDSA object */
1398 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1399 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1400 ldb_dn_get_linearized(ac->req->op.del.dn));
1401 return LDB_ERR_UNWILLING_TO_PERFORM;
1404 /* DC's rIDSet object */
1405 /* Perform this check only when it does exist - this is needed in order
1406 * to don't let existing provisions break. */
1407 ret = samdb_rid_set_dn(ldb, ac, &dn);
1408 if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
1411 if (ret == LDB_SUCCESS) {
1412 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1414 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1415 ldb_dn_get_linearized(ac->req->op.del.dn));
1416 return LDB_ERR_UNWILLING_TO_PERFORM;
1421 /* crossRef objects regarding config, schema and default domain NCs */
1422 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1423 "crossRef") != NULL) {
1424 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1426 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1427 (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0)) {
1430 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the main or configuration partition!",
1431 ldb_dn_get_linearized(ac->req->op.del.dn));
1432 return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF;
1434 if (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0) {
1437 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the schema partition!",
1438 ldb_dn_get_linearized(ac->req->op.del.dn));
1439 return LDB_ERR_UNWILLING_TO_PERFORM;
1446 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1448 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1449 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1450 ldb_dn_get_linearized(ac->req->op.del.dn));
1451 return LDB_ERR_UNWILLING_TO_PERFORM;
1454 return ldb_next_request(ac->module, ac->req);
1457 static int objectclass_init(struct ldb_module *module)
1459 struct ldb_context *ldb = ldb_module_get_ctx(module);
1462 /* Init everything else */
1463 ret = ldb_next_init(module);
1464 if (ret != LDB_SUCCESS) {
1468 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1469 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1474 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1475 .name = "objectclass",
1476 .add = objectclass_add,
1477 .modify = objectclass_modify,
1478 .rename = objectclass_rename,
1479 .del = objectclass_delete,
1480 .init_context = objectclass_init