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 int32_t systemFlags = 0;
449 ldb = ldb_module_get_ctx(ac->module);
451 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
453 /* Check if we have a valid parent - this check is needed since
454 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
455 if (ac->search_res == NULL) {
456 unsigned int instanceType;
458 /* An add operation on partition DNs without "NC-add" operation
460 instanceType = ldb_msg_find_attr_as_uint(ac->req->op.add.message,
462 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
463 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
464 ldb_dn_get_linearized(msg->dn));
465 return LDB_ERR_NO_SUCH_OBJECT;
468 /* Don't keep any error messages - we've to add a partition */
469 ldb_set_errstring(ldb, NULL);
471 /* Fix up the DN to be in the standard form, taking
472 * particular care to match the parent DN */
473 ret = fix_dn(ldb, msg,
474 ac->req->op.add.message->dn,
475 ac->search_res->message->dn,
477 if (ret != LDB_SUCCESS) {
478 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
479 ldb_dn_get_linearized(ac->req->op.add.message->dn));
484 mem_ctx = talloc_new(ac);
485 if (mem_ctx == NULL) {
489 if (ac->schema != NULL) {
490 objectclass_element = ldb_msg_find_element(msg, "objectClass");
491 if (!objectclass_element) {
492 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
493 ldb_dn_get_linearized(msg->dn));
494 talloc_free(mem_ctx);
495 return LDB_ERR_OBJECT_CLASS_VIOLATION;
498 /* Here we do now get the "objectClass" list from the
500 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
501 objectclass_element, &sorted);
502 if (ret != LDB_SUCCESS) {
503 talloc_free(mem_ctx);
507 ldb_msg_remove_element(msg, objectclass_element);
509 /* Well, now we shouldn't find any additional "objectClass"
510 * message element (required by the AD specification). */
511 objectclass_element = ldb_msg_find_element(msg, "objectClass");
512 if (objectclass_element != NULL) {
513 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, only one 'objectclass' attribute specification is allowed!",
514 ldb_dn_get_linearized(msg->dn));
515 talloc_free(mem_ctx);
516 return LDB_ERR_OBJECT_CLASS_VIOLATION;
519 /* We must completely replace the existing objectClass entry,
520 * because we need it sorted. */
521 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
522 if (ret != LDB_SUCCESS) {
523 talloc_free(mem_ctx);
527 /* Move from the linked list back into an ldb msg */
528 for (current = sorted; current; current = current->next) {
529 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
531 talloc_free(mem_ctx);
534 ret = ldb_msg_add_string(msg, "objectClass", value);
535 if (ret != LDB_SUCCESS) {
536 ldb_set_errstring(ldb,
537 "objectclass: could not re-add sorted "
538 "objectclass to modify msg");
539 talloc_free(mem_ctx);
544 talloc_free(mem_ctx);
546 /* Retrive the message again so get_last_structural_class works */
547 objectclass_element = ldb_msg_find_element(msg, "objectClass");
549 /* Make sure its valid to add an object of this type */
550 objectclass = get_last_structural_class(ac->schema,
551 objectclass_element);
552 if(objectclass == NULL) {
553 ldb_asprintf_errstring(ldb,
554 "Failed to find a structural class for %s",
555 ldb_dn_get_linearized(msg->dn));
556 return LDB_ERR_UNWILLING_TO_PERFORM;
559 rdn_name = ldb_dn_get_rdn_name(msg->dn);
560 if (objectclass->rDNAttID
561 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
562 ldb_asprintf_errstring(ldb,
563 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
564 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
565 return LDB_ERR_NAMING_VIOLATION;
568 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
569 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
570 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
571 return LDB_ERR_UNWILLING_TO_PERFORM;
574 if (((strcmp(objectclass->lDAPDisplayName, "secret") == 0) ||
575 (strcmp(objectclass->lDAPDisplayName, "trustedDomain") == 0)) &&
576 !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
577 ldb_asprintf_errstring(ldb, "objectClass %s is LSA-specific, rejecting creation of %s",
578 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
579 return LDB_ERR_UNWILLING_TO_PERFORM;
582 if (ac->search_res && ac->search_res->message) {
583 struct ldb_message_element *oc_el
584 = ldb_msg_find_element(ac->search_res->message, "objectClass");
586 bool allowed_class = false;
588 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
589 const struct dsdb_class *sclass;
591 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
594 /* We don't know this class? what is going on? */
597 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
598 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
599 allowed_class = true;
605 if (!allowed_class) {
606 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
607 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
608 return LDB_ERR_NAMING_VIOLATION;
612 if (!ldb_msg_find_element(msg, "objectCategory")) {
613 struct dsdb_extended_dn_store_format *dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct dsdb_extended_dn_store_format);
614 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
615 /* Strip off extended components */
616 struct ldb_dn *dn = ldb_dn_new(msg, ldb, objectclass->defaultObjectCategory);
617 value = ldb_dn_alloc_linearized(msg, dn);
620 value = talloc_strdup(msg, objectclass->defaultObjectCategory);
625 ldb_msg_add_string(msg, "objectCategory", value);
627 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
628 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
632 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
633 el = ldb_msg_find_element(msg, "systemFlags");
635 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
638 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
639 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
640 ldb_msg_remove_element(msg, el);
643 /* This flag is only allowed on attributeSchema objects */
644 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
645 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
648 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
649 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
650 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
651 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
652 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
653 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
655 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
656 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
657 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
658 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
661 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
663 if (el || systemFlags != 0) {
664 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
667 ret = ldb_msg_sanity_check(ldb, msg);
669 if (ret != LDB_SUCCESS) {
673 ret = ldb_build_add_req(&add_req, ldb, ac,
678 if (ret != LDB_SUCCESS) {
682 /* perform the add */
683 return ldb_next_request(ac->module, add_req);
686 static int oc_modify_callback(struct ldb_request *req,
687 struct ldb_reply *ares);
688 static int objectclass_do_mod(struct oc_context *ac);
690 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
692 struct ldb_context *ldb = ldb_module_get_ctx(module);
693 struct ldb_message_element *objectclass_element;
694 struct ldb_message *msg;
695 struct ldb_request *down_req;
696 struct oc_context *ac;
697 bool oc_changes = false;
700 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
702 /* do not manipulate our control entries */
703 if (ldb_dn_is_special(req->op.mod.message->dn)) {
704 return ldb_next_request(module, req);
707 /* As with the "real" AD we don't accept empty messages */
708 if (req->op.mod.message->num_elements == 0) {
709 ldb_set_errstring(ldb, "objectclass: modify message must have "
710 "elements/attributes!");
711 return LDB_ERR_UNWILLING_TO_PERFORM;
714 ac = oc_init_context(module, req);
716 return ldb_operr(ldb);
719 /* Without schema, there isn't much to do here */
720 if (ac->schema == NULL) {
722 return ldb_next_request(module, req);
725 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
727 return ldb_operr(ldb);
730 /* For now change everything except the objectclasses */
732 objectclass_element = ldb_msg_find_element(msg, "objectClass");
733 if (objectclass_element != NULL) {
734 ldb_msg_remove_attr(msg, "objectClass");
738 ret = ldb_build_mod_req(&down_req, ldb, ac,
741 oc_changes ? oc_modify_callback : oc_op_callback,
743 if (ret != LDB_SUCCESS) {
747 return ldb_next_request(module, down_req);
750 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
752 static const char * const attrs[] = { "objectClass", NULL };
753 struct ldb_context *ldb;
754 struct ldb_request *search_req;
755 struct oc_context *ac;
758 ac = talloc_get_type(req->context, struct oc_context);
759 ldb = ldb_module_get_ctx(ac->module);
762 return ldb_module_done(ac->req, NULL, NULL,
763 LDB_ERR_OPERATIONS_ERROR);
766 if (ares->type == LDB_REPLY_REFERRAL) {
767 return ldb_module_send_referral(ac->req, ares->referral);
770 if (ares->error != LDB_SUCCESS) {
771 return ldb_module_done(ac->req, ares->controls,
772 ares->response, ares->error);
775 if (ares->type != LDB_REPLY_DONE) {
777 return ldb_module_done(ac->req, NULL, NULL,
778 LDB_ERR_OPERATIONS_ERROR);
783 /* this looks up the real existing object for fetching some important
784 * informations (objectclasses) */
785 ret = ldb_build_search_req(&search_req, ldb,
786 ac, ac->req->op.mod.message->dn,
790 ac, get_search_callback,
792 if (ret != LDB_SUCCESS) {
793 return ldb_module_done(ac->req, NULL, NULL, ret);
796 ac->step_fn = objectclass_do_mod;
798 ret = ldb_next_request(ac->module, search_req);
799 if (ret != LDB_SUCCESS) {
800 return ldb_module_done(ac->req, NULL, NULL, ret);
806 static int objectclass_do_mod(struct oc_context *ac)
808 struct ldb_context *ldb;
809 struct ldb_request *mod_req;
811 struct ldb_message_element *oc_el_entry, *oc_el_change;
812 struct ldb_val *vals;
813 struct ldb_message *msg;
815 struct class_list *sorted, *current;
816 const struct dsdb_class *objectclass;
818 bool found, replace = false;
821 ldb = ldb_module_get_ctx(ac->module);
823 /* we should always have a valid entry when we enter here */
824 if (ac->search_res == NULL) {
825 return ldb_operr(ldb);
828 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
830 if (oc_el_entry == NULL) {
831 /* existing entry without a valid object class? */
832 return ldb_operr(ldb);
835 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
837 if (oc_el_change == NULL) {
838 /* we should have an objectclass change operation */
839 return ldb_operr(ldb);
842 /* use a new message structure */
843 msg = ldb_msg_new(ac);
848 msg->dn = ac->req->op.mod.message->dn;
850 mem_ctx = talloc_new(ac);
851 if (mem_ctx == NULL) {
855 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
856 case LDB_FLAG_MOD_ADD:
857 /* Merge the two message elements */
858 for (i = 0; i < oc_el_change->num_values; i++) {
859 for (j = 0; j < oc_el_entry->num_values; j++) {
860 if (strcasecmp((char *)oc_el_change->values[i].data,
861 (char *)oc_el_entry->values[j].data) == 0) {
862 /* we cannot add an already existing object class */
863 talloc_free(mem_ctx);
864 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
867 /* append the new object class value - code was copied
868 * from "ldb_msg_add_value" */
869 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
871 oc_el_entry->num_values + 1);
873 talloc_free(mem_ctx);
876 oc_el_entry->values = vals;
877 oc_el_entry->values[oc_el_entry->num_values] =
878 oc_el_change->values[i];
879 ++(oc_el_entry->num_values);
882 objectclass = get_last_structural_class(ac->schema,
884 if (objectclass != NULL) {
885 /* we cannot add a new structural object class */
886 talloc_free(mem_ctx);
887 return LDB_ERR_OBJECT_CLASS_VIOLATION;
890 /* Now do the sorting */
891 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
892 oc_el_entry, &sorted);
893 if (ret != LDB_SUCCESS) {
894 talloc_free(mem_ctx);
900 case LDB_FLAG_MOD_REPLACE:
901 /* Do the sorting for the change message element */
902 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
903 oc_el_change, &sorted);
904 if (ret != LDB_SUCCESS) {
905 talloc_free(mem_ctx);
909 /* this is a replace */
914 case LDB_FLAG_MOD_DELETE:
915 /* get the actual top-most structural objectclass */
916 objectclass = get_last_structural_class(ac->schema,
918 if (objectclass == NULL) {
919 talloc_free(mem_ctx);
920 return ldb_operr(ldb);
923 /* Merge the two message elements */
924 for (i = 0; i < oc_el_change->num_values; i++) {
926 for (j = 0; j < oc_el_entry->num_values; j++) {
927 if (strcasecmp((char *)oc_el_change->values[i].data,
928 (char *)oc_el_entry->values[j].data) == 0) {
930 /* delete the object class value -
931 * code was copied from
932 * "ldb_msg_remove_element" */
933 if (j != oc_el_entry->num_values - 1) {
934 memmove(&oc_el_entry->values[j],
935 &oc_el_entry->values[j+1],
936 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
938 --(oc_el_entry->num_values);
943 /* we cannot delete a not existing object class */
944 talloc_free(mem_ctx);
945 return LDB_ERR_NO_SUCH_ATTRIBUTE;
949 /* Make sure that the top-most structural objectclass wasn't
952 for (i = 0; i < oc_el_entry->num_values; i++) {
953 if (strcasecmp(objectclass->lDAPDisplayName,
954 (char *)oc_el_entry->values[i].data) == 0) {
959 talloc_free(mem_ctx);
960 return LDB_ERR_OBJECT_CLASS_VIOLATION;
964 /* Now do the sorting */
965 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
966 oc_el_entry, &sorted);
967 if (ret != LDB_SUCCESS) {
968 talloc_free(mem_ctx);
975 ret = ldb_msg_add_empty(msg, "objectClass",
976 LDB_FLAG_MOD_REPLACE, &oc_el_change);
977 if (ret != LDB_SUCCESS) {
979 talloc_free(mem_ctx);
983 /* Move from the linked list back into an ldb msg */
984 for (current = sorted; current; current = current->next) {
985 value = talloc_strdup(msg,
986 current->objectclass->lDAPDisplayName);
988 talloc_free(mem_ctx);
991 ret = ldb_msg_add_string(msg, "objectClass", value);
992 if (ret != LDB_SUCCESS) {
993 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
994 talloc_free(mem_ctx);
999 talloc_free(mem_ctx);
1002 /* Well, on replace we are nearly done: we have to test if
1003 * the change and entry message element are identically. We
1004 * can use "ldb_msg_element_compare" since now the specified
1005 * objectclasses match for sure in case. */
1006 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
1008 ret = ldb_msg_element_compare(oc_el_change,
1012 /* they are the same so we are done in this case */
1013 return ldb_module_done(ac->req, NULL, NULL,
1016 /* they're not exactly the same */
1017 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1021 /* in the other cases we have the real change left to do */
1023 ret = ldb_msg_sanity_check(ldb, msg);
1024 if (ret != LDB_SUCCESS) {
1028 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1033 if (ret != LDB_SUCCESS) {
1037 return ldb_next_request(ac->module, mod_req);
1040 static int objectclass_do_rename(struct oc_context *ac);
1042 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1044 static const char * const attrs[] = { "objectClass", NULL };
1045 struct ldb_context *ldb;
1046 struct ldb_request *search_req;
1047 struct oc_context *ac;
1048 struct ldb_dn *parent_dn;
1051 ldb = ldb_module_get_ctx(module);
1053 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1055 /* do not manipulate our control entries */
1056 if (ldb_dn_is_special(req->op.rename.newdn)) {
1057 return ldb_next_request(module, req);
1060 ac = oc_init_context(module, req);
1062 return ldb_operr(ldb);
1065 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1066 if (parent_dn == NULL) {
1067 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1068 ldb_dn_get_linearized(req->op.rename.olddn));
1069 return LDB_ERR_NO_SUCH_OBJECT;
1072 /* this looks up the parent object for fetching some important
1073 * informations (objectclasses, DN normalisation...) */
1074 ret = ldb_build_search_req(&search_req, ldb,
1075 ac, parent_dn, LDB_SCOPE_BASE,
1078 ac, get_search_callback,
1080 if (ret != LDB_SUCCESS) {
1084 /* we have to add the show deleted control, as otherwise DRS
1085 deletes will be refused as we will think the target parent
1087 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1089 if (ret != LDB_SUCCESS) {
1093 ac->step_fn = objectclass_do_rename;
1095 return ldb_next_request(ac->module, search_req);
1098 static int objectclass_do_rename2(struct oc_context *ac);
1100 static int objectclass_do_rename(struct oc_context *ac)
1102 static const char * const attrs[] = { "objectClass", NULL };
1103 struct ldb_context *ldb;
1104 struct ldb_request *search_req;
1107 ldb = ldb_module_get_ctx(ac->module);
1109 /* Check if we have a valid parent - this check is needed since
1110 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1111 if (ac->search_res == NULL) {
1112 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1113 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1114 return LDB_ERR_OTHER;
1117 /* now assign "search_res2" to the parent entry to have "search_res"
1118 * free for another lookup */
1119 ac->search_res2 = ac->search_res;
1120 ac->search_res = NULL;
1122 /* this looks up the real existing object for fetching some important
1123 * informations (objectclasses) */
1124 ret = ldb_build_search_req(&search_req, ldb,
1125 ac, ac->req->op.rename.olddn,
1129 ac, get_search_callback,
1131 if (ret != LDB_SUCCESS) {
1135 ac->step_fn = objectclass_do_rename2;
1137 return ldb_next_request(ac->module, search_req);
1140 static int objectclass_do_rename2(struct oc_context *ac)
1142 struct ldb_context *ldb;
1143 struct ldb_request *rename_req;
1144 struct ldb_dn *fixed_dn;
1147 ldb = ldb_module_get_ctx(ac->module);
1149 /* Check if we have a valid entry - this check is needed since
1150 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1151 if (ac->search_res == NULL) {
1152 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1153 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1154 return LDB_ERR_NO_SUCH_OBJECT;
1157 if (ac->schema != NULL) {
1158 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1159 const struct dsdb_class *objectclass;
1160 const char *rdn_name;
1161 bool allowed_class = false;
1164 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1166 if (oc_el_entry == NULL) {
1167 /* existing entry without a valid object class? */
1168 return ldb_operr(ldb);
1170 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1171 if (objectclass == NULL) {
1172 /* existing entry without a valid object class? */
1173 return ldb_operr(ldb);
1176 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1177 if ((objectclass->rDNAttID != NULL) &&
1178 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1179 ldb_asprintf_errstring(ldb,
1180 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1182 objectclass->lDAPDisplayName,
1183 objectclass->rDNAttID);
1184 return LDB_ERR_UNWILLING_TO_PERFORM;
1187 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1189 if (oc_el_parent == NULL) {
1190 /* existing entry without a valid object class? */
1191 return ldb_operr(ldb);
1194 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1195 const struct dsdb_class *sclass;
1197 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1198 &oc_el_parent->values[i]);
1200 /* We don't know this class? what is going on? */
1203 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1204 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1205 allowed_class = true;
1211 if (!allowed_class) {
1212 ldb_asprintf_errstring(ldb,
1213 "objectclass: structural objectClass %s is not a valid child class for %s",
1214 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1215 return LDB_ERR_NAMING_VIOLATION;
1219 /* Ensure we are not trying to rename it to be a child of itself */
1220 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1221 ac->req->op.rename.newdn) == 0) &&
1222 (ldb_dn_compare(ac->req->op.rename.olddn,
1223 ac->req->op.rename.newdn) != 0)) {
1224 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1225 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1226 return LDB_ERR_UNWILLING_TO_PERFORM;
1229 /* Fix up the DN to be in the standard form, taking
1230 * particular care to match the parent DN */
1231 ret = fix_dn(ldb, ac,
1232 ac->req->op.rename.newdn,
1233 ac->search_res2->message->dn,
1235 if (ret != LDB_SUCCESS) {
1236 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1237 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1242 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1243 ac->req->op.rename.olddn, fixed_dn,
1247 if (ret != LDB_SUCCESS) {
1251 /* perform the rename */
1252 return ldb_next_request(ac->module, rename_req);
1255 static int objectclass_do_delete(struct oc_context *ac);
1257 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1259 static const char * const attrs[] = { "nCName", "objectClass",
1260 "systemFlags", NULL };
1261 struct ldb_context *ldb;
1262 struct ldb_request *search_req;
1263 struct oc_context *ac;
1266 ldb = ldb_module_get_ctx(module);
1268 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1270 /* do not manipulate our control entries */
1271 if (ldb_dn_is_special(req->op.del.dn)) {
1272 return ldb_next_request(module, req);
1275 /* Bypass the constraint checks when we do have the "RELAX" control
1277 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1278 return ldb_next_request(module, req);
1281 ac = oc_init_context(module, req);
1283 return ldb_operr(ldb);
1286 /* this looks up the entry object for fetching some important
1287 * informations (object classes, system flags...) */
1288 ret = ldb_build_search_req(&search_req, ldb,
1289 ac, req->op.del.dn, LDB_SCOPE_BASE,
1292 ac, get_search_callback,
1294 if (ret != LDB_SUCCESS) {
1298 ac->step_fn = objectclass_do_delete;
1300 return ldb_next_request(ac->module, search_req);
1303 static int objectclass_do_delete(struct oc_context *ac)
1305 struct ldb_context *ldb;
1307 int32_t systemFlags;
1310 ldb = ldb_module_get_ctx(ac->module);
1312 /* Check if we have a valid entry - this check is needed since
1313 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1314 if (ac->search_res == NULL) {
1315 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1316 ldb_dn_get_linearized(ac->req->op.del.dn));
1317 return LDB_ERR_NO_SUCH_OBJECT;
1320 /* DC's ntDSDSA object */
1321 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1322 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1323 ldb_dn_get_linearized(ac->req->op.del.dn));
1324 return LDB_ERR_UNWILLING_TO_PERFORM;
1327 /* DC's rIDSet object */
1328 ret = samdb_rid_set_dn(ldb, ac, &dn);
1329 if (ret != LDB_SUCCESS) {
1333 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1335 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1336 ldb_dn_get_linearized(ac->req->op.del.dn));
1337 return LDB_ERR_UNWILLING_TO_PERFORM;
1342 /* crossRef objects regarding config, schema and default domain NCs */
1343 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1344 "crossRef") != NULL) {
1345 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1347 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1348 (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0) ||
1349 (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0)) {
1352 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the three main partitions!",
1353 ldb_dn_get_linearized(ac->req->op.del.dn));
1354 return LDB_ERR_UNWILLING_TO_PERFORM;
1361 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1363 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1364 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1365 ldb_dn_get_linearized(ac->req->op.del.dn));
1366 return LDB_ERR_UNWILLING_TO_PERFORM;
1369 return ldb_next_request(ac->module, ac->req);
1372 static int objectclass_init(struct ldb_module *module)
1374 struct ldb_context *ldb = ldb_module_get_ctx(module);
1377 /* Init everything else */
1378 ret = ldb_next_init(module);
1379 if (ret != LDB_SUCCESS) {
1383 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1384 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1389 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1390 .name = "objectclass",
1391 .add = objectclass_add,
1392 .modify = objectclass_modify,
1393 .rename = objectclass_rename,
1394 .del = objectclass_delete,
1395 .init_context = objectclass_init