build: avoid util.h as a public header name due to conflict with MacOS
[ira/wip.git] / source4 / dsdb / samdb / ldb_modules / descriptor.c
1 /*
2    ldb database library
3
4    Copyright (C) Simo Sorce  2006-2008
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
6    Copyright (C) Nadezhda Ivanova  2009
7
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.
12
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.
17
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/>.
20 */
21
22 /*
23  *  Name: ldb
24  *
25  *  Component: DS Security descriptor module
26  *
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
31  *
32  *  Author: Nadezhda Ivanova
33  */
34
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 "dsdb/samdb/ldb_modules/schema.h"
43 #include "auth/auth.h"
44 #include "param/param.h"
45 #include "dsdb/samdb/ldb_modules/util.h"
46
47 struct descriptor_data {
48         int _dummy;
49 };
50
51 struct descriptor_context {
52         struct ldb_module *module;
53         struct ldb_request *req;
54         struct ldb_message *msg;
55         struct ldb_reply *search_res;
56         struct ldb_reply *search_oc_res;
57         struct ldb_val *parentsd_val;
58         struct ldb_message_element *sd_element;
59         struct ldb_val *sd_val;
60         int (*step_fn)(struct descriptor_context *);
61 };
62
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)
67 {
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;
76
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;
81         }
82
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 {
91                         dag_sid = NULL;
92                 }
93         } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
94                 if (security_token_has_sid(token, ea_sid)) {
95                         dag_sid = dom_sid_dup(mem_ctx, ea_sid);
96                 } else if (security_token_has_sid(token, da_sid)) {
97                         dag_sid = dom_sid_dup(mem_ctx, da_sid);
98                 } else {
99                         dag_sid = NULL;
100                 }
101         } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
102                 if (security_token_has_sid(token, da_sid)) {
103                         dag_sid = dom_sid_dup(mem_ctx, da_sid);
104                 } else if (security_token_has_sid(token, ea_sid)) {
105                                 dag_sid = dom_sid_dup(mem_ctx, ea_sid);
106                 } else {
107                         dag_sid = NULL;
108                 }
109         } else {
110                 dag_sid = NULL;
111         }
112
113         talloc_free(tmp_ctx);
114         return dag_sid;
115 }
116
117 static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx,
118                                             const struct dsdb_class *objectclass)
119 {
120         struct ldb_context *ldb = ldb_module_get_ctx(module);
121         struct security_descriptor *sd;
122         const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
123
124         if (!objectclass->defaultSecurityDescriptor || !domain_sid) {
125                 return NULL;
126         }
127
128         sd = sddl_decode(mem_ctx,
129                          objectclass->defaultSecurityDescriptor,
130                          domain_sid);
131         return sd;
132 }
133
134 static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
135                                          struct ldb_context *ldb,
136                                          struct dom_sid *dag)
137 {
138         if (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008) {
139                 return dag;
140         }
141
142         return NULL;
143 }
144
145 static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
146                                                          struct security_descriptor *new_sd,
147                                                          struct security_descriptor *old_sd,
148                                                          uint32_t sd_flags)
149 {
150         struct security_descriptor *final_sd; 
151         /* if there is no control or control == 0 modify everything */
152         if (!sd_flags) {
153                 return new_sd;
154         }
155
156         final_sd = talloc_zero(mem_ctx, struct security_descriptor);
157         final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
158         final_sd->type = SEC_DESC_SELF_RELATIVE;
159
160         if (sd_flags & (SECINFO_OWNER)) {
161                 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
162                 final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
163         }
164         else if (old_sd) {
165                 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
166                 final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
167         }
168
169         if (sd_flags & (SECINFO_GROUP)) {
170                 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
171                 final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
172         } 
173         else if (old_sd) {
174                 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
175                 final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
176         }
177
178         if (sd_flags & (SECINFO_SACL)) {
179                 final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
180                 final_sd->type |= new_sd->type & (SEC_DESC_SACL_PRESENT |
181                         SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
182                         SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
183                         SEC_DESC_SERVER_SECURITY);
184         } 
185         else if (old_sd && old_sd->sacl) {
186                 final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
187                 final_sd->type |= old_sd->type & (SEC_DESC_SACL_PRESENT |
188                         SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
189                         SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
190                         SEC_DESC_SERVER_SECURITY);
191         }
192
193         if (sd_flags & (SECINFO_DACL)) {
194                 final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
195                 final_sd->type |= new_sd->type & (SEC_DESC_DACL_PRESENT |
196                         SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
197                         SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
198                         SEC_DESC_DACL_TRUSTED);
199         } 
200         else if (old_sd && old_sd->dacl) {
201                 final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
202                 final_sd->type |= old_sd->type & (SEC_DESC_DACL_PRESENT |
203                         SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
204                         SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
205                         SEC_DESC_DACL_TRUSTED);
206         }
207         /* not so sure about this */
208         final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
209         return final_sd;
210 }
211
212 static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
213                                      struct ldb_dn *dn,
214                                      TALLOC_CTX *mem_ctx,
215                                      const struct dsdb_class *objectclass,
216                                      const struct ldb_val *parent,
217                                      const struct ldb_val *object,
218                                      const struct ldb_val *old_sd,
219                                      uint32_t sd_flags)
220 {
221         struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
222         struct security_descriptor *old_descriptor = NULL;
223         struct security_descriptor *new_sd, *final_sd;
224         DATA_BLOB *linear_sd;
225         enum ndr_err_code ndr_err;
226         struct ldb_context *ldb = ldb_module_get_ctx(module);
227         struct auth_session_info *session_info
228                 = ldb_get_opaque(ldb, "sessionInfo");
229         const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
230         char *sddl_sd;
231         struct dom_sid *default_owner;
232         struct dom_sid *default_group;
233
234         if (object) {
235                 user_descriptor = talloc(mem_ctx, struct security_descriptor);
236                 if (!user_descriptor) {
237                         return NULL;
238                 }
239                 ndr_err = ndr_pull_struct_blob(object, user_descriptor, 
240                                                user_descriptor,
241                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
242
243                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
244                         talloc_free(user_descriptor);
245                         return NULL;
246                 }
247         } else {
248                 user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
249         }
250
251         if (old_sd) {
252                 old_descriptor = talloc(mem_ctx, struct security_descriptor);
253                 if (!old_descriptor) {
254                         return NULL;
255                 }
256                 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor, 
257                                                old_descriptor,
258                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
259
260                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
261                         talloc_free(old_descriptor);
262                         return NULL;
263                 }
264         }
265
266         if (parent) {
267                 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
268                 if (!parent_descriptor) {
269                         return NULL;
270                 }
271                 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor, 
272                                                parent_descriptor,
273                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
274
275                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
276                         talloc_free(parent_descriptor);
277                         return NULL;
278                 }
279         }
280
281         default_owner = get_default_ag(mem_ctx, dn,
282                                        session_info->security_token, ldb);
283         default_group = get_default_group(mem_ctx, ldb, default_owner);
284         new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true,
285                                             NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT,
286                                             session_info->security_token,
287                                             default_owner, default_group,
288                                             map_generic_rights_ds);
289         if (!new_sd) {
290                 return NULL;
291         }
292         final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
293
294         if (!final_sd) {
295                 return NULL;
296         }
297
298         if (final_sd->dacl) {
299                 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
300         }
301         if (final_sd->sacl) {
302                 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
303         }
304
305         sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
306         DEBUG(10, ("Object %s created with desriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
307
308         linear_sd = talloc(mem_ctx, DATA_BLOB);
309         if (!linear_sd) {
310                 return NULL;
311         }
312
313         ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
314                                        final_sd,
315                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
316         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
317                 return NULL;
318         }
319
320         return linear_sd;
321 }
322
323 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
324                                                TALLOC_CTX *mem_ctx,
325                                                struct ldb_val *sd,
326                                                uint32_t sd_flags)
327 {
328         struct security_descriptor *old_sd, *final_sd;
329         DATA_BLOB *linear_sd;
330         enum ndr_err_code ndr_err;
331
332         old_sd = talloc(mem_ctx, struct security_descriptor);
333         if (!old_sd) {
334                 return NULL;
335         }
336         ndr_err = ndr_pull_struct_blob(sd, old_sd, 
337                                        old_sd,
338                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
339
340         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341                 talloc_free(old_sd);
342                 return NULL;
343         }
344
345         final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
346
347         if (!final_sd) {
348                 return NULL;
349         }
350
351         linear_sd = talloc(mem_ctx, DATA_BLOB);
352         if (!linear_sd) {
353                 return NULL;
354         }
355
356         ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
357                                        final_sd,
358                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
359         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
360                 return NULL;
361         }
362
363         return linear_sd;
364 }
365
366 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
367                                                           struct ldb_request *req)
368 {
369         struct ldb_context *ldb;
370         struct descriptor_context *ac;
371
372         ldb = ldb_module_get_ctx(module);
373
374         ac = talloc_zero(req, struct descriptor_context);
375         if (ac == NULL) {
376                 ldb_set_errstring(ldb, "Out of Memory");
377                 return NULL;
378         }
379
380         ac->module = module;
381         ac->req = req;
382         return ac;
383 }
384
385 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
386 {
387         struct descriptor_context *ac;
388         struct ldb_control *sd_control;
389         struct ldb_val *sd_val = NULL;
390         struct ldb_message_element *sd_el;
391         DATA_BLOB *show_sd;
392         int ret;
393         uint32_t sd_flags = 0;
394
395         ac = talloc_get_type(req->context, struct descriptor_context);
396
397         if (!ares) {
398                 ret = LDB_ERR_OPERATIONS_ERROR;
399                 goto fail;
400         }
401         if (ares->error != LDB_SUCCESS) {
402                 return ldb_module_done(ac->req, ares->controls,
403                                         ares->response, ares->error);
404         }
405
406         sd_control = ldb_request_get_control(ac->req, LDB_CONTROL_SD_FLAGS_OID);
407         if (sd_control) {
408                 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data;
409                 sd_flags = sdctr->secinfo_flags;
410                 /* we only care for the last 4 bits */
411                 sd_flags = sd_flags & 0x0000000F;
412                 if (sd_flags == 0) {
413                         /* MS-ADTS 3.1.1.3.4.1.11 says that no bits
414                            equals all 4 bits */
415                         sd_flags = 0xF;
416                 }
417         }
418
419         switch (ares->type) {
420         case LDB_REPLY_ENTRY:
421                 if (sd_flags != 0) {
422                         sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
423                         if (sd_el) {
424                                 sd_val = sd_el->values;
425                         }
426                 }
427                 if (sd_val) {
428                         show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
429                                                                sd_val, sd_flags);
430                         if (!show_sd) {
431                                 ret = LDB_ERR_OPERATIONS_ERROR;
432                                 goto fail;
433                         }
434                         ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
435                         ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
436                         if (ret != LDB_SUCCESS) {
437                                 goto fail;
438                         }
439                 }
440                 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
441
442         case LDB_REPLY_REFERRAL:
443                 return ldb_module_send_referral(ac->req, ares->referral);
444
445         case LDB_REPLY_DONE:
446                 return ldb_module_done(ac->req, ares->controls,
447                                         ares->response, ares->error);
448         }
449
450 fail:
451         talloc_free(ares);
452         return ldb_module_done(ac->req, NULL, NULL, ret);
453 }
454
455 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
456 {
457         struct ldb_context *ldb;
458         struct ldb_request *add_req;
459         struct ldb_message *msg;
460         struct ldb_result *parent_res;
461         const struct ldb_val *parent_sd = NULL;
462         const struct ldb_val *user_sd;
463         struct ldb_dn *parent_dn, *dn, *nc_root;
464         struct ldb_message_element *objectclass_element, *sd_element;
465         int ret;
466         const struct dsdb_schema *schema;
467         DATA_BLOB *sd;
468         const struct dsdb_class *objectclass;
469         static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
470
471         ldb = ldb_module_get_ctx(module);
472         dn = req->op.add.message->dn;
473         user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
474         sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
475         /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
476         if (user_sd == NULL && sd_element) {
477                 return ldb_next_request(module, req);
478         }
479
480         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
481
482         /* do not manipulate our control entries */
483         if (ldb_dn_is_special(dn)) {
484                 return ldb_next_request(module, req);
485         }
486
487         /* if the object has a parent, retrieve its SD to
488          * use for calculation. Unfortunately we do not yet have
489          * instanceType, so we use dsdb_find_nc_root. */
490         parent_dn = ldb_dn_get_parent(req, dn);
491         if (parent_dn == NULL) {
492                 return ldb_oom(ldb);
493         }
494
495         ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
496         if (ret != LDB_SUCCESS) {
497                 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
498                           ldb_dn_get_linearized(dn));
499                 return ret;
500         }
501
502         if (ldb_dn_compare(dn, nc_root) != 0) {
503                 /* we aren't any NC */
504                 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
505                                             parent_attrs,
506                                             DSDB_FLAG_NEXT_MODULE,
507                                             req);
508                 if (ret != LDB_SUCCESS) {
509                         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
510                                   ldb_dn_get_linearized(parent_dn));
511                         return ret;
512                 }
513                 if (parent_res->count != 1) {
514                         return ldb_operr(ldb);
515                 }
516                 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
517         }
518
519         schema = dsdb_get_schema(ldb, req);
520
521         objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
522         if (objectclass_element == NULL) {
523                 return ldb_operr(ldb);
524         }
525
526         objectclass = get_last_structural_class(schema, objectclass_element, req);
527         if (objectclass == NULL) {
528                 return ldb_operr(ldb);
529         }
530
531         sd = get_new_descriptor(module, dn, req,
532                                 objectclass, parent_sd,
533                                 user_sd, NULL, 0);
534         msg = ldb_msg_copy_shallow(req, req->op.add.message);
535         if (sd != NULL) {
536                 if (sd_element != NULL) {
537                         sd_element->values[0] = *sd;
538                 } else {
539                         ret = ldb_msg_add_steal_value(msg,
540                                                       "nTSecurityDescriptor",
541                                                       sd);
542                         if (ret != LDB_SUCCESS) {
543                                 return ret;
544                         }
545                 }
546         }
547
548         ret = ldb_build_add_req(&add_req, ldb, req,
549                                 msg,
550                                 req->controls,
551                                 req, dsdb_next_callback,
552                                 req);
553         LDB_REQ_SET_LOCATION(add_req);
554         if (ret != LDB_SUCCESS) {
555                 return ldb_error(ldb, ret,
556                                  "descriptor_add: Error creating new add request.");
557         }
558
559         return ldb_next_request(module, add_req);
560 }
561
562 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
563 {
564         struct ldb_context *ldb;
565         struct ldb_control *sd_recalculate_control, *sd_flags_control;
566         struct ldb_request *mod_req;
567         struct ldb_message *msg;
568         struct ldb_result *current_res, *parent_res;
569         const struct ldb_val *old_sd = NULL;
570         const struct ldb_val *parent_sd = NULL;
571         const struct ldb_val *user_sd;
572         struct ldb_dn *parent_dn, *dn;
573         struct ldb_message_element *objectclass_element;
574         int ret;
575         uint32_t instanceType, sd_flags = 0;
576         const struct dsdb_schema *schema;
577         DATA_BLOB *sd;
578         const struct dsdb_class *objectclass;
579         static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
580         static const char * const current_attrs[] = { "nTSecurityDescriptor",
581                                                       "instanceType",
582                                                       "objectClass", NULL };
583         ldb = ldb_module_get_ctx(module);
584         dn = req->op.mod.message->dn;
585         user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
586         /* This control forces the recalculation of the SD also when
587          * no modification is performed. */
588         sd_recalculate_control = ldb_request_get_control(req,
589                                              LDB_CONTROL_RECALCULATE_SD_OID);
590         if (!user_sd && !sd_recalculate_control) {
591                 return ldb_next_request(module, req);
592         }
593
594         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
595
596         /* do not manipulate our control entries */
597         if (ldb_dn_is_special(dn)) {
598                 return ldb_next_request(module, req);
599         }
600
601         ret = dsdb_module_search_dn(module, req, &current_res, dn,
602                                     current_attrs,
603                                     DSDB_FLAG_NEXT_MODULE,
604                                     req);
605         if (ret != LDB_SUCCESS) {
606                 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
607                           ldb_dn_get_linearized(dn));
608                 return ret;
609         }
610
611         instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
612                                                  "instanceType", 0);
613         /* if the object has a parent, retrieve its SD to
614          * use for calculation */
615         if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
616             !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
617                 parent_dn = ldb_dn_get_parent(req, dn);
618                 if (parent_dn == NULL) {
619                         return ldb_oom(ldb);
620                 }
621                 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
622                                             parent_attrs,
623                                             DSDB_FLAG_NEXT_MODULE,
624                                             req);
625                 if (ret != LDB_SUCCESS) {
626                         ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
627                                   ldb_dn_get_linearized(parent_dn));
628                         return ret;
629                 }
630                 if (parent_res->count != 1) {
631                         return ldb_operr(ldb);
632                 }
633                 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
634         }
635         sd_flags_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
636
637         schema = dsdb_get_schema(ldb, req);
638
639         objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
640         if (objectclass_element == NULL) {
641                 return ldb_operr(ldb);
642         }
643
644         objectclass = get_last_structural_class(schema, objectclass_element, req);
645         if (objectclass == NULL) {
646                 return ldb_operr(ldb);
647         }
648
649         if (sd_flags_control) {
650                 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_flags_control->data;
651                 sd_flags = sdctr->secinfo_flags;
652                 /* we only care for the last 4 bits */
653                 sd_flags = sd_flags & 0x0000000F;
654         }
655         if (sd_flags != 0) {
656                 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
657         }
658
659         sd = get_new_descriptor(module, dn, req,
660                                 objectclass, parent_sd,
661                                 user_sd, old_sd, sd_flags);
662         msg = ldb_msg_copy_shallow(req, req->op.mod.message);
663         if (sd != NULL) {
664                 struct ldb_message_element *sd_element;
665                 if (user_sd != NULL) {
666                         sd_element = ldb_msg_find_element(msg,
667                                                           "nTSecurityDescriptor");
668                         sd_element->values[0] = *sd;
669                 } else if (sd_recalculate_control != NULL) {
670                         /* In this branch we really do force the recalculation
671                          * of the SD */
672                         ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
673
674                         ret = ldb_msg_add_steal_value(msg,
675                                                       "nTSecurityDescriptor",
676                                                       sd);
677                         if (ret != LDB_SUCCESS) {
678                                 return ldb_error(ldb, ret,
679                                          "descriptor_modify: Could not replace SD value in message.");
680                         }
681                         sd_element = ldb_msg_find_element(msg,
682                                                           "nTSecurityDescriptor");
683                         sd_element->flags = LDB_FLAG_MOD_REPLACE;
684                 }
685         }
686
687         /* mark the controls as non-critical since we've handled them */
688         if (sd_flags_control != NULL) {
689                 sd_flags_control->critical = 0;
690         }
691         if (sd_recalculate_control != NULL) {
692                 sd_recalculate_control->critical = 0;
693         }
694
695         ret = ldb_build_mod_req(&mod_req, ldb, req,
696                                 msg,
697                                 req->controls,
698                                 req,
699                                 dsdb_next_callback,
700                                 req);
701         LDB_REQ_SET_LOCATION(mod_req);
702         if (ret != LDB_SUCCESS) {
703                 return ret;
704         }
705
706         return ldb_next_request(module, mod_req);
707 }
708
709 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
710 {
711         int ret;
712         struct ldb_context *ldb;
713         struct ldb_control *sd_control;
714         struct ldb_request *down_req;
715         struct descriptor_context *ac;
716
717         sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
718         if (!sd_control) {
719                 return ldb_next_request(module, req);
720         }
721
722         ldb = ldb_module_get_ctx(module);
723         ac = descriptor_init_context(module, req);
724         if (ac == NULL) {
725                 return ldb_operr(ldb);
726         }
727
728         ret = ldb_build_search_req_ex(&down_req, ldb, ac,
729                                       req->op.search.base,
730                                       req->op.search.scope,
731                                       req->op.search.tree,
732                                       req->op.search.attrs,
733                                       req->controls,
734                                       ac, descriptor_search_callback,
735                                       ac->req);
736         LDB_REQ_SET_LOCATION(down_req);
737         if (ret != LDB_SUCCESS) {
738                 return ret;
739         }
740         /* mark it as handled */
741         if (sd_control) {
742                 sd_control->critical = 0;
743         }
744
745         return ldb_next_request(ac->module, down_req);
746 }
747 /* TODO */
748 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
749 {
750         struct ldb_context *ldb = ldb_module_get_ctx(module);
751         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn));
752
753         /* do not manipulate our control entries */
754         if (ldb_dn_is_special(req->op.rename.olddn)) {
755                 return ldb_next_request(module, req);
756         }
757
758         return ldb_next_request(module, req);
759 }
760
761 static int descriptor_init(struct ldb_module *module)
762 {
763         int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
764         struct ldb_context *ldb = ldb_module_get_ctx(module);
765         if (ret != LDB_SUCCESS) {
766                 ldb_debug(ldb, LDB_DEBUG_ERROR,
767                         "descriptor: Unable to register control with rootdse!\n");
768                 return ldb_operr(ldb);
769         }
770         return ldb_next_init(module);
771 }
772
773
774 static const struct ldb_module_ops ldb_descriptor_module_ops = {
775         .name          = "descriptor",
776         .search        = descriptor_search,
777         .add           = descriptor_add,
778         .modify        = descriptor_modify,
779         .rename        = descriptor_rename,
780         .init_context  = descriptor_init
781 };
782
783 int ldb_descriptor_module_init(const char *version)
784 {
785         LDB_MODULE_CHECK_VERSION(version);
786         return ldb_register_module(&ldb_descriptor_module_ops);
787 }