s4:dsdb/descriptor: recalculate nTSecurityDescriptor after a rename (bug #8621)
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / descriptor.c
blob36a64d06e6f58cce4de4296aba4b21d84a1e1fc5
1 /*
2 ldb database library
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/>.
23 * Name: ldb
25 * Component: DS Security descriptor module
27 * Description:
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
35 #include "includes.h"
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;
51 struct ldb_dn *dn;
52 bool force_self;
53 bool force_children;
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;
71 uint32_t sd_flags;
72 int (*step_fn)(struct descriptor_context *);
75 static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
76 struct ldb_dn *dn,
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;
87 int ret;
89 ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root);
90 if (ret != LDB_SUCCESS) {
91 talloc_free(tmp_ctx);
92 return NULL;
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);
104 } else {
105 dag_sid = NULL;
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);
114 } else {
115 dag_sid = NULL;
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);
124 } else {
125 dag_sid = NULL;
127 } else {
128 dag_sid = NULL;
131 talloc_free(tmp_ctx);
132 return dag_sid;
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) {
143 return NULL;
146 sd = sddl_decode(mem_ctx,
147 objectclass->defaultSecurityDescriptor,
148 domain_sid);
149 return sd;
152 static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
153 struct ldb_context *ldb,
154 struct dom_sid *dag)
156 if (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008) {
157 return dag;
160 return NULL;
163 static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
164 struct security_descriptor *new_sd,
165 struct security_descriptor *old_sd,
166 uint32_t sd_flags)
168 struct security_descriptor *final_sd;
169 /* if there is no control or control == 0 modify everything */
170 if (!sd_flags) {
171 return new_sd;
174 final_sd = talloc_zero(mem_ctx, struct security_descriptor);
175 final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
176 final_sd->type = SEC_DESC_SELF_RELATIVE;
178 if (sd_flags & (SECINFO_OWNER)) {
179 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
180 final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
182 else if (old_sd) {
183 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
184 final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
187 if (sd_flags & (SECINFO_GROUP)) {
188 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
189 final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
191 else if (old_sd) {
192 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
193 final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
196 if (sd_flags & (SECINFO_SACL)) {
197 final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
198 final_sd->type |= new_sd->type & (SEC_DESC_SACL_PRESENT |
199 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
200 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
201 SEC_DESC_SERVER_SECURITY);
203 else if (old_sd && old_sd->sacl) {
204 final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
205 final_sd->type |= old_sd->type & (SEC_DESC_SACL_PRESENT |
206 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
207 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
208 SEC_DESC_SERVER_SECURITY);
211 if (sd_flags & (SECINFO_DACL)) {
212 final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
213 final_sd->type |= new_sd->type & (SEC_DESC_DACL_PRESENT |
214 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
215 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
216 SEC_DESC_DACL_TRUSTED);
218 else if (old_sd && old_sd->dacl) {
219 final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
220 final_sd->type |= old_sd->type & (SEC_DESC_DACL_PRESENT |
221 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
222 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
223 SEC_DESC_DACL_TRUSTED);
225 /* not so sure about this */
226 final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
227 return final_sd;
230 static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
231 struct ldb_dn *dn,
232 TALLOC_CTX *mem_ctx,
233 const struct dsdb_class *objectclass,
234 const struct ldb_val *parent,
235 const struct ldb_val *object,
236 const struct ldb_val *old_sd,
237 uint32_t sd_flags)
239 struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
240 struct security_descriptor *old_descriptor = NULL;
241 struct security_descriptor *new_sd, *final_sd;
242 DATA_BLOB *linear_sd;
243 enum ndr_err_code ndr_err;
244 struct ldb_context *ldb = ldb_module_get_ctx(module);
245 struct auth_session_info *session_info
246 = ldb_get_opaque(ldb, "sessionInfo");
247 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
248 char *sddl_sd;
249 struct dom_sid *default_owner;
250 struct dom_sid *default_group;
251 struct security_descriptor *default_descriptor = NULL;
253 if (objectclass != NULL) {
254 default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
257 if (object) {
258 user_descriptor = talloc(mem_ctx, struct security_descriptor);
259 if (!user_descriptor) {
260 return NULL;
262 ndr_err = ndr_pull_struct_blob(object, user_descriptor,
263 user_descriptor,
264 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
266 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
267 talloc_free(user_descriptor);
268 return NULL;
270 } else {
271 user_descriptor = default_descriptor;
274 if (old_sd) {
275 old_descriptor = talloc(mem_ctx, struct security_descriptor);
276 if (!old_descriptor) {
277 return NULL;
279 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor,
280 old_descriptor,
281 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
283 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
284 talloc_free(old_descriptor);
285 return NULL;
289 if (parent) {
290 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
291 if (!parent_descriptor) {
292 return NULL;
294 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor,
295 parent_descriptor,
296 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
298 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
299 talloc_free(parent_descriptor);
300 return NULL;
304 if (user_descriptor && default_descriptor &&
305 (user_descriptor->dacl == NULL))
307 user_descriptor->dacl = default_descriptor->dacl;
308 user_descriptor->type |= default_descriptor->type & (
309 SEC_DESC_DACL_PRESENT |
310 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
311 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
312 SEC_DESC_DACL_TRUSTED);
315 if (user_descriptor && default_descriptor &&
316 (user_descriptor->sacl == NULL))
318 user_descriptor->sacl = default_descriptor->sacl;
319 user_descriptor->type |= default_descriptor->type & (
320 SEC_DESC_SACL_PRESENT |
321 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
322 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
323 SEC_DESC_SERVER_SECURITY);
326 default_owner = get_default_ag(mem_ctx, dn,
327 session_info->security_token, ldb);
328 default_group = get_default_group(mem_ctx, ldb, default_owner);
329 new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true,
330 NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT,
331 session_info->security_token,
332 default_owner, default_group,
333 map_generic_rights_ds);
334 if (!new_sd) {
335 return NULL;
337 final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
339 if (!final_sd) {
340 return NULL;
343 if (final_sd->dacl) {
344 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
346 if (final_sd->sacl) {
347 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
350 sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
351 DEBUG(10, ("Object %s created with desriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
353 linear_sd = talloc(mem_ctx, DATA_BLOB);
354 if (!linear_sd) {
355 return NULL;
358 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
359 final_sd,
360 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
361 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
362 return NULL;
365 return linear_sd;
368 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
369 TALLOC_CTX *mem_ctx,
370 struct ldb_val *sd,
371 uint32_t sd_flags)
373 struct security_descriptor *old_sd, *final_sd;
374 DATA_BLOB *linear_sd;
375 enum ndr_err_code ndr_err;
377 old_sd = talloc(mem_ctx, struct security_descriptor);
378 if (!old_sd) {
379 return NULL;
381 ndr_err = ndr_pull_struct_blob(sd, old_sd,
382 old_sd,
383 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
385 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
386 talloc_free(old_sd);
387 return NULL;
390 final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
392 if (!final_sd) {
393 return NULL;
396 linear_sd = talloc(mem_ctx, DATA_BLOB);
397 if (!linear_sd) {
398 return NULL;
401 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
402 final_sd,
403 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
404 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
405 return NULL;
408 return linear_sd;
411 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
412 struct ldb_request *req)
414 struct ldb_context *ldb;
415 struct descriptor_context *ac;
417 ldb = ldb_module_get_ctx(module);
419 ac = talloc_zero(req, struct descriptor_context);
420 if (ac == NULL) {
421 ldb_set_errstring(ldb, "Out of Memory");
422 return NULL;
425 ac->module = module;
426 ac->req = req;
427 return ac;
430 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
432 struct descriptor_context *ac;
433 struct ldb_val *sd_val = NULL;
434 struct ldb_message_element *sd_el;
435 DATA_BLOB *show_sd;
436 int ret;
438 ac = talloc_get_type(req->context, struct descriptor_context);
440 if (!ares) {
441 ret = LDB_ERR_OPERATIONS_ERROR;
442 goto fail;
444 if (ares->error != LDB_SUCCESS) {
445 return ldb_module_done(ac->req, ares->controls,
446 ares->response, ares->error);
449 switch (ares->type) {
450 case LDB_REPLY_ENTRY:
451 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
452 if (sd_el) {
453 sd_val = sd_el->values;
456 if (sd_val) {
457 show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
458 sd_val, ac->sd_flags);
459 if (!show_sd) {
460 ret = LDB_ERR_OPERATIONS_ERROR;
461 goto fail;
463 ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
464 ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
465 if (ret != LDB_SUCCESS) {
466 goto fail;
469 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
471 case LDB_REPLY_REFERRAL:
472 return ldb_module_send_referral(ac->req, ares->referral);
474 case LDB_REPLY_DONE:
475 return ldb_module_done(ac->req, ares->controls,
476 ares->response, ares->error);
479 fail:
480 talloc_free(ares);
481 return ldb_module_done(ac->req, NULL, NULL, ret);
484 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
486 struct ldb_context *ldb = ldb_module_get_ctx(module);
487 struct ldb_request *add_req;
488 struct ldb_message *msg;
489 struct ldb_result *parent_res;
490 const struct ldb_val *parent_sd = NULL;
491 const struct ldb_val *user_sd;
492 struct ldb_dn *dn = req->op.add.message->dn;
493 struct ldb_dn *parent_dn, *nc_root;
494 struct ldb_message_element *objectclass_element, *sd_element;
495 int ret;
496 const struct dsdb_schema *schema;
497 DATA_BLOB *sd;
498 const struct dsdb_class *objectclass;
499 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
500 uint32_t instanceType;
501 bool isNC = false;
502 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
504 /* do not manipulate our control entries */
505 if (ldb_dn_is_special(dn)) {
506 return ldb_next_request(module, req);
509 user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
510 sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
511 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
512 if (user_sd == NULL && sd_element) {
513 return ldb_next_request(module, req);
516 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
518 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
520 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
521 isNC = true;
524 if (!isNC) {
525 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
526 if (ret != LDB_SUCCESS) {
527 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
528 ldb_dn_get_linearized(dn));
529 return ret;
532 if (ldb_dn_compare(dn, nc_root) == 0) {
533 DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
534 isNC = true;
538 if (isNC) {
539 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
541 if (!isNC) {
542 /* if the object has a parent, retrieve its SD to
543 * use for calculation. Unfortunately we do not yet have
544 * instanceType, so we use dsdb_find_nc_root. */
546 parent_dn = ldb_dn_get_parent(req, dn);
547 if (parent_dn == NULL) {
548 return ldb_oom(ldb);
551 /* we aren't any NC */
552 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
553 parent_attrs,
554 DSDB_FLAG_NEXT_MODULE |
555 DSDB_FLAG_AS_SYSTEM |
556 DSDB_SEARCH_SHOW_RECYCLED,
557 req);
558 if (ret != LDB_SUCCESS) {
559 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
560 ldb_dn_get_linearized(parent_dn));
561 return ret;
563 if (parent_res->count != 1) {
564 return ldb_operr(ldb);
566 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
569 schema = dsdb_get_schema(ldb, req);
571 objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
572 if (objectclass_element == NULL) {
573 return ldb_operr(ldb);
576 objectclass = dsdb_get_last_structural_class(schema,
577 objectclass_element);
578 if (objectclass == NULL) {
579 return ldb_operr(ldb);
583 * The SD_FLAG control is ignored on add
584 * and we default to all bits set.
586 sd_flags = 0xF;
588 sd = get_new_descriptor(module, dn, req,
589 objectclass, parent_sd,
590 user_sd, NULL, sd_flags);
591 if (sd == NULL) {
592 return ldb_operr(ldb);
594 msg = ldb_msg_copy_shallow(req, req->op.add.message);
595 if (msg == NULL) {
596 return ldb_oom(ldb);
598 if (sd_element != NULL) {
599 sd_element->values[0] = *sd;
600 } else {
601 ret = ldb_msg_add_steal_value(msg,
602 "nTSecurityDescriptor",
603 sd);
604 if (ret != LDB_SUCCESS) {
605 return ret;
609 ret = ldb_build_add_req(&add_req, ldb, req,
610 msg,
611 req->controls,
612 req, dsdb_next_callback,
613 req);
614 LDB_REQ_SET_LOCATION(add_req);
615 if (ret != LDB_SUCCESS) {
616 return ldb_error(ldb, ret,
617 "descriptor_add: Error creating new add request.");
620 return ldb_next_request(module, add_req);
623 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
625 struct ldb_context *ldb = ldb_module_get_ctx(module);
626 struct ldb_request *mod_req;
627 struct ldb_message *msg;
628 struct ldb_result *current_res, *parent_res;
629 const struct ldb_val *old_sd = NULL;
630 const struct ldb_val *parent_sd = NULL;
631 const struct ldb_val *user_sd;
632 struct ldb_dn *dn = req->op.mod.message->dn;
633 struct ldb_dn *parent_dn;
634 struct ldb_message_element *objectclass_element, *sd_element;
635 int ret;
636 uint32_t instanceType;
637 bool explicit_sd_flags = false;
638 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
639 const struct dsdb_schema *schema;
640 DATA_BLOB *sd;
641 const struct dsdb_class *objectclass;
642 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
643 static const char * const current_attrs[] = { "nTSecurityDescriptor",
644 "instanceType",
645 "objectClass", NULL };
646 struct ldb_control *sd_propagation_control;
648 /* do not manipulate our control entries */
649 if (ldb_dn_is_special(dn)) {
650 return ldb_next_request(module, req);
654 sd_propagation_control = ldb_request_get_control(req,
655 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
656 if (sd_propagation_control != NULL) {
657 if (sd_propagation_control->data != module) {
658 return ldb_operr(ldb);
660 if (req->op.mod.message->num_elements != 0) {
661 return ldb_operr(ldb);
663 if (explicit_sd_flags) {
664 return ldb_operr(ldb);
666 if (sd_flags != 0xF) {
667 return ldb_operr(ldb);
669 if (sd_propagation_control->critical == 0) {
670 return ldb_operr(ldb);
673 sd_propagation_control->critical = 0;
676 sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor");
677 if (sd_propagation_control == NULL && sd_element == NULL) {
678 return ldb_next_request(module, req);
682 * nTSecurityDescriptor with DELETE is not supported yet.
683 * TODO: handle this correctly.
685 if (sd_propagation_control == NULL &&
686 LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE)
688 return ldb_module_error(module,
689 LDB_ERR_UNWILLING_TO_PERFORM,
690 "MOD_DELETE for nTSecurityDescriptor "
691 "not supported yet");
694 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
695 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
696 if (sd_propagation_control == NULL && user_sd == NULL) {
697 return ldb_next_request(module, req);
700 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
702 ret = dsdb_module_search_dn(module, req, &current_res, dn,
703 current_attrs,
704 DSDB_FLAG_NEXT_MODULE |
705 DSDB_FLAG_AS_SYSTEM |
706 DSDB_SEARCH_SHOW_RECYCLED,
707 req);
708 if (ret != LDB_SUCCESS) {
709 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
710 ldb_dn_get_linearized(dn));
711 return ret;
714 instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
715 "instanceType", 0);
716 /* if the object has a parent, retrieve its SD to
717 * use for calculation */
718 if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
719 !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
720 parent_dn = ldb_dn_get_parent(req, dn);
721 if (parent_dn == NULL) {
722 return ldb_oom(ldb);
724 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
725 parent_attrs,
726 DSDB_FLAG_NEXT_MODULE |
727 DSDB_FLAG_AS_SYSTEM |
728 DSDB_SEARCH_SHOW_RECYCLED,
729 req);
730 if (ret != LDB_SUCCESS) {
731 ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
732 ldb_dn_get_linearized(parent_dn));
733 return ret;
735 if (parent_res->count != 1) {
736 return ldb_operr(ldb);
738 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
741 schema = dsdb_get_schema(ldb, req);
743 objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
744 if (objectclass_element == NULL) {
745 return ldb_operr(ldb);
748 objectclass = dsdb_get_last_structural_class(schema,
749 objectclass_element);
750 if (objectclass == NULL) {
751 return ldb_operr(ldb);
754 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
755 if (old_sd == NULL) {
756 return ldb_operr(ldb);
759 if (sd_propagation_control != NULL) {
761 * This just triggers a recalculation of the
762 * inherited aces.
764 user_sd = old_sd;
767 sd = get_new_descriptor(module, dn, req,
768 objectclass, parent_sd,
769 user_sd, old_sd, sd_flags);
770 if (sd == NULL) {
771 return ldb_operr(ldb);
773 msg = ldb_msg_copy_shallow(req, req->op.mod.message);
774 if (msg == NULL) {
775 return ldb_oom(ldb);
777 if (sd_propagation_control != NULL) {
778 ret = data_blob_cmp(old_sd, sd);
779 if (ret == 0) {
781 * The nTSecurityDescriptor is unchanged,
782 * which means we can stop the processing.
784 * We mark the control as critical again,
785 * as we have not processed it, so the caller
786 * can tell that the descriptor was unchanged.
788 sd_propagation_control->critical = 1;
789 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
792 ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor",
793 LDB_FLAG_MOD_REPLACE,
794 &sd_element);
795 if (ret != LDB_SUCCESS) {
796 return ldb_oom(ldb);
798 ret = ldb_msg_add_value(msg, "nTSecurityDescriptor",
799 sd, NULL);
800 if (ret != LDB_SUCCESS) {
801 return ldb_oom(ldb);
803 } else {
804 sd_element->values[0] = *sd;
807 ret = ldb_build_mod_req(&mod_req, ldb, req,
808 msg,
809 req->controls,
810 req,
811 dsdb_next_callback,
812 req);
813 LDB_REQ_SET_LOCATION(mod_req);
814 if (ret != LDB_SUCCESS) {
815 return ret;
818 return ldb_next_request(module, mod_req);
821 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
823 int ret;
824 struct ldb_context *ldb;
825 struct ldb_request *down_req;
826 struct descriptor_context *ac;
827 bool explicit_sd_flags = false;
828 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
829 bool show_sd = explicit_sd_flags;
831 if (!show_sd &&
832 ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor"))
834 show_sd = true;
837 if (!show_sd) {
838 return ldb_next_request(module, req);
841 ldb = ldb_module_get_ctx(module);
842 ac = descriptor_init_context(module, req);
843 if (ac == NULL) {
844 return ldb_operr(ldb);
846 ac->sd_flags = sd_flags;
848 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
849 req->op.search.base,
850 req->op.search.scope,
851 req->op.search.tree,
852 req->op.search.attrs,
853 req->controls,
854 ac, descriptor_search_callback,
855 ac->req);
856 LDB_REQ_SET_LOCATION(down_req);
857 if (ret != LDB_SUCCESS) {
858 return ret;
861 return ldb_next_request(ac->module, down_req);
864 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
866 struct ldb_context *ldb = ldb_module_get_ctx(module);
867 struct ldb_dn *olddn = req->op.rename.olddn;
868 struct ldb_dn *newdn = req->op.rename.newdn;
869 int ret;
871 /* do not manipulate our control entries */
872 if (ldb_dn_is_special(req->op.rename.olddn)) {
873 return ldb_next_request(module, req);
876 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n",
877 ldb_dn_get_linearized(olddn));
879 if (ldb_dn_compare(olddn, newdn) != 0) {
880 struct ldb_dn *nc_root;
882 ret = dsdb_find_nc_root(ldb, req, newdn, &nc_root);
883 if (ret != LDB_SUCCESS) {
884 return ldb_oom(ldb);
887 ret = dsdb_module_schedule_sd_propagation(module, nc_root,
888 newdn, true);
889 if (ret != LDB_SUCCESS) {
890 return ldb_operr(ldb);
894 return ldb_next_request(module, req);
897 static int descriptor_extended_sec_desc_propagation(struct ldb_module *module,
898 struct ldb_request *req)
900 struct descriptor_data *descriptor_private =
901 talloc_get_type_abort(ldb_module_get_private(module),
902 struct descriptor_data);
903 struct ldb_context *ldb = ldb_module_get_ctx(module);
904 struct dsdb_extended_sec_desc_propagation_op *op;
905 TALLOC_CTX *parent_mem = NULL;
906 struct descriptor_changes *parent_change = NULL;
907 struct descriptor_changes *c;
908 int ret;
910 op = talloc_get_type(req->op.extended.data,
911 struct dsdb_extended_sec_desc_propagation_op);
912 if (op == NULL) {
913 ldb_debug(ldb, LDB_DEBUG_FATAL,
914 "descriptor_extended_sec_desc_propagation: "
915 "invalid extended data\n");
916 return LDB_ERR_PROTOCOL_ERROR;
919 if (descriptor_private->trans_mem == NULL) {
920 return ldb_module_operr(module);
923 parent_mem = descriptor_private->trans_mem;
925 for (c = descriptor_private->changes; c; c = c->next) {
926 ret = ldb_dn_compare(c->nc_root, op->nc_root);
927 if (ret != 0) {
928 continue;
931 ret = ldb_dn_compare(c->dn, op->dn);
932 if (ret == 0) {
933 if (op->include_self) {
934 c->force_self = true;
935 } else {
936 c->force_children = true;
938 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
941 ret = ldb_dn_compare_base(c->dn, op->dn);
942 if (ret != 0) {
943 continue;
946 parent_mem = c;
947 parent_change = c;
948 break;
951 c = talloc_zero(parent_mem, struct descriptor_changes);
952 if (c == NULL) {
953 return ldb_module_oom(module);
955 c->nc_root = ldb_dn_copy(c, op->nc_root);
956 if (c->nc_root == NULL) {
957 return ldb_module_oom(module);
959 c->dn = ldb_dn_copy(c, op->dn);
960 if (c->dn == NULL) {
961 return ldb_module_oom(module);
963 if (op->include_self) {
964 c->force_self = true;
965 } else {
966 c->force_children = true;
969 if (parent_change != NULL) {
970 DLIST_ADD_END(parent_change->children, c, NULL);
971 } else {
972 DLIST_ADD_END(descriptor_private->changes, c, NULL);
975 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
978 static int descriptor_extended(struct ldb_module *module, struct ldb_request *req)
980 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID) == 0) {
981 return descriptor_extended_sec_desc_propagation(module, req);
984 return ldb_next_request(module, req);
987 static int descriptor_init(struct ldb_module *module)
989 struct ldb_context *ldb = ldb_module_get_ctx(module);
990 int ret;
991 struct descriptor_data *descriptor_private;
993 ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
994 if (ret != LDB_SUCCESS) {
995 ldb_debug(ldb, LDB_DEBUG_ERROR,
996 "descriptor: Unable to register control with rootdse!\n");
997 return ldb_operr(ldb);
1000 descriptor_private = talloc_zero(module, struct descriptor_data);
1001 if (descriptor_private == NULL) {
1002 ldb_oom(ldb);
1003 return LDB_ERR_OPERATIONS_ERROR;
1005 ldb_module_set_private(module, descriptor_private);
1007 return ldb_next_init(module);
1010 static int descriptor_sd_propagation_object(struct ldb_module *module,
1011 struct ldb_message *msg,
1012 bool *stop)
1014 struct ldb_context *ldb = ldb_module_get_ctx(module);
1015 struct ldb_request *sub_req;
1016 struct ldb_result *mod_res;
1017 struct ldb_control *sd_propagation_control;
1018 int ret;
1020 *stop = false;
1022 mod_res = talloc_zero(msg, struct ldb_result);
1023 if (mod_res == NULL) {
1024 return ldb_module_oom(module);
1027 ret = ldb_build_mod_req(&sub_req, ldb, mod_res,
1028 msg,
1029 NULL,
1030 mod_res,
1031 ldb_modify_default_callback,
1032 NULL);
1033 LDB_REQ_SET_LOCATION(sub_req);
1034 if (ret != LDB_SUCCESS) {
1035 return ldb_module_operr(module);
1038 ldb_req_mark_trusted(sub_req);
1040 ret = ldb_request_add_control(sub_req,
1041 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID,
1042 true, module);
1043 if (ret != LDB_SUCCESS) {
1044 return ldb_module_operr(module);
1047 sd_propagation_control = ldb_request_get_control(sub_req,
1048 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
1049 if (sd_propagation_control == NULL) {
1050 return ldb_module_operr(module);
1053 ret = dsdb_request_add_controls(sub_req,
1054 DSDB_FLAG_AS_SYSTEM |
1055 DSDB_SEARCH_SHOW_RECYCLED);
1056 if (ret != LDB_SUCCESS) {
1057 return ldb_module_operr(module);
1060 ret = descriptor_modify(module, sub_req);
1061 if (ret == LDB_SUCCESS) {
1062 ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL);
1064 if (ret != LDB_SUCCESS) {
1065 return ldb_module_operr(module);
1068 if (sd_propagation_control->critical != 0) {
1069 *stop = true;
1072 talloc_free(mod_res);
1074 return LDB_SUCCESS;
1077 static int descriptor_sd_propagation_msg_sort(struct ldb_message **m1,
1078 struct ldb_message **m2)
1080 struct ldb_dn *dn1 = (*m1)->dn;
1081 struct ldb_dn *dn2 = (*m2)->dn;
1084 * This sorts in tree order, parents first
1086 return ldb_dn_compare(dn2, dn1);
1089 static int descriptor_sd_propagation_dn_sort(struct ldb_dn *dn1,
1090 struct ldb_dn *dn2)
1093 * This sorts in tree order, parents first
1095 return ldb_dn_compare(dn2, dn1);
1098 static int descriptor_sd_propagation_recursive(struct ldb_module *module,
1099 struct descriptor_changes *change)
1101 struct ldb_context *ldb = ldb_module_get_ctx(module);
1102 struct ldb_result *res = NULL;
1103 unsigned int i;
1104 const char * const no_attrs[] = { "@__NONE__", NULL };
1105 struct descriptor_changes *c;
1106 struct descriptor_changes *stopped_stack = NULL;
1107 int ret;
1110 * Note: that we do not search for deleted/recycled objects
1112 ret = dsdb_module_search(module,
1113 change,
1114 &res,
1115 change->dn,
1116 LDB_SCOPE_SUBTREE,
1117 no_attrs,
1118 DSDB_FLAG_NEXT_MODULE |
1119 DSDB_FLAG_AS_SYSTEM,
1120 NULL, /* parent_req */
1121 "(objectClass=*)");
1122 if (ret != LDB_SUCCESS) {
1123 return ret;
1126 TYPESAFE_QSORT(res->msgs, res->count,
1127 descriptor_sd_propagation_msg_sort);
1129 for (c = change->children; c; c = c->next) {
1130 struct ldb_message *msg = NULL;
1132 BINARY_ARRAY_SEARCH_P(res->msgs, res->count, dn, c->dn,
1133 descriptor_sd_propagation_dn_sort,
1134 msg);
1136 if (msg == NULL) {
1137 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1138 "descriptor_sd_propagation_recursive: "
1139 "%s not found under %s",
1140 ldb_dn_get_linearized(c->dn),
1141 ldb_dn_get_linearized(change->dn));
1142 return LDB_ERR_OPERATIONS_ERROR;
1145 msg->elements = (struct ldb_message_element *)c;
1148 DLIST_ADD(stopped_stack, change);
1150 if (change->force_self) {
1151 i = 0;
1152 } else {
1153 i = 1;
1156 for (; i < res->count; i++) {
1157 struct descriptor_changes *cur;
1158 bool stop = false;
1160 cur = talloc_get_type(res->msgs[i]->elements,
1161 struct descriptor_changes);
1162 res->msgs[i]->elements = NULL;
1163 res->msgs[i]->num_elements = 0;
1165 if (cur != NULL) {
1166 DLIST_REMOVE(change->children, cur);
1169 for (c = stopped_stack; c; c = stopped_stack) {
1170 ret = ldb_dn_compare_base(c->dn,
1171 res->msgs[i]->dn);
1172 if (ret == 0) {
1173 break;
1176 c->stopped_dn = NULL;
1177 DLIST_REMOVE(stopped_stack, c);
1180 if (cur != NULL) {
1181 DLIST_ADD(stopped_stack, cur);
1184 if (stopped_stack->stopped_dn != NULL) {
1185 ret = ldb_dn_compare_base(stopped_stack->stopped_dn,
1186 res->msgs[i]->dn);
1187 if (ret == 0) {
1188 continue;
1190 stopped_stack->stopped_dn = NULL;
1193 ret = descriptor_sd_propagation_object(module, res->msgs[i],
1194 &stop);
1195 if (ret != LDB_SUCCESS) {
1196 return ret;
1199 if (cur != NULL && cur->force_children) {
1200 continue;
1203 if (stop) {
1204 stopped_stack->stopped_dn = res->msgs[i]->dn;
1205 continue;
1209 TALLOC_FREE(res);
1210 return LDB_SUCCESS;
1213 static int descriptor_start_transaction(struct ldb_module *module)
1215 struct descriptor_data *descriptor_private =
1216 talloc_get_type_abort(ldb_module_get_private(module),
1217 struct descriptor_data);
1219 if (descriptor_private->trans_mem != NULL) {
1220 return ldb_module_operr(module);
1223 descriptor_private->trans_mem = talloc_new(descriptor_private);
1224 if (descriptor_private->trans_mem == NULL) {
1225 return ldb_module_oom(module);
1227 descriptor_private->changes = NULL;
1229 return ldb_next_start_trans(module);
1232 static int descriptor_prepare_commit(struct ldb_module *module)
1234 struct descriptor_data *descriptor_private =
1235 talloc_get_type_abort(ldb_module_get_private(module),
1236 struct descriptor_data);
1237 struct descriptor_changes *c, *n;
1238 int ret;
1240 for (c = descriptor_private->changes; c; c = n) {
1241 n = c->next;
1242 DLIST_REMOVE(descriptor_private->changes, c);
1244 ret = descriptor_sd_propagation_recursive(module, c);
1245 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1246 continue;
1248 if (ret != LDB_SUCCESS) {
1249 return ret;
1253 return ldb_next_prepare_commit(module);
1256 static int descriptor_end_transaction(struct ldb_module *module)
1258 struct descriptor_data *descriptor_private =
1259 talloc_get_type_abort(ldb_module_get_private(module),
1260 struct descriptor_data);
1262 TALLOC_FREE(descriptor_private->trans_mem);
1263 descriptor_private->changes = NULL;
1265 return ldb_next_end_trans(module);
1268 static int descriptor_del_transaction(struct ldb_module *module)
1270 struct descriptor_data *descriptor_private =
1271 talloc_get_type_abort(ldb_module_get_private(module),
1272 struct descriptor_data);
1274 TALLOC_FREE(descriptor_private->trans_mem);
1275 descriptor_private->changes = NULL;
1277 return ldb_next_del_trans(module);
1280 static const struct ldb_module_ops ldb_descriptor_module_ops = {
1281 .name = "descriptor",
1282 .search = descriptor_search,
1283 .add = descriptor_add,
1284 .modify = descriptor_modify,
1285 .rename = descriptor_rename,
1286 .init_context = descriptor_init,
1287 .extended = descriptor_extended,
1288 .start_transaction = descriptor_start_transaction,
1289 .prepare_commit = descriptor_prepare_commit,
1290 .end_transaction = descriptor_end_transaction,
1291 .del_transaction = descriptor_del_transaction,
1294 int ldb_descriptor_module_init(const char *version)
1296 LDB_MODULE_CHECK_VERSION(version);
1297 return ldb_register_module(&ldb_descriptor_module_ops);