s4:dsdb/descriptor: give SYSTEM the correct default owner (group) sid
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / descriptor.c
blobfd08d49cdf31c47a9d8958a2fc584f993d62ce38
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"
46 struct descriptor_data {
47 int _dummy;
50 struct descriptor_context {
51 struct ldb_module *module;
52 struct ldb_request *req;
53 struct ldb_message *msg;
54 struct ldb_reply *search_res;
55 struct ldb_reply *search_oc_res;
56 struct ldb_val *parentsd_val;
57 struct ldb_message_element *sd_element;
58 struct ldb_val *sd_val;
59 uint32_t sd_flags;
60 int (*step_fn)(struct descriptor_context *);
63 static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
64 struct ldb_dn *dn,
65 struct security_token *token,
66 struct ldb_context *ldb)
68 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
69 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
70 struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
71 struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS);
72 struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS);
73 struct dom_sid *dag_sid;
74 struct ldb_dn *nc_root;
75 int ret;
77 ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root);
78 if (ret != LDB_SUCCESS) {
79 talloc_free(tmp_ctx);
80 return NULL;
83 if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
84 if (security_token_has_sid(token, sa_sid)) {
85 dag_sid = dom_sid_dup(mem_ctx, sa_sid);
86 } else if (security_token_has_sid(token, ea_sid)) {
87 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
88 } else if (security_token_has_sid(token, da_sid)) {
89 dag_sid = dom_sid_dup(mem_ctx, da_sid);
90 } else if (security_token_is_system(token)) {
91 dag_sid = dom_sid_dup(mem_ctx, sa_sid);
92 } else {
93 dag_sid = NULL;
95 } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
96 if (security_token_has_sid(token, ea_sid)) {
97 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
98 } else if (security_token_has_sid(token, da_sid)) {
99 dag_sid = dom_sid_dup(mem_ctx, da_sid);
100 } else if (security_token_is_system(token)) {
101 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
102 } else {
103 dag_sid = NULL;
105 } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
106 if (security_token_has_sid(token, da_sid)) {
107 dag_sid = dom_sid_dup(mem_ctx, da_sid);
108 } else if (security_token_has_sid(token, ea_sid)) {
109 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
110 } else if (security_token_is_system(token)) {
111 dag_sid = dom_sid_dup(mem_ctx, da_sid);
112 } else {
113 dag_sid = NULL;
115 } else {
116 dag_sid = NULL;
119 talloc_free(tmp_ctx);
120 return dag_sid;
123 static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx,
124 const struct dsdb_class *objectclass)
126 struct ldb_context *ldb = ldb_module_get_ctx(module);
127 struct security_descriptor *sd;
128 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
130 if (!objectclass->defaultSecurityDescriptor || !domain_sid) {
131 return NULL;
134 sd = sddl_decode(mem_ctx,
135 objectclass->defaultSecurityDescriptor,
136 domain_sid);
137 return sd;
140 static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
141 struct ldb_context *ldb,
142 struct dom_sid *dag)
144 if (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008) {
145 return dag;
148 return NULL;
151 static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
152 struct security_descriptor *new_sd,
153 struct security_descriptor *old_sd,
154 uint32_t sd_flags)
156 struct security_descriptor *final_sd;
157 /* if there is no control or control == 0 modify everything */
158 if (!sd_flags) {
159 return new_sd;
162 final_sd = talloc_zero(mem_ctx, struct security_descriptor);
163 final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
164 final_sd->type = SEC_DESC_SELF_RELATIVE;
166 if (sd_flags & (SECINFO_OWNER)) {
167 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
168 final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
170 else if (old_sd) {
171 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
172 final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
175 if (sd_flags & (SECINFO_GROUP)) {
176 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
177 final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
179 else if (old_sd) {
180 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
181 final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
184 if (sd_flags & (SECINFO_SACL)) {
185 final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
186 final_sd->type |= new_sd->type & (SEC_DESC_SACL_PRESENT |
187 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
188 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
189 SEC_DESC_SERVER_SECURITY);
191 else if (old_sd && old_sd->sacl) {
192 final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
193 final_sd->type |= old_sd->type & (SEC_DESC_SACL_PRESENT |
194 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
195 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
196 SEC_DESC_SERVER_SECURITY);
199 if (sd_flags & (SECINFO_DACL)) {
200 final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
201 final_sd->type |= new_sd->type & (SEC_DESC_DACL_PRESENT |
202 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
203 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
204 SEC_DESC_DACL_TRUSTED);
206 else if (old_sd && old_sd->dacl) {
207 final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
208 final_sd->type |= old_sd->type & (SEC_DESC_DACL_PRESENT |
209 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
210 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
211 SEC_DESC_DACL_TRUSTED);
213 /* not so sure about this */
214 final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
215 return final_sd;
218 static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
219 struct ldb_dn *dn,
220 TALLOC_CTX *mem_ctx,
221 const struct dsdb_class *objectclass,
222 const struct ldb_val *parent,
223 const struct ldb_val *object,
224 const struct ldb_val *old_sd,
225 uint32_t sd_flags)
227 struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
228 struct security_descriptor *old_descriptor = NULL;
229 struct security_descriptor *new_sd, *final_sd;
230 DATA_BLOB *linear_sd;
231 enum ndr_err_code ndr_err;
232 struct ldb_context *ldb = ldb_module_get_ctx(module);
233 struct auth_session_info *session_info
234 = ldb_get_opaque(ldb, "sessionInfo");
235 const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
236 char *sddl_sd;
237 struct dom_sid *default_owner;
238 struct dom_sid *default_group;
240 if (object) {
241 user_descriptor = talloc(mem_ctx, struct security_descriptor);
242 if (!user_descriptor) {
243 return NULL;
245 ndr_err = ndr_pull_struct_blob(object, user_descriptor,
246 user_descriptor,
247 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
249 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
250 talloc_free(user_descriptor);
251 return NULL;
253 } else {
254 user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
257 if (old_sd) {
258 old_descriptor = talloc(mem_ctx, struct security_descriptor);
259 if (!old_descriptor) {
260 return NULL;
262 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor,
263 old_descriptor,
264 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
266 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
267 talloc_free(old_descriptor);
268 return NULL;
272 if (parent) {
273 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
274 if (!parent_descriptor) {
275 return NULL;
277 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor,
278 parent_descriptor,
279 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
281 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
282 talloc_free(parent_descriptor);
283 return NULL;
287 default_owner = get_default_ag(mem_ctx, dn,
288 session_info->security_token, ldb);
289 default_group = get_default_group(mem_ctx, ldb, default_owner);
290 new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true,
291 NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT,
292 session_info->security_token,
293 default_owner, default_group,
294 map_generic_rights_ds);
295 if (!new_sd) {
296 return NULL;
298 final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
300 if (!final_sd) {
301 return NULL;
304 if (final_sd->dacl) {
305 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
307 if (final_sd->sacl) {
308 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
311 sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
312 DEBUG(10, ("Object %s created with desriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
314 linear_sd = talloc(mem_ctx, DATA_BLOB);
315 if (!linear_sd) {
316 return NULL;
319 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
320 final_sd,
321 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
322 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
323 return NULL;
326 return linear_sd;
329 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
330 TALLOC_CTX *mem_ctx,
331 struct ldb_val *sd,
332 uint32_t sd_flags)
334 struct security_descriptor *old_sd, *final_sd;
335 DATA_BLOB *linear_sd;
336 enum ndr_err_code ndr_err;
338 old_sd = talloc(mem_ctx, struct security_descriptor);
339 if (!old_sd) {
340 return NULL;
342 ndr_err = ndr_pull_struct_blob(sd, old_sd,
343 old_sd,
344 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
346 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
347 talloc_free(old_sd);
348 return NULL;
351 final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
353 if (!final_sd) {
354 return NULL;
357 linear_sd = talloc(mem_ctx, DATA_BLOB);
358 if (!linear_sd) {
359 return NULL;
362 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
363 final_sd,
364 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
365 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
366 return NULL;
369 return linear_sd;
372 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
373 struct ldb_request *req)
375 struct ldb_context *ldb;
376 struct descriptor_context *ac;
378 ldb = ldb_module_get_ctx(module);
380 ac = talloc_zero(req, struct descriptor_context);
381 if (ac == NULL) {
382 ldb_set_errstring(ldb, "Out of Memory");
383 return NULL;
386 ac->module = module;
387 ac->req = req;
388 return ac;
391 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
393 struct descriptor_context *ac;
394 struct ldb_val *sd_val = NULL;
395 struct ldb_message_element *sd_el;
396 DATA_BLOB *show_sd;
397 int ret;
399 ac = talloc_get_type(req->context, struct descriptor_context);
401 if (!ares) {
402 ret = LDB_ERR_OPERATIONS_ERROR;
403 goto fail;
405 if (ares->error != LDB_SUCCESS) {
406 return ldb_module_done(ac->req, ares->controls,
407 ares->response, ares->error);
410 switch (ares->type) {
411 case LDB_REPLY_ENTRY:
412 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
413 if (sd_el) {
414 sd_val = sd_el->values;
417 if (sd_val) {
418 show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
419 sd_val, ac->sd_flags);
420 if (!show_sd) {
421 ret = LDB_ERR_OPERATIONS_ERROR;
422 goto fail;
424 ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
425 ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
426 if (ret != LDB_SUCCESS) {
427 goto fail;
430 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
432 case LDB_REPLY_REFERRAL:
433 return ldb_module_send_referral(ac->req, ares->referral);
435 case LDB_REPLY_DONE:
436 return ldb_module_done(ac->req, ares->controls,
437 ares->response, ares->error);
440 fail:
441 talloc_free(ares);
442 return ldb_module_done(ac->req, NULL, NULL, ret);
445 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
447 struct ldb_context *ldb;
448 struct ldb_request *add_req;
449 struct ldb_message *msg;
450 struct ldb_result *parent_res;
451 const struct ldb_val *parent_sd = NULL;
452 const struct ldb_val *user_sd;
453 struct ldb_dn *parent_dn, *dn, *nc_root;
454 struct ldb_message_element *objectclass_element, *sd_element;
455 int ret;
456 const struct dsdb_schema *schema;
457 DATA_BLOB *sd;
458 const struct dsdb_class *objectclass;
459 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
460 uint32_t instanceType;
461 bool isNC = false;
462 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
464 ldb = ldb_module_get_ctx(module);
465 dn = req->op.add.message->dn;
466 user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
467 sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
468 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
469 if (user_sd == NULL && sd_element) {
470 return ldb_next_request(module, req);
473 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
475 /* do not manipulate our control entries */
476 if (ldb_dn_is_special(dn)) {
477 return ldb_next_request(module, req);
480 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
482 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
483 isNC = true;
486 if (!isNC) {
487 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
488 if (ret != LDB_SUCCESS) {
489 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
490 ldb_dn_get_linearized(dn));
491 return ret;
494 if (ldb_dn_compare(dn, nc_root) == 0) {
495 DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
496 isNC = true;
500 if (isNC) {
501 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
503 if (!isNC) {
504 /* if the object has a parent, retrieve its SD to
505 * use for calculation. Unfortunately we do not yet have
506 * instanceType, so we use dsdb_find_nc_root. */
508 parent_dn = ldb_dn_get_parent(req, dn);
509 if (parent_dn == NULL) {
510 return ldb_oom(ldb);
513 /* we aren't any NC */
514 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
515 parent_attrs,
516 DSDB_FLAG_NEXT_MODULE |
517 DSDB_FLAG_AS_SYSTEM |
518 DSDB_SEARCH_SHOW_RECYCLED,
519 req);
520 if (ret != LDB_SUCCESS) {
521 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
522 ldb_dn_get_linearized(parent_dn));
523 return ret;
525 if (parent_res->count != 1) {
526 return ldb_operr(ldb);
528 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
531 schema = dsdb_get_schema(ldb, req);
533 objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
534 if (objectclass_element == NULL) {
535 return ldb_operr(ldb);
538 objectclass = dsdb_get_last_structural_class(schema,
539 objectclass_element);
540 if (objectclass == NULL) {
541 return ldb_operr(ldb);
545 * The SD_FLAG control is ignored on add
546 * and we default to all bits set.
548 sd_flags = 0xF;
550 sd = get_new_descriptor(module, dn, req,
551 objectclass, parent_sd,
552 user_sd, NULL, sd_flags);
553 msg = ldb_msg_copy_shallow(req, req->op.add.message);
554 if (sd != NULL) {
555 if (sd_element != NULL) {
556 sd_element->values[0] = *sd;
557 } else {
558 ret = ldb_msg_add_steal_value(msg,
559 "nTSecurityDescriptor",
560 sd);
561 if (ret != LDB_SUCCESS) {
562 return ret;
567 ret = ldb_build_add_req(&add_req, ldb, req,
568 msg,
569 req->controls,
570 req, dsdb_next_callback,
571 req);
572 LDB_REQ_SET_LOCATION(add_req);
573 if (ret != LDB_SUCCESS) {
574 return ldb_error(ldb, ret,
575 "descriptor_add: Error creating new add request.");
578 return ldb_next_request(module, add_req);
581 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
583 struct ldb_context *ldb;
584 struct ldb_control *sd_recalculate_control;
585 struct ldb_request *mod_req;
586 struct ldb_message *msg;
587 struct ldb_result *current_res, *parent_res;
588 const struct ldb_val *old_sd = NULL;
589 const struct ldb_val *parent_sd = NULL;
590 const struct ldb_val *user_sd;
591 struct ldb_dn *parent_dn, *dn;
592 struct ldb_message_element *objectclass_element;
593 int ret;
594 uint32_t instanceType;
595 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
596 const struct dsdb_schema *schema;
597 DATA_BLOB *sd;
598 const struct dsdb_class *objectclass;
599 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
600 static const char * const current_attrs[] = { "nTSecurityDescriptor",
601 "instanceType",
602 "objectClass", NULL };
603 ldb = ldb_module_get_ctx(module);
604 dn = req->op.mod.message->dn;
605 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
606 /* This control forces the recalculation of the SD also when
607 * no modification is performed. */
608 sd_recalculate_control = ldb_request_get_control(req,
609 LDB_CONTROL_RECALCULATE_SD_OID);
610 if (!user_sd && !sd_recalculate_control) {
611 return ldb_next_request(module, req);
614 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
616 /* do not manipulate our control entries */
617 if (ldb_dn_is_special(dn)) {
618 return ldb_next_request(module, req);
621 ret = dsdb_module_search_dn(module, req, &current_res, dn,
622 current_attrs,
623 DSDB_FLAG_NEXT_MODULE |
624 DSDB_FLAG_AS_SYSTEM |
625 DSDB_SEARCH_SHOW_RECYCLED,
626 req);
627 if (ret != LDB_SUCCESS) {
628 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
629 ldb_dn_get_linearized(dn));
630 return ret;
633 instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
634 "instanceType", 0);
635 /* if the object has a parent, retrieve its SD to
636 * use for calculation */
637 if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
638 !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
639 parent_dn = ldb_dn_get_parent(req, dn);
640 if (parent_dn == NULL) {
641 return ldb_oom(ldb);
643 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
644 parent_attrs,
645 DSDB_FLAG_NEXT_MODULE |
646 DSDB_FLAG_AS_SYSTEM |
647 DSDB_SEARCH_SHOW_RECYCLED,
648 req);
649 if (ret != LDB_SUCCESS) {
650 ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
651 ldb_dn_get_linearized(parent_dn));
652 return ret;
654 if (parent_res->count != 1) {
655 return ldb_operr(ldb);
657 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
660 schema = dsdb_get_schema(ldb, req);
662 objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
663 if (objectclass_element == NULL) {
664 return ldb_operr(ldb);
667 objectclass = dsdb_get_last_structural_class(schema,
668 objectclass_element);
669 if (objectclass == NULL) {
670 return ldb_operr(ldb);
673 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
675 sd = get_new_descriptor(module, dn, req,
676 objectclass, parent_sd,
677 user_sd, old_sd, sd_flags);
678 msg = ldb_msg_copy_shallow(req, req->op.mod.message);
679 if (sd != NULL) {
680 struct ldb_message_element *sd_element;
681 if (user_sd != NULL) {
682 sd_element = ldb_msg_find_element(msg,
683 "nTSecurityDescriptor");
684 sd_element->values[0] = *sd;
685 } else if (sd_recalculate_control != NULL) {
686 /* In this branch we really do force the recalculation
687 * of the SD */
688 ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
690 ret = ldb_msg_add_steal_value(msg,
691 "nTSecurityDescriptor",
692 sd);
693 if (ret != LDB_SUCCESS) {
694 return ldb_error(ldb, ret,
695 "descriptor_modify: Could not replace SD value in message.");
697 sd_element = ldb_msg_find_element(msg,
698 "nTSecurityDescriptor");
699 sd_element->flags = LDB_FLAG_MOD_REPLACE;
703 /* mark the controls as non-critical since we've handled them */
704 if (sd_recalculate_control != NULL) {
705 sd_recalculate_control->critical = 0;
708 ret = ldb_build_mod_req(&mod_req, ldb, req,
709 msg,
710 req->controls,
711 req,
712 dsdb_next_callback,
713 req);
714 LDB_REQ_SET_LOCATION(mod_req);
715 if (ret != LDB_SUCCESS) {
716 return ret;
719 return ldb_next_request(module, mod_req);
722 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
724 int ret;
725 struct ldb_context *ldb;
726 struct ldb_request *down_req;
727 struct descriptor_context *ac;
728 bool explicit_sd_flags = false;
729 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
730 bool show_sd = explicit_sd_flags;
732 if (!show_sd &&
733 ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor"))
735 show_sd = true;
738 if (!show_sd) {
739 return ldb_next_request(module, req);
742 ldb = ldb_module_get_ctx(module);
743 ac = descriptor_init_context(module, req);
744 if (ac == NULL) {
745 return ldb_operr(ldb);
747 ac->sd_flags = sd_flags;
749 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
750 req->op.search.base,
751 req->op.search.scope,
752 req->op.search.tree,
753 req->op.search.attrs,
754 req->controls,
755 ac, descriptor_search_callback,
756 ac->req);
757 LDB_REQ_SET_LOCATION(down_req);
758 if (ret != LDB_SUCCESS) {
759 return ret;
762 return ldb_next_request(ac->module, down_req);
764 /* TODO */
765 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
767 struct ldb_context *ldb = ldb_module_get_ctx(module);
768 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn));
770 /* do not manipulate our control entries */
771 if (ldb_dn_is_special(req->op.rename.olddn)) {
772 return ldb_next_request(module, req);
775 return ldb_next_request(module, req);
778 static int descriptor_init(struct ldb_module *module)
780 int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
781 struct ldb_context *ldb = ldb_module_get_ctx(module);
782 if (ret != LDB_SUCCESS) {
783 ldb_debug(ldb, LDB_DEBUG_ERROR,
784 "descriptor: Unable to register control with rootdse!\n");
785 return ldb_operr(ldb);
787 return ldb_next_init(module);
791 static const struct ldb_module_ops ldb_descriptor_module_ops = {
792 .name = "descriptor",
793 .search = descriptor_search,
794 .add = descriptor_add,
795 .modify = descriptor_modify,
796 .rename = descriptor_rename,
797 .init_context = descriptor_init
800 int ldb_descriptor_module_init(const char *version)
802 LDB_MODULE_CHECK_VERSION(version);
803 return ldb_register_module(&ldb_descriptor_module_ops);