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