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);
140 return LDB_ERR_OPERATIONS_ERROR;
142 current->objectclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &objectclass_element->values[i]);
143 if (!current->objectclass) {
144 ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema",
145 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
146 /* This looks weird, but windows apparently returns this for invalid objectClass values */
147 return LDB_ERR_NO_SUCH_ATTRIBUTE;
148 } else if (current->objectclass->isDefunct) {
149 ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects",
150 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
151 /* This looks weird, but windows apparently returns this for invalid objectClass values */
152 return LDB_ERR_NO_SUCH_ATTRIBUTE;
155 /* Don't add top to list, we will do that later */
156 if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) != 0) {
157 DLIST_ADD_END(unsorted, current, struct class_list *);
161 /* Add top here, to prevent duplicates */
162 current = talloc(mem_ctx, struct class_list);
163 current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
164 DLIST_ADD_END(sorted, current, struct class_list *);
167 /* For each object: find parent chain */
168 for (current = unsorted; schema && current; current = current->next) {
169 for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) {
170 if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) {
174 /* If we didn't get to the end of the list, we need to add this parent */
175 if (poss_parent || (ldb_attr_cmp("top", current->objectclass->subClassOf) == 0)) {
179 new_parent = talloc(mem_ctx, struct class_list);
180 new_parent->objectclass = dsdb_class_by_lDAPDisplayName(schema, current->objectclass->subClassOf);
181 DLIST_ADD_END(unsorted, new_parent, struct class_list *);
187 current_lowest = NULL;
188 for (current = unsorted; schema && current; current = current->next) {
189 if(current->objectclass->subClass_order < lowest) {
190 current_lowest = current;
191 lowest = current->objectclass->subClass_order;
195 if(current_lowest != NULL) {
196 DLIST_REMOVE(unsorted,current_lowest);
197 DLIST_ADD_END(sorted,current_lowest, struct class_list *);
203 *sorted_out = sorted;
208 /* If we don't have schema yet, then just merge the lists again */
209 DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
210 *sorted_out = sorted;
214 /* This shouldn't happen, and would break MMC, perhaps there
215 * was no 'top', a conflict in the objectClasses or some other
218 ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName);
219 return LDB_ERR_OBJECT_CLASS_VIOLATION;
222 static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares)
224 struct ldb_context *ldb;
225 struct oc_context *ac;
228 ac = talloc_get_type(req->context, struct oc_context);
229 ldb = ldb_module_get_ctx(ac->module);
232 return ldb_module_done(ac->req, NULL, NULL,
233 LDB_ERR_OPERATIONS_ERROR);
235 if (ares->error != LDB_SUCCESS &&
236 ares->error != LDB_ERR_NO_SUCH_OBJECT) {
237 return ldb_module_done(ac->req, ares->controls,
238 ares->response, ares->error);
241 ldb_reset_err_string(ldb);
243 switch (ares->type) {
244 case LDB_REPLY_ENTRY:
245 if (ac->search_res != NULL) {
246 ldb_set_errstring(ldb, "Too many results");
248 return ldb_module_done(ac->req, NULL, NULL,
249 LDB_ERR_OPERATIONS_ERROR);
252 ac->search_res = talloc_steal(ac, ares);
255 case LDB_REPLY_REFERRAL:
262 ret = ac->step_fn(ac);
263 if (ret != LDB_SUCCESS) {
264 return ldb_module_done(ac->req, NULL, NULL, ret);
272 static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)
274 struct oc_context *ac;
276 ac = talloc_get_type(req->context, struct oc_context);
279 return ldb_module_done(ac->req, NULL, NULL,
280 LDB_ERR_OPERATIONS_ERROR);
283 if (ares->type == LDB_REPLY_REFERRAL) {
284 return ldb_module_send_referral(ac->req, ares->referral);
287 if (ares->error != LDB_SUCCESS) {
288 return ldb_module_done(ac->req, ares->controls,
289 ares->response, ares->error);
292 if (ares->type != LDB_REPLY_DONE) {
294 return ldb_module_done(ac->req, NULL, NULL,
295 LDB_ERR_OPERATIONS_ERROR);
298 return ldb_module_done(ac->req, ares->controls,
299 ares->response, ares->error);
302 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN
304 This should mean that if the parent is:
305 CN=Users,DC=samba,DC=example,DC=com
306 and a proposed child is
307 cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM
309 The resulting DN should be:
311 CN=Admins,CN=Users,DC=samba,DC=example,DC=com
314 static int fix_dn(TALLOC_CTX *mem_ctx,
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_ERR_OPERATIONS_ERROR;
331 /* Create a new child */
332 if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
333 return LDB_ERR_OPERATIONS_ERROR;
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;
364 static const char * const parent_attrs[] = { "objectGUID", "objectClass", NULL };
366 ldb = ldb_module_get_ctx(module);
368 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
370 /* do not manipulate our control entries */
371 if (ldb_dn_is_special(req->op.add.message->dn)) {
372 return ldb_next_request(module, req);
375 /* the objectClass must be specified on add */
376 if (ldb_msg_find_element(req->op.add.message,
377 "objectClass") == NULL) {
378 return LDB_ERR_OBJECT_CLASS_VIOLATION;
381 ac = oc_init_context(module, req);
383 return LDB_ERR_OPERATIONS_ERROR;
386 /* If there isn't a parent, just go on to the add processing */
387 if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
388 return objectclass_do_add(ac);
391 /* get copy of parent DN */
392 parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
393 if (parent_dn == NULL) {
395 return LDB_ERR_OPERATIONS_ERROR;
398 ret = ldb_build_search_req(&search_req, ldb,
399 ac, parent_dn, LDB_SCOPE_BASE,
400 "(objectClass=*)", parent_attrs,
402 ac, get_search_callback,
404 if (ret != LDB_SUCCESS) {
408 ac->step_fn = objectclass_do_add;
410 return ldb_next_request(ac->module, search_req);
413 static int objectclass_do_add(struct oc_context *ac)
415 struct ldb_context *ldb;
416 struct ldb_request *add_req;
417 struct ldb_message_element *objectclass_element, *el;
418 struct ldb_message *msg;
420 struct class_list *sorted, *current;
421 const char *rdn_name = NULL;
423 const struct dsdb_class *objectclass;
424 int32_t systemFlags = 0;
427 ldb = ldb_module_get_ctx(ac->module);
429 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
431 /* Check if we have a valid parent - this check is needed since
432 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
433 if (ac->search_res == NULL) {
434 if (ldb_dn_compare(ldb_get_root_basedn(ldb), msg->dn) == 0) {
435 /* Allow the tree to be started but don't keep any
436 * error strings - they're meaningless. */
437 ldb_set_errstring(ldb, NULL);
439 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
440 ldb_dn_get_linearized(msg->dn));
441 return LDB_ERR_NO_SUCH_OBJECT;
444 /* Fix up the DN to be in the standard form, taking
445 * particular care to match the parent DN */
447 ac->req->op.add.message->dn,
448 ac->search_res->message->dn,
450 if (ret != LDB_SUCCESS) {
451 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
452 ldb_dn_get_linearized(ac->req->op.add.message->dn));
457 mem_ctx = talloc_new(ac);
458 if (mem_ctx == NULL) {
460 return LDB_ERR_OPERATIONS_ERROR;
463 if (ac->schema != NULL) {
464 /* This is now the objectClass list from the database */
465 objectclass_element = ldb_msg_find_element(msg, "objectClass");
467 if (!objectclass_element) {
468 /* Where did it go? bail now... */
469 talloc_free(mem_ctx);
470 return LDB_ERR_OPERATIONS_ERROR;
472 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
473 objectclass_element, &sorted);
474 if (ret != LDB_SUCCESS) {
475 talloc_free(mem_ctx);
479 ldb_msg_remove_attr(msg, "objectClass");
480 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
482 if (ret != LDB_SUCCESS) {
483 talloc_free(mem_ctx);
487 /* We must completely replace the existing objectClass entry,
488 * because we need it sorted */
490 /* Move from the linked list back into an ldb msg */
491 for (current = sorted; current; current = current->next) {
492 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
495 talloc_free(mem_ctx);
496 return LDB_ERR_OPERATIONS_ERROR;
498 ret = ldb_msg_add_string(msg, "objectClass", value);
499 if (ret != LDB_SUCCESS) {
500 ldb_set_errstring(ldb,
501 "objectclass: could not re-add sorted "
502 "objectclass to modify msg");
503 talloc_free(mem_ctx);
508 /* Retrive the message again so get_last_structural_class works */
509 objectclass_element = ldb_msg_find_element(msg, "objectClass");
511 /* Make sure its valid to add an object of this type */
512 objectclass = get_last_structural_class(ac->schema,
513 objectclass_element);
514 if(objectclass == NULL) {
515 ldb_asprintf_errstring(ldb,
516 "Failed to find a structural class for %s",
517 ldb_dn_get_linearized(msg->dn));
518 return LDB_ERR_UNWILLING_TO_PERFORM;
521 rdn_name = ldb_dn_get_rdn_name(msg->dn);
522 if (objectclass->rDNAttID
523 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
524 ldb_asprintf_errstring(ldb,
525 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
526 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
527 return LDB_ERR_NAMING_VIOLATION;
530 if (ac->search_res && ac->search_res->message) {
531 struct ldb_message_element *oc_el
532 = ldb_msg_find_element(ac->search_res->message, "objectClass");
534 bool allowed_class = false;
536 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
537 const struct dsdb_class *sclass;
539 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
542 /* We don't know this class? what is going on? */
545 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
546 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
547 allowed_class = true;
553 if (!allowed_class) {
554 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
555 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
556 return LDB_ERR_NAMING_VIOLATION;
560 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
561 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
562 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
563 return LDB_ERR_UNWILLING_TO_PERFORM;
566 if (!ldb_msg_find_element(msg, "objectCategory")) {
567 struct dsdb_extended_dn_store_format *dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct dsdb_extended_dn_store_format);
568 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
569 /* Strip off extended components */
570 struct ldb_dn *dn = ldb_dn_new(msg, ldb, objectclass->defaultObjectCategory);
571 value = ldb_dn_alloc_linearized(msg, dn);
574 value = talloc_strdup(msg, objectclass->defaultObjectCategory);
578 talloc_free(mem_ctx);
579 return LDB_ERR_OPERATIONS_ERROR;
581 ldb_msg_add_string(msg, "objectCategory", value);
583 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
584 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
588 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
589 el = ldb_msg_find_element(msg, "systemFlags");
591 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
594 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
595 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
596 ldb_msg_remove_element(msg, el);
599 /* This flag is only allowed on attributeSchema objects */
600 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
601 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
604 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
605 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
606 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
607 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
608 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
609 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
611 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
612 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
613 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
614 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
617 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
619 if (el || systemFlags != 0) {
620 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
624 talloc_free(mem_ctx);
625 ret = ldb_msg_sanity_check(ldb, msg);
628 if (ret != LDB_SUCCESS) {
632 ret = ldb_build_add_req(&add_req, ldb, ac,
637 if (ret != LDB_SUCCESS) {
641 /* perform the add */
642 return ldb_next_request(ac->module, add_req);
645 static int oc_modify_callback(struct ldb_request *req,
646 struct ldb_reply *ares);
647 static int objectclass_do_mod(struct oc_context *ac);
649 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
651 struct ldb_context *ldb = ldb_module_get_ctx(module);
652 struct ldb_message_element *objectclass_element;
653 struct ldb_message *msg;
654 struct ldb_request *down_req;
655 struct oc_context *ac;
656 bool oc_changes = false;
659 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
661 /* do not manipulate our control entries */
662 if (ldb_dn_is_special(req->op.mod.message->dn)) {
663 return ldb_next_request(module, req);
666 /* As with the "real" AD we don't accept empty messages */
667 if (req->op.mod.message->num_elements == 0) {
668 ldb_set_errstring(ldb, "objectclass: modify message must have "
669 "elements/attributes!");
670 return LDB_ERR_UNWILLING_TO_PERFORM;
673 ac = oc_init_context(module, req);
675 return LDB_ERR_OPERATIONS_ERROR;
678 /* Without schema, there isn't much to do here */
679 if (ac->schema == NULL) {
681 return ldb_next_request(module, req);
684 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
686 return LDB_ERR_OPERATIONS_ERROR;
689 /* For now change everything except the objectclasses */
691 objectclass_element = ldb_msg_find_element(msg, "objectClass");
692 if (objectclass_element != NULL) {
693 ldb_msg_remove_attr(msg, "objectClass");
697 ret = ldb_build_mod_req(&down_req, ldb, ac,
700 oc_changes ? oc_modify_callback : oc_op_callback,
702 if (ret != LDB_SUCCESS) {
706 return ldb_next_request(module, down_req);
709 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
711 static const char * const attrs[] = { "objectClass", NULL };
712 struct ldb_context *ldb;
713 struct ldb_request *search_req;
714 struct oc_context *ac;
717 ac = talloc_get_type(req->context, struct oc_context);
718 ldb = ldb_module_get_ctx(ac->module);
721 return ldb_module_done(ac->req, NULL, NULL,
722 LDB_ERR_OPERATIONS_ERROR);
725 if (ares->type == LDB_REPLY_REFERRAL) {
726 return ldb_module_send_referral(ac->req, ares->referral);
729 if (ares->error != LDB_SUCCESS) {
730 return ldb_module_done(ac->req, ares->controls,
731 ares->response, ares->error);
734 if (ares->type != LDB_REPLY_DONE) {
736 return ldb_module_done(ac->req, NULL, NULL,
737 LDB_ERR_OPERATIONS_ERROR);
742 /* this looks up the real existing object for fetching some important
743 * informations (objectclasses) */
744 ret = ldb_build_search_req(&search_req, ldb,
745 ac, ac->req->op.mod.message->dn,
749 ac, get_search_callback,
751 if (ret != LDB_SUCCESS) {
752 return ldb_module_done(ac->req, NULL, NULL, ret);
755 ac->step_fn = objectclass_do_mod;
757 ret = ldb_next_request(ac->module, search_req);
758 if (ret != LDB_SUCCESS) {
759 return ldb_module_done(ac->req, NULL, NULL, ret);
765 static int objectclass_do_mod(struct oc_context *ac)
767 struct ldb_context *ldb;
768 struct ldb_request *mod_req;
770 struct ldb_message_element *oc_el_entry, *oc_el_change;
771 struct ldb_val *vals;
772 struct ldb_message *msg;
774 struct class_list *sorted, *current;
775 const struct dsdb_class *objectclass;
777 bool found, replace = false;
780 ldb = ldb_module_get_ctx(ac->module);
782 /* we should always have a valid entry when we enter here */
783 if (ac->search_res == NULL) {
784 return LDB_ERR_OPERATIONS_ERROR;
787 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
789 if (oc_el_entry == NULL) {
790 /* existing entry without a valid object class? */
791 return LDB_ERR_OPERATIONS_ERROR;
794 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
796 if (oc_el_change == NULL) {
797 /* we should have an objectclass change operation */
798 return LDB_ERR_OPERATIONS_ERROR;
801 /* use a new message structure */
802 msg = ldb_msg_new(ac);
805 return LDB_ERR_OPERATIONS_ERROR;
808 msg->dn = ac->req->op.mod.message->dn;
810 mem_ctx = talloc_new(ac);
811 if (mem_ctx == NULL) {
813 return LDB_ERR_OPERATIONS_ERROR;
816 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
817 case LDB_FLAG_MOD_ADD:
818 /* Merge the two message elements */
819 for (i = 0; i < oc_el_change->num_values; i++) {
820 for (j = 0; j < oc_el_entry->num_values; j++) {
821 if (strcasecmp((char *)oc_el_change->values[i].data,
822 (char *)oc_el_entry->values[j].data) == 0) {
823 /* we cannot add an already existing object class */
824 talloc_free(mem_ctx);
825 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
828 /* append the new object class value - code was copied
829 * from "ldb_msg_add_value" */
830 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
832 oc_el_entry->num_values + 1);
835 talloc_free(mem_ctx);
836 return LDB_ERR_OPERATIONS_ERROR;
838 oc_el_entry->values = vals;
839 oc_el_entry->values[oc_el_entry->num_values] =
840 oc_el_change->values[i];
841 ++(oc_el_entry->num_values);
844 objectclass = get_last_structural_class(ac->schema,
846 if (objectclass != NULL) {
847 /* we cannot add a new structural object class */
848 talloc_free(mem_ctx);
849 return LDB_ERR_OBJECT_CLASS_VIOLATION;
852 /* Now do the sorting */
853 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
854 oc_el_entry, &sorted);
855 if (ret != LDB_SUCCESS) {
856 talloc_free(mem_ctx);
862 case LDB_FLAG_MOD_REPLACE:
863 /* Do the sorting for the change message element */
864 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
865 oc_el_change, &sorted);
866 if (ret != LDB_SUCCESS) {
867 talloc_free(mem_ctx);
871 /* this is a replace */
876 case LDB_FLAG_MOD_DELETE:
877 /* get the actual top-most structural objectclass */
878 objectclass = get_last_structural_class(ac->schema,
880 if (objectclass == NULL) {
881 talloc_free(mem_ctx);
882 return LDB_ERR_OPERATIONS_ERROR;
885 /* Merge the two message elements */
886 for (i = 0; i < oc_el_change->num_values; i++) {
888 for (j = 0; j < oc_el_entry->num_values; j++) {
889 if (strcasecmp((char *)oc_el_change->values[i].data,
890 (char *)oc_el_entry->values[j].data) == 0) {
892 /* delete the object class value -
893 * code was copied from
894 * "ldb_msg_remove_element" */
895 if (j != oc_el_entry->num_values - 1) {
896 memmove(&oc_el_entry->values[j],
897 &oc_el_entry->values[j+1],
898 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
900 --(oc_el_entry->num_values);
905 /* we cannot delete a not existing object class */
906 talloc_free(mem_ctx);
907 return LDB_ERR_NO_SUCH_ATTRIBUTE;
911 /* Make sure that the top-most structural objectclass wasn't
914 for (i = 0; i < oc_el_entry->num_values; i++) {
915 if (strcasecmp(objectclass->lDAPDisplayName,
916 (char *)oc_el_entry->values[i].data) == 0) {
921 talloc_free(mem_ctx);
922 return LDB_ERR_OBJECT_CLASS_VIOLATION;
926 /* Now do the sorting */
927 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
928 oc_el_entry, &sorted);
929 if (ret != LDB_SUCCESS) {
930 talloc_free(mem_ctx);
937 ret = ldb_msg_add_empty(msg, "objectClass",
938 LDB_FLAG_MOD_REPLACE, &oc_el_change);
939 if (ret != LDB_SUCCESS) {
941 talloc_free(mem_ctx);
945 /* Move from the linked list back into an ldb msg */
946 for (current = sorted; current; current = current->next) {
947 value = talloc_strdup(msg,
948 current->objectclass->lDAPDisplayName);
951 talloc_free(mem_ctx);
952 return LDB_ERR_OPERATIONS_ERROR;
954 ret = ldb_msg_add_string(msg, "objectClass", value);
955 if (ret != LDB_SUCCESS) {
956 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
957 talloc_free(mem_ctx);
962 talloc_free(mem_ctx);
965 /* Well, on replace we are nearly done: we have to test if
966 * the change and entry message element are identically. We
967 * can use "ldb_msg_element_compare" since now the specified
968 * objectclasses match for sure in case. */
969 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
971 ret = ldb_msg_element_compare(oc_el_change,
975 /* they are the same so we are done in this case */
976 return ldb_module_done(ac->req, NULL, NULL,
979 /* they're not exactly the same */
980 return LDB_ERR_OBJECT_CLASS_VIOLATION;
984 /* in the other cases we have the real change left to do */
986 ret = ldb_msg_sanity_check(ldb, msg);
987 if (ret != LDB_SUCCESS) {
991 ret = ldb_build_mod_req(&mod_req, ldb, ac,
996 if (ret != LDB_SUCCESS) {
1000 return ldb_next_request(ac->module, mod_req);
1003 static int objectclass_do_rename(struct oc_context *ac);
1005 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1007 static const char * const attrs[] = { "objectClass", NULL };
1008 struct ldb_context *ldb;
1009 struct ldb_request *search_req;
1010 struct oc_context *ac;
1011 struct ldb_dn *parent_dn;
1014 ldb = ldb_module_get_ctx(module);
1016 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1018 /* do not manipulate our control entries */
1019 if (ldb_dn_is_special(req->op.rename.newdn)) {
1020 return ldb_next_request(module, req);
1023 ac = oc_init_context(module, req);
1025 return LDB_ERR_OPERATIONS_ERROR;
1028 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1029 if (parent_dn == NULL) {
1031 return LDB_ERR_OPERATIONS_ERROR;
1034 /* this looks up the parent object for fetching some important
1035 * informations (objectclasses, DN normalisation...) */
1036 ret = ldb_build_search_req(&search_req, ldb,
1037 ac, parent_dn, LDB_SCOPE_BASE,
1040 ac, get_search_callback,
1042 if (ret != LDB_SUCCESS) {
1046 /* we have to add the show deleted control, as otherwise DRS
1047 deletes will be refused as we will think the target parent
1049 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1051 if (ret != LDB_SUCCESS) {
1055 ac->step_fn = objectclass_do_rename;
1057 return ldb_next_request(ac->module, search_req);
1060 static int objectclass_do_rename2(struct oc_context *ac);
1062 static int objectclass_do_rename(struct oc_context *ac)
1064 static const char * const attrs[] = { "objectClass", NULL };
1065 struct ldb_context *ldb;
1066 struct ldb_request *search_req;
1069 ldb = ldb_module_get_ctx(ac->module);
1071 /* Check if we have a valid parent - this check is needed since
1072 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1073 if (ac->search_res == NULL) {
1074 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1075 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1076 return LDB_ERR_OTHER;
1079 /* now assign "search_res2" to the parent entry to have "search_res"
1080 * free for another lookup */
1081 ac->search_res2 = ac->search_res;
1082 ac->search_res = NULL;
1084 /* this looks up the real existing object for fetching some important
1085 * informations (objectclasses) */
1086 ret = ldb_build_search_req(&search_req, ldb,
1087 ac, ac->req->op.rename.olddn,
1091 ac, get_search_callback,
1093 if (ret != LDB_SUCCESS) {
1097 ac->step_fn = objectclass_do_rename2;
1099 return ldb_next_request(ac->module, search_req);
1102 static int objectclass_do_rename2(struct oc_context *ac)
1104 struct ldb_context *ldb;
1105 struct ldb_request *rename_req;
1106 struct ldb_dn *fixed_dn;
1109 ldb = ldb_module_get_ctx(ac->module);
1111 /* Check if we have a valid entry - this check is needed since
1112 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1113 if (ac->search_res == NULL) {
1114 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1115 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1116 return LDB_ERR_NO_SUCH_OBJECT;
1119 if (ac->schema != NULL) {
1120 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1121 const struct dsdb_class *objectclass;
1122 const char *rdn_name;
1123 bool allowed_class = false;
1126 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1128 if (oc_el_entry == NULL) {
1129 /* existing entry without a valid object class? */
1130 return LDB_ERR_OPERATIONS_ERROR;
1132 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1133 if (objectclass == NULL) {
1134 /* existing entry without a valid object class? */
1135 return LDB_ERR_OPERATIONS_ERROR;
1138 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1139 if ((objectclass->rDNAttID != NULL) &&
1140 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1141 ldb_asprintf_errstring(ldb,
1142 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1144 objectclass->lDAPDisplayName,
1145 objectclass->rDNAttID);
1146 return LDB_ERR_UNWILLING_TO_PERFORM;
1149 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1151 if (oc_el_parent == NULL) {
1152 /* existing entry without a valid object class? */
1153 return LDB_ERR_OPERATIONS_ERROR;
1156 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1157 const struct dsdb_class *sclass;
1159 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1160 &oc_el_parent->values[i]);
1162 /* We don't know this class? what is going on? */
1165 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1166 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1167 allowed_class = true;
1173 if (!allowed_class) {
1174 ldb_asprintf_errstring(ldb,
1175 "objectclass: structural objectClass %s is not a valid child class for %s",
1176 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1177 return LDB_ERR_NAMING_VIOLATION;
1181 /* Ensure we are not trying to rename it to be a child of itself */
1182 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1183 ac->req->op.rename.newdn) == 0) &&
1184 (ldb_dn_compare(ac->req->op.rename.olddn,
1185 ac->req->op.rename.newdn) != 0)) {
1186 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1187 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1188 return LDB_ERR_UNWILLING_TO_PERFORM;
1191 /* Fix up the DN to be in the standard form, taking
1192 * particular care to match the parent DN */
1194 ac->req->op.rename.newdn,
1195 ac->search_res2->message->dn,
1197 if (ret != LDB_SUCCESS) {
1198 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1199 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1204 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1205 ac->req->op.rename.olddn, fixed_dn,
1209 if (ret != LDB_SUCCESS) {
1213 /* perform the rename */
1214 return ldb_next_request(ac->module, rename_req);
1217 static int objectclass_init(struct ldb_module *module)
1219 struct ldb_context *ldb = ldb_module_get_ctx(module);
1221 /* Init everything else */
1222 ret = ldb_next_init(module);
1223 if (ret != LDB_SUCCESS) {
1227 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1228 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1233 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1234 .name = "objectclass",
1235 .add = objectclass_add,
1236 .modify = objectclass_modify,
1237 .rename = objectclass_rename,
1238 .init_context = objectclass_init