0a262885d8c4030ef2eba8a0286eceded8f10444
[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
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                                             req);
526                 if (ret != LDB_SUCCESS) {
527                         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
528                                   ldb_dn_get_linearized(parent_dn));
529                         return ret;
530                 }
531                 if (parent_res->count != 1) {
532                         return ldb_operr(ldb);
533                 }
534                 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
535         }
536
537         schema = dsdb_get_schema(ldb, req);
538
539         objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
540         if (objectclass_element == NULL) {
541                 return ldb_operr(ldb);
542         }
543
544         objectclass = dsdb_get_last_structural_class(schema,
545                                                      objectclass_element);
546         if (objectclass == NULL) {
547                 return ldb_operr(ldb);
548         }
549
550         sd = get_new_descriptor(module, dn, req,
551                                 objectclass, parent_sd,
552                                 user_sd, NULL, 0);
553         msg = ldb_msg_copy_shallow(req, req->op.add.message);
554         if (sd != NULL) {
555                 if (sd_element != NULL) {
556                         sd_element->values[0] = *sd;
557                 } else {
558                         ret = ldb_msg_add_steal_value(msg,
559                                                       "nTSecurityDescriptor",
560                                                       sd);
561                         if (ret != LDB_SUCCESS) {
562                                 return ret;
563                         }
564                 }
565         }
566
567         ret = ldb_build_add_req(&add_req, ldb, req,
568                                 msg,
569                                 req->controls,
570                                 req, dsdb_next_callback,
571                                 req);
572         LDB_REQ_SET_LOCATION(add_req);
573         if (ret != LDB_SUCCESS) {
574                 return ldb_error(ldb, ret,
575                                  "descriptor_add: Error creating new add request.");
576         }
577
578         return ldb_next_request(module, add_req);
579 }
580
581 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
582 {
583         struct ldb_context *ldb;
584         struct ldb_control *sd_recalculate_control, *sd_flags_control, *show_deleted_control;
585         struct ldb_request *mod_req;
586         struct ldb_message *msg;
587         struct ldb_result *current_res, *parent_res;
588         const struct ldb_val *old_sd = NULL;
589         const struct ldb_val *parent_sd = NULL;
590         const struct ldb_val *user_sd;
591         struct ldb_dn *parent_dn, *dn;
592         struct ldb_message_element *objectclass_element;
593         int ret;
594         uint32_t instanceType, sd_flags = 0, flags;
595         const struct dsdb_schema *schema;
596         DATA_BLOB *sd;
597         const struct dsdb_class *objectclass;
598         static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
599         static const char * const current_attrs[] = { "nTSecurityDescriptor",
600                                                       "instanceType",
601                                                       "objectClass", NULL };
602         ldb = ldb_module_get_ctx(module);
603         dn = req->op.mod.message->dn;
604         user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
605         /* This control forces the recalculation of the SD also when
606          * no modification is performed. */
607         show_deleted_control = ldb_request_get_control(req,
608                                              LDB_CONTROL_SHOW_DELETED_OID);
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         flags = DSDB_FLAG_NEXT_MODULE;
622         if (show_deleted_control) {
623                 flags |= DSDB_SEARCH_SHOW_DELETED;
624         }
625         ret = dsdb_module_search_dn(module, req, &current_res, dn,
626                                     current_attrs,
627                                     flags,
628                                     req);
629         if (ret != LDB_SUCCESS) {
630                 ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
631                           ldb_dn_get_linearized(dn));
632                 return ret;
633         }
634
635         instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
636                                                  "instanceType", 0);
637         /* if the object has a parent, retrieve its SD to
638          * use for calculation */
639         if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
640             !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
641                 parent_dn = ldb_dn_get_parent(req, dn);
642                 if (parent_dn == NULL) {
643                         return ldb_oom(ldb);
644                 }
645                 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
646                                             parent_attrs,
647                                             DSDB_FLAG_NEXT_MODULE,
648                                             req);
649                 if (ret != LDB_SUCCESS) {
650                         ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
651                                   ldb_dn_get_linearized(parent_dn));
652                         return ret;
653                 }
654                 if (parent_res->count != 1) {
655                         return ldb_operr(ldb);
656                 }
657                 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
658         }
659         sd_flags_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
660
661         schema = dsdb_get_schema(ldb, req);
662
663         objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
664         if (objectclass_element == NULL) {
665                 return ldb_operr(ldb);
666         }
667
668         objectclass = dsdb_get_last_structural_class(schema,
669                                                      objectclass_element);
670         if (objectclass == NULL) {
671                 return ldb_operr(ldb);
672         }
673
674         if (sd_flags_control) {
675                 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_flags_control->data;
676                 sd_flags = sdctr->secinfo_flags;
677                 /* we only care for the last 4 bits */
678                 sd_flags = sd_flags & 0x0000000F;
679         }
680         if (sd_flags != 0) {
681                 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
682         }
683
684         sd = get_new_descriptor(module, dn, req,
685                                 objectclass, parent_sd,
686                                 user_sd, old_sd, sd_flags);
687         msg = ldb_msg_copy_shallow(req, req->op.mod.message);
688         if (sd != NULL) {
689                 struct ldb_message_element *sd_element;
690                 if (user_sd != NULL) {
691                         sd_element = ldb_msg_find_element(msg,
692                                                           "nTSecurityDescriptor");
693                         sd_element->values[0] = *sd;
694                 } else if (sd_recalculate_control != NULL) {
695                         /* In this branch we really do force the recalculation
696                          * of the SD */
697                         ldb_msg_remove_attr(msg, "nTSecurityDescriptor");
698
699                         ret = ldb_msg_add_steal_value(msg,
700                                                       "nTSecurityDescriptor",
701                                                       sd);
702                         if (ret != LDB_SUCCESS) {
703                                 return ldb_error(ldb, ret,
704                                          "descriptor_modify: Could not replace SD value in message.");
705                         }
706                         sd_element = ldb_msg_find_element(msg,
707                                                           "nTSecurityDescriptor");
708                         sd_element->flags = LDB_FLAG_MOD_REPLACE;
709                 }
710         }
711
712         /* mark the controls as non-critical since we've handled them */
713         if (sd_flags_control != NULL) {
714                 sd_flags_control->critical = 0;
715         }
716         if (sd_recalculate_control != NULL) {
717                 sd_recalculate_control->critical = 0;
718         }
719
720         ret = ldb_build_mod_req(&mod_req, ldb, req,
721                                 msg,
722                                 req->controls,
723                                 req,
724                                 dsdb_next_callback,
725                                 req);
726         LDB_REQ_SET_LOCATION(mod_req);
727         if (ret != LDB_SUCCESS) {
728                 return ret;
729         }
730
731         return ldb_next_request(module, mod_req);
732 }
733
734 static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
735 {
736         int ret;
737         struct ldb_context *ldb;
738         struct ldb_control *sd_control;
739         struct ldb_request *down_req;
740         struct descriptor_context *ac;
741
742         sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
743         if (!sd_control) {
744                 return ldb_next_request(module, req);
745         }
746
747         ldb = ldb_module_get_ctx(module);
748         ac = descriptor_init_context(module, req);
749         if (ac == NULL) {
750                 return ldb_operr(ldb);
751         }
752
753         ret = ldb_build_search_req_ex(&down_req, ldb, ac,
754                                       req->op.search.base,
755                                       req->op.search.scope,
756                                       req->op.search.tree,
757                                       req->op.search.attrs,
758                                       req->controls,
759                                       ac, descriptor_search_callback,
760                                       ac->req);
761         LDB_REQ_SET_LOCATION(down_req);
762         if (ret != LDB_SUCCESS) {
763                 return ret;
764         }
765         /* mark it as handled */
766         if (sd_control) {
767                 sd_control->critical = 0;
768         }
769
770         return ldb_next_request(ac->module, down_req);
771 }
772 /* TODO */
773 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
774 {
775         struct ldb_context *ldb = ldb_module_get_ctx(module);
776         ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn));
777
778         /* do not manipulate our control entries */
779         if (ldb_dn_is_special(req->op.rename.olddn)) {
780                 return ldb_next_request(module, req);
781         }
782
783         return ldb_next_request(module, req);
784 }
785
786 static int descriptor_init(struct ldb_module *module)
787 {
788         int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
789         struct ldb_context *ldb = ldb_module_get_ctx(module);
790         if (ret != LDB_SUCCESS) {
791                 ldb_debug(ldb, LDB_DEBUG_ERROR,
792                         "descriptor: Unable to register control with rootdse!\n");
793                 return ldb_operr(ldb);
794         }
795         return ldb_next_init(module);
796 }
797
798
799 static const struct ldb_module_ops ldb_descriptor_module_ops = {
800         .name          = "descriptor",
801         .search        = descriptor_search,
802         .add           = descriptor_add,
803         .modify        = descriptor_modify,
804         .rename        = descriptor_rename,
805         .init_context  = descriptor_init
806 };
807
808 int ldb_descriptor_module_init(const char *version)
809 {
810         LDB_MODULE_CHECK_VERSION(version);
811         return ldb_register_module(&ldb_descriptor_module_ops);
812 }