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"
37 #include "dsdb/samdb/ldb_modules/ridalloc.h"
40 Note: the RID allocation attributes in AD are very badly named. Here
41 is what we think they really do:
44 - rIDPreviousAllocationPool: the pool which a DC is currently
45 pulling RIDs from. Managed by client DC
47 - rIDAllocationPool: the pool that the DC will switch to next,
48 when rIDPreviousAllocationPool is exhausted. Managed by RID Manager.
50 - rIDNextRID: the last RID allocated by this DC. Managed by client DC
52 in RID Manager object:
53 - rIDAvailablePool: the pool where the RID Manager gets new rID
54 pools from when it gets a EXOP_RID_ALLOC getncchanges call (or
55 locally when the DC is the RID Manager)
60 make a IRPC call to the drepl task to ask it to get the RID
61 Manager to give us another RID pool.
63 This function just sends the message to the drepl task then
64 returns immediately. It should be called well before we
65 completely run out of RIDs
67 static int ridalloc_poke_rid_manager(struct ldb_module *module)
69 struct imessaging_context *msg;
70 struct server_id *server;
71 struct ldb_context *ldb = ldb_module_get_ctx(module);
72 struct loadparm_context *lp_ctx =
73 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
74 TALLOC_CTX *tmp_ctx = talloc_new(module);
77 msg = imessaging_client_init(tmp_ctx, lp_ctx,
78 ldb_get_event_context(ldb));
80 ldb_asprintf_errstring(ldb_module_get_ctx(module),
81 "Failed to send MSG_DREPL_ALLOCATE_RID, "
82 "unable init client messaging context");
83 DEBUG(3,(__location__ ": Failed to create messaging context\n"));
85 return LDB_ERR_UNWILLING_TO_PERFORM;
88 server = irpc_servers_byname(msg, msg, "dreplsrv");
90 ldb_asprintf_errstring(ldb_module_get_ctx(module),
91 "Failed to send MSG_DREPL_ALLOCATE_RID, "
92 "unable to locate dreplsrv");
93 /* this means the drepl service is not running */
95 return LDB_ERR_UNWILLING_TO_PERFORM;
98 status = imessaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);
100 /* Only error out if an error happened, not on STATUS_MORE_ENTRIES, ie a delayed message */
101 if (NT_STATUS_IS_ERR(status)) {
102 ldb_asprintf_errstring(ldb_module_get_ctx(module),
103 "Failed to send MSG_DREPL_ALLOCATE_RID to dreplsrv at %s: %s",
104 server_id_str(tmp_ctx, server), nt_errstr(status));
105 talloc_free(tmp_ctx);
106 return LDB_ERR_UNWILLING_TO_PERFORM;
109 talloc_free(tmp_ctx);
114 static const char * const ridalloc_ridset_attrs[] = {
116 "rIDPreviousAllocationPool",
122 struct ridalloc_ridset_values {
129 static void ridalloc_get_ridset_values(struct ldb_message *msg, struct ridalloc_ridset_values *v)
131 v->alloc_pool = ldb_msg_find_attr_as_uint64(msg, "rIDAllocationPool", UINT64_MAX);
132 v->prev_pool = ldb_msg_find_attr_as_uint64(msg, "rIDPreviousAllocationPool", UINT64_MAX);
133 v->next_rid = ldb_msg_find_attr_as_uint(msg, "rIDNextRID", UINT32_MAX);
134 v->used_pool = ldb_msg_find_attr_as_uint(msg, "rIDUsedPool", UINT32_MAX);
137 static int ridalloc_set_ridset_values(struct ldb_module *module,
138 struct ldb_message *msg,
139 const struct ridalloc_ridset_values *o,
140 const struct ridalloc_ridset_values *n)
142 const uint32_t *o32, *n32;
143 const uint64_t *o64, *n64;
146 #define SETUP_PTRS(field, optr, nptr, max) do { \
149 if (o->field == max) { \
152 if (n->field == max) { \
155 if (o->field == n->field) { \
161 SETUP_PTRS(alloc_pool, o64, n64, UINT64_MAX);
162 ret = dsdb_msg_constrainted_update_uint64(module, msg,
165 if (ret != LDB_SUCCESS) {
169 SETUP_PTRS(prev_pool, o64, n64, UINT64_MAX);
170 ret = dsdb_msg_constrainted_update_uint64(module, msg,
171 "rIDPreviousAllocationPool",
173 if (ret != LDB_SUCCESS) {
177 SETUP_PTRS(next_rid, o32, n32, UINT32_MAX);
178 ret = dsdb_msg_constrainted_update_uint32(module, msg,
181 if (ret != LDB_SUCCESS) {
185 SETUP_PTRS(used_pool, o32, n32, UINT32_MAX);
186 ret = dsdb_msg_constrainted_update_uint32(module, msg,
189 if (ret != LDB_SUCCESS) {
198 allocate a new range of RIDs in the RID Manager object
200 static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool,
201 struct ldb_request *parent)
204 TALLOC_CTX *tmp_ctx = talloc_new(module);
205 const char *attrs[] = { "rIDAvailablePool", NULL };
206 uint64_t rid_pool, new_rid_pool, dc_pool;
207 uint32_t rid_pool_lo, rid_pool_hi;
208 struct ldb_result *res;
209 struct ldb_context *ldb = ldb_module_get_ctx(module);
210 const unsigned alloc_size = 500;
212 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
213 attrs, DSDB_FLAG_NEXT_MODULE, parent);
214 if (ret != LDB_SUCCESS) {
215 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
216 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
217 talloc_free(tmp_ctx);
221 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
222 rid_pool_lo = rid_pool & 0xFFFFFFFF;
223 rid_pool_hi = rid_pool >> 32;
224 if (rid_pool_lo >= rid_pool_hi) {
225 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
226 rid_pool_lo, rid_pool_hi);
227 talloc_free(tmp_ctx);
231 /* lower part of new pool is the low part of the rIDAvailablePool */
232 dc_pool = rid_pool_lo;
234 /* allocate 500 RIDs to this DC */
235 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
237 /* work out upper part of new pool */
238 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
240 /* and new rIDAvailablePool value */
241 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
243 ret = dsdb_module_constrainted_update_uint64(module, rid_manager_dn, "rIDAvailablePool",
244 &rid_pool, &new_rid_pool, parent);
245 if (ret != LDB_SUCCESS) {
246 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
248 talloc_free(tmp_ctx);
252 (*new_pool) = dc_pool;
253 talloc_free(tmp_ctx);
258 create a RID Set object for the specified DC
260 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
261 struct ldb_dn *rid_manager_dn,
262 struct ldb_dn *ntds_dn, struct ldb_dn **dn,
263 struct ldb_request *parent)
265 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
266 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
268 struct ldb_message *msg;
269 struct ldb_context *ldb = ldb_module_get_ctx(module);
270 static const struct ridalloc_ridset_values o = {
271 .alloc_pool = UINT64_MAX,
272 .prev_pool = UINT64_MAX,
273 .next_rid = UINT32_MAX,
274 .used_pool = UINT32_MAX,
276 struct ridalloc_ridset_values n = {
282 const char *no_attrs[] = { NULL };
283 struct ldb_result *res;
288 find the machine object for the DC
289 construct the RID Set DN
290 load rIDAvailablePool to find next available set
291 modify RID Manager object to update rIDAvailablePool
292 add the RID Set object
293 link to the RID Set object in machine object
296 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
298 talloc_free(tmp_ctx);
299 return ldb_module_oom(module);
302 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
303 if (ret != LDB_SUCCESS) {
304 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
305 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
306 talloc_free(tmp_ctx);
310 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
311 if (rid_set_dn == NULL) {
312 talloc_free(tmp_ctx);
313 return ldb_module_oom(module);
316 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
317 talloc_free(tmp_ctx);
318 return ldb_module_oom(module);
321 /* grab a pool from the RID Manager object */
322 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent);
323 if (ret != LDB_SUCCESS) {
324 talloc_free(tmp_ctx);
328 /* create the RID Set object */
329 msg = ldb_msg_new(tmp_ctx);
330 msg->dn = rid_set_dn;
332 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
333 if (ret != LDB_SUCCESS) {
334 talloc_free(tmp_ctx);
338 ret = ridalloc_set_ridset_values(module, msg, &o, &n);
339 if (ret != LDB_SUCCESS) {
340 talloc_free(tmp_ctx);
344 /* we need this to go all the way to the top of the module
345 * stack, as we need all the extra attributes added (including
346 * complex ones like ntsecuritydescriptor) */
347 ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent);
348 if (ret != LDB_SUCCESS) {
349 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
350 ldb_dn_get_linearized(msg->dn),
352 talloc_free(tmp_ctx);
356 /* add the rIDSetReferences link */
357 msg = ldb_msg_new(tmp_ctx);
358 msg->dn = machine_dn;
360 /* we need the extended DN of the RID Set object for
361 * rIDSetReferences */
362 ret = dsdb_module_search_dn(module, msg, &res, rid_set_dn, no_attrs,
363 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, parent);
364 if (ret != LDB_SUCCESS) {
365 ldb_asprintf_errstring(ldb, "Failed to find extended DN of RID Set %s - %s",
366 ldb_dn_get_linearized(msg->dn),
368 talloc_free(tmp_ctx);
371 rid_set_dn = res->msgs[0]->dn;
374 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_extended_linearized(msg, rid_set_dn, 1));
375 if (ret != LDB_SUCCESS) {
376 talloc_free(tmp_ctx);
379 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
381 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
382 if (ret != LDB_SUCCESS) {
383 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
384 ldb_dn_get_linearized(msg->dn),
386 talloc_free(tmp_ctx);
390 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
392 talloc_free(tmp_ctx);
398 create a RID Set object for this DC
400 static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
401 struct ldb_dn **dn, struct ldb_request *parent)
403 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
404 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
406 struct ldb_context *ldb = ldb_module_get_ctx(module);
407 struct GUID fsmo_role_guid;
408 const struct GUID *our_ntds_guid;
411 /* work out who is the RID Manager */
412 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
413 if (ret != LDB_SUCCESS) {
414 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
416 talloc_free(tmp_ctx);
420 /* find the DN of the RID Manager */
421 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
422 if (ret != LDB_SUCCESS) {
423 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
425 talloc_free(tmp_ctx);
429 status = dsdb_get_extended_dn_guid(fsmo_role_dn, &fsmo_role_guid, "GUID");
430 if (!NT_STATUS_IS_OK(status)) {
431 talloc_free(tmp_ctx);
432 return ldb_operr(ldb_module_get_ctx(module));
435 our_ntds_guid = samdb_ntds_objectGUID(ldb_module_get_ctx(module));
436 if (!our_ntds_guid) {
437 talloc_free(tmp_ctx);
438 return ldb_operr(ldb_module_get_ctx(module));
441 if (!GUID_equal(&fsmo_role_guid, our_ntds_guid)) {
442 ret = ridalloc_poke_rid_manager(module);
443 if (ret != LDB_SUCCESS) {
444 ldb_asprintf_errstring(ldb,
445 "Request for remote creation of "
446 "RID Set for this DC failed: %s",
449 ldb_asprintf_errstring(ldb,
450 "Remote RID Set creation needed");
452 talloc_free(tmp_ctx);
453 return LDB_ERR_UNWILLING_TO_PERFORM;
456 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent);
457 talloc_free(tmp_ctx);
462 get a new RID pool for ourselves
463 also returns the first rid for the new pool
465 static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
467 TALLOC_CTX *tmp_ctx = talloc_new(module);
468 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
470 struct ldb_context *ldb = ldb_module_get_ctx(module);
473 /* work out who is the RID Manager */
474 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
475 if (ret != LDB_SUCCESS) {
476 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
478 talloc_free(tmp_ctx);
482 /* find the DN of the RID Manager */
483 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
484 if (ret != LDB_SUCCESS) {
485 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
487 talloc_free(tmp_ctx);
491 ret = samdb_dn_is_our_ntdsa(ldb, fsmo_role_dn, &is_us);
492 if (ret != LDB_SUCCESS) {
493 ldb_asprintf_errstring(ldb, "Failed to confirm if our ntdsDsa is %s: %s",
494 ldb_dn_get_linearized(fsmo_role_dn), ldb_errstring(ldb));
495 talloc_free(tmp_ctx);
500 ret = ridalloc_poke_rid_manager(module);
501 if (ret != LDB_SUCCESS) {
502 ldb_asprintf_errstring(ldb, "Request for remote refresh of RID Set allocation failed: %s",
505 ldb_asprintf_errstring(ldb, "Remote RID Set refresh needed");
507 talloc_free(tmp_ctx);
508 return LDB_ERR_UNWILLING_TO_PERFORM;
511 /* grab a pool from the RID Manager object */
512 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool, parent);
513 if (ret != LDB_SUCCESS) {
514 talloc_free(tmp_ctx);
518 talloc_free(tmp_ctx);
523 /* allocate a RID using our RID Set
524 If we run out of RIDs then allocate a new pool
525 either locally or by contacting the RID Manager
527 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_request *parent)
529 struct ldb_context *ldb;
531 struct ldb_dn *rid_set_dn;
532 struct ldb_result *res;
533 struct ldb_message *msg;
534 struct ridalloc_ridset_values oridset;
535 struct ridalloc_ridset_values nridset;
536 uint32_t prev_pool_lo, prev_pool_hi;
537 TALLOC_CTX *tmp_ctx = talloc_new(module);
540 ldb = ldb_module_get_ctx(module);
542 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
543 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
544 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn, parent);
546 if (ret != LDB_SUCCESS) {
547 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
549 talloc_free(tmp_ctx);
553 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
554 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
555 if (ret != LDB_SUCCESS) {
556 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
557 ldb_dn_get_linearized(rid_set_dn));
558 talloc_free(tmp_ctx);
562 ridalloc_get_ridset_values(res->msgs[0], &oridset);
563 if (oridset.alloc_pool == UINT64_MAX) {
564 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
565 ldb_dn_get_linearized(rid_set_dn));
566 talloc_free(tmp_ctx);
567 return LDB_ERR_OPERATIONS_ERROR;
573 * If we never used a pool, setup out first pool
575 if (nridset.prev_pool == UINT64_MAX ||
576 nridset.next_rid == UINT32_MAX) {
577 nridset.prev_pool = nridset.alloc_pool;
578 nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
582 * Now check if our current pool is still usable
584 nridset.next_rid += 1;
585 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
586 prev_pool_hi = nridset.prev_pool >> 32;
587 if (nridset.next_rid > prev_pool_hi) {
589 * We need a new pool, check if we already have a new one
590 * Otherwise we need to get a new pool.
592 if (nridset.alloc_pool == nridset.prev_pool) {
594 * if we are the RID Manager,
595 * we can get a new pool localy.
596 * Otherwise we fail the operation and
597 * ask async for a new pool.
599 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
600 if (ret != LDB_SUCCESS) {
601 ldb_asprintf_errstring(ldb, "NO RID values available: %s",
603 talloc_free(tmp_ctx);
609 * increment the rIDUsedPool attribute
611 * Note: w2k8r2 doesn't update this attribute,
612 * at least if it's itself the rid master.
614 nridset.used_pool += 1;
616 /* now use the new pool */
617 nridset.prev_pool = nridset.alloc_pool;
618 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
619 prev_pool_hi = nridset.prev_pool >> 32;
620 nridset.next_rid = prev_pool_lo;
623 if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
624 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
625 (unsigned)nridset.next_rid,
626 (unsigned)prev_pool_lo,
627 (unsigned)prev_pool_hi);
628 talloc_free(tmp_ctx);
629 return LDB_ERR_OPERATIONS_ERROR;
633 * if we are half-exhausted then try to get a new pool.
635 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2 &&
636 nridset.alloc_pool == nridset.prev_pool) {
638 * if we are the RID Manager,
639 * we can get a new pool localy.
640 * Otherwise we fail the operation and
641 * ask async for a new pool.
643 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
644 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
645 ldb_reset_err_string(ldb);
648 if (ret != LDB_SUCCESS) {
649 talloc_free(tmp_ctx);
657 msg = ldb_msg_new(tmp_ctx);
659 return ldb_module_oom(module);
661 msg->dn = rid_set_dn;
663 ret = ridalloc_set_ridset_values(module, msg,
665 if (ret != LDB_SUCCESS) {
666 talloc_free(tmp_ctx);
670 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
671 if (ret != LDB_SUCCESS) {
672 talloc_free(tmp_ctx);
676 talloc_free(tmp_ctx);
677 *rid = nridset.next_rid;
683 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
685 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
686 struct ldb_request *parent)
688 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
689 struct ldb_dn *rid_manager_dn;
690 TALLOC_CTX *tmp_ctx = talloc_new(module);
692 struct ldb_context *ldb = ldb_module_get_ctx(module);
693 struct ldb_result *res;
694 struct ldb_message *msg;
695 struct ridalloc_ridset_values oridset, nridset;
697 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn, parent);
698 if (ret != LDB_SUCCESS) {
699 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
700 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
701 talloc_free(tmp_ctx);
705 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
707 talloc_free(tmp_ctx);
708 return ldb_module_oom(module);
711 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
712 if (ret != LDB_SUCCESS) {
713 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
714 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
715 talloc_free(tmp_ctx);
719 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
720 if (ret != LDB_SUCCESS) {
721 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
723 talloc_free(tmp_ctx);
727 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn, parent);
728 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
729 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn, parent);
730 talloc_free(tmp_ctx);
734 if (ret != LDB_SUCCESS) {
735 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
736 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
737 talloc_free(tmp_ctx);
741 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
742 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
743 if (ret != LDB_SUCCESS) {
744 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
745 ldb_dn_get_linearized(rid_set_dn));
746 talloc_free(tmp_ctx);
750 ridalloc_get_ridset_values(res->msgs[0], &oridset);
751 if (oridset.alloc_pool == UINT64_MAX) {
752 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
753 ldb_dn_get_linearized(rid_set_dn));
754 talloc_free(tmp_ctx);
755 return LDB_ERR_OPERATIONS_ERROR;
760 if (exop->fsmo_info != 0) {
762 if (nridset.alloc_pool != exop->fsmo_info) {
763 /* it has already been updated */
764 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
765 (unsigned long long)exop->fsmo_info,
766 (unsigned long long)nridset.alloc_pool));
767 talloc_free(tmp_ctx);
772 /* grab a pool from the RID Manager object */
773 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &nridset.alloc_pool, parent);
774 if (ret != LDB_SUCCESS) {
775 talloc_free(tmp_ctx);
782 msg = ldb_msg_new(tmp_ctx);
784 return ldb_module_oom(module);
786 msg->dn = rid_set_dn;
788 ret = ridalloc_set_ridset_values(module, msg,
790 if (ret != LDB_SUCCESS) {
791 talloc_free(tmp_ctx);
795 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
796 if (ret != LDB_SUCCESS) {
797 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
798 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
799 talloc_free(tmp_ctx);
803 talloc_free(tmp_ctx);