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 deleted 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_DELETED_OID, false, NULL);
1162 if (ret != LDB_SUCCESS) {
1166 ac->step_fn = objectclass_do_rename;
1168 return ldb_next_request(ac->module, search_req);
1171 static int objectclass_do_rename2(struct oc_context *ac);
1173 static int objectclass_do_rename(struct oc_context *ac)
1175 static const char * const attrs[] = { "objectClass", NULL };
1176 struct ldb_context *ldb;
1177 struct ldb_request *search_req;
1180 ldb = ldb_module_get_ctx(ac->module);
1182 /* Check if we have a valid parent - this check is needed since
1183 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1184 if (ac->search_res == NULL) {
1185 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1186 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1187 return LDB_ERR_OTHER;
1190 /* now assign "search_res2" to the parent entry to have "search_res"
1191 * free for another lookup */
1192 ac->search_res2 = ac->search_res;
1193 ac->search_res = NULL;
1195 /* this looks up the real existing object for fetching some important
1196 * informations (objectclasses) */
1197 ret = ldb_build_search_req(&search_req, ldb,
1198 ac, ac->req->op.rename.olddn,
1202 ac, get_search_callback,
1204 LDB_REQ_SET_LOCATION(search_req);
1205 if (ret != LDB_SUCCESS) {
1209 ac->step_fn = objectclass_do_rename2;
1211 return ldb_next_request(ac->module, search_req);
1214 static int objectclass_do_rename2(struct oc_context *ac)
1216 struct ldb_context *ldb;
1217 struct ldb_request *rename_req;
1218 struct ldb_dn *fixed_dn;
1221 ldb = ldb_module_get_ctx(ac->module);
1223 /* Check if we have a valid entry - this check is needed since
1224 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1225 if (ac->search_res == NULL) {
1226 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1227 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1228 return LDB_ERR_NO_SUCH_OBJECT;
1231 if (ac->schema != NULL) {
1232 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1233 const struct dsdb_class *objectclass;
1234 const char *rdn_name;
1235 bool allowed_class = false;
1238 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1240 if (oc_el_entry == NULL) {
1241 /* existing entry without a valid object class? */
1242 return ldb_operr(ldb);
1244 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1245 if (objectclass == NULL) {
1246 /* existing entry without a valid object class? */
1247 return ldb_operr(ldb);
1250 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1251 if ((objectclass->rDNAttID != NULL) &&
1252 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1253 ldb_asprintf_errstring(ldb,
1254 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1256 objectclass->lDAPDisplayName,
1257 objectclass->rDNAttID);
1258 return LDB_ERR_UNWILLING_TO_PERFORM;
1261 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1263 if (oc_el_parent == NULL) {
1264 /* existing entry without a valid object class? */
1265 return ldb_operr(ldb);
1268 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1269 const struct dsdb_class *sclass;
1271 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1272 &oc_el_parent->values[i]);
1274 /* We don't know this class? what is going on? */
1277 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1278 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1279 allowed_class = true;
1285 if (!allowed_class) {
1286 ldb_asprintf_errstring(ldb,
1287 "objectclass: structural objectClass %s is not a valid child class for %s",
1288 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1289 return LDB_ERR_NAMING_VIOLATION;
1293 /* Ensure we are not trying to rename it to be a child of itself */
1294 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1295 ac->req->op.rename.newdn) == 0) &&
1296 (ldb_dn_compare(ac->req->op.rename.olddn,
1297 ac->req->op.rename.newdn) != 0)) {
1298 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1299 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1300 return LDB_ERR_UNWILLING_TO_PERFORM;
1303 /* Fix up the DN to be in the standard form, taking
1304 * particular care to match the parent DN */
1305 ret = fix_dn(ldb, ac,
1306 ac->req->op.rename.newdn,
1307 ac->search_res2->message->dn,
1309 if (ret != LDB_SUCCESS) {
1310 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1311 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1316 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1317 ac->req->op.rename.olddn, fixed_dn,
1321 LDB_REQ_SET_LOCATION(rename_req);
1322 if (ret != LDB_SUCCESS) {
1326 /* perform the rename */
1327 return ldb_next_request(ac->module, rename_req);
1330 static int objectclass_do_delete(struct oc_context *ac);
1332 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1334 static const char * const attrs[] = { "nCName", "objectClass",
1335 "systemFlags", NULL };
1336 struct ldb_context *ldb;
1337 struct ldb_request *search_req;
1338 struct oc_context *ac;
1341 ldb = ldb_module_get_ctx(module);
1343 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1345 /* do not manipulate our control entries */
1346 if (ldb_dn_is_special(req->op.del.dn)) {
1347 return ldb_next_request(module, req);
1350 /* Bypass the constraint checks when we do have the "RELAX" control
1352 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1353 return ldb_next_request(module, req);
1356 ac = oc_init_context(module, req);
1358 return ldb_operr(ldb);
1361 /* this looks up the entry object for fetching some important
1362 * informations (object classes, system flags...) */
1363 ret = ldb_build_search_req(&search_req, ldb,
1364 ac, req->op.del.dn, LDB_SCOPE_BASE,
1367 ac, get_search_callback,
1369 LDB_REQ_SET_LOCATION(search_req);
1370 if (ret != LDB_SUCCESS) {
1374 ac->step_fn = objectclass_do_delete;
1376 return ldb_next_request(ac->module, search_req);
1379 static int objectclass_do_delete(struct oc_context *ac)
1381 struct ldb_context *ldb;
1383 int32_t systemFlags;
1386 ldb = ldb_module_get_ctx(ac->module);
1388 /* Check if we have a valid entry - this check is needed since
1389 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1390 if (ac->search_res == NULL) {
1391 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1392 ldb_dn_get_linearized(ac->req->op.del.dn));
1393 return LDB_ERR_NO_SUCH_OBJECT;
1396 /* DC's ntDSDSA object */
1397 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1398 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1399 ldb_dn_get_linearized(ac->req->op.del.dn));
1400 return LDB_ERR_UNWILLING_TO_PERFORM;
1403 /* DC's rIDSet object */
1404 /* Perform this check only when it does exist - this is needed in order
1405 * to don't let existing provisions break. */
1406 ret = samdb_rid_set_dn(ldb, ac, &dn);
1407 if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
1410 if (ret == LDB_SUCCESS) {
1411 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1413 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1414 ldb_dn_get_linearized(ac->req->op.del.dn));
1415 return LDB_ERR_UNWILLING_TO_PERFORM;
1420 /* crossRef objects regarding config, schema and default domain NCs */
1421 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1422 "crossRef") != NULL) {
1423 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1425 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1426 (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0) ||
1427 (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0)) {
1430 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the three main partitions!",
1431 ldb_dn_get_linearized(ac->req->op.del.dn));
1432 return LDB_ERR_UNWILLING_TO_PERFORM;
1439 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1441 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1442 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1443 ldb_dn_get_linearized(ac->req->op.del.dn));
1444 return LDB_ERR_UNWILLING_TO_PERFORM;
1447 return ldb_next_request(ac->module, ac->req);
1450 static int objectclass_init(struct ldb_module *module)
1452 struct ldb_context *ldb = ldb_module_get_ctx(module);
1455 /* Init everything else */
1456 ret = ldb_next_init(module);
1457 if (ret != LDB_SUCCESS) {
1461 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1462 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1467 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1468 .name = "objectclass",
1469 .add = objectclass_add,
1470 .modify = objectclass_modify,
1471 .rename = objectclass_rename,
1472 .del = objectclass_delete,
1473 .init_context = objectclass_init