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;
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_ERR_OPERATIONS_ERROR;
391 value = talloc_asprintf(req, "ldap://%s/%s", val->data,
392 ldb_dn_get_linearized(req->op.add.message->dn));
394 return LDB_ERR_OPERATIONS_ERROR;
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_ERR_OPERATIONS_ERROR;
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) {
422 return LDB_ERR_OPERATIONS_ERROR;
425 ret = ldb_build_search_req(&search_req, ldb,
426 ac, parent_dn, LDB_SCOPE_BASE,
427 "(objectClass=*)", parent_attrs,
429 ac, get_search_callback,
431 if (ret != LDB_SUCCESS) {
435 ac->step_fn = objectclass_do_add;
437 return ldb_next_request(ac->module, search_req);
440 static int objectclass_do_add(struct oc_context *ac)
442 struct ldb_context *ldb;
443 struct ldb_request *add_req;
444 struct ldb_message_element *objectclass_element, *el;
445 struct ldb_message *msg;
447 struct class_list *sorted, *current;
448 const char *rdn_name = NULL;
450 const struct dsdb_class *objectclass;
451 int32_t systemFlags = 0;
454 ldb = ldb_module_get_ctx(ac->module);
456 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
458 /* Check if we have a valid parent - this check is needed since
459 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
460 if (ac->search_res == NULL) {
461 if (ldb_dn_compare(ldb_get_root_basedn(ldb), msg->dn) == 0) {
462 /* Allow the tree to be started but don't keep any
463 * error strings - they're meaningless. */
464 ldb_set_errstring(ldb, NULL);
466 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
467 ldb_dn_get_linearized(msg->dn));
468 return LDB_ERR_NO_SUCH_OBJECT;
471 /* Fix up the DN to be in the standard form, taking
472 * particular care to match the parent DN */
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) {
487 return LDB_ERR_OPERATIONS_ERROR;
490 if (ac->schema != NULL) {
491 /* This is now the objectClass list from the database */
492 objectclass_element = ldb_msg_find_element(msg, "objectClass");
494 if (!objectclass_element) {
495 /* Where did it go? bail now... */
496 talloc_free(mem_ctx);
497 return LDB_ERR_OPERATIONS_ERROR;
499 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
500 objectclass_element, &sorted);
501 if (ret != LDB_SUCCESS) {
502 talloc_free(mem_ctx);
506 ldb_msg_remove_attr(msg, "objectClass");
507 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
509 if (ret != LDB_SUCCESS) {
510 talloc_free(mem_ctx);
514 /* We must completely replace the existing objectClass entry,
515 * because we need it sorted */
517 /* Move from the linked list back into an ldb msg */
518 for (current = sorted; current; current = current->next) {
519 value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
522 talloc_free(mem_ctx);
523 return LDB_ERR_OPERATIONS_ERROR;
525 ret = ldb_msg_add_string(msg, "objectClass", value);
526 if (ret != LDB_SUCCESS) {
527 ldb_set_errstring(ldb,
528 "objectclass: could not re-add sorted "
529 "objectclass to modify msg");
530 talloc_free(mem_ctx);
535 /* Retrive the message again so get_last_structural_class works */
536 objectclass_element = ldb_msg_find_element(msg, "objectClass");
538 /* Make sure its valid to add an object of this type */
539 objectclass = get_last_structural_class(ac->schema,
540 objectclass_element);
541 if(objectclass == NULL) {
542 ldb_asprintf_errstring(ldb,
543 "Failed to find a structural class for %s",
544 ldb_dn_get_linearized(msg->dn));
545 return LDB_ERR_UNWILLING_TO_PERFORM;
548 rdn_name = ldb_dn_get_rdn_name(msg->dn);
549 if (objectclass->rDNAttID
550 && ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0) {
551 ldb_asprintf_errstring(ldb,
552 "RDN %s is not correct for most specific structural objectclass %s, should be %s",
553 rdn_name, objectclass->lDAPDisplayName, objectclass->rDNAttID);
554 return LDB_ERR_NAMING_VIOLATION;
557 if (ac->search_res && ac->search_res->message) {
558 struct ldb_message_element *oc_el
559 = ldb_msg_find_element(ac->search_res->message, "objectClass");
561 bool allowed_class = false;
563 for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
564 const struct dsdb_class *sclass;
566 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
569 /* We don't know this class? what is going on? */
572 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
573 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
574 allowed_class = true;
580 if (!allowed_class) {
581 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
582 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
583 return LDB_ERR_NAMING_VIOLATION;
587 if (objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
588 ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
589 objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
590 return LDB_ERR_UNWILLING_TO_PERFORM;
593 if (!ldb_msg_find_element(msg, "objectCategory")) {
594 struct dsdb_extended_dn_store_format *dn_format = talloc_get_type(ldb_module_get_private(ac->module), struct dsdb_extended_dn_store_format);
595 if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
596 /* Strip off extended components */
597 struct ldb_dn *dn = ldb_dn_new(msg, ldb, objectclass->defaultObjectCategory);
598 value = ldb_dn_alloc_linearized(msg, dn);
601 value = talloc_strdup(msg, objectclass->defaultObjectCategory);
605 talloc_free(mem_ctx);
606 return LDB_ERR_OPERATIONS_ERROR;
608 ldb_msg_add_string(msg, "objectCategory", value);
610 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
611 ldb_msg_add_string(msg, "showInAdvancedViewOnly",
615 /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */
616 el = ldb_msg_find_element(msg, "systemFlags");
618 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
621 /* Only these flags may be set by a client, but we can't tell between a client and our provision at this point */
622 /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */
623 ldb_msg_remove_element(msg, el);
626 /* This flag is only allowed on attributeSchema objects */
627 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") == 0) {
628 systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
631 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
632 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
633 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
634 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serverContainer") == 0
635 || ldb_attr_cmp(objectclass->lDAPDisplayName, "ntDSDSA") == 0) {
636 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
638 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
639 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
640 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
641 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
644 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
646 if (el || systemFlags != 0) {
647 samdb_msg_add_int(ldb, msg, msg, "systemFlags", systemFlags);
651 talloc_free(mem_ctx);
652 ret = ldb_msg_sanity_check(ldb, msg);
655 if (ret != LDB_SUCCESS) {
659 ret = ldb_build_add_req(&add_req, ldb, ac,
664 if (ret != LDB_SUCCESS) {
668 /* perform the add */
669 return ldb_next_request(ac->module, add_req);
672 static int oc_modify_callback(struct ldb_request *req,
673 struct ldb_reply *ares);
674 static int objectclass_do_mod(struct oc_context *ac);
676 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
678 struct ldb_context *ldb = ldb_module_get_ctx(module);
679 struct ldb_message_element *objectclass_element;
680 struct ldb_message *msg;
681 struct ldb_request *down_req;
682 struct oc_context *ac;
683 bool oc_changes = false;
686 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
688 /* do not manipulate our control entries */
689 if (ldb_dn_is_special(req->op.mod.message->dn)) {
690 return ldb_next_request(module, req);
693 /* As with the "real" AD we don't accept empty messages */
694 if (req->op.mod.message->num_elements == 0) {
695 ldb_set_errstring(ldb, "objectclass: modify message must have "
696 "elements/attributes!");
697 return LDB_ERR_UNWILLING_TO_PERFORM;
700 ac = oc_init_context(module, req);
702 return LDB_ERR_OPERATIONS_ERROR;
705 /* Without schema, there isn't much to do here */
706 if (ac->schema == NULL) {
708 return ldb_next_request(module, req);
711 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
713 return LDB_ERR_OPERATIONS_ERROR;
716 /* For now change everything except the objectclasses */
718 objectclass_element = ldb_msg_find_element(msg, "objectClass");
719 if (objectclass_element != NULL) {
720 ldb_msg_remove_attr(msg, "objectClass");
724 ret = ldb_build_mod_req(&down_req, ldb, ac,
727 oc_changes ? oc_modify_callback : oc_op_callback,
729 if (ret != LDB_SUCCESS) {
733 return ldb_next_request(module, down_req);
736 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
738 static const char * const attrs[] = { "objectClass", NULL };
739 struct ldb_context *ldb;
740 struct ldb_request *search_req;
741 struct oc_context *ac;
744 ac = talloc_get_type(req->context, struct oc_context);
745 ldb = ldb_module_get_ctx(ac->module);
748 return ldb_module_done(ac->req, NULL, NULL,
749 LDB_ERR_OPERATIONS_ERROR);
752 if (ares->type == LDB_REPLY_REFERRAL) {
753 return ldb_module_send_referral(ac->req, ares->referral);
756 if (ares->error != LDB_SUCCESS) {
757 return ldb_module_done(ac->req, ares->controls,
758 ares->response, ares->error);
761 if (ares->type != LDB_REPLY_DONE) {
763 return ldb_module_done(ac->req, NULL, NULL,
764 LDB_ERR_OPERATIONS_ERROR);
769 /* this looks up the real existing object for fetching some important
770 * informations (objectclasses) */
771 ret = ldb_build_search_req(&search_req, ldb,
772 ac, ac->req->op.mod.message->dn,
776 ac, get_search_callback,
778 if (ret != LDB_SUCCESS) {
779 return ldb_module_done(ac->req, NULL, NULL, ret);
782 ac->step_fn = objectclass_do_mod;
784 ret = ldb_next_request(ac->module, search_req);
785 if (ret != LDB_SUCCESS) {
786 return ldb_module_done(ac->req, NULL, NULL, ret);
792 static int objectclass_do_mod(struct oc_context *ac)
794 struct ldb_context *ldb;
795 struct ldb_request *mod_req;
797 struct ldb_message_element *oc_el_entry, *oc_el_change;
798 struct ldb_val *vals;
799 struct ldb_message *msg;
801 struct class_list *sorted, *current;
802 const struct dsdb_class *objectclass;
804 bool found, replace = false;
807 ldb = ldb_module_get_ctx(ac->module);
809 /* we should always have a valid entry when we enter here */
810 if (ac->search_res == NULL) {
811 return LDB_ERR_OPERATIONS_ERROR;
814 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
816 if (oc_el_entry == NULL) {
817 /* existing entry without a valid object class? */
818 return LDB_ERR_OPERATIONS_ERROR;
821 oc_el_change = ldb_msg_find_element(ac->req->op.mod.message,
823 if (oc_el_change == NULL) {
824 /* we should have an objectclass change operation */
825 return LDB_ERR_OPERATIONS_ERROR;
828 /* use a new message structure */
829 msg = ldb_msg_new(ac);
832 return LDB_ERR_OPERATIONS_ERROR;
835 msg->dn = ac->req->op.mod.message->dn;
837 mem_ctx = talloc_new(ac);
838 if (mem_ctx == NULL) {
840 return LDB_ERR_OPERATIONS_ERROR;
843 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
844 case LDB_FLAG_MOD_ADD:
845 /* Merge the two message elements */
846 for (i = 0; i < oc_el_change->num_values; i++) {
847 for (j = 0; j < oc_el_entry->num_values; j++) {
848 if (strcasecmp((char *)oc_el_change->values[i].data,
849 (char *)oc_el_entry->values[j].data) == 0) {
850 /* we cannot add an already existing object class */
851 talloc_free(mem_ctx);
852 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
855 /* append the new object class value - code was copied
856 * from "ldb_msg_add_value" */
857 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
859 oc_el_entry->num_values + 1);
862 talloc_free(mem_ctx);
863 return LDB_ERR_OPERATIONS_ERROR;
865 oc_el_entry->values = vals;
866 oc_el_entry->values[oc_el_entry->num_values] =
867 oc_el_change->values[i];
868 ++(oc_el_entry->num_values);
871 objectclass = get_last_structural_class(ac->schema,
873 if (objectclass != NULL) {
874 /* we cannot add a new structural object class */
875 talloc_free(mem_ctx);
876 return LDB_ERR_OBJECT_CLASS_VIOLATION;
879 /* Now do the sorting */
880 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
881 oc_el_entry, &sorted);
882 if (ret != LDB_SUCCESS) {
883 talloc_free(mem_ctx);
889 case LDB_FLAG_MOD_REPLACE:
890 /* Do the sorting for the change message element */
891 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
892 oc_el_change, &sorted);
893 if (ret != LDB_SUCCESS) {
894 talloc_free(mem_ctx);
898 /* this is a replace */
903 case LDB_FLAG_MOD_DELETE:
904 /* get the actual top-most structural objectclass */
905 objectclass = get_last_structural_class(ac->schema,
907 if (objectclass == NULL) {
908 talloc_free(mem_ctx);
909 return LDB_ERR_OPERATIONS_ERROR;
912 /* Merge the two message elements */
913 for (i = 0; i < oc_el_change->num_values; i++) {
915 for (j = 0; j < oc_el_entry->num_values; j++) {
916 if (strcasecmp((char *)oc_el_change->values[i].data,
917 (char *)oc_el_entry->values[j].data) == 0) {
919 /* delete the object class value -
920 * code was copied from
921 * "ldb_msg_remove_element" */
922 if (j != oc_el_entry->num_values - 1) {
923 memmove(&oc_el_entry->values[j],
924 &oc_el_entry->values[j+1],
925 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
927 --(oc_el_entry->num_values);
932 /* we cannot delete a not existing object class */
933 talloc_free(mem_ctx);
934 return LDB_ERR_NO_SUCH_ATTRIBUTE;
938 /* Make sure that the top-most structural objectclass wasn't
941 for (i = 0; i < oc_el_entry->num_values; i++) {
942 if (strcasecmp(objectclass->lDAPDisplayName,
943 (char *)oc_el_entry->values[i].data) == 0) {
948 talloc_free(mem_ctx);
949 return LDB_ERR_OBJECT_CLASS_VIOLATION;
953 /* Now do the sorting */
954 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
955 oc_el_entry, &sorted);
956 if (ret != LDB_SUCCESS) {
957 talloc_free(mem_ctx);
964 ret = ldb_msg_add_empty(msg, "objectClass",
965 LDB_FLAG_MOD_REPLACE, &oc_el_change);
966 if (ret != LDB_SUCCESS) {
968 talloc_free(mem_ctx);
972 /* Move from the linked list back into an ldb msg */
973 for (current = sorted; current; current = current->next) {
974 value = talloc_strdup(msg,
975 current->objectclass->lDAPDisplayName);
978 talloc_free(mem_ctx);
979 return LDB_ERR_OPERATIONS_ERROR;
981 ret = ldb_msg_add_string(msg, "objectClass", value);
982 if (ret != LDB_SUCCESS) {
983 ldb_set_errstring(ldb, "objectclass: could not re-add sorted objectclass to modify msg");
984 talloc_free(mem_ctx);
989 talloc_free(mem_ctx);
992 /* Well, on replace we are nearly done: we have to test if
993 * the change and entry message element are identically. We
994 * can use "ldb_msg_element_compare" since now the specified
995 * objectclasses match for sure in case. */
996 ret = ldb_msg_element_compare(oc_el_entry, oc_el_change);
998 ret = ldb_msg_element_compare(oc_el_change,
1002 /* they are the same so we are done in this case */
1003 return ldb_module_done(ac->req, NULL, NULL,
1006 /* they're not exactly the same */
1007 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1011 /* in the other cases we have the real change left to do */
1013 ret = ldb_msg_sanity_check(ldb, msg);
1014 if (ret != LDB_SUCCESS) {
1018 ret = ldb_build_mod_req(&mod_req, ldb, ac,
1023 if (ret != LDB_SUCCESS) {
1027 return ldb_next_request(ac->module, mod_req);
1030 static int objectclass_do_rename(struct oc_context *ac);
1032 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1034 static const char * const attrs[] = { "objectClass", NULL };
1035 struct ldb_context *ldb;
1036 struct ldb_request *search_req;
1037 struct oc_context *ac;
1038 struct ldb_dn *parent_dn;
1041 ldb = ldb_module_get_ctx(module);
1043 ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1045 /* do not manipulate our control entries */
1046 if (ldb_dn_is_special(req->op.rename.newdn)) {
1047 return ldb_next_request(module, req);
1050 ac = oc_init_context(module, req);
1052 return LDB_ERR_OPERATIONS_ERROR;
1055 parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1056 if (parent_dn == NULL) {
1057 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1058 ldb_dn_get_linearized(req->op.rename.olddn));
1059 return LDB_ERR_NO_SUCH_OBJECT;
1062 /* this looks up the parent object for fetching some important
1063 * informations (objectclasses, DN normalisation...) */
1064 ret = ldb_build_search_req(&search_req, ldb,
1065 ac, parent_dn, LDB_SCOPE_BASE,
1068 ac, get_search_callback,
1070 if (ret != LDB_SUCCESS) {
1074 /* we have to add the show deleted control, as otherwise DRS
1075 deletes will be refused as we will think the target parent
1077 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, false, NULL);
1079 if (ret != LDB_SUCCESS) {
1083 ac->step_fn = objectclass_do_rename;
1085 return ldb_next_request(ac->module, search_req);
1088 static int objectclass_do_rename2(struct oc_context *ac);
1090 static int objectclass_do_rename(struct oc_context *ac)
1092 static const char * const attrs[] = { "objectClass", NULL };
1093 struct ldb_context *ldb;
1094 struct ldb_request *search_req;
1097 ldb = ldb_module_get_ctx(ac->module);
1099 /* Check if we have a valid parent - this check is needed since
1100 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1101 if (ac->search_res == NULL) {
1102 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1103 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1104 return LDB_ERR_OTHER;
1107 /* now assign "search_res2" to the parent entry to have "search_res"
1108 * free for another lookup */
1109 ac->search_res2 = ac->search_res;
1110 ac->search_res = NULL;
1112 /* this looks up the real existing object for fetching some important
1113 * informations (objectclasses) */
1114 ret = ldb_build_search_req(&search_req, ldb,
1115 ac, ac->req->op.rename.olddn,
1119 ac, get_search_callback,
1121 if (ret != LDB_SUCCESS) {
1125 ac->step_fn = objectclass_do_rename2;
1127 return ldb_next_request(ac->module, search_req);
1130 static int objectclass_do_rename2(struct oc_context *ac)
1132 struct ldb_context *ldb;
1133 struct ldb_request *rename_req;
1134 struct ldb_dn *fixed_dn;
1137 ldb = ldb_module_get_ctx(ac->module);
1139 /* Check if we have a valid entry - this check is needed since
1140 * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1141 if (ac->search_res == NULL) {
1142 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1143 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1144 return LDB_ERR_NO_SUCH_OBJECT;
1147 if (ac->schema != NULL) {
1148 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1149 const struct dsdb_class *objectclass;
1150 const char *rdn_name;
1151 bool allowed_class = false;
1154 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1156 if (oc_el_entry == NULL) {
1157 /* existing entry without a valid object class? */
1158 return LDB_ERR_OPERATIONS_ERROR;
1160 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1161 if (objectclass == NULL) {
1162 /* existing entry without a valid object class? */
1163 return LDB_ERR_OPERATIONS_ERROR;
1166 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1167 if ((objectclass->rDNAttID != NULL) &&
1168 (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1169 ldb_asprintf_errstring(ldb,
1170 "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1172 objectclass->lDAPDisplayName,
1173 objectclass->rDNAttID);
1174 return LDB_ERR_UNWILLING_TO_PERFORM;
1177 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1179 if (oc_el_parent == NULL) {
1180 /* existing entry without a valid object class? */
1181 return LDB_ERR_OPERATIONS_ERROR;
1184 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1185 const struct dsdb_class *sclass;
1187 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1188 &oc_el_parent->values[i]);
1190 /* We don't know this class? what is going on? */
1193 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1194 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1195 allowed_class = true;
1201 if (!allowed_class) {
1202 ldb_asprintf_errstring(ldb,
1203 "objectclass: structural objectClass %s is not a valid child class for %s",
1204 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1205 return LDB_ERR_NAMING_VIOLATION;
1209 /* Ensure we are not trying to rename it to be a child of itself */
1210 if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1211 ac->req->op.rename.newdn) == 0) &&
1212 (ldb_dn_compare(ac->req->op.rename.olddn,
1213 ac->req->op.rename.newdn) != 0)) {
1214 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1215 ldb_dn_get_linearized(ac->req->op.rename.olddn));
1216 return LDB_ERR_UNWILLING_TO_PERFORM;
1219 /* Fix up the DN to be in the standard form, taking
1220 * particular care to match the parent DN */
1222 ac->req->op.rename.newdn,
1223 ac->search_res2->message->dn,
1225 if (ret != LDB_SUCCESS) {
1226 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1227 ldb_dn_get_linearized(ac->req->op.rename.newdn));
1232 ret = ldb_build_rename_req(&rename_req, ldb, ac,
1233 ac->req->op.rename.olddn, fixed_dn,
1237 if (ret != LDB_SUCCESS) {
1241 /* perform the rename */
1242 return ldb_next_request(ac->module, rename_req);
1245 static int objectclass_init(struct ldb_module *module)
1247 struct ldb_context *ldb = ldb_module_get_ctx(module);
1249 /* Init everything else */
1250 ret = ldb_next_init(module);
1251 if (ret != LDB_SUCCESS) {
1255 /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1256 ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1261 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1262 .name = "objectclass",
1263 .add = objectclass_add,
1264 .modify = objectclass_modify,
1265 .rename = objectclass_rename,
1266 .init_context = objectclass_init