TODO: SEC_DEFAULT_DESCRIPTOR...
[metze/samba/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 "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         uint32_t inherit_flags = SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT;
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                 inherit_flags |= SEC_DEFAULT_DESCRIPTOR;
249
250                 user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
251         }
252
253         if (old_sd) {
254                 old_descriptor = talloc(mem_ctx, struct security_descriptor);
255                 if (!old_descriptor) {
256                         return NULL;
257                 }
258                 ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor, 
259                                                old_descriptor,
260                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
261
262                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
263                         talloc_free(old_descriptor);
264                         return NULL;
265                 }
266         }
267
268         if (parent) {
269                 parent_descriptor = talloc(mem_ctx, struct security_descriptor);
270                 if (!parent_descriptor) {
271                         return NULL;
272                 }
273                 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor, 
274                                                parent_descriptor,
275                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
276
277                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
278                         talloc_free(parent_descriptor);
279                         return NULL;
280                 }
281         }
282
283         default_owner = get_default_ag(mem_ctx, dn,
284                                        session_info->security_token, ldb);
285         default_group = get_default_group(mem_ctx, ldb, default_owner);
286         new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true,
287                                             NULL, inherit_flags,
288                                             session_info->security_token,
289                                             default_owner, default_group,
290                                             map_generic_rights_ds);
291         if (!new_sd) {
292                 return NULL;
293         }
294         final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
295
296         if (!final_sd) {
297                 return NULL;
298         }
299
300         if (final_sd->dacl) {
301                 final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
302         }
303         if (final_sd->sacl) {
304                 final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
305         }
306
307         sddl_sd = sddl_encode(mem_ctx, final_sd, domain_sid);
308         DEBUG(10, ("Object %s created with desriptor %s\n\n", ldb_dn_get_linearized(dn), sddl_sd));
309
310         linear_sd = talloc(mem_ctx, DATA_BLOB);
311         if (!linear_sd) {
312                 return NULL;
313         }
314
315         ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
316                                        final_sd,
317                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
318         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
319                 return NULL;
320         }
321
322         return linear_sd;
323 }
324
325 static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
326                                                TALLOC_CTX *mem_ctx,
327                                                struct ldb_val *sd,
328                                                uint32_t sd_flags)
329 {
330         struct security_descriptor *old_sd, *final_sd;
331         DATA_BLOB *linear_sd;
332         enum ndr_err_code ndr_err;
333
334         old_sd = talloc(mem_ctx, struct security_descriptor);
335         if (!old_sd) {
336                 return NULL;
337         }
338         ndr_err = ndr_pull_struct_blob(sd, old_sd, 
339                                        old_sd,
340                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
341
342         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
343                 talloc_free(old_sd);
344                 return NULL;
345         }
346
347         final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
348
349         if (!final_sd) {
350                 return NULL;
351         }
352
353         linear_sd = talloc(mem_ctx, DATA_BLOB);
354         if (!linear_sd) {
355                 return NULL;
356         }
357
358         ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
359                                        final_sd,
360                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
361         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
362                 return NULL;
363         }
364
365         return linear_sd;
366 }
367
368 static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
369                                                           struct ldb_request *req)
370 {
371         struct ldb_context *ldb;
372         struct descriptor_context *ac;
373
374         ldb = ldb_module_get_ctx(module);
375
376         ac = talloc_zero(req, struct descriptor_context);
377         if (ac == NULL) {
378                 ldb_set_errstring(ldb, "Out of Memory");
379                 return NULL;
380         }
381
382         ac->module = module;
383         ac->req = req;
384         return ac;
385 }
386
387 static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
388 {
389         struct descriptor_context *ac;
390         struct ldb_control *sd_control;
391         struct ldb_val *sd_val = NULL;
392         struct ldb_message_element *sd_el;
393         DATA_BLOB *show_sd;
394         int ret;
395         uint32_t sd_flags = 0;
396
397         ac = talloc_get_type(req->context, struct descriptor_context);
398
399         if (!ares) {
400                 ret = LDB_ERR_OPERATIONS_ERROR;
401                 goto fail;
402         }
403         if (ares->error != LDB_SUCCESS) {
404                 return ldb_module_done(ac->req, ares->controls,
405                                         ares->response, ares->error);
406         }
407
408         sd_control = ldb_request_get_control(ac->req, LDB_CONTROL_SD_FLAGS_OID);
409         if (sd_control) {
410                 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data;
411                 sd_flags = sdctr->secinfo_flags;
412                 /* we only care for the last 4 bits */
413                 sd_flags = sd_flags & 0x0000000F;
414                 if (sd_flags == 0) {
415                         /* MS-ADTS 3.1.1.3.4.1.11 says that no bits
416                            equals all 4 bits */
417                         sd_flags = 0xF;
418                 }
419         }
420
421         switch (ares->type) {
422         case LDB_REPLY_ENTRY:
423                 if (sd_flags != 0) {
424                         sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
425                         if (sd_el) {
426                                 sd_val = sd_el->values;
427                         }
428                 }
429                 if (sd_val) {
430                         show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
431                                                                sd_val, sd_flags);
432                         if (!show_sd) {
433                                 ret = LDB_ERR_OPERATIONS_ERROR;
434                                 goto fail;
435                         }
436                         ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
437                         ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
438                         if (ret != LDB_SUCCESS) {
439                                 goto fail;
440                         }
441                 }
442                 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
443
444         case LDB_REPLY_REFERRAL:
445                 return ldb_module_send_referral(ac->req, ares->referral);
446
447         case LDB_REPLY_DONE:
448                 return ldb_module_done(ac->req, ares->controls,
449                                         ares->response, ares->error);
450         }
451
452 fail:
453         talloc_free(ares);
454         return ldb_module_done(ac->req, NULL, NULL, ret);
455 }
456
457 static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
458 {
459         struct ldb_context *ldb;
460         struct ldb_request *add_req;
461         struct ldb_message *msg;
462         struct ldb_result *parent_res;
463         const struct ldb_val *parent_sd = NULL;
464         const struct ldb_val *user_sd;
465         struct ldb_dn *parent_dn, *dn, *nc_root;
466         struct ldb_message_element *objectclass_element, *sd_element;
467         int ret;
468         const struct dsdb_schema *schema;
469         DATA_BLOB *sd;
470         const struct dsdb_class *objectclass;
471         static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
472         uint32_t instanceType;
473         bool isNC = false;
474
475         ldb = ldb_module_get_ctx(module);
476         dn = req->op.add.message->dn;
477         user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
478         sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
479         /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
480         if (user_sd == NULL && sd_element) {
481                 return ldb_next_request(module, req);
482         }
483
484         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
485
486         /* do not manipulate our control entries */
487         if (ldb_dn_is_special(dn)) {
488                 return ldb_next_request(module, req);
489         }
490
491         instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
492
493         if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
494                 isNC = true;
495         }
496
497         if (!isNC) {
498                 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
499                 if (ret != LDB_SUCCESS) {
500                         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
501                                 ldb_dn_get_linearized(dn));
502                         return ret;
503                 }
504
505                 if (ldb_dn_compare(dn, nc_root) == 0) {
506                         DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
507                         isNC = true;
508                 }
509         }
510
511         if (isNC) {
512                 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
513         }
514         if (!isNC) {
515                 /* if the object has a parent, retrieve its SD to
516                  * use for calculation. Unfortunately we do not yet have
517                  * instanceType, so we use dsdb_find_nc_root. */
518
519                 parent_dn = ldb_dn_get_parent(req, dn);
520                 if (parent_dn == NULL) {
521                         return ldb_oom(ldb);
522                 }
523
524                 /* we aren't any NC */
525                 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
526                                             parent_attrs,
527                                             DSDB_FLAG_NEXT_MODULE,
528                                             req);
529                 if (ret != LDB_SUCCESS) {
530                         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
531                                   ldb_dn_get_linearized(parent_dn));
532                         return ret;
533                 }
534                 if (parent_res->count != 1) {
535                         return ldb_operr(ldb);
536                 }
537                 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
538         }
539
540         schema = dsdb_get_schema(ldb, req);
541
542         objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
543         if (objectclass_element == NULL) {
544                 return ldb_operr(ldb);
545         }
546
547         objectclass = dsdb_get_last_structural_class(schema,
548                                                      objectclass_element);
549         if (objectclass == NULL) {
550                 return ldb_operr(ldb);
551         }
552
553         sd = get_new_descriptor(module, dn, req,
554                                 objectclass, parent_sd,
555                                 user_sd, NULL, 0);
556         msg = ldb_msg_copy_shallow(req, req->op.add.message);
557         if (sd != NULL) {
558                 if (sd_element != NULL) {
559                         sd_element->values[0] = *sd;
560                 } else {
561                         ret = ldb_msg_add_steal_value(msg,
562                                                       "nTSecurityDescriptor",
563                                                       sd);
564                         if (ret != LDB_SUCCESS) {
565                                 return ret;
566                         }
567                 }
568         }
569
570         ret = ldb_build_add_req(&add_req, ldb, req,
571                                 msg,
572                                 req->controls,
573                                 req, dsdb_next_callback,
574                                 req);
575         LDB_REQ_SET_LOCATION(add_req);
576         if (ret != LDB_SUCCESS) {
577                 return ldb_error(ldb, ret,
578                                  "descriptor_add: Error creating new add request.");
579         }
580
581         return ldb_next_request(module, add_req);
582 }
583
584 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
585 {
586         struct ldb_context *ldb;
587         struct ldb_control *sd_recalculate_control, *sd_flags_control, *show_deleted_control;
588         struct ldb_request *mod_req;
589         struct ldb_message *msg;
590         struct ldb_result *current_res, *parent_res;
591         const struct ldb_val *old_sd = NULL;
592         const struct ldb_val *parent_sd = NULL;
593         const struct ldb_val *user_sd;
594         struct ldb_dn *parent_dn, *dn;
595         struct ldb_message_element *objectclass_element;
596         int ret;
597         uint32_t instanceType, sd_flags = 0, flags;
598         const struct dsdb_schema *schema;
599         DATA_BLOB *sd;
600         const struct dsdb_class *objectclass;
601         static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
602         static const char * const current_attrs[] = { "nTSecurityDescriptor",
603                                                       "instanceType",
604                                                       "objectClass", NULL };
605         ldb = ldb_module_get_ctx(module);
606         dn = req->op.mod.message->dn;
607         user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
608         /* This control forces the recalculation of the SD also when
609          * no modification is performed. */
610         show_deleted_control = ldb_request_get_control(req,
611                                              LDB_CONTROL_SHOW_DELETED_OID);
612         sd_recalculate_control = ldb_request_get_control(req,
613                                              LDB_CONTROL_RECALCULATE_SD_OID);
614         if (!user_sd && !sd_recalculate_control) {
615                 return ldb_next_request(module, req);
616         }
617
618         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
619
620         /* do not manipulate our control entries */
621         if (ldb_dn_is_special(dn)) {
622                 return ldb_next_request(module, req);
623         }
624         flags = DSDB_FLAG_NEXT_MODULE;
625         if (show_deleted_control) {
626                 flags |= DSDB_SEARCH_SHOW_DELETED;
627         }
628         ret = dsdb_module_search_dn(module, req, &current_res, dn,
629                                     current_attrs,
630                                     flags,
631                                     req);
632         if (ret != LDB_SUCCESS) {
633                 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
634                           ldb_dn_get_linearized(dn));
635                 return ret;
636         }
637
638         instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
639                                                  "instanceType", 0);
640         /* if the object has a parent, retrieve its SD to
641          * use for calculation */
642         if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
643             !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
644                 parent_dn = ldb_dn_get_parent(req, dn);
645                 if (parent_dn == NULL) {
646                         return ldb_oom(ldb);
647                 }
648                 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
649                                             parent_attrs,
650                                             DSDB_FLAG_NEXT_MODULE,
651                                             req);
652                 if (ret != LDB_SUCCESS) {
653                         ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
654                                   ldb_dn_get_linearized(parent_dn));
655                         return ret;
656                 }
657                 if (parent_res->count != 1) {
658                         return ldb_operr(ldb);
659                 }
660                 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
661         }
662         sd_flags_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
663
664         schema = dsdb_get_schema(ldb, req);
665
666         objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
667         if (objectclass_element == NULL) {
668                 return ldb_operr(ldb);
669         }
670
671         objectclass = dsdb_get_last_structural_class(schema,
672                                                      objectclass_element);
673         if (objectclass == NULL) {
674                 return ldb_operr(ldb);
675         }
676
677         if (sd_flags_control) {
678                 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_flags_control->data;
679                 sd_flags = sdctr->secinfo_flags;
680                 /* we only care for the last 4 bits */
681                 sd_flags = sd_flags & 0x0000000F;
682         }
683         if (sd_flags != 0) {
684                 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
685         }
686
687         sd = get_new_descriptor(module, dn, req,
688                                 objectclass, parent_sd,
689                                 user_sd, old_sd, sd_flags);
690         msg = ldb_msg_copy_shallow(req, req->op.mod.message);
691         if (sd != NULL) {
692                 struct ldb_message_element *sd_element;
693                 if (user_sd != NULL) {
694                         sd_element = ldb_msg_find_element(msg,
695                                                           "nTSecurityDescriptor");
696                         sd_element->values[0] = *sd;
697                 } else if (sd_recalculate_control != NULL) {
698                         /* In this branch we really do force the recalculation
699                          * of the SD */
700                         ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
701
702                         ret = ldb_msg_add_steal_value(msg,
703                                                       "nTSecurityDescriptor",
704                                                       sd);
705                         if (ret != LDB_SUCCESS) {
706                                 return ldb_error(ldb, ret,
707                                          "descriptor_modify: Could not replace SD value in message.");
708                         }
709                         sd_element = ldb_msg_find_element(msg,
710                                                           "nTSecurityDescriptor");
711                         sd_element->flags = LDB_FLAG_MOD_REPLACE;
712                 }
713         }
714
715         /* mark the controls as non-critical since we've handled them */
716         if (sd_flags_control != NULL) {
717                 sd_flags_control->critical = 0;
718         }
719         if (sd_recalculate_control != NULL) {
720                 sd_recalculate_control->critical = 0;
721         }
722
723         ret = ldb_build_mod_req(&mod_req, ldb, req,
724                                 msg,
725                                 req->controls,
726                                 req,
727                                 dsdb_next_callback,
728                                 req);
729         LDB_REQ_SET_LOCATION(mod_req);
730         if (ret != LDB_SUCCESS) {
731                 return ret;
732         }
733
734         return ldb_next_request(module, mod_req);
735 }
736
737 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
738 {
739         int ret;
740         struct ldb_context *ldb;
741         struct ldb_control *sd_control;
742         struct ldb_request *down_req;
743         struct descriptor_context *ac;
744
745         sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
746         if (!sd_control) {
747                 return ldb_next_request(module, req);
748         }
749
750         ldb = ldb_module_get_ctx(module);
751         ac = descriptor_init_context(module, req);
752         if (ac == NULL) {
753                 return ldb_operr(ldb);
754         }
755
756         ret = ldb_build_search_req_ex(&down_req, ldb, ac,
757                                       req->op.search.base,
758                                       req->op.search.scope,
759                                       req->op.search.tree,
760                                       req->op.search.attrs,
761                                       req->controls,
762                                       ac, descriptor_search_callback,
763                                       ac->req);
764         LDB_REQ_SET_LOCATION(down_req);
765         if (ret != LDB_SUCCESS) {
766                 return ret;
767         }
768         /* mark it as handled */
769         if (sd_control) {
770                 sd_control->critical = 0;
771         }
772
773         return ldb_next_request(ac->module, down_req);
774 }
775 /* TODO */
776 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
777 {
778         struct ldb_context *ldb = ldb_module_get_ctx(module);
779         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn));
780
781         /* do not manipulate our control entries */
782         if (ldb_dn_is_special(req->op.rename.olddn)) {
783                 return ldb_next_request(module, req);
784         }
785
786         return ldb_next_request(module, req);
787 }
788
789 static int descriptor_init(struct ldb_module *module)
790 {
791         int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
792         struct ldb_context *ldb = ldb_module_get_ctx(module);
793         if (ret != LDB_SUCCESS) {
794                 ldb_debug(ldb, LDB_DEBUG_ERROR,
795                         "descriptor: Unable to register control with rootdse!\n");
796                 return ldb_operr(ldb);
797         }
798         return ldb_next_init(module);
799 }
800
801
802 static const struct ldb_module_ops ldb_descriptor_module_ops = {
803         .name          = "descriptor",
804         .search        = descriptor_search,
805         .add           = descriptor_add,
806         .modify        = descriptor_modify,
807         .rename        = descriptor_rename,
808         .init_context  = descriptor_init
809 };
810
811 int ldb_descriptor_module_init(const char *version)
812 {
813         LDB_MODULE_CHECK_VERSION(version);
814         return ldb_register_module(&ldb_descriptor_module_ops);
815 }