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 root basedn has a special handling when the
378 * relax control isn't specified. */
379 if (ldb_dn_compare(ldb_get_root_basedn(ldb), req->op.add.message->dn) == 0) {
380 if (ldb_request_get_control(req,
381 LDB_CONTROL_RELAX_OID) == NULL) {
382 /* When we are trying to readd the root basedn then
383 * this is denied, but with an interesting mechanism:
384 * there is generated a referral with the last
385 * component value as hostname. */
386 val = ldb_dn_get_component_val(req->op.add.message->dn,
387 ldb_dn_get_comp_num(req->op.add.message->dn) - 1);
389 return ldb_operr(ldb);
391 value = talloc_asprintf(req, "ldap://%s/%s", val->data,
392 ldb_dn_get_linearized(req->op.add.message->dn));
397 return ldb_module_send_referral(req, value);
401 /* the various objectclasses must be specified on add operations */
402 if (ldb_msg_find_element(req->op.add.message, "objectClass") == NULL) {
403 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
404 ldb_dn_get_linearized(req->op.add.message->dn));
405 return LDB_ERR_OBJECT_CLASS_VIOLATION;
408 ac = oc_init_context(module, req);
410 return ldb_operr(ldb);
413 /* If there isn't a parent, just go on to the add processing */
414 if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
415 return objectclass_do_add(ac);
418 /* get copy of parent DN */
419 parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
420 if (parent_dn == NULL) {
424 ret = ldb_build_search_req(&search_req, ldb,
425 ac, parent_dn, LDB_SCOPE_BASE,
426 "(objectClass=*)", parent_attrs,
428 ac, get_search_callback,
430 if (ret != LDB_SUCCESS) {
434 ac->step_fn = objectclass_do_add;
436 return ldb_next_request(ac->module, search_req);
439 static int objectclass_do_add(struct oc_context *ac)
441 struct ldb_context *ldb;
442 struct ldb_request *add_req;
443 struct ldb_message_element *objectclass_element, *el;
444 struct ldb_message *msg;
446 struct class_list *sorted, *current;
447 const char *rdn_name = NULL;
449 const struct dsdb_class *objectclass;
450 int32_t systemFlags = 0;
453 ldb = ldb_module_get_ctx(ac->module);
455 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
457 /* Check if we have a valid parent - this check is needed since
458 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
459 if (ac->search_res == NULL) {
460 if (ldb_dn_compare(ldb_get_root_basedn(ldb), msg->dn) == 0) {
461 /* Allow the tree to be started but don't keep any
462 * error strings - they're meaningless. */
463 ldb_set_errstring(ldb, NULL);
465 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
466 ldb_dn_get_linearized(msg->dn));
467 return LDB_ERR_NO_SUCH_OBJECT;
470 /* Fix up the DN to be in the standard form, taking
471 * particular care to match the parent DN */
472 ret = fix_dn(ldb, msg,
473 ac->req->op.add.message->dn,
474 ac->search_res->message->dn,
476 if (ret != LDB_SUCCESS) {
477 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
478 ldb_dn_get_linearized(ac->req->op.add.message->dn));
483 mem_ctx = talloc_new(ac);
484 if (mem_ctx == NULL) {
488 if (ac->schema != NULL) {
489 /* This is now the objectClass list from the database */
490 objectclass_element = ldb_msg_find_element(msg, "objectClass");
492 if (!objectclass_element) {
493 /* Where did it go? bail now... */
494 talloc_free(mem_ctx);
495 return ldb_operr(ldb);
497 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
498 objectclass_element, &sorted);
499 if (ret != LDB_SUCCESS) {
500 talloc_free(mem_ctx);
504 ldb_msg_remove_attr(msg, "objectClass");
505 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
507 if (ret != LDB_SUCCESS) {
508 talloc_free(mem_ctx);
512 /* We must completely replace the existing objectClass entry,
513 * because we need it sorted */
515 /* Move from the linked list back into an ldb msg */
516 for (current = sorted; current; current = current->next) {
517 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
519 talloc_free(mem_ctx);
522 ret = ldb_msg_add_string(msg, "objectClass", value);
523 if (ret != LDB_SUCCESS) {
524 ldb_set_errstring(ldb,
525 "objectclass: could not re-add sorted "
526 "objectclass to modify msg");
527 talloc_free(mem_ctx);
532 /* Retrive the message again so get_last_structural_class works */
533 objectclass_element = ldb_msg_find_element(msg, "objectClass");
535 /* Make sure its valid to add an object of this type */
536 objectclass = get_last_structural_class(ac->schema,
537 objectclass_element);
538 if(objectclass == NULL) {
539 ldb_asprintf_errstring(ldb,
540 "Failed to find a structural class for %s",
541 ldb_dn_get_linearized(msg->dn));
542 return LDB_ERR_UNWILLING_TO_PERFORM;
545 rdn_name = ldb_dn_get_rdn_name(msg->dn);
546 if (objectclass->rDNAttID
547 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
548 ldb_asprintf_errstring(ldb,
549 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
550 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
551 return LDB_ERR_NAMING_VIOLATION;
554 if (ac->search_res && ac->search_res->message) {
555 struct ldb_message_element *oc_el
556 = ldb_msg_find_element(ac->search_res->message, "objectClass");
558 bool allowed_class = false;
560 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
561 const struct dsdb_class *sclass;
563 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
566 /* We don't know this class? what is going on? */
569 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
570 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
571 allowed_class = true;
577 if (!allowed_class) {
578 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
579 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
580 return LDB_ERR_NAMING_VIOLATION;
584 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
585 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
586 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
587 return LDB_ERR_UNWILLING_TO_PERFORM;
590 if (!ldb_msg_find_element(msg, "objectCategory")) {
591 struct dsdb_extended_dn_store_format *dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct dsdb_extended_dn_store_format);
592 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
593 /* Strip off extended components */
594 struct ldb_dn *dn = ldb_dn_new(msg, ldb, objectclass->defaultObjectCategory);
595 value = ldb_dn_alloc_linearized(msg, dn);
598 value = talloc_strdup(msg, objectclass->defaultObjectCategory);
601 talloc_free(mem_ctx);
604 ldb_msg_add_string(msg, "objectCategory", value);
606 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
607 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
611 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
612 el = ldb_msg_find_element(msg, "systemFlags");
614 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
617 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
618 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
619 ldb_msg_remove_element(msg, el);
622 /* This flag is only allowed on attributeSchema objects */
623 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
624 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
627 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
628 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
629 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
630 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
631 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
632 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
634 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
635 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
636 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
637 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
640 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
642 if (el || systemFlags != 0) {
643 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
647 talloc_free(mem_ctx);
648 ret = ldb_msg_sanity_check(ldb, msg);
651 if (ret != LDB_SUCCESS) {
655 ret = ldb_build_add_req(&add_req, ldb, ac,
660 if (ret != LDB_SUCCESS) {
664 /* perform the add */
665 return ldb_next_request(ac->module, add_req);
668 static int oc_modify_callback(struct ldb_request *req,
669 struct ldb_reply *ares);
670 static int objectclass_do_mod(struct oc_context *ac);
672 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
674 struct ldb_context *ldb = ldb_module_get_ctx(module);
675 struct ldb_message_element *objectclass_element;
676 struct ldb_message *msg;
677 struct ldb_request *down_req;
678 struct oc_context *ac;
679 bool oc_changes = false;
682 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
684 /* do not manipulate our control entries */
685 if (ldb_dn_is_special(req->op.mod.message->dn)) {
686 return ldb_next_request(module, req);
689 /* As with the "real" AD we don't accept empty messages */
690 if (req->op.mod.message->num_elements == 0) {
691 ldb_set_errstring(ldb, "objectclass: modify message must have "
692 "elements/attributes!");
693 return LDB_ERR_UNWILLING_TO_PERFORM;
696 ac = oc_init_context(module, req);
698 return ldb_operr(ldb);
701 /* Without schema, there isn't much to do here */
702 if (ac->schema == NULL) {
704 return ldb_next_request(module, req);
707 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
709 return ldb_operr(ldb);
712 /* For now change everything except the objectclasses */
714 objectclass_element = ldb_msg_find_element(msg, "objectClass");
715 if (objectclass_element != NULL) {
716 ldb_msg_remove_attr(msg, "objectClass");
720 ret = ldb_build_mod_req(&down_req, ldb, ac,
723 oc_changes ? oc_modify_callback : oc_op_callback,
725 if (ret != LDB_SUCCESS) {
729 return ldb_next_request(module, down_req);
732 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
734 static const char * const attrs[] = { "objectClass", NULL };
735 struct ldb_context *ldb;
736 struct ldb_request *search_req;
737 struct oc_context *ac;
740 ac = talloc_get_type(req->context, struct oc_context);
741 ldb = ldb_module_get_ctx(ac->module);
744 return ldb_module_done(ac->req, NULL, NULL,
745 LDB_ERR_OPERATIONS_ERROR);
748 if (ares->type == LDB_REPLY_REFERRAL) {
749 return ldb_module_send_referral(ac->req, ares->referral);
752 if (ares->error != LDB_SUCCESS) {
753 return ldb_module_done(ac->req, ares->controls,
754 ares->response, ares->error);
757 if (ares->type != LDB_REPLY_DONE) {
759 return ldb_module_done(ac->req, NULL, NULL,
760 LDB_ERR_OPERATIONS_ERROR);
765 /* this looks up the real existing object for fetching some important
766 * informations (objectclasses) */
767 ret = ldb_build_search_req(&search_req, ldb,
768 ac, ac->req->op.mod.message->dn,
772 ac, get_search_callback,
774 if (ret != LDB_SUCCESS) {
775 return ldb_module_done(ac->req, NULL, NULL, ret);
778 ac->step_fn = objectclass_do_mod;
780 ret = ldb_next_request(ac->module, search_req);
781 if (ret != LDB_SUCCESS) {
782 return ldb_module_done(ac->req, NULL, NULL, ret);
788 static int objectclass_do_mod(struct oc_context *ac)
790 struct ldb_context *ldb;
791 struct ldb_request *mod_req;
793 struct ldb_message_element *oc_el_entry, *oc_el_change;
794 struct ldb_val *vals;
795 struct ldb_message *msg;
797 struct class_list *sorted, *current;
798 const struct dsdb_class *objectclass;
800 bool found, replace = false;
803 ldb = ldb_module_get_ctx(ac->module);
805 /* we should always have a valid entry when we enter here */
806 if (ac->search_res == NULL) {
807 return ldb_operr(ldb);
810 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
812 if (oc_el_entry == NULL) {
813 /* existing entry without a valid object class? */
814 return ldb_operr(ldb);
817 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
819 if (oc_el_change == NULL) {
820 /* we should have an objectclass change operation */
821 return ldb_operr(ldb);
824 /* use a new message structure */
825 msg = ldb_msg_new(ac);
830 msg->dn = ac->req->op.mod.message->dn;
832 mem_ctx = talloc_new(ac);
833 if (mem_ctx == NULL) {
837 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
838 case LDB_FLAG_MOD_ADD:
839 /* Merge the two message elements */
840 for (i = 0; i < oc_el_change->num_values; i++) {
841 for (j = 0; j < oc_el_entry->num_values; j++) {
842 if (strcasecmp((char *)oc_el_change->values[i].data,
843 (char *)oc_el_entry->values[j].data) == 0) {
844 /* we cannot add an already existing object class */
845 talloc_free(mem_ctx);
846 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
849 /* append the new object class value - code was copied
850 * from "ldb_msg_add_value" */
851 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
853 oc_el_entry->num_values + 1);
855 talloc_free(mem_ctx);
858 oc_el_entry->values = vals;
859 oc_el_entry->values[oc_el_entry->num_values] =
860 oc_el_change->values[i];
861 ++(oc_el_entry->num_values);
864 objectclass = get_last_structural_class(ac->schema,
866 if (objectclass != NULL) {
867 /* we cannot add a new structural object class */
868 talloc_free(mem_ctx);
869 return LDB_ERR_OBJECT_CLASS_VIOLATION;
872 /* Now do the sorting */
873 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
874 oc_el_entry, &sorted);
875 if (ret != LDB_SUCCESS) {
876 talloc_free(mem_ctx);
882 case LDB_FLAG_MOD_REPLACE:
883 /* Do the sorting for the change message element */
884 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
885 oc_el_change, &sorted);
886 if (ret != LDB_SUCCESS) {
887 talloc_free(mem_ctx);
891 /* this is a replace */
896 case LDB_FLAG_MOD_DELETE:
897 /* get the actual top-most structural objectclass */
898 objectclass = get_last_structural_class(ac->schema,
900 if (objectclass == NULL) {
901 talloc_free(mem_ctx);
902 return ldb_operr(ldb);
905 /* Merge the two message elements */
906 for (i = 0; i < oc_el_change->num_values; i++) {
908 for (j = 0; j < oc_el_entry->num_values; j++) {
909 if (strcasecmp((char *)oc_el_change->values[i].data,
910 (char *)oc_el_entry->values[j].data) == 0) {
912 /* delete the object class value -
913 * code was copied from
914 * "ldb_msg_remove_element" */
915 if (j != oc_el_entry->num_values - 1) {
916 memmove(&oc_el_entry->values[j],
917 &oc_el_entry->values[j+1],
918 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
920 --(oc_el_entry->num_values);
925 /* we cannot delete a not existing object class */
926 talloc_free(mem_ctx);
927 return LDB_ERR_NO_SUCH_ATTRIBUTE;
931 /* Make sure that the top-most structural objectclass wasn't
934 for (i = 0; i < oc_el_entry->num_values; i++) {
935 if (strcasecmp(objectclass->lDAPDisplayName,
936 (char *)oc_el_entry->values[i].data) == 0) {
941 talloc_free(mem_ctx);
942 return LDB_ERR_OBJECT_CLASS_VIOLATION;
946 /* Now do the sorting */
947 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
948 oc_el_entry, &sorted);
949 if (ret != LDB_SUCCESS) {
950 talloc_free(mem_ctx);
957 ret = ldb_msg_add_empty(msg, "objectClass",
958 LDB_FLAG_MOD_REPLACE, &oc_el_change);
959 if (ret != LDB_SUCCESS) {
961 talloc_free(mem_ctx);
965 /* Move from the linked list back into an ldb msg */
966 for (current = sorted; current; current = current->next) {
967 value = talloc_strdup(msg,
968 current->objectclass->lDAPDisplayName);
970 talloc_free(mem_ctx);
973 ret = ldb_msg_add_string(msg, "objectClass", value);
974 if (ret != LDB_SUCCESS) {
975 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
976 talloc_free(mem_ctx);
981 talloc_free(mem_ctx);
984 /* Well, on replace we are nearly done: we have to test if
985 * the change and entry message element are identically. We
986 * can use "ldb_msg_element_compare" since now the specified
987 * objectclasses match for sure in case. */
988 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
990 ret = ldb_msg_element_compare(oc_el_change,
994 /* they are the same so we are done in this case */
995 return ldb_module_done(ac->req, NULL, NULL,
998 /* they're not exactly the same */
999 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1003 /* in the other cases we have the real change left to do */
1005 ret = ldb_msg_sanity_check(ldb, msg);
1006 if (ret != LDB_SUCCESS) {
1010 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1015 if (ret != LDB_SUCCESS) {
1019 return ldb_next_request(ac->module, mod_req);
1022 static int objectclass_do_rename(struct oc_context *ac);
1024 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1026 static const char * const attrs[] = { "objectClass", NULL };
1027 struct ldb_context *ldb;
1028 struct ldb_request *search_req;
1029 struct oc_context *ac;
1030 struct ldb_dn *parent_dn;
1033 ldb = ldb_module_get_ctx(module);
1035 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1037 /* do not manipulate our control entries */
1038 if (ldb_dn_is_special(req->op.rename.newdn)) {
1039 return ldb_next_request(module, req);
1042 ac = oc_init_context(module, req);
1044 return ldb_operr(ldb);
1047 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1048 if (parent_dn == NULL) {
1049 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1050 ldb_dn_get_linearized(req->op.rename.olddn));
1051 return LDB_ERR_NO_SUCH_OBJECT;
1054 /* this looks up the parent object for fetching some important
1055 * informations (objectclasses, DN normalisation...) */
1056 ret = ldb_build_search_req(&search_req, ldb,
1057 ac, parent_dn, LDB_SCOPE_BASE,
1060 ac, get_search_callback,
1062 if (ret != LDB_SUCCESS) {
1066 /* we have to add the show deleted control, as otherwise DRS
1067 deletes will be refused as we will think the target parent
1069 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1071 if (ret != LDB_SUCCESS) {
1075 ac->step_fn = objectclass_do_rename;
1077 return ldb_next_request(ac->module, search_req);
1080 static int objectclass_do_rename2(struct oc_context *ac);
1082 static int objectclass_do_rename(struct oc_context *ac)
1084 static const char * const attrs[] = { "objectClass", NULL };
1085 struct ldb_context *ldb;
1086 struct ldb_request *search_req;
1089 ldb = ldb_module_get_ctx(ac->module);
1091 /* Check if we have a valid parent - this check is needed since
1092 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1093 if (ac->search_res == NULL) {
1094 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1095 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1096 return LDB_ERR_OTHER;
1099 /* now assign "search_res2" to the parent entry to have "search_res"
1100 * free for another lookup */
1101 ac->search_res2 = ac->search_res;
1102 ac->search_res = NULL;
1104 /* this looks up the real existing object for fetching some important
1105 * informations (objectclasses) */
1106 ret = ldb_build_search_req(&search_req, ldb,
1107 ac, ac->req->op.rename.olddn,
1111 ac, get_search_callback,
1113 if (ret != LDB_SUCCESS) {
1117 ac->step_fn = objectclass_do_rename2;
1119 return ldb_next_request(ac->module, search_req);
1122 static int objectclass_do_rename2(struct oc_context *ac)
1124 struct ldb_context *ldb;
1125 struct ldb_request *rename_req;
1126 struct ldb_dn *fixed_dn;
1129 ldb = ldb_module_get_ctx(ac->module);
1131 /* Check if we have a valid entry - this check is needed since
1132 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1133 if (ac->search_res == NULL) {
1134 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1135 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1136 return LDB_ERR_NO_SUCH_OBJECT;
1139 if (ac->schema != NULL) {
1140 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1141 const struct dsdb_class *objectclass;
1142 const char *rdn_name;
1143 bool allowed_class = false;
1146 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1148 if (oc_el_entry == NULL) {
1149 /* existing entry without a valid object class? */
1150 return ldb_operr(ldb);
1152 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1153 if (objectclass == NULL) {
1154 /* existing entry without a valid object class? */
1155 return ldb_operr(ldb);
1158 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1159 if ((objectclass->rDNAttID != NULL) &&
1160 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1161 ldb_asprintf_errstring(ldb,
1162 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1164 objectclass->lDAPDisplayName,
1165 objectclass->rDNAttID);
1166 return LDB_ERR_UNWILLING_TO_PERFORM;
1169 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1171 if (oc_el_parent == NULL) {
1172 /* existing entry without a valid object class? */
1173 return ldb_operr(ldb);
1176 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1177 const struct dsdb_class *sclass;
1179 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1180 &oc_el_parent->values[i]);
1182 /* We don't know this class? what is going on? */
1185 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1186 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1187 allowed_class = true;
1193 if (!allowed_class) {
1194 ldb_asprintf_errstring(ldb,
1195 "objectclass: structural objectClass %s is not a valid child class for %s",
1196 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1197 return LDB_ERR_NAMING_VIOLATION;
1201 /* Ensure we are not trying to rename it to be a child of itself */
1202 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1203 ac->req->op.rename.newdn) == 0) &&
1204 (ldb_dn_compare(ac->req->op.rename.olddn,
1205 ac->req->op.rename.newdn) != 0)) {
1206 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1207 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1208 return LDB_ERR_UNWILLING_TO_PERFORM;
1211 /* Fix up the DN to be in the standard form, taking
1212 * particular care to match the parent DN */
1213 ret = fix_dn(ldb, ac,
1214 ac->req->op.rename.newdn,
1215 ac->search_res2->message->dn,
1217 if (ret != LDB_SUCCESS) {
1218 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1219 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1224 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1225 ac->req->op.rename.olddn, fixed_dn,
1229 if (ret != LDB_SUCCESS) {
1233 /* perform the rename */
1234 return ldb_next_request(ac->module, rename_req);
1237 static int objectclass_do_delete(struct oc_context *ac);
1239 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1241 static const char * const attrs[] = { "systemFlags", NULL };
1242 struct ldb_context *ldb;
1243 struct ldb_request *search_req;
1244 struct oc_context *ac;
1247 ldb = ldb_module_get_ctx(module);
1249 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1251 /* do not manipulate our control entries */
1252 if (ldb_dn_is_special(req->op.del.dn)) {
1253 return ldb_next_request(module, req);
1256 /* Bypass the "systemFlags" checks when we do have the "RELAX" control
1258 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1259 return ldb_next_request(module, req);
1262 ac = oc_init_context(module, req);
1264 return ldb_operr(ldb);
1267 /* this looks up the entry object for fetching some important
1268 * informations (systemFlags...) */
1269 ret = ldb_build_search_req(&search_req, ldb,
1270 ac, req->op.del.dn, LDB_SCOPE_BASE,
1273 ac, get_search_callback,
1275 if (ret != LDB_SUCCESS) {
1279 ac->step_fn = objectclass_do_delete;
1281 return ldb_next_request(ac->module, search_req);
1284 static int objectclass_do_delete(struct oc_context *ac)
1286 struct ldb_context *ldb;
1287 int32_t systemFlags;
1289 ldb = ldb_module_get_ctx(ac->module);
1291 /* Check if we have a valid entry - this check is needed since
1292 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1293 if (ac->search_res == NULL) {
1294 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1295 ldb_dn_get_linearized(ac->req->op.del.dn));
1296 return LDB_ERR_NO_SUCH_OBJECT;
1299 systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1301 if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1302 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1303 ldb_dn_get_linearized(ac->req->op.del.dn));
1304 return LDB_ERR_UNWILLING_TO_PERFORM;
1307 return ldb_next_request(ac->module, ac->req);
1310 static int objectclass_init(struct ldb_module *module)
1312 struct ldb_context *ldb = ldb_module_get_ctx(module);
1315 /* Init everything else */
1316 ret = ldb_next_init(module);
1317 if (ret != LDB_SUCCESS) {
1321 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1322 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1327 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1328 .name = "objectclass",
1329 .add = objectclass_add,
1330 .modify = objectclass_modify,
1331 .rename = objectclass_rename,
1332 .del = objectclass_delete,
1333 .init_context = objectclass_init