s4:dsdb/descriptor: sort descriptor_changes tree based
[Samba.git] / source4 / dsdb / samdb / ldb_modules / descriptor.c
blob6e96361117acf1298dce9b2167507ea8943bb66b
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/util_tdb.h"
46 #include "lib/dbwrap/dbwrap.h"
47 #include "lib/dbwrap/dbwrap_rbt.h"
49 struct descriptor_changes {
50 struct descriptor_changes *prev, *next;
51 struct ldb_dn *nc_root;
52 struct GUID guid;
53 struct GUID parent_guid;
54 bool force_self;
55 bool force_children;
56 struct ldb_dn *stopped_dn;
57 size_t ref_count;
58 size_t sort_count;
61 struct descriptor_transaction {
62 TALLOC_CTX *mem;
63 struct {
65 * We used to have a list of changes, appended with each
66 * DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID operation.
68 * But the main problem was that a replication
69 * cycle (mainly the initial replication) calls
70 * DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID for the
71 * same object[GUID] more than once. With
72 * DRSUAPI_DRS_GET_TGT we'll get the naming
73 * context head object and other top level
74 * containers, every often.
76 * It means we'll process objects more
77 * than once and waste a lot of time
78 * doing the same work again and again.
80 * We use an objectGUID based map in order to
81 * avoid registering objects more than once.
82 * In an domain with 22000 object it can
83 * reduce the work from 4 hours down to ~ 3.5 minutes.
85 struct descriptor_changes *list;
86 struct db_context *map;
87 size_t num_registrations;
88 size_t num_registered;
89 size_t num_toplevel;
90 size_t num_processed;
91 } changes;
92 struct {
93 size_t num_processed;
94 } objects;
97 struct descriptor_data {
98 struct descriptor_transaction transaction;
101 struct descriptor_context {
102 struct ldb_module *module;
103 struct ldb_request *req;
104 struct ldb_message *msg;
105 struct ldb_reply *search_res;
106 struct ldb_reply *search_oc_res;
107 struct ldb_val *parentsd_val;
108 struct ldb_message_element *sd_element;
109 struct ldb_val *sd_val;
110 uint32_t sd_flags;
111 int (*step_fn)(struct descriptor_context *);
114 static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
115 struct ldb_dn *dn,
116 struct security_token *token,
117 struct ldb_context *ldb)
119 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
120 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
121 struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
122 struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS);
123 struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS);
124 struct dom_sid *dag_sid;
125 struct ldb_dn *nc_root;
126 int ret;
128 ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root);
129 if (ret != LDB_SUCCESS) {
130 talloc_free(tmp_ctx);
131 return NULL;
134 if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
135 if (security_token_has_sid(token, sa_sid)) {
136 dag_sid = dom_sid_dup(mem_ctx, sa_sid);
137 } else if (security_token_has_sid(token, ea_sid)) {
138 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
139 } else if (security_token_has_sid(token, da_sid)) {
140 dag_sid = dom_sid_dup(mem_ctx, da_sid);
141 } else if (security_token_is_system(token)) {
142 dag_sid = dom_sid_dup(mem_ctx, sa_sid);
143 } else {
144 dag_sid = NULL;
146 } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
147 if (security_token_has_sid(token, ea_sid)) {
148 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
149 } else if (security_token_has_sid(token, da_sid)) {
150 dag_sid = dom_sid_dup(mem_ctx, da_sid);
151 } else if (security_token_is_system(token)) {
152 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
153 } else {
154 dag_sid = NULL;
156 } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
157 if (security_token_has_sid(token, da_sid)) {
158 dag_sid = dom_sid_dup(mem_ctx, da_sid);
159 } else if (security_token_has_sid(token, ea_sid)) {
160 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
161 } else if (security_token_is_system(token)) {
162 dag_sid = dom_sid_dup(mem_ctx, da_sid);
163 } else {
164 dag_sid = NULL;
166 } else {
167 dag_sid = NULL;
170 talloc_free(tmp_ctx);
171 return dag_sid;
174 static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx,
175 const struct dsdb_class *objectclass)
177 struct ldb_context *ldb = ldb_module_get_ctx(module);
178 struct security_descriptor *sd;
179 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
181 if (!objectclass->defaultSecurityDescriptor || !domain_sid) {
182 return NULL;
185 sd = sddl_decode(mem_ctx,
186 objectclass->defaultSecurityDescriptor,
187 domain_sid);
188 return sd;
191 static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
192 struct ldb_context *ldb,
193 struct dom_sid *dag)
196 * This depends on the function level of the DC
197 * which is 2008R2 in our case. Which means it is
198 * higher than 2003 and we should use the
199 * "default administrator group" also as owning group.
201 * This matches dcpromo for a 2003 domain
202 * on a Windows 2008R2 DC.
204 return dag;
207 static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
208 struct security_descriptor *new_sd,
209 struct security_descriptor *old_sd,
210 uint32_t sd_flags)
212 struct security_descriptor *final_sd;
213 /* if there is no control or control == 0 modify everything */
214 if (!sd_flags) {
215 return new_sd;
218 final_sd = talloc_zero(mem_ctx, struct security_descriptor);
219 final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
220 final_sd->type = SEC_DESC_SELF_RELATIVE;
222 if (sd_flags & (SECINFO_OWNER)) {
223 if (new_sd->owner_sid) {
224 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
226 final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
228 else if (old_sd) {
229 if (old_sd->owner_sid) {
230 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
232 final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
235 if (sd_flags & (SECINFO_GROUP)) {
236 if (new_sd->group_sid) {
237 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
239 final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
241 else if (old_sd) {
242 if (old_sd->group_sid) {
243 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
245 final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
248 if (sd_flags & (SECINFO_SACL)) {
249 final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
250 final_sd->type |= new_sd->type & (SEC_DESC_SACL_PRESENT |
251 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
252 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
253 SEC_DESC_SERVER_SECURITY);
255 else if (old_sd && old_sd->sacl) {
256 final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
257 final_sd->type |= old_sd->type & (SEC_DESC_SACL_PRESENT |
258 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
259 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
260 SEC_DESC_SERVER_SECURITY);
263 if (sd_flags & (SECINFO_DACL)) {
264 final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
265 final_sd->type |= new_sd->type & (SEC_DESC_DACL_PRESENT |
266 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
267 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
268 SEC_DESC_DACL_TRUSTED);
270 else if (old_sd && old_sd->dacl) {
271 final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
272 final_sd->type |= old_sd->type & (SEC_DESC_DACL_PRESENT |
273 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
274 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
275 SEC_DESC_DACL_TRUSTED);
277 /* not so sure about this */
278 final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
279 return final_sd;
282 static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
283 struct ldb_dn *dn,
284 TALLOC_CTX *mem_ctx,
285 const struct dsdb_class *objectclass,
286 const struct ldb_val *parent,
287 const struct ldb_val *object,
288 const struct ldb_val *old_sd,
289 uint32_t sd_flags)
291 struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
292 struct security_descriptor *old_descriptor = NULL;
293 struct security_descriptor *new_sd, *final_sd;
294 DATA_BLOB *linear_sd;
295 enum ndr_err_code ndr_err;
296 struct ldb_context *ldb = ldb_module_get_ctx(module);
297 struct auth_session_info *session_info
298 = ldb_get_opaque(ldb, DSDB_SESSION_INFO);
299 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
300 struct dom_sid *default_owner;
301 struct dom_sid *default_group;
302 struct security_descriptor *default_descriptor = NULL;
303 struct GUID *object_list = NULL;
305 if (objectclass != NULL) {
306 default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
307 object_list = talloc_zero_array(mem_ctx, struct GUID, 2);
308 if (object_list == NULL) {
309 return NULL;
311 object_list[0] = objectclass->schemaIDGUID;
314 if (object) {
315 user_descriptor = talloc(mem_ctx, struct security_descriptor);
316 if (!user_descriptor) {
317 return NULL;
319 ndr_err = ndr_pull_struct_blob(object, user_descriptor,
320 user_descriptor,
321 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
323 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
324 talloc_free(user_descriptor);
325 return NULL;
327 } else {
328 user_descriptor = default_descriptor;
331 if (old_sd) {
332 old_descriptor = talloc(mem_ctx, struct security_descriptor);
333 if (!old_descriptor) {
334 return NULL;
336 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor,
337 old_descriptor,
338 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
340 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341 talloc_free(old_descriptor);
342 return NULL;
346 if (parent) {
347 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
348 if (!parent_descriptor) {
349 return NULL;
351 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor,
352 parent_descriptor,
353 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
355 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
356 talloc_free(parent_descriptor);
357 return NULL;
361 if (user_descriptor && default_descriptor &&
362 (user_descriptor->dacl == NULL))
364 user_descriptor->dacl = default_descriptor->dacl;
365 user_descriptor->type |= default_descriptor->type & (
366 SEC_DESC_DACL_PRESENT |
367 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
368 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
369 SEC_DESC_DACL_TRUSTED);
372 if (user_descriptor && default_descriptor &&
373 (user_descriptor->sacl == NULL))
375 user_descriptor->sacl = default_descriptor->sacl;
376 user_descriptor->type |= default_descriptor->type & (
377 SEC_DESC_SACL_PRESENT |
378 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
379 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
380 SEC_DESC_SERVER_SECURITY);
384 if (!(sd_flags & SECINFO_OWNER) && user_descriptor) {
385 user_descriptor->owner_sid = NULL;
388 * We need the correct owner sid
389 * when calculating the DACL or SACL
391 if (old_descriptor) {
392 user_descriptor->owner_sid = old_descriptor->owner_sid;
395 if (!(sd_flags & SECINFO_GROUP) && user_descriptor) {
396 user_descriptor->group_sid = NULL;
399 * We need the correct group sid
400 * when calculating the DACL or SACL
402 if (old_descriptor) {
403 user_descriptor->group_sid = old_descriptor->group_sid;
406 if (!(sd_flags & SECINFO_DACL) && user_descriptor) {
407 user_descriptor->dacl = NULL;
410 * We add SEC_DESC_DACL_PROTECTED so that
411 * create_security_descriptor() skips
412 * the unused inheritance calculation
414 user_descriptor->type |= SEC_DESC_DACL_PROTECTED;
416 if (!(sd_flags & SECINFO_SACL) && user_descriptor) {
417 user_descriptor->sacl = NULL;
420 * We add SEC_DESC_SACL_PROTECTED so that
421 * create_security_descriptor() skips
422 * the unused inheritance calculation
424 user_descriptor->type |= SEC_DESC_SACL_PROTECTED;
427 default_owner = get_default_ag(mem_ctx, dn,
428 session_info->security_token, ldb);
429 default_group = get_default_group(mem_ctx, ldb, default_owner);
430 new_sd = create_security_descriptor(mem_ctx,
431 parent_descriptor,
432 user_descriptor,
433 true,
434 object_list,
435 SEC_DACL_AUTO_INHERIT |
436 SEC_SACL_AUTO_INHERIT,
437 session_info->security_token,
438 default_owner, default_group,
439 map_generic_rights_ds);
440 if (!new_sd) {
441 return NULL;
443 final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
445 if (!final_sd) {
446 return NULL;
449 if (final_sd->dacl) {
450 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
452 if (final_sd->sacl) {
453 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
457 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
458 DBG_DEBUG("Object %s created with descriptor %s\n\n",
459 ldb_dn_get_linearized(dn),
460 sddl_encode(tmp_ctx, final_sd, domain_sid));
461 TALLOC_FREE(tmp_ctx);
464 linear_sd = talloc(mem_ctx, DATA_BLOB);
465 if (!linear_sd) {
466 return NULL;
469 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
470 final_sd,
471 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
472 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
473 return NULL;
476 return linear_sd;
479 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
480 TALLOC_CTX *mem_ctx,
481 struct ldb_val *sd,
482 uint32_t sd_flags)
484 struct security_descriptor *old_sd, *final_sd;
485 DATA_BLOB *linear_sd;
486 enum ndr_err_code ndr_err;
488 old_sd = talloc(mem_ctx, struct security_descriptor);
489 if (!old_sd) {
490 return NULL;
492 ndr_err = ndr_pull_struct_blob(sd, old_sd,
493 old_sd,
494 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
496 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
497 talloc_free(old_sd);
498 return NULL;
501 final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
503 if (!final_sd) {
504 return NULL;
507 linear_sd = talloc(mem_ctx, DATA_BLOB);
508 if (!linear_sd) {
509 return NULL;
512 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
513 final_sd,
514 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
515 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
516 return NULL;
519 return linear_sd;
522 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
523 struct ldb_request *req)
525 struct ldb_context *ldb;
526 struct descriptor_context *ac;
528 ldb = ldb_module_get_ctx(module);
530 ac = talloc_zero(req, struct descriptor_context);
531 if (ac == NULL) {
532 ldb_set_errstring(ldb, "Out of Memory");
533 return NULL;
536 ac->module = module;
537 ac->req = req;
538 return ac;
541 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
543 struct descriptor_context *ac;
544 struct ldb_val *sd_val = NULL;
545 struct ldb_message_element *sd_el;
546 DATA_BLOB *show_sd;
547 int ret = LDB_SUCCESS;
549 ac = talloc_get_type(req->context, struct descriptor_context);
551 if (!ares) {
552 ret = LDB_ERR_OPERATIONS_ERROR;
553 goto fail;
555 if (ares->error != LDB_SUCCESS) {
556 return ldb_module_done(ac->req, ares->controls,
557 ares->response, ares->error);
560 switch (ares->type) {
561 case LDB_REPLY_ENTRY:
562 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
563 if (sd_el) {
564 sd_val = sd_el->values;
567 if (sd_val) {
568 show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
569 sd_val, ac->sd_flags);
570 if (!show_sd) {
571 ret = LDB_ERR_OPERATIONS_ERROR;
572 goto fail;
574 ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
575 ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
576 if (ret != LDB_SUCCESS) {
577 goto fail;
580 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
582 case LDB_REPLY_REFERRAL:
583 return ldb_module_send_referral(ac->req, ares->referral);
585 case LDB_REPLY_DONE:
586 return ldb_module_done(ac->req, ares->controls,
587 ares->response, ares->error);
590 fail:
591 talloc_free(ares);
592 return ldb_module_done(ac->req, NULL, NULL, ret);
595 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
597 struct ldb_context *ldb = ldb_module_get_ctx(module);
598 struct ldb_request *add_req;
599 struct ldb_message *msg;
600 struct ldb_result *parent_res;
601 const struct ldb_val *parent_sd = NULL;
602 const struct ldb_val *user_sd;
603 struct ldb_dn *dn = req->op.add.message->dn;
604 struct ldb_dn *parent_dn, *nc_root;
605 struct ldb_message_element *objectclass_element, *sd_element;
606 int ret;
607 const struct dsdb_schema *schema;
608 DATA_BLOB *sd;
609 const struct dsdb_class *objectclass;
610 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
611 uint32_t instanceType;
612 bool isNC = false;
613 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
615 /* do not manipulate our control entries */
616 if (ldb_dn_is_special(dn)) {
617 return ldb_next_request(module, req);
620 user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
621 sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
622 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
623 if (user_sd == NULL && sd_element) {
624 return ldb_next_request(module, req);
627 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
629 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
631 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
632 isNC = true;
635 if (!isNC) {
636 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
637 if (ret != LDB_SUCCESS) {
638 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
639 ldb_dn_get_linearized(dn));
640 return ret;
643 if (ldb_dn_compare(dn, nc_root) == 0) {
644 DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
645 isNC = true;
649 if (isNC) {
650 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
652 if (!isNC) {
653 /* if the object has a parent, retrieve its SD to
654 * use for calculation. Unfortunately we do not yet have
655 * instanceType, so we use dsdb_find_nc_root. */
657 parent_dn = ldb_dn_get_parent(req, dn);
658 if (parent_dn == NULL) {
659 return ldb_oom(ldb);
662 /* we aren't any NC */
663 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
664 parent_attrs,
665 DSDB_FLAG_NEXT_MODULE |
666 DSDB_FLAG_AS_SYSTEM |
667 DSDB_SEARCH_SHOW_RECYCLED,
668 req);
669 if (ret != LDB_SUCCESS) {
670 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
671 ldb_dn_get_linearized(parent_dn));
672 return ret;
674 if (parent_res->count != 1) {
675 return ldb_operr(ldb);
677 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
680 schema = dsdb_get_schema(ldb, req);
682 objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
683 if (objectclass_element == NULL) {
684 return ldb_operr(ldb);
687 objectclass = dsdb_get_last_structural_class(schema,
688 objectclass_element);
689 if (objectclass == NULL) {
690 return ldb_operr(ldb);
694 * The SD_FLAG control is ignored on add
695 * and we default to all bits set.
697 sd_flags = SECINFO_OWNER|SECINFO_GROUP|SECINFO_SACL|SECINFO_DACL;
699 sd = get_new_descriptor(module, dn, req,
700 objectclass, parent_sd,
701 user_sd, NULL, sd_flags);
702 if (sd == NULL) {
703 return ldb_operr(ldb);
705 msg = ldb_msg_copy_shallow(req, req->op.add.message);
706 if (msg == NULL) {
707 return ldb_oom(ldb);
709 if (sd_element != NULL) {
710 sd_element->values[0] = *sd;
711 } else {
712 ret = ldb_msg_add_steal_value(msg,
713 "nTSecurityDescriptor",
714 sd);
715 if (ret != LDB_SUCCESS) {
716 return ret;
720 ret = ldb_build_add_req(&add_req, ldb, req,
721 msg,
722 req->controls,
723 req, dsdb_next_callback,
724 req);
725 LDB_REQ_SET_LOCATION(add_req);
726 if (ret != LDB_SUCCESS) {
727 return ldb_error(ldb, ret,
728 "descriptor_add: Error creating new add request.");
731 return ldb_next_request(module, add_req);
734 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
736 struct ldb_context *ldb = ldb_module_get_ctx(module);
737 struct ldb_request *mod_req;
738 struct ldb_message *msg;
739 struct ldb_result *current_res, *parent_res;
740 const struct ldb_val *old_sd = NULL;
741 const struct ldb_val *parent_sd = NULL;
742 const struct ldb_val *user_sd;
743 struct ldb_dn *dn = req->op.mod.message->dn;
744 struct ldb_dn *parent_dn;
745 struct ldb_message_element *objectclass_element, *sd_element;
746 int ret;
747 uint32_t instanceType;
748 bool explicit_sd_flags = false;
749 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
750 const struct dsdb_schema *schema;
751 DATA_BLOB *sd;
752 const struct dsdb_class *objectclass;
753 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
754 static const char * const current_attrs[] = { "nTSecurityDescriptor",
755 "instanceType",
756 "objectClass", NULL };
757 struct GUID parent_guid = { .time_low = 0 };
758 struct ldb_control *sd_propagation_control;
759 int cmp_ret = -1;
761 /* do not manipulate our control entries */
762 if (ldb_dn_is_special(dn)) {
763 return ldb_next_request(module, req);
766 sd_propagation_control = ldb_request_get_control(req,
767 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
768 if (sd_propagation_control != NULL) {
769 if (sd_propagation_control->data != module) {
770 return ldb_operr(ldb);
772 if (req->op.mod.message->num_elements != 0) {
773 return ldb_operr(ldb);
775 if (explicit_sd_flags) {
776 return ldb_operr(ldb);
778 if (sd_flags != 0xF) {
779 return ldb_operr(ldb);
781 if (sd_propagation_control->critical == 0) {
782 return ldb_operr(ldb);
785 sd_propagation_control->critical = 0;
788 sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor");
789 if (sd_propagation_control == NULL && sd_element == NULL) {
790 return ldb_next_request(module, req);
794 * nTSecurityDescriptor with DELETE is not supported yet.
795 * TODO: handle this correctly.
797 if (sd_propagation_control == NULL &&
798 LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE)
800 return ldb_module_error(module,
801 LDB_ERR_UNWILLING_TO_PERFORM,
802 "MOD_DELETE for nTSecurityDescriptor "
803 "not supported yet");
806 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
807 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
808 if (sd_propagation_control == NULL && user_sd == NULL) {
809 return ldb_next_request(module, req);
812 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
814 ret = dsdb_module_search_dn(module, req, &current_res, dn,
815 current_attrs,
816 DSDB_FLAG_NEXT_MODULE |
817 DSDB_FLAG_AS_SYSTEM |
818 DSDB_SEARCH_SHOW_RECYCLED |
819 DSDB_SEARCH_SHOW_EXTENDED_DN,
820 req);
821 if (ret != LDB_SUCCESS) {
822 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
823 ldb_dn_get_linearized(dn));
824 return ret;
827 instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
828 "instanceType", 0);
829 /* if the object has a parent, retrieve its SD to
830 * use for calculation */
831 if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
832 !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
833 NTSTATUS status;
835 parent_dn = ldb_dn_get_parent(req, dn);
836 if (parent_dn == NULL) {
837 return ldb_oom(ldb);
839 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
840 parent_attrs,
841 DSDB_FLAG_NEXT_MODULE |
842 DSDB_FLAG_AS_SYSTEM |
843 DSDB_SEARCH_SHOW_RECYCLED |
844 DSDB_SEARCH_SHOW_EXTENDED_DN,
845 req);
846 if (ret != LDB_SUCCESS) {
847 ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
848 ldb_dn_get_linearized(parent_dn));
849 return ret;
851 if (parent_res->count != 1) {
852 return ldb_operr(ldb);
854 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
856 status = dsdb_get_extended_dn_guid(parent_res->msgs[0]->dn,
857 &parent_guid,
858 "GUID");
859 if (!NT_STATUS_IS_OK(status)) {
860 return ldb_operr(ldb);
864 schema = dsdb_get_schema(ldb, req);
866 objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
867 if (objectclass_element == NULL) {
868 return ldb_operr(ldb);
871 objectclass = dsdb_get_last_structural_class(schema,
872 objectclass_element);
873 if (objectclass == NULL) {
874 return ldb_operr(ldb);
877 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
878 if (old_sd == NULL) {
879 return ldb_operr(ldb);
882 if (sd_propagation_control != NULL) {
884 * This just triggers a recalculation of the
885 * inherited aces.
887 user_sd = old_sd;
890 sd = get_new_descriptor(module, current_res->msgs[0]->dn, req,
891 objectclass, parent_sd,
892 user_sd, old_sd, sd_flags);
893 if (sd == NULL) {
894 return ldb_operr(ldb);
896 msg = ldb_msg_copy_shallow(req, req->op.mod.message);
897 if (msg == NULL) {
898 return ldb_oom(ldb);
900 cmp_ret = data_blob_cmp(old_sd, sd);
901 if (sd_propagation_control != NULL) {
902 if (cmp_ret == 0) {
904 * The nTSecurityDescriptor is unchanged,
905 * which means we can stop the processing.
907 * We mark the control as critical again,
908 * as we have not processed it, so the caller
909 * can tell that the descriptor was unchanged.
911 sd_propagation_control->critical = 1;
912 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
915 ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor",
916 LDB_FLAG_MOD_REPLACE,
917 &sd_element);
918 if (ret != LDB_SUCCESS) {
919 return ldb_oom(ldb);
921 ret = ldb_msg_add_value(msg, "nTSecurityDescriptor",
922 sd, NULL);
923 if (ret != LDB_SUCCESS) {
924 return ldb_oom(ldb);
926 } else if (cmp_ret != 0) {
927 struct GUID guid;
928 struct ldb_dn *nc_root;
929 NTSTATUS status;
931 ret = dsdb_find_nc_root(ldb,
932 msg,
933 current_res->msgs[0]->dn,
934 &nc_root);
935 if (ret != LDB_SUCCESS) {
936 return ldb_oom(ldb);
939 status = dsdb_get_extended_dn_guid(current_res->msgs[0]->dn,
940 &guid,
941 "GUID");
942 if (!NT_STATUS_IS_OK(status)) {
943 return ldb_operr(ldb);
947 * Force SD propagation on children of this record
949 ret = dsdb_module_schedule_sd_propagation(module,
950 nc_root,
951 guid,
952 parent_guid,
953 false);
954 if (ret != LDB_SUCCESS) {
955 return ldb_operr(ldb);
957 sd_element->values[0] = *sd;
958 } else {
959 sd_element->values[0] = *sd;
962 ret = ldb_build_mod_req(&mod_req, ldb, req,
963 msg,
964 req->controls,
965 req,
966 dsdb_next_callback,
967 req);
968 LDB_REQ_SET_LOCATION(mod_req);
969 if (ret != LDB_SUCCESS) {
970 return ret;
973 return ldb_next_request(module, mod_req);
976 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
978 int ret;
979 struct ldb_context *ldb;
980 struct ldb_request *down_req;
981 struct descriptor_context *ac;
982 bool explicit_sd_flags = false;
983 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
984 bool show_sd = explicit_sd_flags;
986 if (!show_sd &&
987 ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor"))
989 show_sd = true;
992 if (!show_sd) {
993 return ldb_next_request(module, req);
996 ldb = ldb_module_get_ctx(module);
997 ac = descriptor_init_context(module, req);
998 if (ac == NULL) {
999 return ldb_operr(ldb);
1001 ac->sd_flags = sd_flags;
1003 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
1004 req->op.search.base,
1005 req->op.search.scope,
1006 req->op.search.tree,
1007 req->op.search.attrs,
1008 req->controls,
1009 ac, descriptor_search_callback,
1010 ac->req);
1011 LDB_REQ_SET_LOCATION(down_req);
1012 if (ret != LDB_SUCCESS) {
1013 return ret;
1016 return ldb_next_request(ac->module, down_req);
1019 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
1021 struct ldb_context *ldb = ldb_module_get_ctx(module);
1022 struct ldb_dn *olddn = req->op.rename.olddn;
1023 struct ldb_dn *newdn = req->op.rename.newdn;
1024 int ret;
1026 /* do not manipulate our control entries */
1027 if (ldb_dn_is_special(req->op.rename.olddn)) {
1028 return ldb_next_request(module, req);
1031 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n",
1032 ldb_dn_get_linearized(olddn));
1034 if (ldb_dn_compare(olddn, newdn) != 0) {
1035 struct ldb_dn *nc_root;
1036 struct GUID guid;
1038 ret = dsdb_find_nc_root(ldb, req, newdn, &nc_root);
1039 if (ret != LDB_SUCCESS) {
1040 return ldb_oom(ldb);
1043 ret = dsdb_module_guid_by_dn(module,
1044 olddn,
1045 &guid,
1046 req);
1047 if (ret == LDB_SUCCESS) {
1049 * Without disturbing any errors if the olddn
1050 * does not exit, force SD propagation on
1051 * this record (get a new inherited SD from
1052 * the potentially new parent
1054 * We don't now the parent guid here,
1055 * but we're not in a hot code path here,
1056 * as the "descriptor" module is located
1057 * above the "repl_meta_data", only
1058 * originating changes are handled here.
1060 * If it turns out to be a problem we may
1061 * search for the new parent guid.
1063 struct GUID parent_guid = { .time_low = 0 };
1065 ret = dsdb_module_schedule_sd_propagation(module,
1066 nc_root,
1067 guid,
1068 parent_guid,
1069 true);
1070 if (ret != LDB_SUCCESS) {
1071 return ldb_operr(ldb);
1076 return ldb_next_request(module, req);
1079 static void descriptor_changes_parser(TDB_DATA key, TDB_DATA data, void *private_data)
1081 struct descriptor_changes **c_ptr = (struct descriptor_changes **)private_data;
1082 uintptr_t ptr = 0;
1084 SMB_ASSERT(data.dsize == sizeof(ptr));
1086 memcpy(&ptr, data.dptr, data.dsize);
1088 *c_ptr = talloc_get_type_abort((void *)ptr, struct descriptor_changes);
1091 static int descriptor_extended_sec_desc_propagation(struct ldb_module *module,
1092 struct ldb_request *req)
1094 struct descriptor_data *descriptor_private =
1095 talloc_get_type_abort(ldb_module_get_private(module),
1096 struct descriptor_data);
1097 struct descriptor_transaction *t = &descriptor_private->transaction;
1098 struct ldb_context *ldb = ldb_module_get_ctx(module);
1099 struct dsdb_extended_sec_desc_propagation_op *op;
1100 struct descriptor_changes *c = NULL;
1101 TDB_DATA key;
1102 NTSTATUS status;
1104 op = talloc_get_type(req->op.extended.data,
1105 struct dsdb_extended_sec_desc_propagation_op);
1106 if (op == NULL) {
1107 ldb_debug(ldb, LDB_DEBUG_FATAL,
1108 "descriptor_extended_sec_desc_propagation: "
1109 "invalid extended data\n");
1110 return LDB_ERR_PROTOCOL_ERROR;
1113 if (t->mem == NULL) {
1114 return ldb_module_operr(module);
1117 if (GUID_equal(&op->parent_guid, &op->guid)) {
1119 * This is an unexpected situation,
1120 * it should never happen!
1122 DBG_ERR("ERROR: Object %s is its own parent (nc_root=%s)\n",
1123 GUID_string(t->mem, &op->guid),
1124 ldb_dn_get_extended_linearized(t->mem, op->nc_root, 1));
1125 return ldb_module_operr(module);
1129 * First we check if we already have an registration
1130 * for the given object.
1133 key = make_tdb_data((const void*)&op->guid, sizeof(op->guid));
1134 status = dbwrap_parse_record(t->changes.map, key,
1135 descriptor_changes_parser, &c);
1136 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1137 c = NULL;
1138 status = NT_STATUS_OK;
1140 if (!NT_STATUS_IS_OK(status)) {
1141 ldb_debug(ldb, LDB_DEBUG_FATAL,
1142 "dbwrap_parse_record() - %s\n",
1143 nt_errstr(status));
1144 return ldb_module_operr(module);
1147 if (c == NULL) {
1149 * Create a new structure if we
1150 * don't know about the object yet.
1153 c = talloc_zero(t->mem, struct descriptor_changes);
1154 if (c == NULL) {
1155 return ldb_module_oom(module);
1157 c->nc_root = ldb_dn_copy(c, op->nc_root);
1158 if (c->nc_root == NULL) {
1159 return ldb_module_oom(module);
1161 c->guid = op->guid;
1164 if (ldb_dn_compare(c->nc_root, op->nc_root) != 0) {
1166 * This is an unexpected situation,
1167 * we don't expect the nc root to change
1168 * during a replication cycle.
1170 DBG_ERR("ERROR: Object %s nc_root changed %s => %s\n",
1171 GUID_string(c, &c->guid),
1172 ldb_dn_get_extended_linearized(c, c->nc_root, 1),
1173 ldb_dn_get_extended_linearized(c, op->nc_root, 1));
1174 return ldb_module_operr(module);
1177 c->ref_count += 1;
1180 * always use the last known parent_guid.
1182 c->parent_guid = op->parent_guid;
1185 * Note that we only set, but don't clear values here,
1186 * it means c->force_self and c->force_children can
1187 * both be true in the end.
1189 if (op->include_self) {
1190 c->force_self = true;
1191 } else {
1192 c->force_children = true;
1195 if (c->ref_count == 1) {
1196 struct TDB_DATA val = make_tdb_data((const void*)&c, sizeof(c));
1199 * Remember the change by objectGUID in order
1200 * to avoid processing it more than once.
1203 status = dbwrap_store(t->changes.map, key, val, TDB_INSERT);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 ldb_debug(ldb, LDB_DEBUG_FATAL,
1206 "dbwrap_parse_record() - %s\n",
1207 nt_errstr(status));
1208 return ldb_module_operr(module);
1211 DLIST_ADD_END(t->changes.list, c);
1212 t->changes.num_registered += 1;
1214 t->changes.num_registrations += 1;
1216 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1219 static int descriptor_extended(struct ldb_module *module, struct ldb_request *req)
1221 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID) == 0) {
1222 return descriptor_extended_sec_desc_propagation(module, req);
1225 return ldb_next_request(module, req);
1228 static int descriptor_init(struct ldb_module *module)
1230 struct ldb_context *ldb = ldb_module_get_ctx(module);
1231 int ret;
1232 struct descriptor_data *descriptor_private;
1234 ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
1235 if (ret != LDB_SUCCESS) {
1236 ldb_debug(ldb, LDB_DEBUG_ERROR,
1237 "descriptor: Unable to register control with rootdse!\n");
1238 return ldb_operr(ldb);
1241 descriptor_private = talloc_zero(module, struct descriptor_data);
1242 if (descriptor_private == NULL) {
1243 ldb_oom(ldb);
1244 return LDB_ERR_OPERATIONS_ERROR;
1246 ldb_module_set_private(module, descriptor_private);
1248 return ldb_next_init(module);
1251 static int descriptor_sd_propagation_object(struct ldb_module *module,
1252 struct ldb_message *msg,
1253 bool *stop)
1255 struct descriptor_data *descriptor_private =
1256 talloc_get_type_abort(ldb_module_get_private(module),
1257 struct descriptor_data);
1258 struct descriptor_transaction *t = &descriptor_private->transaction;
1259 struct ldb_context *ldb = ldb_module_get_ctx(module);
1260 struct ldb_request *sub_req;
1261 struct ldb_result *mod_res;
1262 struct ldb_control *sd_propagation_control;
1263 struct GUID guid;
1264 int ret;
1265 TDB_DATA key;
1266 NTSTATUS status;
1267 struct descriptor_changes *c = NULL;
1269 *stop = false;
1271 t->objects.num_processed += 1;
1274 * We get the GUID of the object
1275 * in order to check if there's
1276 * a descriptor_changes in our list.
1279 status = dsdb_get_extended_dn_guid(msg->dn, &guid, "GUID");
1280 if (!NT_STATUS_IS_OK(status)) {
1281 return ldb_operr(ldb);
1284 key = make_tdb_data((const void*)&guid, sizeof(guid));
1285 status = dbwrap_parse_record(t->changes.map, key, descriptor_changes_parser, &c);
1286 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1287 c = NULL;
1288 status = NT_STATUS_OK;
1290 if (!NT_STATUS_IS_OK(status)) {
1291 ldb_debug(ldb, LDB_DEBUG_FATAL,
1292 "dbwrap_parse_record() - %s\n",
1293 nt_errstr(status));
1294 return ldb_module_operr(module);
1297 mod_res = talloc_zero(msg, struct ldb_result);
1298 if (mod_res == NULL) {
1299 return ldb_module_oom(module);
1302 ret = ldb_build_mod_req(&sub_req, ldb, mod_res,
1303 msg,
1304 NULL,
1305 mod_res,
1306 ldb_modify_default_callback,
1307 NULL);
1308 LDB_REQ_SET_LOCATION(sub_req);
1309 if (ret != LDB_SUCCESS) {
1310 return ldb_module_operr(module);
1313 ldb_req_mark_trusted(sub_req);
1315 ret = ldb_request_add_control(sub_req,
1316 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID,
1317 true, module);
1318 if (ret != LDB_SUCCESS) {
1319 return ldb_module_operr(module);
1322 sd_propagation_control = ldb_request_get_control(sub_req,
1323 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
1324 if (sd_propagation_control == NULL) {
1325 return ldb_module_operr(module);
1328 ret = dsdb_request_add_controls(sub_req,
1329 DSDB_FLAG_AS_SYSTEM |
1330 DSDB_SEARCH_SHOW_RECYCLED);
1331 if (ret != LDB_SUCCESS) {
1332 return ldb_module_operr(module);
1335 ret = descriptor_modify(module, sub_req);
1336 if (ret == LDB_SUCCESS) {
1337 ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL);
1339 if (ret != LDB_SUCCESS) {
1340 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1341 "descriptor_modify on %s failed: %s",
1342 ldb_dn_get_linearized(msg->dn),
1343 ldb_errstring(ldb_module_get_ctx(module)));
1344 return LDB_ERR_OPERATIONS_ERROR;
1347 if (sd_propagation_control->critical != 0) {
1348 if (c == NULL) {
1350 * If we don't have a
1351 * descriptor_changes structure
1352 * we're done.
1354 *stop = true;
1355 } else if (!c->force_children) {
1357 * If we don't need to
1358 * propagate to children,
1359 * we're done.
1361 *stop = true;
1365 if (c != NULL && !c->force_children) {
1367 * Remove the pending change,
1368 * we already done all required work,
1369 * there's no need to do it again.
1371 * Note DLIST_REMOVE() is a noop
1372 * if the element is not part of
1373 * the list.
1375 DLIST_REMOVE(t->changes.list, c);
1378 talloc_free(mod_res);
1380 return LDB_SUCCESS;
1383 static int descriptor_sd_propagation_msg_sort(struct ldb_message **m1,
1384 struct ldb_message **m2)
1386 struct ldb_dn *dn1 = (*m1)->dn;
1387 struct ldb_dn *dn2 = (*m2)->dn;
1390 * This sorts in tree order, parents first
1392 return ldb_dn_compare(dn2, dn1);
1395 static int descriptor_sd_propagation_recursive(struct ldb_module *module,
1396 struct descriptor_changes *change)
1398 struct descriptor_data *descriptor_private =
1399 talloc_get_type_abort(ldb_module_get_private(module),
1400 struct descriptor_data);
1401 struct descriptor_transaction *t = &descriptor_private->transaction;
1402 struct ldb_result *guid_res = NULL;
1403 struct ldb_result *res = NULL;
1404 unsigned int i;
1405 const char * const no_attrs[] = { "@__NONE__", NULL };
1406 struct ldb_dn *stopped_dn = NULL;
1407 struct GUID_txt_buf guid_buf;
1408 int ret;
1409 bool stop = false;
1411 t->changes.num_processed += 1;
1414 * First confirm this object has children, or exists
1415 * (depending on change->force_self)
1417 * LDB_SCOPE_SUBTREE searches are expensive.
1419 * We know this is safe against a rename race as we are in the
1420 * prepare_commit(), so must be in a transaction.
1423 /* Find the DN by GUID, as this is stable under rename */
1424 ret = dsdb_module_search(module,
1425 change,
1426 &guid_res,
1427 change->nc_root,
1428 LDB_SCOPE_SUBTREE,
1429 no_attrs,
1430 DSDB_FLAG_NEXT_MODULE |
1431 DSDB_FLAG_AS_SYSTEM |
1432 DSDB_SEARCH_SHOW_DELETED |
1433 DSDB_SEARCH_SHOW_RECYCLED |
1434 DSDB_SEARCH_SHOW_EXTENDED_DN,
1435 NULL, /* parent_req */
1436 "(objectGUID=%s)",
1437 GUID_buf_string(&change->guid,
1438 &guid_buf));
1440 if (ret != LDB_SUCCESS) {
1441 return ret;
1444 if (guid_res->count != 1) {
1446 * We were just given this GUID during the same
1447 * transaction, if it is missing this is a big
1448 * problem.
1450 * Cleanup of tombstones does not trigger this module
1451 * as it just does a delete.
1453 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1454 "failed to find GUID %s under %s "
1455 "for transaction-end SD inheritance: %d results",
1456 GUID_buf_string(&change->guid,
1457 &guid_buf),
1458 ldb_dn_get_linearized(change->nc_root),
1459 guid_res->count);
1460 return LDB_ERR_OPERATIONS_ERROR;
1464 * OK, so there was a parent, are there children? Note: that
1465 * this time we do not search for deleted/recycled objects
1467 ret = dsdb_module_search(module,
1468 change,
1469 &res,
1470 guid_res->msgs[0]->dn,
1471 LDB_SCOPE_ONELEVEL,
1472 no_attrs,
1473 DSDB_FLAG_NEXT_MODULE |
1474 DSDB_FLAG_AS_SYSTEM,
1475 NULL, /* parent_req */
1476 "(objectClass=*)");
1477 if (ret != LDB_SUCCESS) {
1479 * LDB_ERR_NO_SUCH_OBJECT, say if the DN was a deleted
1480 * object, is ignored by the caller
1482 return ret;
1485 if (res->count == 0 && !change->force_self) {
1486 /* All done, no children */
1487 TALLOC_FREE(res);
1488 return LDB_SUCCESS;
1492 * First, if we are in force_self mode (eg renamed under new
1493 * parent) then apply the SD to the top object
1495 if (change->force_self) {
1496 ret = descriptor_sd_propagation_object(module,
1497 guid_res->msgs[0],
1498 &stop);
1499 if (ret != LDB_SUCCESS) {
1500 TALLOC_FREE(guid_res);
1501 return ret;
1504 if (stop == true && !change->force_children) {
1505 /* There was no change, nothing more to do */
1506 TALLOC_FREE(guid_res);
1507 return LDB_SUCCESS;
1510 if (res->count == 0) {
1511 /* All done! */
1512 TALLOC_FREE(guid_res);
1513 return LDB_SUCCESS;
1518 * Look for children
1520 * Note: that we do not search for deleted/recycled objects
1522 ret = dsdb_module_search(module,
1523 change,
1524 &res,
1525 guid_res->msgs[0]->dn,
1526 LDB_SCOPE_SUBTREE,
1527 no_attrs,
1528 DSDB_FLAG_NEXT_MODULE |
1529 DSDB_FLAG_AS_SYSTEM |
1530 DSDB_SEARCH_SHOW_EXTENDED_DN,
1531 NULL, /* parent_req */
1532 "(objectClass=*)");
1533 if (ret != LDB_SUCCESS) {
1534 return ret;
1537 TYPESAFE_QSORT(res->msgs, res->count,
1538 descriptor_sd_propagation_msg_sort);
1540 /* We start from 1, the top object has been done */
1541 for (i = 1; i < res->count; i++) {
1543 * ldb_dn_compare_base() does not match for NULL but
1544 * this is clearer
1546 if (stopped_dn != NULL) {
1547 ret = ldb_dn_compare_base(stopped_dn,
1548 res->msgs[i]->dn);
1550 * Skip further processing of this
1551 * sub-subtree
1553 if (ret == 0) {
1554 continue;
1557 ret = descriptor_sd_propagation_object(module,
1558 res->msgs[i],
1559 &stop);
1560 if (ret != LDB_SUCCESS) {
1561 return ret;
1564 if (stop) {
1566 * If this child didn't change, then nothing
1567 * under it needs to change
1569 * res has been sorted into tree order so the
1570 * next few entries can be skipped
1572 stopped_dn = res->msgs[i]->dn;
1576 TALLOC_FREE(res);
1577 return LDB_SUCCESS;
1580 static int descriptor_start_transaction(struct ldb_module *module)
1582 struct descriptor_data *descriptor_private =
1583 talloc_get_type_abort(ldb_module_get_private(module),
1584 struct descriptor_data);
1585 struct descriptor_transaction *t = &descriptor_private->transaction;
1587 if (t->mem != NULL) {
1588 return ldb_module_operr(module);
1591 *t = (struct descriptor_transaction) { .mem = NULL, };
1592 t->mem = talloc_new(descriptor_private);
1593 if (t->mem == NULL) {
1594 return ldb_module_oom(module);
1596 t->changes.map = db_open_rbt(t->mem);
1597 if (t->changes.map == NULL) {
1598 TALLOC_FREE(t->mem);
1599 *t = (struct descriptor_transaction) { .mem = NULL, };
1600 return ldb_module_oom(module);
1603 return ldb_next_start_trans(module);
1606 static int descriptor_prepare_commit(struct ldb_module *module)
1608 struct descriptor_data *descriptor_private =
1609 talloc_get_type_abort(ldb_module_get_private(module),
1610 struct descriptor_data);
1611 struct descriptor_transaction *t = &descriptor_private->transaction;
1612 struct ldb_context *ldb = ldb_module_get_ctx(module);
1613 struct descriptor_changes *c, *n;
1614 int ret;
1616 DBG_NOTICE("changes: num_registrations=%zu\n",
1617 t->changes.num_registrations);
1618 DBG_NOTICE("changes: num_registered=%zu\n",
1619 t->changes.num_registered);
1622 * The security descriptor propagation
1623 * needs to apply the inheritance from
1624 * an object to itself and/or all it's
1625 * children.
1627 * In the initial replication during
1628 * a join, we have every object in our
1629 * list.
1631 * In order to avoid useless work it's
1632 * better to start with toplevel objects and
1633 * move down to the leaf object from there.
1635 * So if the parent_guid is also in our list,
1636 * we better move the object behind its parent.
1638 * It allows that the recursive processing of
1639 * the parent already does the work needed
1640 * for the child.
1642 * If we have a list for this directory tree:
1645 * -> B
1646 * -> C
1647 * -> D
1648 * -> E
1650 * The initial list would have the order D, E, B, A, C
1652 * By still processing from the front, we ensure that,
1653 * when D is found to be below C, that E follows because
1654 * we keep peeling items off the front for checking and
1655 * move them behind their parent.
1657 * So we would go:
1659 * E B A C D
1661 * B A C D E
1663 * A B C D E
1665 for (c = t->changes.list; c; c = n) {
1666 struct descriptor_changes *pc = NULL;
1667 n = c->next;
1669 if (c->sort_count >= t->changes.num_registered) {
1671 * This should never happen, but it's
1672 * a sanity check in order to avoid
1673 * endless loops. Just stop sorting.
1675 break;
1679 * Check if we have the parent also in the list.
1681 if (!GUID_all_zero((const void*)&c->parent_guid)) {
1682 TDB_DATA pkey;
1683 NTSTATUS status;
1685 pkey = make_tdb_data((const void*)&c->parent_guid,
1686 sizeof(c->parent_guid));
1688 status = dbwrap_parse_record(t->changes.map, pkey,
1689 descriptor_changes_parser, &pc);
1690 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1691 pc = NULL;
1692 status = NT_STATUS_OK;
1694 if (!NT_STATUS_IS_OK(status)) {
1695 ldb_debug(ldb, LDB_DEBUG_FATAL,
1696 "dbwrap_parse_record() - %s\n",
1697 nt_errstr(status));
1698 return ldb_module_operr(module);
1702 if (pc == NULL) {
1704 * There is no parent in the list
1706 t->changes.num_toplevel += 1;
1707 continue;
1711 * Move the child after the parent
1713 * Note that we do that multiple times
1714 * in case the parent already moved itself.
1716 * See the comment above the loop.
1718 DLIST_REMOVE(t->changes.list, c);
1719 DLIST_ADD_AFTER(t->changes.list, c, pc);
1722 * Remember how often we moved the object
1723 * in order to avoid endless loops.
1725 c->sort_count += 1;
1728 DBG_NOTICE("changes: num_toplevel=%zu\n", t->changes.num_toplevel);
1730 while (t->changes.list != NULL) {
1731 c = t->changes.list;
1733 DLIST_REMOVE(t->changes.list, c);
1736 * Note that descriptor_sd_propagation_recursive()
1737 * may also remove other elements of the list,
1738 * so we can't use a next pointer
1740 ret = descriptor_sd_propagation_recursive(module, c);
1741 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1742 continue;
1744 if (ret != LDB_SUCCESS) {
1745 return ret;
1749 DBG_NOTICE("changes: num_processed=%zu\n", t->changes.num_processed);
1750 DBG_NOTICE("objects: num_processed=%zu\n", t->objects.num_processed);
1752 return ldb_next_prepare_commit(module);
1755 static int descriptor_end_transaction(struct ldb_module *module)
1757 struct descriptor_data *descriptor_private =
1758 talloc_get_type_abort(ldb_module_get_private(module),
1759 struct descriptor_data);
1760 struct descriptor_transaction *t = &descriptor_private->transaction;
1762 TALLOC_FREE(t->mem);
1763 *t = (struct descriptor_transaction) { .mem = NULL, };
1765 return ldb_next_end_trans(module);
1768 static int descriptor_del_transaction(struct ldb_module *module)
1770 struct descriptor_data *descriptor_private =
1771 talloc_get_type_abort(ldb_module_get_private(module),
1772 struct descriptor_data);
1773 struct descriptor_transaction *t = &descriptor_private->transaction;
1775 TALLOC_FREE(t->mem);
1776 *t = (struct descriptor_transaction) { .mem = NULL, };
1778 return ldb_next_del_trans(module);
1781 static const struct ldb_module_ops ldb_descriptor_module_ops = {
1782 .name = "descriptor",
1783 .search = descriptor_search,
1784 .add = descriptor_add,
1785 .modify = descriptor_modify,
1786 .rename = descriptor_rename,
1787 .init_context = descriptor_init,
1788 .extended = descriptor_extended,
1789 .start_transaction = descriptor_start_transaction,
1790 .prepare_commit = descriptor_prepare_commit,
1791 .end_transaction = descriptor_end_transaction,
1792 .del_transaction = descriptor_del_transaction,
1795 int ldb_descriptor_module_init(const char *version)
1797 LDB_MODULE_CHECK_VERSION(version);
1798 return ldb_register_module(&ldb_descriptor_module_ops);