2 RID allocation helper functions
4 Copyright (C) Andrew Bartlett 2010
5 Copyright (C) Andrew Tridgell 2010
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Component: RID allocation logic
26 * Description: manage RID Set and RID Manager objects
31 #include "ldb_module.h"
32 #include "dsdb/samdb/samdb.h"
33 #include "dsdb/samdb/ldb_modules/util.h"
34 #include "lib/messaging/irpc.h"
35 #include "param/param.h"
36 #include "librpc/gen_ndr/ndr_misc.h"
39 Note: the RID allocation attributes in AD are very badly named. Here
40 is what we think they really do:
43 - rIDPreviousAllocationPool: the pool which a DC is currently
44 pulling RIDs from. Managed by client DC
46 - rIDAllocationPool: the pool that the DC will switch to next,
47 when rIDPreviousAllocationPool is exhausted. Managed by RID Manager.
49 - rIDNextRID: the last RID allocated by this DC. Managed by client DC
51 in RID Manager object:
52 - rIDAvailablePool: the pool where the RID Manager gets new rID
53 pools from when it gets a EXOP_RID_ALLOC getncchanges call (or
54 locally when the DC is the RID Manager)
59 make a IRPC call to the drepl task to ask it to get the RID
60 Manager to give us another RID pool.
62 This function just sends the message to the drepl task then
63 returns immediately. It should be called well before we
64 completely run out of RIDs
66 static void ridalloc_poke_rid_manager(struct ldb_module *module)
68 struct messaging_context *msg;
69 struct server_id *server;
70 struct ldb_context *ldb = ldb_module_get_ctx(module);
71 struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
72 TALLOC_CTX *tmp_ctx = talloc_new(module);
74 msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, lp_ctx),
75 ldb_get_event_context(ldb));
77 DEBUG(3,(__location__ ": Failed to create messaging context\n"));
82 server = irpc_servers_byname(msg, msg, "dreplsrv");
84 /* this means the drepl service is not running */
89 messaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);
91 /* we don't care if the message got through */
97 allocate a new range of RIDs in the RID Manager object
99 static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool)
102 TALLOC_CTX *tmp_ctx = talloc_new(module);
103 const char *attrs[] = { "rIDAvailablePool", NULL };
104 uint64_t rid_pool, new_rid_pool, dc_pool;
105 uint32_t rid_pool_lo, rid_pool_hi;
106 struct ldb_result *res;
107 struct ldb_context *ldb = ldb_module_get_ctx(module);
108 const unsigned alloc_size = 500;
110 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
111 attrs, DSDB_FLAG_NEXT_MODULE);
112 if (ret != LDB_SUCCESS) {
113 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
114 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
115 talloc_free(tmp_ctx);
119 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
120 rid_pool_lo = rid_pool & 0xFFFFFFFF;
121 rid_pool_hi = rid_pool >> 32;
122 if (rid_pool_lo >= rid_pool_hi) {
123 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
124 rid_pool_lo, rid_pool_hi);
125 talloc_free(tmp_ctx);
129 /* lower part of new pool is the low part of the rIDAvailablePool */
130 dc_pool = rid_pool_lo;
132 /* allocate 500 RIDs to this DC */
133 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
135 /* work out upper part of new pool */
136 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
138 /* and new rIDAvailablePool value */
139 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
141 ret = dsdb_module_constrainted_update_integer(module, rid_manager_dn, "rIDAvailablePool",
142 rid_pool, new_rid_pool);
143 if (ret != LDB_SUCCESS) {
144 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
146 talloc_free(tmp_ctx);
150 (*new_pool) = dc_pool;
151 talloc_free(tmp_ctx);
156 create a RID Set object for the specified DC
158 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
159 struct ldb_dn *rid_manager_dn,
160 struct ldb_dn *ntds_dn, struct ldb_dn **dn)
162 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
163 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
166 struct ldb_message *msg;
167 struct ldb_context *ldb = ldb_module_get_ctx(module);
172 find the machine object for the DC
173 construct the RID Set DN
174 load rIDAvailablePool to find next available set
175 modify RID Manager object to update rIDAvailablePool
176 add the RID Set object
177 link to the RID Set object in machine object
180 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
182 talloc_free(tmp_ctx);
183 return ldb_module_oom(module);
186 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
187 if (ret != LDB_SUCCESS) {
188 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
189 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
190 talloc_free(tmp_ctx);
194 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
195 if (rid_set_dn == NULL) {
196 talloc_free(tmp_ctx);
197 return ldb_module_oom(module);
200 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
201 talloc_free(tmp_ctx);
202 return ldb_module_oom(module);
205 /* grab a pool from the RID Manager object */
206 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &dc_pool);
207 if (ret != LDB_SUCCESS) {
208 talloc_free(tmp_ctx);
212 /* create the RID Set object */
213 msg = ldb_msg_new(tmp_ctx);
214 msg->dn = rid_set_dn;
216 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
217 if (ret != LDB_SUCCESS) {
218 talloc_free(tmp_ctx);
221 ret = ldb_msg_add_fmt(msg, "rIDAllocationPool", "%llu", (unsigned long long)dc_pool);
222 if (ret != LDB_SUCCESS) {
223 talloc_free(tmp_ctx);
227 /* w2k8-r2 sets these to zero when first created */
228 ret = ldb_msg_add_fmt(msg, "rIDPreviousAllocationPool", "0");
229 if (ret != LDB_SUCCESS) {
230 talloc_free(tmp_ctx);
233 ret = ldb_msg_add_fmt(msg, "rIDUsedPool", "0");
234 if (ret != LDB_SUCCESS) {
235 talloc_free(tmp_ctx);
238 ret = ldb_msg_add_fmt(msg, "rIDNextRID", "0");
239 if (ret != LDB_SUCCESS) {
240 talloc_free(tmp_ctx);
244 /* we need this to go all the way to the top of the module
245 * stack, as we need all the extra attributes added (including
246 * complex ones like ntsecuritydescriptor) */
247 ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX);
248 if (ret != LDB_SUCCESS) {
249 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
250 ldb_dn_get_linearized(msg->dn),
252 talloc_free(tmp_ctx);
256 /* add the rIDSetReferences link */
257 msg = ldb_msg_new(tmp_ctx);
258 msg->dn = machine_dn;
260 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
261 if (ret != LDB_SUCCESS) {
262 talloc_free(tmp_ctx);
265 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
267 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
268 if (ret != LDB_SUCCESS) {
269 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
270 ldb_dn_get_linearized(msg->dn),
272 talloc_free(tmp_ctx);
276 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
278 talloc_free(tmp_ctx);
284 create a RID Set object for this DC
286 static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
289 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
290 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
292 struct ldb_context *ldb = ldb_module_get_ctx(module);
294 /* work out who is the RID Manager */
295 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
296 if (ret != LDB_SUCCESS) {
297 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
299 talloc_free(tmp_ctx);
303 /* find the DN of the RID Manager */
304 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
305 if (ret != LDB_SUCCESS) {
306 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
308 talloc_free(tmp_ctx);
312 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
313 ridalloc_poke_rid_manager(module);
314 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
315 talloc_free(tmp_ctx);
316 return LDB_ERR_UNWILLING_TO_PERFORM;
319 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn);
320 talloc_free(tmp_ctx);
325 refresh a RID Set object for the specified DC
326 also returns the first RID for the new pool
328 static int ridalloc_refresh_rid_set_ntds(struct ldb_module *module,
329 struct ldb_dn *rid_manager_dn,
330 struct ldb_dn *ntds_dn, uint64_t *new_pool)
332 TALLOC_CTX *tmp_ctx = talloc_new(module);
333 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
334 struct ldb_context *ldb = ldb_module_get_ctx(module);
337 /* grab a pool from the RID Manager object */
338 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool);
339 if (ret != LDB_SUCCESS) {
340 talloc_free(tmp_ctx);
344 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
346 talloc_free(tmp_ctx);
347 return ldb_module_oom(module);
350 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
351 if (ret != LDB_SUCCESS) {
352 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
353 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
354 talloc_free(tmp_ctx);
358 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
359 if (ret != LDB_SUCCESS) {
360 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
361 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
362 talloc_free(tmp_ctx);
366 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDAllocationPool", *new_pool);
367 if (ret != LDB_SUCCESS) {
368 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
369 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
370 talloc_free(tmp_ctx);
374 talloc_free(tmp_ctx);
380 get a new RID pool for ourselves
381 also returns the first rid for the new pool
383 static int ridalloc_refresh_own_pool(struct ldb_module *module, uint64_t *new_pool)
385 TALLOC_CTX *tmp_ctx = talloc_new(module);
386 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
388 struct ldb_context *ldb = ldb_module_get_ctx(module);
390 /* work out who is the RID Manager */
391 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
392 if (ret != LDB_SUCCESS) {
393 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
395 talloc_free(tmp_ctx);
399 /* find the DN of the RID Manager */
400 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
401 if (ret != LDB_SUCCESS) {
402 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
404 talloc_free(tmp_ctx);
408 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
409 ridalloc_poke_rid_manager(module);
410 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
411 talloc_free(tmp_ctx);
412 return LDB_ERR_UNWILLING_TO_PERFORM;
415 ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, fsmo_role_dn, new_pool);
416 talloc_free(tmp_ctx);
421 /* allocate a RID using our RID Set
422 If we run out of RIDs then allocate a new pool
423 either locally or by contacting the RID Manager
425 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
427 struct ldb_context *ldb;
428 static const char * const attrs[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
429 "rIDNextRID" , "rIDUsedPool", NULL };
431 struct ldb_dn *rid_set_dn;
432 struct ldb_result *res;
433 uint64_t alloc_pool, prev_alloc_pool;
434 uint32_t prev_alloc_pool_lo, prev_alloc_pool_hi;
435 uint32_t rid_used_pool;
437 TALLOC_CTX *tmp_ctx = talloc_new(module);
440 ldb = ldb_module_get_ctx(module);
442 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
443 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
444 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
446 if (ret != LDB_SUCCESS) {
447 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
449 talloc_free(tmp_ctx);
453 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
454 attrs, DSDB_FLAG_NEXT_MODULE);
455 if (ret != LDB_SUCCESS) {
456 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
457 ldb_dn_get_linearized(rid_set_dn));
458 talloc_free(tmp_ctx);
462 prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
463 alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
464 prev_rid = ldb_msg_find_attr_as_int(res->msgs[0], "rIDNextRID", 0);
465 rid_used_pool = ldb_msg_find_attr_as_int(res->msgs[0], "rIDUsedPool", 0);
466 if (alloc_pool == 0) {
467 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
468 ldb_dn_get_linearized(rid_set_dn));
469 talloc_free(tmp_ctx);
470 return LDB_ERR_OPERATIONS_ERROR;
473 prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
474 prev_alloc_pool_hi = prev_alloc_pool >> 32;
475 if (prev_rid >= prev_alloc_pool_hi) {
476 if (prev_alloc_pool == 0) {
477 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDPreviousAllocationPool", alloc_pool);
479 ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
480 prev_alloc_pool, alloc_pool);
482 if (ret != LDB_SUCCESS) {
483 ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
484 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
485 talloc_free(tmp_ctx);
488 prev_alloc_pool = alloc_pool;
489 prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
490 prev_alloc_pool_hi = prev_alloc_pool >> 32;
493 * update the rIDUsedPool attribute
495 * Note: w2k8r2 doesn't update this attribute,
496 * at least if it's itself the rid master.
498 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDUsedPool", rid_used_pool+1);
499 if (ret != LDB_SUCCESS) {
500 ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDUsedPool on %s - %s",
501 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
502 talloc_free(tmp_ctx);
506 (*rid) = prev_alloc_pool_lo;
509 /* see if we are still out of RIDs, and if so then ask
510 the RID Manager to give us more */
511 if (prev_rid >= prev_alloc_pool_hi) {
513 ret = ridalloc_refresh_own_pool(module, &new_pool);
514 if (ret != LDB_SUCCESS) {
515 talloc_free(tmp_ctx);
518 ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
519 prev_alloc_pool, new_pool);
520 if (ret != LDB_SUCCESS) {
521 ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
522 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
523 talloc_free(tmp_ctx);
526 prev_alloc_pool = new_pool;
527 prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
528 prev_alloc_pool_hi = prev_alloc_pool >> 32;
529 (*rid) = prev_alloc_pool_lo;
531 /* despite the name, rIDNextRID is the value of the last user
532 * added by this DC, not the next available RID */
534 (*rid) = prev_rid + 1;
538 if (*rid < prev_alloc_pool_lo || *rid > prev_alloc_pool_hi) {
539 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
540 (unsigned)*rid, (unsigned)prev_alloc_pool_lo,
541 (unsigned)prev_alloc_pool_hi);
542 talloc_free(tmp_ctx);
543 return LDB_ERR_OPERATIONS_ERROR;
546 /* now modify the RID Set to use up this RID using a
547 * constrained delete/add if possible */
549 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDNextRID", *rid);
551 ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDNextRID", prev_rid, *rid);
554 /* if we are half-exhausted then ask the repl task to start
555 * getting another one */
556 if (*rid > (prev_alloc_pool_hi + prev_alloc_pool_lo)/2) {
557 ridalloc_poke_rid_manager(module);
560 talloc_free(tmp_ctx);
567 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
569 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop)
571 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
572 struct ldb_dn *rid_manager_dn;
573 TALLOC_CTX *tmp_ctx = talloc_new(module);
575 struct ldb_context *ldb = ldb_module_get_ctx(module);
578 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn);
579 if (ret != LDB_SUCCESS) {
580 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
581 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
582 talloc_free(tmp_ctx);
586 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
588 talloc_free(tmp_ctx);
589 return ldb_module_oom(module);
592 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
593 if (ret != LDB_SUCCESS) {
594 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
595 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
596 talloc_free(tmp_ctx);
601 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
602 if (ret != LDB_SUCCESS) {
603 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
605 talloc_free(tmp_ctx);
609 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
610 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
611 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn);
612 talloc_free(tmp_ctx);
616 if (ret != LDB_SUCCESS) {
617 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
618 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
619 talloc_free(tmp_ctx);
623 if (exop->fsmo_info != 0) {
624 const char *attrs[] = { "rIDAllocationPool", NULL };
625 struct ldb_result *res;
628 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
629 attrs, DSDB_FLAG_NEXT_MODULE);
630 if (ret != LDB_SUCCESS) {
631 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
632 ldb_dn_get_linearized(rid_set_dn));
633 talloc_free(tmp_ctx);
637 alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
638 if (alloc_pool != exop->fsmo_info) {
639 /* it has already been updated */
640 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
641 (unsigned long long)exop->fsmo_info,
642 (unsigned long long)alloc_pool));
643 talloc_free(tmp_ctx);
648 ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, ntds_dn, &new_pool);
649 talloc_free(tmp_ctx);