s4:dsdb/descriptor: remove some nesting from descriptor_modify
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / descriptor.c
blobb41c0aafba8c7eacf1a6ae485eedfe4ab4018f74
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;
239 struct security_descriptor *default_descriptor = NULL;
241 if (objectclass != NULL) {
242 default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
245 if (object) {
246 user_descriptor = talloc(mem_ctx, struct security_descriptor);
247 if (!user_descriptor) {
248 return NULL;
250 ndr_err = ndr_pull_struct_blob(object, user_descriptor,
251 user_descriptor,
252 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
254 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
255 talloc_free(user_descriptor);
256 return NULL;
258 } else {
259 user_descriptor = default_descriptor;
262 if (old_sd) {
263 old_descriptor = talloc(mem_ctx, struct security_descriptor);
264 if (!old_descriptor) {
265 return NULL;
267 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor,
268 old_descriptor,
269 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
271 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
272 talloc_free(old_descriptor);
273 return NULL;
277 if (parent) {
278 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
279 if (!parent_descriptor) {
280 return NULL;
282 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor,
283 parent_descriptor,
284 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
286 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
287 talloc_free(parent_descriptor);
288 return NULL;
292 if (user_descriptor && default_descriptor &&
293 (user_descriptor->dacl == NULL))
295 user_descriptor->dacl = default_descriptor->dacl;
296 user_descriptor->type |= default_descriptor->type & (
297 SEC_DESC_DACL_PRESENT |
298 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
299 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
300 SEC_DESC_DACL_TRUSTED);
303 if (user_descriptor && default_descriptor &&
304 (user_descriptor->sacl == NULL))
306 user_descriptor->sacl = default_descriptor->sacl;
307 user_descriptor->type |= default_descriptor->type & (
308 SEC_DESC_SACL_PRESENT |
309 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
310 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
311 SEC_DESC_SERVER_SECURITY);
314 default_owner = get_default_ag(mem_ctx, dn,
315 session_info->security_token, ldb);
316 default_group = get_default_group(mem_ctx, ldb, default_owner);
317 new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true,
318 NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT,
319 session_info->security_token,
320 default_owner, default_group,
321 map_generic_rights_ds);
322 if (!new_sd) {
323 return NULL;
325 final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
327 if (!final_sd) {
328 return NULL;
331 if (final_sd->dacl) {
332 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
334 if (final_sd->sacl) {
335 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
338 sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
339 DEBUG(10, ("Object %s created with desriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
341 linear_sd = talloc(mem_ctx, DATA_BLOB);
342 if (!linear_sd) {
343 return NULL;
346 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
347 final_sd,
348 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
349 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
350 return NULL;
353 return linear_sd;
356 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
357 TALLOC_CTX *mem_ctx,
358 struct ldb_val *sd,
359 uint32_t sd_flags)
361 struct security_descriptor *old_sd, *final_sd;
362 DATA_BLOB *linear_sd;
363 enum ndr_err_code ndr_err;
365 old_sd = talloc(mem_ctx, struct security_descriptor);
366 if (!old_sd) {
367 return NULL;
369 ndr_err = ndr_pull_struct_blob(sd, old_sd,
370 old_sd,
371 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
373 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
374 talloc_free(old_sd);
375 return NULL;
378 final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
380 if (!final_sd) {
381 return NULL;
384 linear_sd = talloc(mem_ctx, DATA_BLOB);
385 if (!linear_sd) {
386 return NULL;
389 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
390 final_sd,
391 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
392 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
393 return NULL;
396 return linear_sd;
399 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
400 struct ldb_request *req)
402 struct ldb_context *ldb;
403 struct descriptor_context *ac;
405 ldb = ldb_module_get_ctx(module);
407 ac = talloc_zero(req, struct descriptor_context);
408 if (ac == NULL) {
409 ldb_set_errstring(ldb, "Out of Memory");
410 return NULL;
413 ac->module = module;
414 ac->req = req;
415 return ac;
418 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
420 struct descriptor_context *ac;
421 struct ldb_val *sd_val = NULL;
422 struct ldb_message_element *sd_el;
423 DATA_BLOB *show_sd;
424 int ret;
426 ac = talloc_get_type(req->context, struct descriptor_context);
428 if (!ares) {
429 ret = LDB_ERR_OPERATIONS_ERROR;
430 goto fail;
432 if (ares->error != LDB_SUCCESS) {
433 return ldb_module_done(ac->req, ares->controls,
434 ares->response, ares->error);
437 switch (ares->type) {
438 case LDB_REPLY_ENTRY:
439 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
440 if (sd_el) {
441 sd_val = sd_el->values;
444 if (sd_val) {
445 show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
446 sd_val, ac->sd_flags);
447 if (!show_sd) {
448 ret = LDB_ERR_OPERATIONS_ERROR;
449 goto fail;
451 ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
452 ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
453 if (ret != LDB_SUCCESS) {
454 goto fail;
457 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
459 case LDB_REPLY_REFERRAL:
460 return ldb_module_send_referral(ac->req, ares->referral);
462 case LDB_REPLY_DONE:
463 return ldb_module_done(ac->req, ares->controls,
464 ares->response, ares->error);
467 fail:
468 talloc_free(ares);
469 return ldb_module_done(ac->req, NULL, NULL, ret);
472 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
474 struct ldb_context *ldb = ldb_module_get_ctx(module);
475 struct ldb_request *add_req;
476 struct ldb_message *msg;
477 struct ldb_result *parent_res;
478 const struct ldb_val *parent_sd = NULL;
479 const struct ldb_val *user_sd;
480 struct ldb_dn *dn = req->op.add.message->dn;
481 struct ldb_dn *parent_dn, *nc_root;
482 struct ldb_message_element *objectclass_element, *sd_element;
483 int ret;
484 const struct dsdb_schema *schema;
485 DATA_BLOB *sd;
486 const struct dsdb_class *objectclass;
487 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
488 uint32_t instanceType;
489 bool isNC = false;
490 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
492 /* do not manipulate our control entries */
493 if (ldb_dn_is_special(dn)) {
494 return ldb_next_request(module, req);
497 user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
498 sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
499 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
500 if (user_sd == NULL && sd_element) {
501 return ldb_next_request(module, req);
504 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
506 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
508 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
509 isNC = true;
512 if (!isNC) {
513 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
514 if (ret != LDB_SUCCESS) {
515 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
516 ldb_dn_get_linearized(dn));
517 return ret;
520 if (ldb_dn_compare(dn, nc_root) == 0) {
521 DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
522 isNC = true;
526 if (isNC) {
527 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
529 if (!isNC) {
530 /* if the object has a parent, retrieve its SD to
531 * use for calculation. Unfortunately we do not yet have
532 * instanceType, so we use dsdb_find_nc_root. */
534 parent_dn = ldb_dn_get_parent(req, dn);
535 if (parent_dn == NULL) {
536 return ldb_oom(ldb);
539 /* we aren't any NC */
540 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
541 parent_attrs,
542 DSDB_FLAG_NEXT_MODULE |
543 DSDB_FLAG_AS_SYSTEM |
544 DSDB_SEARCH_SHOW_RECYCLED,
545 req);
546 if (ret != LDB_SUCCESS) {
547 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
548 ldb_dn_get_linearized(parent_dn));
549 return ret;
551 if (parent_res->count != 1) {
552 return ldb_operr(ldb);
554 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
557 schema = dsdb_get_schema(ldb, req);
559 objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
560 if (objectclass_element == NULL) {
561 return ldb_operr(ldb);
564 objectclass = dsdb_get_last_structural_class(schema,
565 objectclass_element);
566 if (objectclass == NULL) {
567 return ldb_operr(ldb);
571 * The SD_FLAG control is ignored on add
572 * and we default to all bits set.
574 sd_flags = 0xF;
576 sd = get_new_descriptor(module, dn, req,
577 objectclass, parent_sd,
578 user_sd, NULL, sd_flags);
579 if (sd == NULL) {
580 return ldb_operr(ldb);
582 msg = ldb_msg_copy_shallow(req, req->op.add.message);
583 if (msg == NULL) {
584 return ldb_oom(ldb);
586 if (sd_element != NULL) {
587 sd_element->values[0] = *sd;
588 } else {
589 ret = ldb_msg_add_steal_value(msg,
590 "nTSecurityDescriptor",
591 sd);
592 if (ret != LDB_SUCCESS) {
593 return ret;
597 ret = ldb_build_add_req(&add_req, ldb, req,
598 msg,
599 req->controls,
600 req, dsdb_next_callback,
601 req);
602 LDB_REQ_SET_LOCATION(add_req);
603 if (ret != LDB_SUCCESS) {
604 return ldb_error(ldb, ret,
605 "descriptor_add: Error creating new add request.");
608 return ldb_next_request(module, add_req);
611 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
613 struct ldb_context *ldb = ldb_module_get_ctx(module);
614 struct ldb_request *mod_req;
615 struct ldb_message *msg;
616 struct ldb_result *current_res, *parent_res;
617 const struct ldb_val *old_sd = NULL;
618 const struct ldb_val *parent_sd = NULL;
619 const struct ldb_val *user_sd;
620 struct ldb_dn *dn = req->op.mod.message->dn;
621 struct ldb_dn *parent_dn;
622 struct ldb_message_element *objectclass_element, *sd_element;
623 int ret;
624 uint32_t instanceType;
625 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
626 const struct dsdb_schema *schema;
627 DATA_BLOB *sd;
628 const struct dsdb_class *objectclass;
629 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
630 static const char * const current_attrs[] = { "nTSecurityDescriptor",
631 "instanceType",
632 "objectClass", NULL };
634 /* do not manipulate our control entries */
635 if (ldb_dn_is_special(dn)) {
636 return ldb_next_request(module, req);
640 sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor");
641 if (sd_element == NULL) {
642 return ldb_next_request(module, req);
645 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
646 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
647 if (user_sd == NULL) {
648 return ldb_next_request(module, req);
651 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
653 ret = dsdb_module_search_dn(module, req, &current_res, dn,
654 current_attrs,
655 DSDB_FLAG_NEXT_MODULE |
656 DSDB_FLAG_AS_SYSTEM |
657 DSDB_SEARCH_SHOW_RECYCLED,
658 req);
659 if (ret != LDB_SUCCESS) {
660 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
661 ldb_dn_get_linearized(dn));
662 return ret;
665 instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
666 "instanceType", 0);
667 /* if the object has a parent, retrieve its SD to
668 * use for calculation */
669 if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
670 !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
671 parent_dn = ldb_dn_get_parent(req, dn);
672 if (parent_dn == NULL) {
673 return ldb_oom(ldb);
675 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
676 parent_attrs,
677 DSDB_FLAG_NEXT_MODULE |
678 DSDB_FLAG_AS_SYSTEM |
679 DSDB_SEARCH_SHOW_RECYCLED,
680 req);
681 if (ret != LDB_SUCCESS) {
682 ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
683 ldb_dn_get_linearized(parent_dn));
684 return ret;
686 if (parent_res->count != 1) {
687 return ldb_operr(ldb);
689 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
692 schema = dsdb_get_schema(ldb, req);
694 objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
695 if (objectclass_element == NULL) {
696 return ldb_operr(ldb);
699 objectclass = dsdb_get_last_structural_class(schema,
700 objectclass_element);
701 if (objectclass == NULL) {
702 return ldb_operr(ldb);
705 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
707 sd = get_new_descriptor(module, dn, req,
708 objectclass, parent_sd,
709 user_sd, old_sd, sd_flags);
710 if (sd == NULL) {
711 return ldb_operr(ldb);
713 msg = ldb_msg_copy_shallow(req, req->op.mod.message);
714 if (msg == NULL) {
715 return ldb_oom(ldb);
717 sd_element->values[0] = *sd;
719 ret = ldb_build_mod_req(&mod_req, ldb, req,
720 msg,
721 req->controls,
722 req,
723 dsdb_next_callback,
724 req);
725 LDB_REQ_SET_LOCATION(mod_req);
726 if (ret != LDB_SUCCESS) {
727 return ret;
730 return ldb_next_request(module, mod_req);
733 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
735 int ret;
736 struct ldb_context *ldb;
737 struct ldb_request *down_req;
738 struct descriptor_context *ac;
739 bool explicit_sd_flags = false;
740 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
741 bool show_sd = explicit_sd_flags;
743 if (!show_sd &&
744 ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor"))
746 show_sd = true;
749 if (!show_sd) {
750 return ldb_next_request(module, req);
753 ldb = ldb_module_get_ctx(module);
754 ac = descriptor_init_context(module, req);
755 if (ac == NULL) {
756 return ldb_operr(ldb);
758 ac->sd_flags = sd_flags;
760 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
761 req->op.search.base,
762 req->op.search.scope,
763 req->op.search.tree,
764 req->op.search.attrs,
765 req->controls,
766 ac, descriptor_search_callback,
767 ac->req);
768 LDB_REQ_SET_LOCATION(down_req);
769 if (ret != LDB_SUCCESS) {
770 return ret;
773 return ldb_next_request(ac->module, down_req);
775 /* TODO */
776 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
778 struct ldb_context *ldb = ldb_module_get_ctx(module);
779 struct ldb_dn *olddn = req->op.rename.olddn;
781 /* do not manipulate our control entries */
782 if (ldb_dn_is_special(req->op.rename.olddn)) {
783 return ldb_next_request(module, req);
786 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n",
787 ldb_dn_get_linearized(olddn));
789 return ldb_next_request(module, req);
792 static int descriptor_init(struct ldb_module *module)
794 int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
795 struct ldb_context *ldb = ldb_module_get_ctx(module);
796 if (ret != LDB_SUCCESS) {
797 ldb_debug(ldb, LDB_DEBUG_ERROR,
798 "descriptor: Unable to register control with rootdse!\n");
799 return ldb_operr(ldb);
801 return ldb_next_init(module);
805 static const struct ldb_module_ops ldb_descriptor_module_ops = {
806 .name = "descriptor",
807 .search = descriptor_search,
808 .add = descriptor_add,
809 .modify = descriptor_modify,
810 .rename = descriptor_rename,
811 .init_context = descriptor_init
814 int ldb_descriptor_module_init(const char *version)
816 LDB_MODULE_CHECK_VERSION(version);
817 return ldb_register_module(&ldb_descriptor_module_ops);