4 Copyright (C) Simo Sorce 2006-2008
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
6 Copyright (C) Nadezhda Ivanova 2009
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: DS Security descriptor module
28 * - Calculate the security descriptor of a newly created object
29 * - Perform sd recalculation on a move operation
30 * - Handle sd modification invariants
32 * Author: Nadezhda Ivanova
36 #include <ldb_module.h>
37 #include "util/dlinklist.h"
38 #include "dsdb/samdb/samdb.h"
39 #include "librpc/ndr/libndr.h"
40 #include "librpc/gen_ndr/ndr_security.h"
41 #include "libcli/security/security.h"
42 #include "auth/auth.h"
43 #include "param/param.h"
44 #include "dsdb/samdb/ldb_modules/util.h"
45 #include "lib/util/binsearch.h"
47 struct descriptor_changes {
48 struct descriptor_changes *prev, *next;
49 struct descriptor_changes *children;
50 struct ldb_dn *nc_root;
54 struct ldb_dn *stopped_dn;
57 struct descriptor_data {
58 TALLOC_CTX *trans_mem;
59 struct descriptor_changes *changes;
62 struct descriptor_context {
63 struct ldb_module *module;
64 struct ldb_request *req;
65 struct ldb_message *msg;
66 struct ldb_reply *search_res;
67 struct ldb_reply *search_oc_res;
68 struct ldb_val *parentsd_val;
69 struct ldb_message_element *sd_element;
70 struct ldb_val *sd_val;
72 int (*step_fn)(struct descriptor_context *);
75 static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
77 struct security_token *token,
78 struct ldb_context *ldb)
80 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
81 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
82 struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
83 struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS);
84 struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS);
85 struct dom_sid *dag_sid;
86 struct ldb_dn *nc_root;
89 ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root);
90 if (ret != LDB_SUCCESS) {
95 if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
96 if (security_token_has_sid(token, sa_sid)) {
97 dag_sid = dom_sid_dup(mem_ctx, sa_sid);
98 } else if (security_token_has_sid(token, ea_sid)) {
99 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
100 } else if (security_token_has_sid(token, da_sid)) {
101 dag_sid = dom_sid_dup(mem_ctx, da_sid);
102 } else if (security_token_is_system(token)) {
103 dag_sid = dom_sid_dup(mem_ctx, sa_sid);
107 } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
108 if (security_token_has_sid(token, ea_sid)) {
109 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
110 } else if (security_token_has_sid(token, da_sid)) {
111 dag_sid = dom_sid_dup(mem_ctx, da_sid);
112 } else if (security_token_is_system(token)) {
113 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
117 } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
118 if (security_token_has_sid(token, da_sid)) {
119 dag_sid = dom_sid_dup(mem_ctx, da_sid);
120 } else if (security_token_has_sid(token, ea_sid)) {
121 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
122 } else if (security_token_is_system(token)) {
123 dag_sid = dom_sid_dup(mem_ctx, da_sid);
131 talloc_free(tmp_ctx);
135 static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx,
136 const struct dsdb_class *objectclass)
138 struct ldb_context *ldb = ldb_module_get_ctx(module);
139 struct security_descriptor *sd;
140 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
142 if (!objectclass->defaultSecurityDescriptor || !domain_sid) {
146 sd = sddl_decode(mem_ctx,
147 objectclass->defaultSecurityDescriptor,
152 static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
153 struct ldb_context *ldb,
157 * This depends on the function level of the DC
158 * which is 2008R2 in our case. Which means it is
159 * higher than 2003 and we should use the
160 * "default administrator group" also as owning group.
162 * This matches dcpromo for a 2003 domain
163 * on a Windows 2008R2 DC.
168 static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
169 struct security_descriptor *new_sd,
170 struct security_descriptor *old_sd,
173 struct security_descriptor *final_sd;
174 /* if there is no control or control == 0 modify everything */
179 final_sd = talloc_zero(mem_ctx, struct security_descriptor);
180 final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
181 final_sd->type = SEC_DESC_SELF_RELATIVE;
183 if (sd_flags & (SECINFO_OWNER)) {
184 if (new_sd->owner_sid) {
185 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
187 final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
190 if (old_sd->owner_sid) {
191 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
193 final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
196 if (sd_flags & (SECINFO_GROUP)) {
197 if (new_sd->group_sid) {
198 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
200 final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
203 if (old_sd->group_sid) {
204 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
206 final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
209 if (sd_flags & (SECINFO_SACL)) {
210 final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
211 final_sd->type |= new_sd->type & (SEC_DESC_SACL_PRESENT |
212 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
213 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
214 SEC_DESC_SERVER_SECURITY);
216 else if (old_sd && old_sd->sacl) {
217 final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
218 final_sd->type |= old_sd->type & (SEC_DESC_SACL_PRESENT |
219 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
220 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
221 SEC_DESC_SERVER_SECURITY);
224 if (sd_flags & (SECINFO_DACL)) {
225 final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
226 final_sd->type |= new_sd->type & (SEC_DESC_DACL_PRESENT |
227 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
228 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
229 SEC_DESC_DACL_TRUSTED);
231 else if (old_sd && old_sd->dacl) {
232 final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
233 final_sd->type |= old_sd->type & (SEC_DESC_DACL_PRESENT |
234 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
235 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
236 SEC_DESC_DACL_TRUSTED);
238 /* not so sure about this */
239 final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
243 static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
246 const struct dsdb_class *objectclass,
247 const struct ldb_val *parent,
248 const struct ldb_val *object,
249 const struct ldb_val *old_sd,
252 struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
253 struct security_descriptor *old_descriptor = NULL;
254 struct security_descriptor *new_sd, *final_sd;
255 DATA_BLOB *linear_sd;
256 enum ndr_err_code ndr_err;
257 struct ldb_context *ldb = ldb_module_get_ctx(module);
258 struct auth_session_info *session_info
259 = ldb_get_opaque(ldb, DSDB_SESSION_INFO);
260 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
262 struct dom_sid *default_owner;
263 struct dom_sid *default_group;
264 struct security_descriptor *default_descriptor = NULL;
265 struct GUID *object_list = NULL;
267 if (objectclass != NULL) {
268 default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
269 object_list = talloc_zero_array(mem_ctx, struct GUID, 2);
270 if (object_list == NULL) {
273 object_list[0] = objectclass->schemaIDGUID;
277 user_descriptor = talloc(mem_ctx, struct security_descriptor);
278 if (!user_descriptor) {
281 ndr_err = ndr_pull_struct_blob(object, user_descriptor,
283 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
285 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
286 talloc_free(user_descriptor);
290 user_descriptor = default_descriptor;
294 old_descriptor = talloc(mem_ctx, struct security_descriptor);
295 if (!old_descriptor) {
298 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor,
300 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
302 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
303 talloc_free(old_descriptor);
309 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
310 if (!parent_descriptor) {
313 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor,
315 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
317 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
318 talloc_free(parent_descriptor);
323 if (user_descriptor && default_descriptor &&
324 (user_descriptor->dacl == NULL))
326 user_descriptor->dacl = default_descriptor->dacl;
327 user_descriptor->type |= default_descriptor->type & (
328 SEC_DESC_DACL_PRESENT |
329 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
330 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
331 SEC_DESC_DACL_TRUSTED);
334 if (user_descriptor && default_descriptor &&
335 (user_descriptor->sacl == NULL))
337 user_descriptor->sacl = default_descriptor->sacl;
338 user_descriptor->type |= default_descriptor->type & (
339 SEC_DESC_SACL_PRESENT |
340 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
341 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
342 SEC_DESC_SERVER_SECURITY);
346 if (!(sd_flags & SECINFO_OWNER) && user_descriptor) {
347 user_descriptor->owner_sid = NULL;
350 * We need the correct owner sid
351 * when calculating the DACL or SACL
353 if (old_descriptor) {
354 user_descriptor->owner_sid = old_descriptor->owner_sid;
357 if (!(sd_flags & SECINFO_GROUP) && user_descriptor) {
358 user_descriptor->group_sid = NULL;
361 * We need the correct group sid
362 * when calculating the DACL or SACL
364 if (old_descriptor) {
365 user_descriptor->group_sid = old_descriptor->group_sid;
368 if (!(sd_flags & SECINFO_DACL) && user_descriptor) {
369 user_descriptor->dacl = NULL;
372 * We add SEC_DESC_DACL_PROTECTED so that
373 * create_security_descriptor() skips
374 * the unused inheritance calculation
376 user_descriptor->type |= SEC_DESC_DACL_PROTECTED;
378 if (!(sd_flags & SECINFO_SACL) && user_descriptor) {
379 user_descriptor->sacl = NULL;
382 * We add SEC_DESC_SACL_PROTECTED so that
383 * create_security_descriptor() skips
384 * the unused inheritance calculation
386 user_descriptor->type |= SEC_DESC_SACL_PROTECTED;
389 default_owner = get_default_ag(mem_ctx, dn,
390 session_info->security_token, ldb);
391 default_group = get_default_group(mem_ctx, ldb, default_owner);
392 new_sd = create_security_descriptor(mem_ctx,
397 SEC_DACL_AUTO_INHERIT |
398 SEC_SACL_AUTO_INHERIT,
399 session_info->security_token,
400 default_owner, default_group,
401 map_generic_rights_ds);
405 final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
411 if (final_sd->dacl) {
412 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
414 if (final_sd->sacl) {
415 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
418 sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
419 DEBUG(10, ("Object %s created with descriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
421 linear_sd = talloc(mem_ctx, DATA_BLOB);
426 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
428 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
429 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
436 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
441 struct security_descriptor *old_sd, *final_sd;
442 DATA_BLOB *linear_sd;
443 enum ndr_err_code ndr_err;
445 old_sd = talloc(mem_ctx, struct security_descriptor);
449 ndr_err = ndr_pull_struct_blob(sd, old_sd,
451 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
453 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
458 final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
464 linear_sd = talloc(mem_ctx, DATA_BLOB);
469 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
471 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
472 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
479 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
480 struct ldb_request *req)
482 struct ldb_context *ldb;
483 struct descriptor_context *ac;
485 ldb = ldb_module_get_ctx(module);
487 ac = talloc_zero(req, struct descriptor_context);
489 ldb_set_errstring(ldb, "Out of Memory");
498 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
500 struct descriptor_context *ac;
501 struct ldb_val *sd_val = NULL;
502 struct ldb_message_element *sd_el;
504 int ret = LDB_SUCCESS;
506 ac = talloc_get_type(req->context, struct descriptor_context);
509 ret = LDB_ERR_OPERATIONS_ERROR;
512 if (ares->error != LDB_SUCCESS) {
513 return ldb_module_done(ac->req, ares->controls,
514 ares->response, ares->error);
517 switch (ares->type) {
518 case LDB_REPLY_ENTRY:
519 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
521 sd_val = sd_el->values;
525 show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
526 sd_val, ac->sd_flags);
528 ret = LDB_ERR_OPERATIONS_ERROR;
531 ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
532 ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
533 if (ret != LDB_SUCCESS) {
537 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
539 case LDB_REPLY_REFERRAL:
540 return ldb_module_send_referral(ac->req, ares->referral);
543 return ldb_module_done(ac->req, ares->controls,
544 ares->response, ares->error);
549 return ldb_module_done(ac->req, NULL, NULL, ret);
552 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
554 struct ldb_context *ldb = ldb_module_get_ctx(module);
555 struct ldb_request *add_req;
556 struct ldb_message *msg;
557 struct ldb_result *parent_res;
558 const struct ldb_val *parent_sd = NULL;
559 const struct ldb_val *user_sd;
560 struct ldb_dn *dn = req->op.add.message->dn;
561 struct ldb_dn *parent_dn, *nc_root;
562 struct ldb_message_element *objectclass_element, *sd_element;
564 const struct dsdb_schema *schema;
566 const struct dsdb_class *objectclass;
567 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
568 uint32_t instanceType;
570 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
572 /* do not manipulate our control entries */
573 if (ldb_dn_is_special(dn)) {
574 return ldb_next_request(module, req);
577 user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
578 sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
579 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
580 if (user_sd == NULL && sd_element) {
581 return ldb_next_request(module, req);
584 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
586 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
588 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
593 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
594 if (ret != LDB_SUCCESS) {
595 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
596 ldb_dn_get_linearized(dn));
600 if (ldb_dn_compare(dn, nc_root) == 0) {
601 DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
607 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
610 /* if the object has a parent, retrieve its SD to
611 * use for calculation. Unfortunately we do not yet have
612 * instanceType, so we use dsdb_find_nc_root. */
614 parent_dn = ldb_dn_get_parent(req, dn);
615 if (parent_dn == NULL) {
619 /* we aren't any NC */
620 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
622 DSDB_FLAG_NEXT_MODULE |
623 DSDB_FLAG_AS_SYSTEM |
624 DSDB_SEARCH_SHOW_RECYCLED,
626 if (ret != LDB_SUCCESS) {
627 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
628 ldb_dn_get_linearized(parent_dn));
631 if (parent_res->count != 1) {
632 return ldb_operr(ldb);
634 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
637 schema = dsdb_get_schema(ldb, req);
639 objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
640 if (objectclass_element == NULL) {
641 return ldb_operr(ldb);
644 objectclass = dsdb_get_last_structural_class(schema,
645 objectclass_element);
646 if (objectclass == NULL) {
647 return ldb_operr(ldb);
651 * The SD_FLAG control is ignored on add
652 * and we default to all bits set.
654 sd_flags = SECINFO_OWNER|SECINFO_GROUP|SECINFO_SACL|SECINFO_DACL;
656 sd = get_new_descriptor(module, dn, req,
657 objectclass, parent_sd,
658 user_sd, NULL, sd_flags);
660 return ldb_operr(ldb);
662 msg = ldb_msg_copy_shallow(req, req->op.add.message);
666 if (sd_element != NULL) {
667 sd_element->values[0] = *sd;
669 ret = ldb_msg_add_steal_value(msg,
670 "nTSecurityDescriptor",
672 if (ret != LDB_SUCCESS) {
677 ret = ldb_build_add_req(&add_req, ldb, req,
680 req, dsdb_next_callback,
682 LDB_REQ_SET_LOCATION(add_req);
683 if (ret != LDB_SUCCESS) {
684 return ldb_error(ldb, ret,
685 "descriptor_add: Error creating new add request.");
688 return ldb_next_request(module, add_req);
691 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
693 struct ldb_context *ldb = ldb_module_get_ctx(module);
694 struct ldb_request *mod_req;
695 struct ldb_message *msg;
696 struct ldb_result *current_res, *parent_res;
697 const struct ldb_val *old_sd = NULL;
698 const struct ldb_val *parent_sd = NULL;
699 const struct ldb_val *user_sd;
700 struct ldb_dn *dn = req->op.mod.message->dn;
701 struct ldb_dn *parent_dn;
702 struct ldb_message_element *objectclass_element, *sd_element;
704 uint32_t instanceType;
705 bool explicit_sd_flags = false;
706 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
707 const struct dsdb_schema *schema;
709 const struct dsdb_class *objectclass;
710 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
711 static const char * const current_attrs[] = { "nTSecurityDescriptor",
713 "objectClass", NULL };
714 struct ldb_control *sd_propagation_control;
717 /* do not manipulate our control entries */
718 if (ldb_dn_is_special(dn)) {
719 return ldb_next_request(module, req);
722 sd_propagation_control = ldb_request_get_control(req,
723 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
724 if (sd_propagation_control != NULL) {
725 if (sd_propagation_control->data != module) {
726 return ldb_operr(ldb);
728 if (req->op.mod.message->num_elements != 0) {
729 return ldb_operr(ldb);
731 if (explicit_sd_flags) {
732 return ldb_operr(ldb);
734 if (sd_flags != 0xF) {
735 return ldb_operr(ldb);
737 if (sd_propagation_control->critical == 0) {
738 return ldb_operr(ldb);
741 sd_propagation_control->critical = 0;
744 sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor");
745 if (sd_propagation_control == NULL && sd_element == NULL) {
746 return ldb_next_request(module, req);
750 * nTSecurityDescriptor with DELETE is not supported yet.
751 * TODO: handle this correctly.
753 if (sd_propagation_control == NULL &&
754 LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE)
756 return ldb_module_error(module,
757 LDB_ERR_UNWILLING_TO_PERFORM,
758 "MOD_DELETE for nTSecurityDescriptor "
759 "not supported yet");
762 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
763 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
764 if (sd_propagation_control == NULL && user_sd == NULL) {
765 return ldb_next_request(module, req);
768 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
770 ret = dsdb_module_search_dn(module, req, ¤t_res, dn,
772 DSDB_FLAG_NEXT_MODULE |
773 DSDB_FLAG_AS_SYSTEM |
774 DSDB_SEARCH_SHOW_RECYCLED,
776 if (ret != LDB_SUCCESS) {
777 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
778 ldb_dn_get_linearized(dn));
782 instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
784 /* if the object has a parent, retrieve its SD to
785 * use for calculation */
786 if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
787 !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
788 parent_dn = ldb_dn_get_parent(req, dn);
789 if (parent_dn == NULL) {
792 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
794 DSDB_FLAG_NEXT_MODULE |
795 DSDB_FLAG_AS_SYSTEM |
796 DSDB_SEARCH_SHOW_RECYCLED,
798 if (ret != LDB_SUCCESS) {
799 ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
800 ldb_dn_get_linearized(parent_dn));
803 if (parent_res->count != 1) {
804 return ldb_operr(ldb);
806 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
809 schema = dsdb_get_schema(ldb, req);
811 objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
812 if (objectclass_element == NULL) {
813 return ldb_operr(ldb);
816 objectclass = dsdb_get_last_structural_class(schema,
817 objectclass_element);
818 if (objectclass == NULL) {
819 return ldb_operr(ldb);
822 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
823 if (old_sd == NULL) {
824 return ldb_operr(ldb);
827 if (sd_propagation_control != NULL) {
829 * This just triggers a recalculation of the
835 sd = get_new_descriptor(module, dn, req,
836 objectclass, parent_sd,
837 user_sd, old_sd, sd_flags);
839 return ldb_operr(ldb);
841 msg = ldb_msg_copy_shallow(req, req->op.mod.message);
845 cmp_ret = data_blob_cmp(old_sd, sd);
846 if (sd_propagation_control != NULL) {
849 * The nTSecurityDescriptor is unchanged,
850 * which means we can stop the processing.
852 * We mark the control as critical again,
853 * as we have not processed it, so the caller
854 * can tell that the descriptor was unchanged.
856 sd_propagation_control->critical = 1;
857 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
860 ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor",
861 LDB_FLAG_MOD_REPLACE,
863 if (ret != LDB_SUCCESS) {
866 ret = ldb_msg_add_value(msg, "nTSecurityDescriptor",
868 if (ret != LDB_SUCCESS) {
871 } else if (cmp_ret != 0) {
872 struct ldb_dn *nc_root;
874 ret = dsdb_find_nc_root(ldb, msg, dn, &nc_root);
875 if (ret != LDB_SUCCESS) {
880 * Force SD propagation on children of this record
882 ret = dsdb_module_schedule_sd_propagation(module, nc_root,
884 if (ret != LDB_SUCCESS) {
885 return ldb_operr(ldb);
887 sd_element->values[0] = *sd;
889 sd_element->values[0] = *sd;
892 ret = ldb_build_mod_req(&mod_req, ldb, req,
898 LDB_REQ_SET_LOCATION(mod_req);
899 if (ret != LDB_SUCCESS) {
903 return ldb_next_request(module, mod_req);
906 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
909 struct ldb_context *ldb;
910 struct ldb_request *down_req;
911 struct descriptor_context *ac;
912 bool explicit_sd_flags = false;
913 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
914 bool show_sd = explicit_sd_flags;
917 ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor"))
923 return ldb_next_request(module, req);
926 ldb = ldb_module_get_ctx(module);
927 ac = descriptor_init_context(module, req);
929 return ldb_operr(ldb);
931 ac->sd_flags = sd_flags;
933 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
935 req->op.search.scope,
937 req->op.search.attrs,
939 ac, descriptor_search_callback,
941 LDB_REQ_SET_LOCATION(down_req);
942 if (ret != LDB_SUCCESS) {
946 return ldb_next_request(ac->module, down_req);
949 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
951 struct ldb_context *ldb = ldb_module_get_ctx(module);
952 struct ldb_dn *olddn = req->op.rename.olddn;
953 struct ldb_dn *newdn = req->op.rename.newdn;
956 /* do not manipulate our control entries */
957 if (ldb_dn_is_special(req->op.rename.olddn)) {
958 return ldb_next_request(module, req);
961 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n",
962 ldb_dn_get_linearized(olddn));
964 if (ldb_dn_compare(olddn, newdn) != 0) {
965 struct ldb_dn *nc_root;
967 ret = dsdb_find_nc_root(ldb, req, newdn, &nc_root);
968 if (ret != LDB_SUCCESS) {
973 * Force SD propagation on this record (get a new
974 * inherited SD from the potentially new parent
976 ret = dsdb_module_schedule_sd_propagation(module, nc_root,
978 if (ret != LDB_SUCCESS) {
979 return ldb_operr(ldb);
983 return ldb_next_request(module, req);
986 static int descriptor_extended_sec_desc_propagation(struct ldb_module *module,
987 struct ldb_request *req)
989 struct descriptor_data *descriptor_private =
990 talloc_get_type_abort(ldb_module_get_private(module),
991 struct descriptor_data);
992 struct ldb_context *ldb = ldb_module_get_ctx(module);
993 struct dsdb_extended_sec_desc_propagation_op *op;
994 TALLOC_CTX *parent_mem = NULL;
995 struct descriptor_changes *parent_change = NULL;
996 struct descriptor_changes *c;
999 op = talloc_get_type(req->op.extended.data,
1000 struct dsdb_extended_sec_desc_propagation_op);
1002 ldb_debug(ldb, LDB_DEBUG_FATAL,
1003 "descriptor_extended_sec_desc_propagation: "
1004 "invalid extended data\n");
1005 return LDB_ERR_PROTOCOL_ERROR;
1008 if (descriptor_private->trans_mem == NULL) {
1009 return ldb_module_operr(module);
1012 parent_mem = descriptor_private->trans_mem;
1014 for (c = descriptor_private->changes; c; c = c->next) {
1015 ret = ldb_dn_compare(c->nc_root, op->nc_root);
1020 ret = ldb_dn_compare(c->dn, op->dn);
1022 if (op->include_self) {
1023 c->force_self = true;
1025 c->force_children = true;
1027 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1030 ret = ldb_dn_compare_base(c->dn, op->dn);
1040 c = talloc_zero(parent_mem, struct descriptor_changes);
1042 return ldb_module_oom(module);
1044 c->nc_root = ldb_dn_copy(c, op->nc_root);
1045 if (c->nc_root == NULL) {
1046 return ldb_module_oom(module);
1048 c->dn = ldb_dn_copy(c, op->dn);
1049 if (c->dn == NULL) {
1050 return ldb_module_oom(module);
1052 if (op->include_self) {
1053 c->force_self = true;
1055 c->force_children = true;
1058 if (parent_change != NULL) {
1059 DLIST_ADD_END(parent_change->children, c);
1061 DLIST_ADD_END(descriptor_private->changes, c);
1064 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1067 static int descriptor_extended(struct ldb_module *module, struct ldb_request *req)
1069 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID) == 0) {
1070 return descriptor_extended_sec_desc_propagation(module, req);
1073 return ldb_next_request(module, req);
1076 static int descriptor_init(struct ldb_module *module)
1078 struct ldb_context *ldb = ldb_module_get_ctx(module);
1080 struct descriptor_data *descriptor_private;
1082 ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
1083 if (ret != LDB_SUCCESS) {
1084 ldb_debug(ldb, LDB_DEBUG_ERROR,
1085 "descriptor: Unable to register control with rootdse!\n");
1086 return ldb_operr(ldb);
1089 descriptor_private = talloc_zero(module, struct descriptor_data);
1090 if (descriptor_private == NULL) {
1092 return LDB_ERR_OPERATIONS_ERROR;
1094 ldb_module_set_private(module, descriptor_private);
1096 return ldb_next_init(module);
1099 static int descriptor_sd_propagation_object(struct ldb_module *module,
1100 struct ldb_message *msg,
1103 struct ldb_context *ldb = ldb_module_get_ctx(module);
1104 struct ldb_request *sub_req;
1105 struct ldb_result *mod_res;
1106 struct ldb_control *sd_propagation_control;
1111 mod_res = talloc_zero(msg, struct ldb_result);
1112 if (mod_res == NULL) {
1113 return ldb_module_oom(module);
1116 ret = ldb_build_mod_req(&sub_req, ldb, mod_res,
1120 ldb_modify_default_callback,
1122 LDB_REQ_SET_LOCATION(sub_req);
1123 if (ret != LDB_SUCCESS) {
1124 return ldb_module_operr(module);
1127 ldb_req_mark_trusted(sub_req);
1129 ret = ldb_request_add_control(sub_req,
1130 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID,
1132 if (ret != LDB_SUCCESS) {
1133 return ldb_module_operr(module);
1136 sd_propagation_control = ldb_request_get_control(sub_req,
1137 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
1138 if (sd_propagation_control == NULL) {
1139 return ldb_module_operr(module);
1142 ret = dsdb_request_add_controls(sub_req,
1143 DSDB_FLAG_AS_SYSTEM |
1144 DSDB_SEARCH_SHOW_RECYCLED);
1145 if (ret != LDB_SUCCESS) {
1146 return ldb_module_operr(module);
1149 ret = descriptor_modify(module, sub_req);
1150 if (ret == LDB_SUCCESS) {
1151 ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL);
1153 if (ret != LDB_SUCCESS) {
1154 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1155 "descriptor_modify on %s failed: %s",
1156 ldb_dn_get_linearized(msg->dn),
1157 ldb_errstring(ldb_module_get_ctx(module)));
1158 return LDB_ERR_OPERATIONS_ERROR;
1161 if (sd_propagation_control->critical != 0) {
1165 talloc_free(mod_res);
1170 static int descriptor_sd_propagation_msg_sort(struct ldb_message **m1,
1171 struct ldb_message **m2)
1173 struct ldb_dn *dn1 = (*m1)->dn;
1174 struct ldb_dn *dn2 = (*m2)->dn;
1177 * This sorts in tree order, parents first
1179 return ldb_dn_compare(dn2, dn1);
1182 static int descriptor_sd_propagation_dn_sort(struct ldb_dn *dn1,
1186 * This sorts in tree order, parents first
1188 return ldb_dn_compare(dn2, dn1);
1191 static int descriptor_sd_propagation_recursive(struct ldb_module *module,
1192 struct descriptor_changes *change)
1194 struct ldb_context *ldb = ldb_module_get_ctx(module);
1195 struct ldb_result *res = NULL;
1197 const char * const no_attrs[] = { "@__NONE__", NULL };
1198 struct descriptor_changes *c;
1199 struct descriptor_changes *stopped_stack = NULL;
1200 enum ldb_scope scope;
1204 * First confirm this object has children, or exists (depending on change->force_self)
1206 * LDB_SCOPE_SUBTREE searches are expensive.
1208 * Note: that we do not search for deleted/recycled objects
1210 * We know this is safe against a rename race as we are in the
1211 * prepare_commit(), so must be in a transaction.
1213 ret = dsdb_module_search(module,
1219 DSDB_FLAG_NEXT_MODULE |
1220 DSDB_FLAG_AS_SYSTEM,
1221 NULL, /* parent_req */
1223 if (ret != LDB_SUCCESS) {
1227 if (res->count == 0 && !change->force_self) {
1230 } else if (res->count == 0 && change->force_self) {
1231 scope = LDB_SCOPE_BASE;
1233 scope = LDB_SCOPE_SUBTREE;
1237 * Note: that we do not search for deleted/recycled objects
1239 ret = dsdb_module_search(module,
1245 DSDB_FLAG_NEXT_MODULE |
1246 DSDB_FLAG_AS_SYSTEM,
1247 NULL, /* parent_req */
1249 if (ret != LDB_SUCCESS) {
1253 TYPESAFE_QSORT(res->msgs, res->count,
1254 descriptor_sd_propagation_msg_sort);
1256 for (c = change->children; c; c = c->next) {
1257 struct ldb_message *msg = NULL;
1259 BINARY_ARRAY_SEARCH_P(res->msgs, res->count, dn, c->dn,
1260 descriptor_sd_propagation_dn_sort,
1264 ldb_debug(ldb, LDB_DEBUG_WARNING,
1265 "descriptor_sd_propagation_recursive: "
1266 "%s not found under %s",
1267 ldb_dn_get_linearized(c->dn),
1268 ldb_dn_get_linearized(change->dn));
1272 msg->elements = (struct ldb_message_element *)c;
1275 DLIST_ADD(stopped_stack, change);
1277 if (change->force_self) {
1283 for (; i < res->count; i++) {
1284 struct descriptor_changes *cur;
1287 cur = talloc_get_type(res->msgs[i]->elements,
1288 struct descriptor_changes);
1289 res->msgs[i]->elements = NULL;
1290 res->msgs[i]->num_elements = 0;
1293 DLIST_REMOVE(change->children, cur);
1296 for (c = stopped_stack; c; c = stopped_stack) {
1297 ret = ldb_dn_compare_base(c->dn,
1303 c->stopped_dn = NULL;
1304 DLIST_REMOVE(stopped_stack, c);
1308 DLIST_ADD(stopped_stack, cur);
1311 if (stopped_stack->stopped_dn != NULL) {
1312 ret = ldb_dn_compare_base(stopped_stack->stopped_dn,
1317 stopped_stack->stopped_dn = NULL;
1320 ret = descriptor_sd_propagation_object(module, res->msgs[i],
1322 if (ret != LDB_SUCCESS) {
1326 if (cur != NULL && cur->force_children) {
1331 stopped_stack->stopped_dn = res->msgs[i]->dn;
1340 static int descriptor_start_transaction(struct ldb_module *module)
1342 struct descriptor_data *descriptor_private =
1343 talloc_get_type_abort(ldb_module_get_private(module),
1344 struct descriptor_data);
1346 if (descriptor_private->trans_mem != NULL) {
1347 return ldb_module_operr(module);
1350 descriptor_private->trans_mem = talloc_new(descriptor_private);
1351 if (descriptor_private->trans_mem == NULL) {
1352 return ldb_module_oom(module);
1354 descriptor_private->changes = NULL;
1356 return ldb_next_start_trans(module);
1359 static int descriptor_prepare_commit(struct ldb_module *module)
1361 struct descriptor_data *descriptor_private =
1362 talloc_get_type_abort(ldb_module_get_private(module),
1363 struct descriptor_data);
1364 struct descriptor_changes *c, *n;
1367 for (c = descriptor_private->changes; c; c = n) {
1369 DLIST_REMOVE(descriptor_private->changes, c);
1371 ret = descriptor_sd_propagation_recursive(module, c);
1372 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1375 if (ret != LDB_SUCCESS) {
1380 return ldb_next_prepare_commit(module);
1383 static int descriptor_end_transaction(struct ldb_module *module)
1385 struct descriptor_data *descriptor_private =
1386 talloc_get_type_abort(ldb_module_get_private(module),
1387 struct descriptor_data);
1389 TALLOC_FREE(descriptor_private->trans_mem);
1390 descriptor_private->changes = NULL;
1392 return ldb_next_end_trans(module);
1395 static int descriptor_del_transaction(struct ldb_module *module)
1397 struct descriptor_data *descriptor_private =
1398 talloc_get_type_abort(ldb_module_get_private(module),
1399 struct descriptor_data);
1401 TALLOC_FREE(descriptor_private->trans_mem);
1402 descriptor_private->changes = NULL;
1404 return ldb_next_del_trans(module);
1407 static const struct ldb_module_ops ldb_descriptor_module_ops = {
1408 .name = "descriptor",
1409 .search = descriptor_search,
1410 .add = descriptor_add,
1411 .modify = descriptor_modify,
1412 .rename = descriptor_rename,
1413 .init_context = descriptor_init,
1414 .extended = descriptor_extended,
1415 .start_transaction = descriptor_start_transaction,
1416 .prepare_commit = descriptor_prepare_commit,
1417 .end_transaction = descriptor_end_transaction,
1418 .del_transaction = descriptor_del_transaction,
1421 int ldb_descriptor_module_init(const char *version)
1423 LDB_MODULE_CHECK_VERSION(version);
1424 return ldb_register_module(&ldb_descriptor_module_ops);