Line data Source code
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 : #include "lib/util/util_tdb.h"
46 : #include "lib/dbwrap/dbwrap.h"
47 : #include "lib/dbwrap/dbwrap_rbt.h"
48 :
49 : struct descriptor_changes {
50 : struct descriptor_changes *prev, *next;
51 : struct ldb_dn *nc_root;
52 : struct GUID guid;
53 : struct GUID parent_guid;
54 : bool force_self;
55 : bool force_children;
56 : struct ldb_dn *stopped_dn;
57 : size_t ref_count;
58 : size_t sort_count;
59 : };
60 :
61 : struct descriptor_transaction {
62 : TALLOC_CTX *mem;
63 : struct {
64 : /*
65 : * We used to have a list of changes, appended with each
66 : * DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID operation.
67 : *
68 : * But the main problem was that a replication
69 : * cycle (mainly the initial replication) calls
70 : * DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID for the
71 : * same object[GUID] more than once. With
72 : * DRSUAPI_DRS_GET_TGT we'll get the naming
73 : * context head object and other top level
74 : * containers, every often.
75 : *
76 : * It means we'll process objects more
77 : * than once and waste a lot of time
78 : * doing the same work again and again.
79 : *
80 : * We use an objectGUID based map in order to
81 : * avoid registering objects more than once.
82 : * In an domain with 22000 object it can
83 : * reduce the work from 4 hours down to ~ 3.5 minutes.
84 : */
85 : struct descriptor_changes *list;
86 : struct db_context *map;
87 : size_t num_registrations;
88 : size_t num_registered;
89 : size_t num_toplevel;
90 : size_t num_processed;
91 : } changes;
92 : struct {
93 : struct db_context *map;
94 : size_t num_processed;
95 : size_t num_skipped;
96 : } objects;
97 : };
98 :
99 : struct descriptor_data {
100 : struct descriptor_transaction transaction;
101 : };
102 :
103 : struct descriptor_context {
104 : struct ldb_module *module;
105 : struct ldb_request *req;
106 : struct ldb_message *msg;
107 : struct ldb_reply *search_res;
108 : struct ldb_reply *search_oc_res;
109 : struct ldb_val *parentsd_val;
110 : struct ldb_message_element *sd_element;
111 : struct ldb_val *sd_val;
112 : uint32_t sd_flags;
113 : int (*step_fn)(struct descriptor_context *);
114 : };
115 :
116 999114 : static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
117 : struct ldb_dn *dn,
118 : struct security_token *token,
119 : struct ldb_context *ldb)
120 : {
121 999114 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
122 999114 : const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
123 999114 : struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
124 999114 : struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS);
125 999114 : struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS);
126 : struct dom_sid *dag_sid;
127 : struct ldb_dn *nc_root;
128 : int ret;
129 :
130 999114 : ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root);
131 999114 : if (ret != LDB_SUCCESS) {
132 0 : talloc_free(tmp_ctx);
133 0 : return NULL;
134 : }
135 :
136 999114 : if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
137 477872 : if (security_token_has_sid(token, sa_sid)) {
138 334512 : dag_sid = dom_sid_dup(mem_ctx, sa_sid);
139 143360 : } else if (security_token_has_sid(token, ea_sid)) {
140 54 : dag_sid = dom_sid_dup(mem_ctx, ea_sid);
141 143306 : } else if (security_token_has_sid(token, da_sid)) {
142 27 : dag_sid = dom_sid_dup(mem_ctx, da_sid);
143 143279 : } else if (security_token_is_system(token)) {
144 143261 : dag_sid = dom_sid_dup(mem_ctx, sa_sid);
145 : } else {
146 18 : dag_sid = NULL;
147 : }
148 521242 : } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
149 355940 : if (security_token_has_sid(token, ea_sid)) {
150 236827 : dag_sid = dom_sid_dup(mem_ctx, ea_sid);
151 119113 : } else if (security_token_has_sid(token, da_sid)) {
152 54 : dag_sid = dom_sid_dup(mem_ctx, da_sid);
153 119059 : } else if (security_token_is_system(token)) {
154 119022 : dag_sid = dom_sid_dup(mem_ctx, ea_sid);
155 : } else {
156 37 : dag_sid = NULL;
157 : }
158 165302 : } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
159 154829 : if (security_token_has_sid(token, da_sid)) {
160 101138 : dag_sid = dom_sid_dup(mem_ctx, da_sid);
161 53691 : } else if (security_token_has_sid(token, ea_sid)) {
162 54 : dag_sid = dom_sid_dup(mem_ctx, ea_sid);
163 53637 : } else if (security_token_is_system(token)) {
164 52759 : dag_sid = dom_sid_dup(mem_ctx, da_sid);
165 : } else {
166 878 : dag_sid = NULL;
167 : }
168 : } else {
169 10473 : dag_sid = NULL;
170 : }
171 :
172 999114 : talloc_free(tmp_ctx);
173 999114 : return dag_sid;
174 : }
175 :
176 999114 : static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx,
177 : const struct dsdb_class *objectclass)
178 : {
179 999114 : struct ldb_context *ldb = ldb_module_get_ctx(module);
180 : struct security_descriptor *sd;
181 999114 : const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
182 :
183 999114 : if (!objectclass->defaultSecurityDescriptor || !domain_sid) {
184 38 : return NULL;
185 : }
186 :
187 999076 : sd = sddl_decode(mem_ctx,
188 189779 : objectclass->defaultSecurityDescriptor,
189 : domain_sid);
190 999076 : return sd;
191 : }
192 :
193 999114 : static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx,
194 : struct ldb_context *ldb,
195 : struct dom_sid *dag)
196 : {
197 : /*
198 : * This depends on the function level of the DC
199 : * which is 2008R2 in our case. Which means it is
200 : * higher than 2003 and we should use the
201 : * "default administrator group" also as owning group.
202 : *
203 : * This matches dcpromo for a 2003 domain
204 : * on a Windows 2008R2 DC.
205 : */
206 999114 : return dag;
207 : }
208 :
209 1923157 : static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx,
210 : struct security_descriptor *new_sd,
211 : struct security_descriptor *old_sd,
212 : uint32_t sd_flags)
213 : {
214 : struct security_descriptor *final_sd;
215 : /* if there is no control or control == 0 modify everything */
216 1923157 : if (!sd_flags) {
217 0 : return new_sd;
218 : }
219 :
220 1923157 : final_sd = talloc_zero(mem_ctx, struct security_descriptor);
221 1923157 : final_sd->revision = SECURITY_DESCRIPTOR_REVISION_1;
222 1923157 : final_sd->type = SEC_DESC_SELF_RELATIVE;
223 :
224 1923157 : if (sd_flags & (SECINFO_OWNER)) {
225 1907864 : if (new_sd->owner_sid) {
226 1907864 : final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid));
227 : }
228 1907864 : final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
229 : }
230 15293 : else if (old_sd) {
231 15175 : if (old_sd->owner_sid) {
232 15175 : final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid));
233 : }
234 15175 : final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
235 : }
236 :
237 1923157 : if (sd_flags & (SECINFO_GROUP)) {
238 1907864 : if (new_sd->group_sid) {
239 1907864 : final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid));
240 : }
241 1907864 : final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
242 : }
243 15293 : else if (old_sd) {
244 15175 : if (old_sd->group_sid) {
245 15175 : final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid));
246 : }
247 15175 : final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
248 : }
249 :
250 1923157 : if (sd_flags & (SECINFO_SACL)) {
251 1908920 : final_sd->sacl = security_acl_dup(mem_ctx,new_sd->sacl);
252 1908920 : final_sd->type |= new_sd->type & (SEC_DESC_SACL_PRESENT |
253 : SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
254 : SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
255 : SEC_DESC_SERVER_SECURITY);
256 : }
257 14237 : else if (old_sd && old_sd->sacl) {
258 13961 : final_sd->sacl = security_acl_dup(mem_ctx,old_sd->sacl);
259 13961 : final_sd->type |= old_sd->type & (SEC_DESC_SACL_PRESENT |
260 : SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
261 : SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
262 : SEC_DESC_SERVER_SECURITY);
263 : }
264 :
265 1923157 : if (sd_flags & (SECINFO_DACL)) {
266 1923022 : final_sd->dacl = security_acl_dup(mem_ctx,new_sd->dacl);
267 1923022 : final_sd->type |= new_sd->type & (SEC_DESC_DACL_PRESENT |
268 : SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
269 : SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
270 : SEC_DESC_DACL_TRUSTED);
271 : }
272 135 : else if (old_sd && old_sd->dacl) {
273 108 : final_sd->dacl = security_acl_dup(mem_ctx,old_sd->dacl);
274 108 : final_sd->type |= old_sd->type & (SEC_DESC_DACL_PRESENT |
275 : SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
276 : SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
277 : SEC_DESC_DACL_TRUSTED);
278 : }
279 : /* not so sure about this */
280 1923157 : final_sd->type |= new_sd->type & SEC_DESC_RM_CONTROL_VALID;
281 1923157 : return final_sd;
282 : }
283 :
284 999114 : static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
285 : struct ldb_dn *dn,
286 : TALLOC_CTX *mem_ctx,
287 : const struct dsdb_class *objectclass,
288 : const struct ldb_val *parent,
289 : const struct ldb_val *object,
290 : const struct ldb_val *old_sd,
291 : uint32_t sd_flags)
292 : {
293 999114 : struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
294 999114 : struct security_descriptor *old_descriptor = NULL;
295 : struct security_descriptor *new_sd, *final_sd;
296 : DATA_BLOB *linear_sd;
297 : enum ndr_err_code ndr_err;
298 999114 : struct ldb_context *ldb = ldb_module_get_ctx(module);
299 809327 : struct auth_session_info *session_info
300 189787 : = ldb_get_opaque(ldb, DSDB_SESSION_INFO);
301 999114 : const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
302 : struct dom_sid *default_owner;
303 : struct dom_sid *default_group;
304 999114 : struct security_descriptor *default_descriptor = NULL;
305 999114 : struct GUID *object_list = NULL;
306 :
307 999114 : if (objectclass != NULL) {
308 999114 : default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
309 999114 : object_list = talloc_zero_array(mem_ctx, struct GUID, 2);
310 999114 : if (object_list == NULL) {
311 0 : return NULL;
312 : }
313 999114 : object_list[0] = objectclass->schemaIDGUID;
314 : }
315 :
316 999114 : if (object) {
317 683013 : user_descriptor = talloc(mem_ctx, struct security_descriptor);
318 683013 : if (!user_descriptor) {
319 0 : return NULL;
320 : }
321 683013 : ndr_err = ndr_pull_struct_blob(object, user_descriptor,
322 : user_descriptor,
323 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
324 :
325 683013 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
326 0 : talloc_free(user_descriptor);
327 0 : return NULL;
328 : }
329 : } else {
330 316101 : user_descriptor = default_descriptor;
331 : }
332 :
333 999114 : if (old_sd) {
334 679209 : old_descriptor = talloc(mem_ctx, struct security_descriptor);
335 679209 : if (!old_descriptor) {
336 0 : return NULL;
337 : }
338 679209 : ndr_err = ndr_pull_struct_blob(old_sd, old_descriptor,
339 : old_descriptor,
340 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
341 :
342 679209 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
343 0 : talloc_free(old_descriptor);
344 0 : return NULL;
345 : }
346 : }
347 :
348 999114 : if (parent) {
349 998198 : parent_descriptor = talloc(mem_ctx, struct security_descriptor);
350 998198 : if (!parent_descriptor) {
351 0 : return NULL;
352 : }
353 998198 : ndr_err = ndr_pull_struct_blob(parent, parent_descriptor,
354 : parent_descriptor,
355 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
356 :
357 998198 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
358 0 : talloc_free(parent_descriptor);
359 0 : return NULL;
360 : }
361 : }
362 :
363 1808409 : if (user_descriptor && default_descriptor &&
364 999074 : (user_descriptor->dacl == NULL))
365 : {
366 6879 : user_descriptor->dacl = default_descriptor->dacl;
367 6879 : user_descriptor->type |= default_descriptor->type & (
368 : SEC_DESC_DACL_PRESENT |
369 : SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ |
370 : SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED |
371 : SEC_DESC_DACL_TRUSTED);
372 : }
373 :
374 1808409 : if (user_descriptor && default_descriptor &&
375 999074 : (user_descriptor->sacl == NULL))
376 : {
377 439314 : user_descriptor->sacl = default_descriptor->sacl;
378 439314 : user_descriptor->type |= default_descriptor->type & (
379 : SEC_DESC_SACL_PRESENT |
380 : SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ |
381 : SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED |
382 : SEC_DESC_SERVER_SECURITY);
383 : }
384 :
385 :
386 999114 : if (!(sd_flags & SECINFO_OWNER) && user_descriptor) {
387 15175 : user_descriptor->owner_sid = NULL;
388 :
389 : /*
390 : * We need the correct owner sid
391 : * when calculating the DACL or SACL
392 : */
393 15175 : if (old_descriptor) {
394 15175 : user_descriptor->owner_sid = old_descriptor->owner_sid;
395 : }
396 : }
397 999114 : if (!(sd_flags & SECINFO_GROUP) && user_descriptor) {
398 15175 : user_descriptor->group_sid = NULL;
399 :
400 : /*
401 : * We need the correct group sid
402 : * when calculating the DACL or SACL
403 : */
404 15175 : if (old_descriptor) {
405 15175 : user_descriptor->group_sid = old_descriptor->group_sid;
406 : }
407 : }
408 999114 : if (!(sd_flags & SECINFO_DACL) && user_descriptor) {
409 108 : user_descriptor->dacl = NULL;
410 :
411 : /*
412 : * We add SEC_DESC_DACL_PROTECTED so that
413 : * create_security_descriptor() skips
414 : * the unused inheritance calculation
415 : */
416 108 : user_descriptor->type |= SEC_DESC_DACL_PROTECTED;
417 : }
418 999114 : if (!(sd_flags & SECINFO_SACL) && user_descriptor) {
419 13961 : user_descriptor->sacl = NULL;
420 :
421 : /*
422 : * We add SEC_DESC_SACL_PROTECTED so that
423 : * create_security_descriptor() skips
424 : * the unused inheritance calculation
425 : */
426 13961 : user_descriptor->type |= SEC_DESC_SACL_PROTECTED;
427 : }
428 :
429 999114 : default_owner = get_default_ag(mem_ctx, dn,
430 : session_info->security_token, ldb);
431 999114 : default_group = get_default_group(mem_ctx, ldb, default_owner);
432 999114 : new_sd = create_security_descriptor(mem_ctx,
433 : parent_descriptor,
434 : user_descriptor,
435 : true,
436 : object_list,
437 : SEC_DACL_AUTO_INHERIT |
438 : SEC_SACL_AUTO_INHERIT,
439 : session_info->security_token,
440 : default_owner, default_group,
441 : map_generic_rights_ds);
442 999114 : if (!new_sd) {
443 0 : return NULL;
444 : }
445 999114 : final_sd = descr_handle_sd_flags(mem_ctx, new_sd, old_descriptor, sd_flags);
446 :
447 999114 : if (!final_sd) {
448 0 : return NULL;
449 : }
450 :
451 999114 : if (final_sd->dacl) {
452 999114 : final_sd->dacl->revision = SECURITY_ACL_REVISION_ADS;
453 : }
454 999114 : if (final_sd->sacl) {
455 646657 : final_sd->sacl->revision = SECURITY_ACL_REVISION_ADS;
456 : }
457 :
458 : {
459 999114 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
460 999114 : DBG_DEBUG("Object %s created with descriptor %s\n\n",
461 : ldb_dn_get_linearized(dn),
462 : sddl_encode(tmp_ctx, final_sd, domain_sid));
463 999114 : TALLOC_FREE(tmp_ctx);
464 : }
465 :
466 999114 : linear_sd = talloc(mem_ctx, DATA_BLOB);
467 999114 : if (!linear_sd) {
468 0 : return NULL;
469 : }
470 :
471 999114 : ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
472 : final_sd,
473 : (ndr_push_flags_fn_t)ndr_push_security_descriptor);
474 999114 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
475 0 : return NULL;
476 : }
477 :
478 999114 : return linear_sd;
479 : }
480 :
481 924043 : static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module,
482 : TALLOC_CTX *mem_ctx,
483 : struct ldb_val *sd,
484 : uint32_t sd_flags)
485 : {
486 : struct security_descriptor *old_sd, *final_sd;
487 : DATA_BLOB *linear_sd;
488 : enum ndr_err_code ndr_err;
489 :
490 924043 : old_sd = talloc(mem_ctx, struct security_descriptor);
491 924043 : if (!old_sd) {
492 0 : return NULL;
493 : }
494 924043 : ndr_err = ndr_pull_struct_blob(sd, old_sd,
495 : old_sd,
496 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
497 :
498 924043 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
499 0 : talloc_free(old_sd);
500 0 : return NULL;
501 : }
502 :
503 924043 : final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags);
504 :
505 924043 : if (!final_sd) {
506 0 : return NULL;
507 : }
508 :
509 924043 : linear_sd = talloc(mem_ctx, DATA_BLOB);
510 924043 : if (!linear_sd) {
511 0 : return NULL;
512 : }
513 :
514 924043 : ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
515 : final_sd,
516 : (ndr_push_flags_fn_t)ndr_push_security_descriptor);
517 924043 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
518 0 : return NULL;
519 : }
520 :
521 924043 : return linear_sd;
522 : }
523 :
524 1435487 : static struct descriptor_context *descriptor_init_context(struct ldb_module *module,
525 : struct ldb_request *req)
526 : {
527 : struct ldb_context *ldb;
528 : struct descriptor_context *ac;
529 :
530 1435487 : ldb = ldb_module_get_ctx(module);
531 :
532 1435487 : ac = talloc_zero(req, struct descriptor_context);
533 1435487 : if (ac == NULL) {
534 0 : ldb_set_errstring(ldb, "Out of Memory");
535 0 : return NULL;
536 : }
537 :
538 1435487 : ac->module = module;
539 1435487 : ac->req = req;
540 1435487 : return ac;
541 : }
542 :
543 2872644 : static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares)
544 : {
545 : struct descriptor_context *ac;
546 2872644 : struct ldb_val *sd_val = NULL;
547 : struct ldb_message_element *sd_el;
548 : DATA_BLOB *show_sd;
549 2872644 : int ret = LDB_SUCCESS;
550 :
551 2872644 : ac = talloc_get_type(req->context, struct descriptor_context);
552 :
553 2872644 : if (!ares) {
554 0 : ret = LDB_ERR_OPERATIONS_ERROR;
555 0 : goto fail;
556 : }
557 2872644 : if (ares->error != LDB_SUCCESS) {
558 0 : return ldb_module_done(ac->req, ares->controls,
559 : ares->response, ares->error);
560 : }
561 :
562 2872644 : switch (ares->type) {
563 1436820 : case LDB_REPLY_ENTRY:
564 1436820 : sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor");
565 1436820 : if (sd_el) {
566 924043 : sd_val = sd_el->values;
567 : }
568 :
569 1436820 : if (sd_val) {
570 924043 : show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
571 : sd_val, ac->sd_flags);
572 924043 : if (!show_sd) {
573 0 : ret = LDB_ERR_OPERATIONS_ERROR;
574 0 : goto fail;
575 : }
576 924043 : ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor");
577 924043 : ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd);
578 924043 : if (ret != LDB_SUCCESS) {
579 0 : goto fail;
580 : }
581 : }
582 1436820 : return ldb_module_send_entry(ac->req, ares->message, ares->controls);
583 :
584 1256 : case LDB_REPLY_REFERRAL:
585 1256 : return ldb_module_send_referral(ac->req, ares->referral);
586 :
587 1434568 : case LDB_REPLY_DONE:
588 1434568 : return ldb_module_done(ac->req, ares->controls,
589 : ares->response, ares->error);
590 : }
591 :
592 0 : fail:
593 0 : talloc_free(ares);
594 0 : return ldb_module_done(ac->req, NULL, NULL, ret);
595 : }
596 :
597 320278 : static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
598 : {
599 320278 : struct ldb_context *ldb = ldb_module_get_ctx(module);
600 : struct ldb_request *add_req;
601 : struct ldb_message *msg;
602 : struct ldb_result *parent_res;
603 320278 : const struct ldb_val *parent_sd = NULL;
604 : const struct ldb_val *user_sd;
605 320278 : struct ldb_dn *dn = req->op.add.message->dn;
606 : struct ldb_dn *parent_dn, *nc_root;
607 : struct ldb_message_element *objectclass_element, *sd_element;
608 : int ret;
609 : const struct dsdb_schema *schema;
610 : DATA_BLOB *sd;
611 : const struct dsdb_class *objectclass;
612 : static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
613 : uint32_t instanceType;
614 320278 : bool isNC = false;
615 320278 : uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);
616 :
617 : /* do not manipulate our control entries */
618 320278 : if (ldb_dn_is_special(dn)) {
619 371 : return ldb_next_request(module, req);
620 : }
621 :
622 319907 : user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
623 319907 : sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
624 : /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
625 319907 : if (user_sd == NULL && sd_element) {
626 1 : return ldb_next_request(module, req);
627 : }
628 :
629 319906 : ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
630 :
631 319906 : instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
632 :
633 319906 : if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
634 358 : isNC = true;
635 : }
636 :
637 319906 : if (!isNC) {
638 319548 : ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
639 319548 : if (ret != LDB_SUCCESS) {
640 1 : ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
641 : ldb_dn_get_linearized(dn));
642 1 : return ret;
643 : }
644 :
645 319547 : if (ldb_dn_compare(dn, nc_root) == 0) {
646 0 : DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
647 0 : isNC = true;
648 : }
649 : }
650 :
651 319905 : if (isNC) {
652 358 : DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
653 : }
654 319905 : if (!isNC) {
655 : /* if the object has a parent, retrieve its SD to
656 : * use for calculation. Unfortunately we do not yet have
657 : * instanceType, so we use dsdb_find_nc_root. */
658 :
659 319547 : parent_dn = ldb_dn_get_parent(req, dn);
660 319547 : if (parent_dn == NULL) {
661 0 : return ldb_oom(ldb);
662 : }
663 :
664 : /* we aren't any NC */
665 319547 : ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
666 : parent_attrs,
667 : DSDB_FLAG_NEXT_MODULE |
668 : DSDB_FLAG_AS_SYSTEM |
669 : DSDB_SEARCH_SHOW_RECYCLED,
670 : req);
671 319547 : if (ret != LDB_SUCCESS) {
672 0 : ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
673 : ldb_dn_get_linearized(parent_dn));
674 0 : return ret;
675 : }
676 319547 : if (parent_res->count != 1) {
677 0 : return ldb_operr(ldb);
678 : }
679 319547 : parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
680 : }
681 :
682 319905 : schema = dsdb_get_schema(ldb, req);
683 :
684 319905 : objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
685 319905 : if (objectclass_element == NULL) {
686 0 : return ldb_operr(ldb);
687 : }
688 :
689 319905 : objectclass = dsdb_get_last_structural_class(schema,
690 : objectclass_element);
691 319905 : if (objectclass == NULL) {
692 0 : return ldb_operr(ldb);
693 : }
694 :
695 : /*
696 : * The SD_FLAG control is ignored on add
697 : * and we default to all bits set.
698 : */
699 319905 : sd_flags = SECINFO_OWNER|SECINFO_GROUP|SECINFO_SACL|SECINFO_DACL;
700 :
701 319905 : sd = get_new_descriptor(module, dn, req,
702 : objectclass, parent_sd,
703 : user_sd, NULL, sd_flags);
704 319905 : if (sd == NULL) {
705 0 : return ldb_operr(ldb);
706 : }
707 319905 : msg = ldb_msg_copy_shallow(req, req->op.add.message);
708 319905 : if (msg == NULL) {
709 0 : return ldb_oom(ldb);
710 : }
711 319905 : if (sd_element != NULL) {
712 3804 : sd_element->values[0] = *sd;
713 : } else {
714 316101 : ret = ldb_msg_add_steal_value(msg,
715 : "nTSecurityDescriptor",
716 : sd);
717 316101 : if (ret != LDB_SUCCESS) {
718 0 : return ret;
719 : }
720 : }
721 :
722 319905 : ret = ldb_build_add_req(&add_req, ldb, req,
723 : msg,
724 : req->controls,
725 : req, dsdb_next_callback,
726 : req);
727 319905 : LDB_REQ_SET_LOCATION(add_req);
728 319905 : if (ret != LDB_SUCCESS) {
729 0 : return ldb_error(ldb, ret,
730 : "descriptor_add: Error creating new add request.");
731 : }
732 :
733 319905 : return ldb_next_request(module, add_req);
734 : }
735 :
736 895948 : static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
737 : {
738 895948 : struct ldb_context *ldb = ldb_module_get_ctx(module);
739 : struct ldb_request *mod_req;
740 : struct ldb_message *msg;
741 : struct ldb_result *current_res, *parent_res;
742 895948 : const struct ldb_val *old_sd = NULL;
743 895948 : const struct ldb_val *parent_sd = NULL;
744 : const struct ldb_val *user_sd;
745 895948 : struct ldb_dn *dn = req->op.mod.message->dn;
746 : struct ldb_dn *parent_dn;
747 : struct ldb_message_element *objectclass_element, *sd_element;
748 : int ret;
749 : uint32_t instanceType;
750 895948 : bool explicit_sd_flags = false;
751 895948 : uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
752 : const struct dsdb_schema *schema;
753 : DATA_BLOB *sd;
754 : const struct dsdb_class *objectclass;
755 : static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
756 : static const char * const current_attrs[] = { "nTSecurityDescriptor",
757 : "instanceType",
758 : "objectClass", NULL };
759 895948 : struct GUID parent_guid = { .time_low = 0 };
760 : struct ldb_control *sd_propagation_control;
761 895948 : int cmp_ret = -1;
762 :
763 : /* do not manipulate our control entries */
764 895948 : if (ldb_dn_is_special(dn)) {
765 558 : return ldb_next_request(module, req);
766 : }
767 :
768 895390 : sd_propagation_control = ldb_request_get_control(req,
769 : DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
770 895390 : if (sd_propagation_control != NULL) {
771 652611 : if (sd_propagation_control->data != module) {
772 0 : return ldb_operr(ldb);
773 : }
774 652611 : if (req->op.mod.message->num_elements != 0) {
775 0 : return ldb_operr(ldb);
776 : }
777 652611 : if (explicit_sd_flags) {
778 0 : return ldb_operr(ldb);
779 : }
780 652611 : if (sd_flags != 0xF) {
781 0 : return ldb_operr(ldb);
782 : }
783 652611 : if (sd_propagation_control->critical == 0) {
784 0 : return ldb_operr(ldb);
785 : }
786 :
787 652611 : sd_propagation_control->critical = 0;
788 : }
789 :
790 895390 : sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor");
791 895390 : if (sd_propagation_control == NULL && sd_element == NULL) {
792 216166 : return ldb_next_request(module, req);
793 : }
794 :
795 : /*
796 : * nTSecurityDescriptor with DELETE is not supported yet.
797 : * TODO: handle this correctly.
798 : */
799 698694 : if (sd_propagation_control == NULL &&
800 26613 : LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE)
801 : {
802 7 : return ldb_module_error(module,
803 : LDB_ERR_UNWILLING_TO_PERFORM,
804 : "MOD_DELETE for nTSecurityDescriptor "
805 : "not supported yet");
806 : }
807 :
808 679217 : user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor");
809 : /* nTSecurityDescriptor without a value is an error, letting through so it is handled */
810 679217 : if (sd_propagation_control == NULL && user_sd == NULL) {
811 8 : return ldb_next_request(module, req);
812 : }
813 :
814 679209 : ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn));
815 :
816 679209 : ret = dsdb_module_search_dn(module, req, ¤t_res, dn,
817 : current_attrs,
818 : DSDB_FLAG_NEXT_MODULE |
819 : DSDB_FLAG_AS_SYSTEM |
820 : DSDB_SEARCH_SHOW_RECYCLED |
821 : DSDB_SEARCH_SHOW_EXTENDED_DN,
822 : req);
823 679209 : if (ret != LDB_SUCCESS) {
824 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,"descriptor_modify: Could not find %s\n",
825 : ldb_dn_get_linearized(dn));
826 0 : return ret;
827 : }
828 :
829 679209 : instanceType = ldb_msg_find_attr_as_uint(current_res->msgs[0],
830 : "instanceType", 0);
831 : /* if the object has a parent, retrieve its SD to
832 : * use for calculation */
833 1231157 : if (!ldb_dn_is_null(current_res->msgs[0]->dn) &&
834 679209 : !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
835 : NTSTATUS status;
836 :
837 678651 : parent_dn = ldb_dn_get_parent(req, dn);
838 678651 : if (parent_dn == NULL) {
839 0 : return ldb_oom(ldb);
840 : }
841 678651 : ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
842 : parent_attrs,
843 : DSDB_FLAG_NEXT_MODULE |
844 : DSDB_FLAG_AS_SYSTEM |
845 : DSDB_SEARCH_SHOW_RECYCLED |
846 : DSDB_SEARCH_SHOW_EXTENDED_DN,
847 : req);
848 678651 : if (ret != LDB_SUCCESS) {
849 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "descriptor_modify: Could not find SD for %s\n",
850 : ldb_dn_get_linearized(parent_dn));
851 0 : return ret;
852 : }
853 678651 : if (parent_res->count != 1) {
854 0 : return ldb_operr(ldb);
855 : }
856 678651 : parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
857 :
858 678651 : status = dsdb_get_extended_dn_guid(parent_res->msgs[0]->dn,
859 : &parent_guid,
860 : "GUID");
861 678651 : if (!NT_STATUS_IS_OK(status)) {
862 0 : return ldb_operr(ldb);
863 : }
864 : }
865 :
866 679209 : schema = dsdb_get_schema(ldb, req);
867 :
868 679209 : objectclass_element = ldb_msg_find_element(current_res->msgs[0], "objectClass");
869 679209 : if (objectclass_element == NULL) {
870 0 : return ldb_operr(ldb);
871 : }
872 :
873 679209 : objectclass = dsdb_get_last_structural_class(schema,
874 : objectclass_element);
875 679209 : if (objectclass == NULL) {
876 0 : return ldb_operr(ldb);
877 : }
878 :
879 679209 : old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor");
880 679209 : if (old_sd == NULL) {
881 0 : return ldb_operr(ldb);
882 : }
883 :
884 679209 : if (sd_propagation_control != NULL) {
885 : /*
886 : * This just triggers a recalculation of the
887 : * inherited aces.
888 : */
889 652611 : user_sd = old_sd;
890 : }
891 :
892 679209 : sd = get_new_descriptor(module, current_res->msgs[0]->dn, req,
893 : objectclass, parent_sd,
894 : user_sd, old_sd, sd_flags);
895 679209 : if (sd == NULL) {
896 0 : return ldb_operr(ldb);
897 : }
898 679209 : msg = ldb_msg_copy_shallow(req, req->op.mod.message);
899 679209 : if (msg == NULL) {
900 0 : return ldb_oom(ldb);
901 : }
902 679209 : cmp_ret = data_blob_cmp(old_sd, sd);
903 679209 : if (sd_propagation_control != NULL) {
904 652611 : if (cmp_ret == 0) {
905 : /*
906 : * The nTSecurityDescriptor is unchanged,
907 : * which means we can stop the processing.
908 : *
909 : * We mark the control as critical again,
910 : * as we have not processed it, so the caller
911 : * can tell that the descriptor was unchanged.
912 : */
913 529594 : sd_propagation_control->critical = 1;
914 529594 : return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
915 : }
916 :
917 123017 : ret = ldb_msg_append_value(msg, "nTSecurityDescriptor",
918 : sd, LDB_FLAG_MOD_REPLACE);
919 123017 : if (ret != LDB_SUCCESS) {
920 0 : return ldb_oom(ldb);
921 : }
922 26598 : } else if (cmp_ret != 0) {
923 : struct GUID guid;
924 : struct ldb_dn *nc_root;
925 : NTSTATUS status;
926 :
927 25732 : ret = dsdb_find_nc_root(ldb,
928 : msg,
929 25732 : current_res->msgs[0]->dn,
930 : &nc_root);
931 25732 : if (ret != LDB_SUCCESS) {
932 0 : return ldb_oom(ldb);
933 : }
934 :
935 25732 : status = dsdb_get_extended_dn_guid(current_res->msgs[0]->dn,
936 : &guid,
937 : "GUID");
938 25732 : if (!NT_STATUS_IS_OK(status)) {
939 0 : return ldb_operr(ldb);
940 : }
941 :
942 : /*
943 : * Force SD propagation on children of this record
944 : */
945 25732 : ret = dsdb_module_schedule_sd_propagation(module,
946 : nc_root,
947 : guid,
948 : parent_guid,
949 : false);
950 25732 : if (ret != LDB_SUCCESS) {
951 0 : return ldb_operr(ldb);
952 : }
953 25732 : sd_element->values[0] = *sd;
954 : } else {
955 866 : sd_element->values[0] = *sd;
956 : }
957 :
958 149615 : ret = ldb_build_mod_req(&mod_req, ldb, req,
959 : msg,
960 : req->controls,
961 : req,
962 : dsdb_next_callback,
963 : req);
964 149615 : LDB_REQ_SET_LOCATION(mod_req);
965 149615 : if (ret != LDB_SUCCESS) {
966 0 : return ret;
967 : }
968 :
969 149615 : return ldb_next_request(module, mod_req);
970 : }
971 :
972 17789936 : static int descriptor_search(struct ldb_module *module, struct ldb_request *req)
973 : {
974 : int ret;
975 : struct ldb_context *ldb;
976 : struct ldb_request *down_req;
977 : struct descriptor_context *ac;
978 17789936 : bool explicit_sd_flags = false;
979 17789936 : uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags);
980 17789936 : bool show_sd = explicit_sd_flags;
981 :
982 34753237 : if (!show_sd &&
983 16963301 : ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor"))
984 : {
985 607933 : show_sd = true;
986 : }
987 :
988 17789936 : if (!show_sd) {
989 16355368 : return ldb_next_request(module, req);
990 : }
991 :
992 1434568 : ldb = ldb_module_get_ctx(module);
993 1434568 : ac = descriptor_init_context(module, req);
994 1434568 : if (ac == NULL) {
995 0 : return ldb_operr(ldb);
996 : }
997 1434568 : ac->sd_flags = sd_flags;
998 :
999 1434568 : ret = ldb_build_search_req_ex(&down_req, ldb, ac,
1000 : req->op.search.base,
1001 : req->op.search.scope,
1002 : req->op.search.tree,
1003 : req->op.search.attrs,
1004 : req->controls,
1005 : ac, descriptor_search_callback,
1006 : ac->req);
1007 1434568 : LDB_REQ_SET_LOCATION(down_req);
1008 1434568 : if (ret != LDB_SUCCESS) {
1009 0 : return ret;
1010 : }
1011 :
1012 1434568 : return ldb_next_request(ac->module, down_req);
1013 : }
1014 :
1015 919 : static int descriptor_rename_callback(struct ldb_request *req,
1016 : struct ldb_reply *ares)
1017 : {
1018 919 : struct descriptor_context *ac = NULL;
1019 919 : struct ldb_context *ldb = NULL;
1020 919 : struct ldb_dn *newdn = req->op.rename.newdn;
1021 : struct GUID guid;
1022 : struct ldb_dn *nc_root;
1023 919 : struct GUID parent_guid = { .time_low = 0 };
1024 : int ret;
1025 :
1026 919 : ac = talloc_get_type_abort(req->context, struct descriptor_context);
1027 919 : ldb = ldb_module_get_ctx(ac->module);
1028 :
1029 919 : if (!ares) {
1030 0 : return ldb_module_done(ac->req, NULL, NULL,
1031 : LDB_ERR_OPERATIONS_ERROR);
1032 : }
1033 919 : if (ares->error != LDB_SUCCESS) {
1034 70 : return ldb_module_done(ac->req, ares->controls,
1035 : ares->response, ares->error);
1036 : }
1037 :
1038 849 : if (ares->type != LDB_REPLY_DONE) {
1039 0 : return ldb_module_done(ac->req, NULL, NULL,
1040 : LDB_ERR_OPERATIONS_ERROR);
1041 : }
1042 :
1043 849 : ret = dsdb_module_guid_by_dn(ac->module,
1044 : newdn,
1045 : &guid,
1046 : req);
1047 849 : if (ret != LDB_SUCCESS) {
1048 0 : return ldb_module_done(ac->req, NULL, NULL,
1049 : ret);
1050 : }
1051 849 : ret = dsdb_find_nc_root(ldb, req, newdn, &nc_root);
1052 849 : if (ret != LDB_SUCCESS) {
1053 0 : return ldb_module_done(ac->req, NULL, NULL,
1054 : ret);
1055 : }
1056 :
1057 : /*
1058 : * After a successful rename, force SD propagation on this
1059 : * record (get a new inherited SD from the potentially new
1060 : * parent
1061 : *
1062 : * We don't know the parent guid here (it is filled in as
1063 : * all-zero in the initialiser above), but we're not in a hot
1064 : * code path here, as the "descriptor" module is located above
1065 : * the "repl_meta_data", only originating changes are handled
1066 : * here.
1067 : *
1068 : * If it turns out to be a problem we may search for the new
1069 : * parent guid.
1070 : */
1071 :
1072 849 : ret = dsdb_module_schedule_sd_propagation(ac->module,
1073 : nc_root,
1074 : guid,
1075 : parent_guid,
1076 : true);
1077 849 : if (ret != LDB_SUCCESS) {
1078 0 : ret = ldb_operr(ldb);
1079 0 : return ldb_module_done(ac->req, NULL, NULL,
1080 : ret);
1081 : }
1082 :
1083 849 : return ldb_module_done(ac->req, ares->controls,
1084 : ares->response, ares->error);
1085 : }
1086 :
1087 :
1088 :
1089 :
1090 925 : static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
1091 : {
1092 925 : struct descriptor_context *ac = NULL;
1093 925 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1094 925 : struct ldb_dn *olddn = req->op.rename.olddn;
1095 925 : struct ldb_dn *newdn = req->op.rename.newdn;
1096 : struct ldb_request *down_req;
1097 : int ret;
1098 :
1099 : /* do not manipulate our control entries */
1100 925 : if (ldb_dn_is_special(req->op.rename.olddn)) {
1101 0 : return ldb_next_request(module, req);
1102 : }
1103 :
1104 925 : ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n",
1105 : ldb_dn_get_linearized(olddn));
1106 :
1107 925 : if (ldb_dn_compare(olddn, newdn) == 0) {
1108 : /* No special work required for a case-only rename */
1109 6 : return ldb_next_request(module, req);
1110 : }
1111 :
1112 919 : ac = descriptor_init_context(module, req);
1113 919 : if (ac == NULL) {
1114 0 : return ldb_operr(ldb);
1115 : }
1116 :
1117 919 : ret = ldb_build_rename_req(&down_req, ldb, ac,
1118 : req->op.rename.olddn,
1119 : req->op.rename.newdn,
1120 : req->controls,
1121 : ac, descriptor_rename_callback,
1122 : req);
1123 919 : LDB_REQ_SET_LOCATION(down_req);
1124 919 : if (ret != LDB_SUCCESS) {
1125 0 : return ret;
1126 : }
1127 :
1128 919 : return ldb_next_request(module, down_req);
1129 : }
1130 :
1131 577392 : static void descriptor_changes_parser(TDB_DATA key, TDB_DATA data, void *private_data)
1132 : {
1133 577392 : struct descriptor_changes **c_ptr = (struct descriptor_changes **)private_data;
1134 577392 : uintptr_t ptr = 0;
1135 :
1136 577392 : SMB_ASSERT(data.dsize == sizeof(ptr));
1137 :
1138 577392 : memcpy(&ptr, data.dptr, data.dsize);
1139 :
1140 577392 : *c_ptr = talloc_get_type_abort((void *)ptr, struct descriptor_changes);
1141 577392 : }
1142 :
1143 116047 : static void descriptor_object_parser(TDB_DATA key, TDB_DATA data, void *private_data)
1144 : {
1145 116047 : SMB_ASSERT(data.dsize == 0);
1146 116047 : }
1147 :
1148 333437 : static int descriptor_extended_sec_desc_propagation(struct ldb_module *module,
1149 : struct ldb_request *req)
1150 : {
1151 320084 : struct descriptor_data *descriptor_private =
1152 333437 : talloc_get_type_abort(ldb_module_get_private(module),
1153 : struct descriptor_data);
1154 333437 : struct descriptor_transaction *t = &descriptor_private->transaction;
1155 333437 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1156 : struct dsdb_extended_sec_desc_propagation_op *op;
1157 333437 : struct descriptor_changes *c = NULL;
1158 : TDB_DATA key;
1159 : NTSTATUS status;
1160 :
1161 333437 : op = talloc_get_type(req->op.extended.data,
1162 : struct dsdb_extended_sec_desc_propagation_op);
1163 333437 : if (op == NULL) {
1164 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1165 : "descriptor_extended_sec_desc_propagation: "
1166 : "invalid extended data\n");
1167 0 : return LDB_ERR_PROTOCOL_ERROR;
1168 : }
1169 :
1170 333437 : if (t->mem == NULL) {
1171 0 : return ldb_module_operr(module);
1172 : }
1173 :
1174 333437 : if (GUID_equal(&op->parent_guid, &op->guid)) {
1175 : /*
1176 : * This is an unexpected situation,
1177 : * it should never happen!
1178 : */
1179 0 : DBG_ERR("ERROR: Object %s is its own parent (nc_root=%s)\n",
1180 : GUID_string(t->mem, &op->guid),
1181 : ldb_dn_get_extended_linearized(t->mem, op->nc_root, 1));
1182 0 : return ldb_module_operr(module);
1183 : }
1184 :
1185 : /*
1186 : * First we check if we already have an registration
1187 : * for the given object.
1188 : */
1189 :
1190 333437 : key = make_tdb_data((const void*)&op->guid, sizeof(op->guid));
1191 333437 : status = dbwrap_parse_record(t->changes.map, key,
1192 : descriptor_changes_parser, &c);
1193 333437 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1194 296780 : c = NULL;
1195 296780 : status = NT_STATUS_OK;
1196 : }
1197 333437 : if (!NT_STATUS_IS_OK(status)) {
1198 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1199 : "dbwrap_parse_record() - %s\n",
1200 : nt_errstr(status));
1201 0 : return ldb_module_operr(module);
1202 : }
1203 :
1204 333437 : if (c == NULL) {
1205 : /*
1206 : * Create a new structure if we
1207 : * don't know about the object yet.
1208 : */
1209 :
1210 296780 : c = talloc_zero(t->mem, struct descriptor_changes);
1211 296780 : if (c == NULL) {
1212 0 : return ldb_module_oom(module);
1213 : }
1214 296780 : c->nc_root = ldb_dn_copy(c, op->nc_root);
1215 296780 : if (c->nc_root == NULL) {
1216 0 : return ldb_module_oom(module);
1217 : }
1218 296780 : c->guid = op->guid;
1219 : }
1220 :
1221 333437 : if (ldb_dn_compare(c->nc_root, op->nc_root) != 0) {
1222 : /*
1223 : * This is an unexpected situation,
1224 : * we don't expect the nc root to change
1225 : * during a replication cycle.
1226 : */
1227 0 : DBG_ERR("ERROR: Object %s nc_root changed %s => %s\n",
1228 : GUID_string(c, &c->guid),
1229 : ldb_dn_get_extended_linearized(c, c->nc_root, 1),
1230 : ldb_dn_get_extended_linearized(c, op->nc_root, 1));
1231 0 : return ldb_module_operr(module);
1232 : }
1233 :
1234 333437 : c->ref_count += 1;
1235 :
1236 : /*
1237 : * always use the last known parent_guid.
1238 : */
1239 333437 : c->parent_guid = op->parent_guid;
1240 :
1241 : /*
1242 : * Note that we only set, but don't clear values here,
1243 : * it means c->force_self and c->force_children can
1244 : * both be true in the end.
1245 : */
1246 333437 : if (op->include_self) {
1247 268642 : c->force_self = true;
1248 : } else {
1249 64795 : c->force_children = true;
1250 : }
1251 :
1252 333437 : if (c->ref_count == 1) {
1253 296780 : struct TDB_DATA val = make_tdb_data((const void*)&c, sizeof(c));
1254 :
1255 : /*
1256 : * Remember the change by objectGUID in order
1257 : * to avoid processing it more than once.
1258 : */
1259 :
1260 296780 : status = dbwrap_store(t->changes.map, key, val, TDB_INSERT);
1261 296780 : if (!NT_STATUS_IS_OK(status)) {
1262 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1263 : "dbwrap_parse_record() - %s\n",
1264 : nt_errstr(status));
1265 0 : return ldb_module_operr(module);
1266 : }
1267 :
1268 296780 : DLIST_ADD_END(t->changes.list, c);
1269 296780 : t->changes.num_registered += 1;
1270 : }
1271 333437 : t->changes.num_registrations += 1;
1272 :
1273 333437 : return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1274 : }
1275 :
1276 1226402 : static int descriptor_extended(struct ldb_module *module, struct ldb_request *req)
1277 : {
1278 1226402 : if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID) == 0) {
1279 333437 : return descriptor_extended_sec_desc_propagation(module, req);
1280 : }
1281 :
1282 892965 : return ldb_next_request(module, req);
1283 : }
1284 :
1285 108013 : static int descriptor_init(struct ldb_module *module)
1286 : {
1287 108013 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1288 : int ret;
1289 : struct descriptor_data *descriptor_private;
1290 :
1291 108013 : ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
1292 108013 : if (ret != LDB_SUCCESS) {
1293 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
1294 : "descriptor: Unable to register control with rootdse!\n");
1295 0 : return ldb_operr(ldb);
1296 : }
1297 :
1298 108013 : descriptor_private = talloc_zero(module, struct descriptor_data);
1299 108013 : if (descriptor_private == NULL) {
1300 0 : ldb_oom(ldb);
1301 0 : return LDB_ERR_OPERATIONS_ERROR;
1302 : }
1303 108013 : ldb_module_set_private(module, descriptor_private);
1304 :
1305 108013 : return ldb_next_init(module);
1306 : }
1307 :
1308 768658 : static int descriptor_sd_propagation_object(struct ldb_module *module,
1309 : struct ldb_message *msg,
1310 : bool *stop)
1311 : {
1312 648536 : struct descriptor_data *descriptor_private =
1313 768658 : talloc_get_type_abort(ldb_module_get_private(module),
1314 : struct descriptor_data);
1315 768658 : struct descriptor_transaction *t = &descriptor_private->transaction;
1316 768658 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1317 : struct ldb_request *sub_req;
1318 : struct ldb_result *mod_res;
1319 : struct ldb_control *sd_propagation_control;
1320 : struct GUID guid;
1321 : int ret;
1322 : TDB_DATA key;
1323 768658 : TDB_DATA empty_val = { .dsize = 0, };
1324 : NTSTATUS status;
1325 768658 : struct descriptor_changes *c = NULL;
1326 :
1327 768658 : *stop = false;
1328 :
1329 : /*
1330 : * We get the GUID of the object
1331 : * in order to have the cache key
1332 : * for the object.
1333 : */
1334 :
1335 768658 : status = dsdb_get_extended_dn_guid(msg->dn, &guid, "GUID");
1336 768658 : if (!NT_STATUS_IS_OK(status)) {
1337 0 : return ldb_operr(ldb);
1338 : }
1339 768658 : key = make_tdb_data((const void*)&guid, sizeof(guid));
1340 :
1341 : /*
1342 : * Check if we already processed this object.
1343 : */
1344 768658 : status = dbwrap_parse_record(t->objects.map, key,
1345 : descriptor_object_parser, NULL);
1346 768658 : if (NT_STATUS_IS_OK(status)) {
1347 : /*
1348 : * All work is already one
1349 : */
1350 116047 : t->objects.num_skipped += 1;
1351 116047 : *stop = true;
1352 116047 : return LDB_SUCCESS;
1353 : }
1354 652611 : if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1355 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1356 : "dbwrap_parse_record() - %s\n",
1357 : nt_errstr(status));
1358 0 : return ldb_module_operr(module);
1359 : }
1360 :
1361 652611 : t->objects.num_processed += 1;
1362 :
1363 : /*
1364 : * Remember that we're processing this object.
1365 : */
1366 652611 : status = dbwrap_store(t->objects.map, key, empty_val, TDB_INSERT);
1367 652611 : if (!NT_STATUS_IS_OK(status)) {
1368 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1369 : "dbwrap_parse_record() - %s\n",
1370 : nt_errstr(status));
1371 0 : return ldb_module_operr(module);
1372 : }
1373 :
1374 : /*
1375 : * Check that if there's a descriptor_change in our list,
1376 : * which we may be able to remove from the pending list
1377 : * when we processed the object.
1378 : */
1379 :
1380 652611 : status = dbwrap_parse_record(t->changes.map, key, descriptor_changes_parser, &c);
1381 652611 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1382 375916 : c = NULL;
1383 375916 : status = NT_STATUS_OK;
1384 : }
1385 652611 : if (!NT_STATUS_IS_OK(status)) {
1386 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1387 : "dbwrap_parse_record() - %s\n",
1388 : nt_errstr(status));
1389 0 : return ldb_module_operr(module);
1390 : }
1391 :
1392 652611 : mod_res = talloc_zero(msg, struct ldb_result);
1393 652611 : if (mod_res == NULL) {
1394 0 : return ldb_module_oom(module);
1395 : }
1396 :
1397 652611 : ret = ldb_build_mod_req(&sub_req, ldb, mod_res,
1398 : msg,
1399 : NULL,
1400 : mod_res,
1401 : ldb_modify_default_callback,
1402 : NULL);
1403 652611 : LDB_REQ_SET_LOCATION(sub_req);
1404 652611 : if (ret != LDB_SUCCESS) {
1405 0 : return ldb_module_operr(module);
1406 : }
1407 :
1408 652611 : ldb_req_mark_trusted(sub_req);
1409 :
1410 652611 : ret = ldb_request_add_control(sub_req,
1411 : DSDB_CONTROL_SEC_DESC_PROPAGATION_OID,
1412 : true, module);
1413 652611 : if (ret != LDB_SUCCESS) {
1414 0 : return ldb_module_operr(module);
1415 : }
1416 :
1417 652611 : sd_propagation_control = ldb_request_get_control(sub_req,
1418 : DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
1419 652611 : if (sd_propagation_control == NULL) {
1420 0 : return ldb_module_operr(module);
1421 : }
1422 :
1423 652611 : ret = dsdb_request_add_controls(sub_req,
1424 : DSDB_FLAG_AS_SYSTEM |
1425 : DSDB_SEARCH_SHOW_RECYCLED);
1426 652611 : if (ret != LDB_SUCCESS) {
1427 0 : return ldb_module_operr(module);
1428 : }
1429 :
1430 652611 : ret = descriptor_modify(module, sub_req);
1431 652611 : if (ret == LDB_SUCCESS) {
1432 652611 : ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL);
1433 : }
1434 652611 : if (ret != LDB_SUCCESS) {
1435 0 : ldb_asprintf_errstring(ldb_module_get_ctx(module),
1436 : "descriptor_modify on %s failed: %s",
1437 : ldb_dn_get_linearized(msg->dn),
1438 : ldb_errstring(ldb_module_get_ctx(module)));
1439 0 : return LDB_ERR_OPERATIONS_ERROR;
1440 : }
1441 :
1442 652611 : if (sd_propagation_control->critical != 0) {
1443 529594 : if (c == NULL) {
1444 : /*
1445 : * If we don't have a
1446 : * descriptor_changes structure
1447 : * we're done.
1448 : */
1449 259312 : *stop = true;
1450 270282 : } else if (!c->force_children) {
1451 : /*
1452 : * If we don't need to
1453 : * propagate to children,
1454 : * we're done.
1455 : */
1456 225114 : *stop = true;
1457 : }
1458 : }
1459 :
1460 652611 : if (c != NULL && !c->force_children) {
1461 : /*
1462 : * Remove the pending change,
1463 : * we already done all required work,
1464 : * there's no need to do it again.
1465 : *
1466 : * Note DLIST_REMOVE() is a noop
1467 : * if the element is not part of
1468 : * the list.
1469 : */
1470 231527 : DLIST_REMOVE(t->changes.list, c);
1471 : }
1472 :
1473 652611 : talloc_free(mod_res);
1474 :
1475 652611 : return LDB_SUCCESS;
1476 : }
1477 :
1478 4338093 : static int descriptor_sd_propagation_msg_sort(struct ldb_message **m1,
1479 : struct ldb_message **m2)
1480 : {
1481 4338093 : struct ldb_dn *dn1 = (*m1)->dn;
1482 4338093 : struct ldb_dn *dn2 = (*m2)->dn;
1483 :
1484 : /*
1485 : * This sorts in tree order, parents first
1486 : */
1487 4338093 : return ldb_dn_compare(dn2, dn1);
1488 : }
1489 :
1490 288724 : static int descriptor_sd_propagation_recursive(struct ldb_module *module,
1491 : struct descriptor_changes *change)
1492 : {
1493 275371 : struct descriptor_data *descriptor_private =
1494 288724 : talloc_get_type_abort(ldb_module_get_private(module),
1495 : struct descriptor_data);
1496 288724 : struct descriptor_transaction *t = &descriptor_private->transaction;
1497 288724 : struct ldb_result *guid_res = NULL;
1498 288724 : struct ldb_result *res = NULL;
1499 : unsigned int i;
1500 288724 : const char * const no_attrs[] = { "@__NONE__", NULL };
1501 288724 : struct ldb_dn *stopped_dn = NULL;
1502 : struct GUID_txt_buf guid_buf;
1503 : int ret;
1504 288724 : bool stop = false;
1505 :
1506 288724 : t->changes.num_processed += 1;
1507 :
1508 : /*
1509 : * First confirm this object has children, or exists
1510 : * (depending on change->force_self)
1511 : *
1512 : * LDB_SCOPE_SUBTREE searches are expensive.
1513 : *
1514 : * We know this is safe against a rename race as we are in the
1515 : * prepare_commit(), so must be in a transaction.
1516 : */
1517 :
1518 : /* Find the DN by GUID, as this is stable under rename */
1519 288724 : ret = dsdb_module_search(module,
1520 : change,
1521 : &guid_res,
1522 : change->nc_root,
1523 : LDB_SCOPE_SUBTREE,
1524 : no_attrs,
1525 : DSDB_FLAG_NEXT_MODULE |
1526 : DSDB_FLAG_AS_SYSTEM |
1527 : DSDB_SEARCH_SHOW_DELETED |
1528 : DSDB_SEARCH_SHOW_RECYCLED |
1529 : DSDB_SEARCH_SHOW_EXTENDED_DN,
1530 : NULL, /* parent_req */
1531 : "(objectGUID=%s)",
1532 288724 : GUID_buf_string(&change->guid,
1533 : &guid_buf));
1534 :
1535 288724 : if (ret != LDB_SUCCESS) {
1536 0 : return ret;
1537 : }
1538 :
1539 288724 : if (guid_res->count != 1) {
1540 : /*
1541 : * We were just given this GUID during the same
1542 : * transaction, if it is missing this is a big
1543 : * problem.
1544 : *
1545 : * Cleanup of tombstones does not trigger this module
1546 : * as it just does a delete.
1547 : */
1548 0 : ldb_asprintf_errstring(ldb_module_get_ctx(module),
1549 : "failed to find GUID %s under %s "
1550 : "for transaction-end SD inheritance: %d results",
1551 0 : GUID_buf_string(&change->guid,
1552 : &guid_buf),
1553 : ldb_dn_get_linearized(change->nc_root),
1554 0 : guid_res->count);
1555 0 : return LDB_ERR_OPERATIONS_ERROR;
1556 : }
1557 :
1558 : /*
1559 : * OK, so there was a parent, are there children? Note: that
1560 : * this time we do not search for deleted/recycled objects
1561 : */
1562 288724 : ret = dsdb_module_search(module,
1563 : change,
1564 : &res,
1565 288724 : guid_res->msgs[0]->dn,
1566 : LDB_SCOPE_ONELEVEL,
1567 : no_attrs,
1568 : DSDB_FLAG_NEXT_MODULE |
1569 : DSDB_FLAG_AS_SYSTEM,
1570 : NULL, /* parent_req */
1571 : "(objectClass=*)");
1572 288724 : if (ret != LDB_SUCCESS) {
1573 : /*
1574 : * LDB_ERR_NO_SUCH_OBJECT, say if the DN was a deleted
1575 : * object, is ignored by the caller
1576 : */
1577 0 : return ret;
1578 : }
1579 :
1580 288724 : if (res->count == 0 && !change->force_self) {
1581 : /* All done, no children */
1582 20208 : TALLOC_FREE(res);
1583 20208 : return LDB_SUCCESS;
1584 : }
1585 :
1586 : /*
1587 : * First, if we are in force_self mode (eg renamed under new
1588 : * parent) then apply the SD to the top object
1589 : */
1590 268516 : if (change->force_self) {
1591 260586 : ret = descriptor_sd_propagation_object(module,
1592 260586 : guid_res->msgs[0],
1593 : &stop);
1594 260586 : if (ret != LDB_SUCCESS) {
1595 0 : TALLOC_FREE(guid_res);
1596 0 : return ret;
1597 : }
1598 :
1599 260586 : if (stop == true && !change->force_children) {
1600 : /* There was no change, nothing more to do */
1601 217524 : TALLOC_FREE(guid_res);
1602 217524 : return LDB_SUCCESS;
1603 : }
1604 :
1605 43062 : if (res->count == 0) {
1606 : /* All done! */
1607 41343 : TALLOC_FREE(guid_res);
1608 41343 : return LDB_SUCCESS;
1609 : }
1610 : }
1611 :
1612 : /*
1613 : * Look for children
1614 : *
1615 : * Note: that we do not search for deleted/recycled objects
1616 : */
1617 9649 : ret = dsdb_module_search(module,
1618 : change,
1619 : &res,
1620 9649 : guid_res->msgs[0]->dn,
1621 : LDB_SCOPE_SUBTREE,
1622 : no_attrs,
1623 : DSDB_FLAG_NEXT_MODULE |
1624 : DSDB_FLAG_AS_SYSTEM |
1625 : DSDB_SEARCH_SHOW_EXTENDED_DN,
1626 : NULL, /* parent_req */
1627 : "(objectClass=*)");
1628 9649 : if (ret != LDB_SUCCESS) {
1629 0 : return ret;
1630 : }
1631 :
1632 9649 : TYPESAFE_QSORT(res->msgs, res->count,
1633 : descriptor_sd_propagation_msg_sort);
1634 :
1635 : /* We start from 1, the top object has been done */
1636 527279 : for (i = 1; i < res->count; i++) {
1637 : /*
1638 : * ldb_dn_compare_base() does not match for NULL but
1639 : * this is clearer
1640 : */
1641 517630 : if (stopped_dn != NULL) {
1642 361592 : ret = ldb_dn_compare_base(stopped_dn,
1643 361592 : res->msgs[i]->dn);
1644 : /*
1645 : * Skip further processing of this
1646 : * sub-subtree
1647 : */
1648 361592 : if (ret == 0) {
1649 9558 : continue;
1650 : }
1651 : }
1652 508072 : ret = descriptor_sd_propagation_object(module,
1653 508072 : res->msgs[i],
1654 : &stop);
1655 508072 : if (ret != LDB_SUCCESS) {
1656 0 : return ret;
1657 : }
1658 :
1659 508072 : if (stop) {
1660 : /*
1661 : * If this child didn't change, then nothing
1662 : * under it needs to change
1663 : *
1664 : * res has been sorted into tree order so the
1665 : * next few entries can be skipped
1666 : */
1667 346378 : stopped_dn = res->msgs[i]->dn;
1668 : }
1669 : }
1670 :
1671 9649 : TALLOC_FREE(res);
1672 9649 : return LDB_SUCCESS;
1673 : }
1674 :
1675 244076 : static int descriptor_start_transaction(struct ldb_module *module)
1676 : {
1677 187428 : struct descriptor_data *descriptor_private =
1678 244076 : talloc_get_type_abort(ldb_module_get_private(module),
1679 : struct descriptor_data);
1680 244076 : struct descriptor_transaction *t = &descriptor_private->transaction;
1681 :
1682 244076 : if (t->mem != NULL) {
1683 0 : return ldb_module_operr(module);
1684 : }
1685 :
1686 244076 : *t = (struct descriptor_transaction) { .mem = NULL, };
1687 244076 : t->mem = talloc_new(descriptor_private);
1688 244076 : if (t->mem == NULL) {
1689 0 : return ldb_module_oom(module);
1690 : }
1691 244076 : t->changes.map = db_open_rbt(t->mem);
1692 244076 : if (t->changes.map == NULL) {
1693 0 : TALLOC_FREE(t->mem);
1694 0 : *t = (struct descriptor_transaction) { .mem = NULL, };
1695 0 : return ldb_module_oom(module);
1696 : }
1697 244076 : t->objects.map = db_open_rbt(t->mem);
1698 244076 : if (t->objects.map == NULL) {
1699 0 : TALLOC_FREE(t->mem);
1700 0 : *t = (struct descriptor_transaction) { .mem = NULL, };
1701 0 : return ldb_module_oom(module);
1702 : }
1703 :
1704 244076 : return ldb_next_start_trans(module);
1705 : }
1706 :
1707 212234 : static int descriptor_prepare_commit(struct ldb_module *module)
1708 : {
1709 167039 : struct descriptor_data *descriptor_private =
1710 212234 : talloc_get_type_abort(ldb_module_get_private(module),
1711 : struct descriptor_data);
1712 212234 : struct descriptor_transaction *t = &descriptor_private->transaction;
1713 212234 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1714 : struct descriptor_changes *c, *n;
1715 : int ret;
1716 :
1717 212234 : DBG_NOTICE("changes: num_registrations=%zu\n",
1718 : t->changes.num_registrations);
1719 212234 : DBG_NOTICE("changes: num_registered=%zu\n",
1720 : t->changes.num_registered);
1721 :
1722 : /*
1723 : * The security descriptor propagation
1724 : * needs to apply the inheritance from
1725 : * an object to itself and/or all it's
1726 : * children.
1727 : *
1728 : * In the initial replication during
1729 : * a join, we have every object in our
1730 : * list.
1731 : *
1732 : * In order to avoid useless work it's
1733 : * better to start with toplevel objects and
1734 : * move down to the leaf object from there.
1735 : *
1736 : * So if the parent_guid is also in our list,
1737 : * we better move the object behind its parent.
1738 : *
1739 : * It allows that the recursive processing of
1740 : * the parent already does the work needed
1741 : * for the child.
1742 : *
1743 : * If we have a list for this directory tree:
1744 : *
1745 : * A
1746 : * -> B
1747 : * -> C
1748 : * -> D
1749 : * -> E
1750 : *
1751 : * The initial list would have the order D, E, B, A, C
1752 : *
1753 : * By still processing from the front, we ensure that,
1754 : * when D is found to be below C, that E follows because
1755 : * we keep peeling items off the front for checking and
1756 : * move them behind their parent.
1757 : *
1758 : * So we would go:
1759 : *
1760 : * E B A C D
1761 : *
1762 : * B A C D E
1763 : *
1764 : * A B C D E
1765 : */
1766 509697 : for (c = t->changes.list; c; c = n) {
1767 297463 : struct descriptor_changes *pc = NULL;
1768 297463 : n = c->next;
1769 :
1770 297463 : if (c->sort_count >= t->changes.num_registered) {
1771 : /*
1772 : * This should never happen, but it's
1773 : * a sanity check in order to avoid
1774 : * endless loops. Just stop sorting.
1775 : */
1776 0 : break;
1777 : }
1778 :
1779 : /*
1780 : * Check if we have the parent also in the list.
1781 : */
1782 297463 : if (!GUID_all_zero((const void*)&c->parent_guid)) {
1783 : TDB_DATA pkey;
1784 : NTSTATUS status;
1785 :
1786 295973 : pkey = make_tdb_data((const void*)&c->parent_guid,
1787 : sizeof(c->parent_guid));
1788 :
1789 295973 : status = dbwrap_parse_record(t->changes.map, pkey,
1790 : descriptor_changes_parser, &pc);
1791 295973 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1792 31933 : pc = NULL;
1793 31933 : status = NT_STATUS_OK;
1794 : }
1795 295973 : if (!NT_STATUS_IS_OK(status)) {
1796 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
1797 : "dbwrap_parse_record() - %s\n",
1798 : nt_errstr(status));
1799 0 : return ldb_module_operr(module);
1800 : }
1801 : }
1802 :
1803 297463 : if (pc == NULL) {
1804 : /*
1805 : * There is no parent in the list
1806 : */
1807 33423 : t->changes.num_toplevel += 1;
1808 33423 : continue;
1809 : }
1810 :
1811 : /*
1812 : * Move the child after the parent
1813 : *
1814 : * Note that we do that multiple times
1815 : * in case the parent already moved itself.
1816 : *
1817 : * See the comment above the loop.
1818 : */
1819 264040 : DLIST_REMOVE(t->changes.list, c);
1820 264040 : DLIST_ADD_AFTER(t->changes.list, c, pc);
1821 :
1822 : /*
1823 : * Remember how often we moved the object
1824 : * in order to avoid endless loops.
1825 : */
1826 264040 : c->sort_count += 1;
1827 : }
1828 :
1829 212234 : DBG_NOTICE("changes: num_toplevel=%zu\n", t->changes.num_toplevel);
1830 :
1831 667997 : while (t->changes.list != NULL) {
1832 288724 : c = t->changes.list;
1833 :
1834 288724 : DLIST_REMOVE(t->changes.list, c);
1835 :
1836 : /*
1837 : * Note that descriptor_sd_propagation_recursive()
1838 : * may also remove other elements of the list,
1839 : * so we can't use a next pointer
1840 : */
1841 288724 : ret = descriptor_sd_propagation_recursive(module, c);
1842 288724 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1843 0 : continue;
1844 : }
1845 288724 : if (ret != LDB_SUCCESS) {
1846 0 : return ret;
1847 : }
1848 : }
1849 :
1850 212234 : DBG_NOTICE("changes: num_processed=%zu\n", t->changes.num_processed);
1851 212234 : DBG_NOTICE("objects: num_processed=%zu\n", t->objects.num_processed);
1852 212234 : DBG_NOTICE("objects: num_skipped=%zu\n", t->objects.num_skipped);
1853 :
1854 212234 : return ldb_next_prepare_commit(module);
1855 : }
1856 :
1857 212231 : static int descriptor_end_transaction(struct ldb_module *module)
1858 : {
1859 167036 : struct descriptor_data *descriptor_private =
1860 212231 : talloc_get_type_abort(ldb_module_get_private(module),
1861 : struct descriptor_data);
1862 212231 : struct descriptor_transaction *t = &descriptor_private->transaction;
1863 :
1864 212231 : TALLOC_FREE(t->mem);
1865 212231 : *t = (struct descriptor_transaction) { .mem = NULL, };
1866 :
1867 212231 : return ldb_next_end_trans(module);
1868 : }
1869 :
1870 31844 : static int descriptor_del_transaction(struct ldb_module *module)
1871 : {
1872 20391 : struct descriptor_data *descriptor_private =
1873 31844 : talloc_get_type_abort(ldb_module_get_private(module),
1874 : struct descriptor_data);
1875 31844 : struct descriptor_transaction *t = &descriptor_private->transaction;
1876 :
1877 31844 : TALLOC_FREE(t->mem);
1878 31844 : *t = (struct descriptor_transaction) { .mem = NULL, };
1879 :
1880 31844 : return ldb_next_del_trans(module);
1881 : }
1882 :
1883 : static const struct ldb_module_ops ldb_descriptor_module_ops = {
1884 : .name = "descriptor",
1885 : .search = descriptor_search,
1886 : .add = descriptor_add,
1887 : .modify = descriptor_modify,
1888 : .rename = descriptor_rename,
1889 : .init_context = descriptor_init,
1890 : .extended = descriptor_extended,
1891 : .start_transaction = descriptor_start_transaction,
1892 : .prepare_commit = descriptor_prepare_commit,
1893 : .end_transaction = descriptor_end_transaction,
1894 : .del_transaction = descriptor_del_transaction,
1895 : };
1896 :
1897 4310 : int ldb_descriptor_module_init(const char *version)
1898 : {
1899 4310 : LDB_MODULE_CHECK_VERSION(version);
1900 4310 : return ldb_register_module(&ldb_descriptor_module_ops);
1901 : }
|