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 "lib/util/server_id.h"
33 #include "dsdb/samdb/samdb.h"
34 #include "dsdb/samdb/ldb_modules/util.h"
35 #include "lib/messaging/irpc.h"
36 #include "param/param.h"
37 #include "librpc/gen_ndr/ndr_misc.h"
38 #include "dsdb/samdb/ldb_modules/ridalloc.h"
41 Note: the RID allocation attributes in AD are very badly named. Here
42 is what we think they really do:
45 - rIDPreviousAllocationPool: the pool which a DC is currently
46 pulling RIDs from. Managed by client DC
48 - rIDAllocationPool: the pool that the DC will switch to next,
49 when rIDPreviousAllocationPool is exhausted. Managed by RID Manager.
51 - rIDNextRID: the last RID allocated by this DC. Managed by client DC
53 in RID Manager object:
54 - rIDAvailablePool: the pool where the RID Manager gets new rID
55 pools from when it gets a EXOP_RID_ALLOC getncchanges call (or
56 locally when the DC is the RID Manager)
61 make a IRPC call to the drepl task to ask it to get the RID
62 Manager to give us another RID pool.
64 This function just sends the message to the drepl task then
65 returns immediately. It should be called well before we
66 completely run out of RIDs
68 static int ridalloc_poke_rid_manager(struct ldb_module *module)
70 struct imessaging_context *msg;
72 struct server_id *servers;
73 struct ldb_context *ldb = ldb_module_get_ctx(module);
74 struct loadparm_context *lp_ctx =
75 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
76 TALLOC_CTX *tmp_ctx = talloc_new(module);
79 msg = imessaging_client_init(tmp_ctx, lp_ctx,
80 ldb_get_event_context(ldb));
82 ldb_asprintf_errstring(ldb_module_get_ctx(module),
83 "Failed to send MSG_DREPL_ALLOCATE_RID, "
84 "unable init client messaging context");
85 DEBUG(3,(__location__ ": Failed to create messaging context\n"));
87 return LDB_ERR_UNWILLING_TO_PERFORM;
90 status = irpc_servers_byname(msg, msg, "dreplsrv",
91 &num_servers, &servers);
92 if (!NT_STATUS_IS_OK(status)) {
93 ldb_asprintf_errstring(ldb_module_get_ctx(module),
94 "Failed to send MSG_DREPL_ALLOCATE_RID, "
95 "unable to locate dreplsrv");
96 /* this means the drepl service is not running */
98 return LDB_ERR_UNWILLING_TO_PERFORM;
101 status = imessaging_send(msg, servers[0], MSG_DREPL_ALLOCATE_RID, NULL);
103 /* Only error out if an error happened, not on STATUS_MORE_ENTRIES, ie a delayed message */
104 if (NT_STATUS_IS_ERR(status)) {
105 struct server_id_buf idbuf;
106 ldb_asprintf_errstring(ldb_module_get_ctx(module),
107 "Failed to send MSG_DREPL_ALLOCATE_RID to dreplsrv at %s: %s",
108 server_id_str_buf(*servers, &idbuf),
110 talloc_free(tmp_ctx);
111 return LDB_ERR_UNWILLING_TO_PERFORM;
114 talloc_free(tmp_ctx);
119 static const char * const ridalloc_ridset_attrs[] = {
121 "rIDPreviousAllocationPool",
127 struct ridalloc_ridset_values {
134 static void ridalloc_get_ridset_values(struct ldb_message *msg, struct ridalloc_ridset_values *v)
136 v->alloc_pool = ldb_msg_find_attr_as_uint64(msg, "rIDAllocationPool", UINT64_MAX);
137 v->prev_pool = ldb_msg_find_attr_as_uint64(msg, "rIDPreviousAllocationPool", UINT64_MAX);
138 v->next_rid = ldb_msg_find_attr_as_uint(msg, "rIDNextRID", UINT32_MAX);
139 v->used_pool = ldb_msg_find_attr_as_uint(msg, "rIDUsedPool", UINT32_MAX);
142 static int ridalloc_set_ridset_values(struct ldb_module *module,
143 struct ldb_message *msg,
144 const struct ridalloc_ridset_values *o,
145 const struct ridalloc_ridset_values *n)
147 const uint32_t *o32, *n32;
148 const uint64_t *o64, *n64;
151 #define SETUP_PTRS(field, optr, nptr, max) do { \
154 if (o->field == max) { \
157 if (n->field == max) { \
160 if (o->field == n->field) { \
166 SETUP_PTRS(alloc_pool, o64, n64, UINT64_MAX);
167 ret = dsdb_msg_constrainted_update_uint64(module, msg,
170 if (ret != LDB_SUCCESS) {
174 SETUP_PTRS(prev_pool, o64, n64, UINT64_MAX);
175 ret = dsdb_msg_constrainted_update_uint64(module, msg,
176 "rIDPreviousAllocationPool",
178 if (ret != LDB_SUCCESS) {
182 SETUP_PTRS(next_rid, o32, n32, UINT32_MAX);
183 ret = dsdb_msg_constrainted_update_uint32(module, msg,
186 if (ret != LDB_SUCCESS) {
190 SETUP_PTRS(used_pool, o32, n32, UINT32_MAX);
191 ret = dsdb_msg_constrainted_update_uint32(module, msg,
194 if (ret != LDB_SUCCESS) {
203 allocate a new range of RIDs in the RID Manager object
205 static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool,
206 struct ldb_request *parent)
209 TALLOC_CTX *tmp_ctx = talloc_new(module);
210 const char *attrs[] = { "rIDAvailablePool", NULL };
211 uint64_t rid_pool, new_rid_pool, dc_pool;
212 uint32_t rid_pool_lo, rid_pool_hi;
213 struct ldb_result *res;
214 struct ldb_context *ldb = ldb_module_get_ctx(module);
215 const unsigned alloc_size = 500;
217 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
218 attrs, DSDB_FLAG_NEXT_MODULE, parent);
219 if (ret != LDB_SUCCESS) {
220 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
221 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
222 talloc_free(tmp_ctx);
226 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
227 rid_pool_lo = rid_pool & 0xFFFFFFFF;
228 rid_pool_hi = rid_pool >> 32;
229 if (rid_pool_lo >= rid_pool_hi) {
230 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
231 rid_pool_lo, rid_pool_hi);
232 talloc_free(tmp_ctx);
236 /* lower part of new pool is the low part of the rIDAvailablePool */
237 dc_pool = rid_pool_lo;
239 /* allocate 500 RIDs to this DC */
240 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
242 /* work out upper part of new pool */
243 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
245 /* and new rIDAvailablePool value */
246 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
248 ret = dsdb_module_constrainted_update_uint64(module, rid_manager_dn, "rIDAvailablePool",
249 &rid_pool, &new_rid_pool, parent);
250 if (ret != LDB_SUCCESS) {
251 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
253 talloc_free(tmp_ctx);
257 (*new_pool) = dc_pool;
258 talloc_free(tmp_ctx);
263 create a RID Set object for the specified DC
265 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
266 struct ldb_dn *rid_manager_dn,
267 struct ldb_dn *ntds_dn, struct ldb_dn **dn,
268 struct ldb_request *parent)
270 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
271 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
273 struct ldb_message *msg;
274 struct ldb_context *ldb = ldb_module_get_ctx(module);
275 static const struct ridalloc_ridset_values o = {
276 .alloc_pool = UINT64_MAX,
277 .prev_pool = UINT64_MAX,
278 .next_rid = UINT32_MAX,
279 .used_pool = UINT32_MAX,
281 struct ridalloc_ridset_values n = {
287 const char *no_attrs[] = { NULL };
288 struct ldb_result *res;
293 find the machine object for the DC
294 construct the RID Set DN
295 load rIDAvailablePool to find next available set
296 modify RID Manager object to update rIDAvailablePool
297 add the RID Set object
298 link to the RID Set object in machine object
301 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
303 talloc_free(tmp_ctx);
304 return ldb_module_oom(module);
307 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
308 if (ret != LDB_SUCCESS) {
309 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
310 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
311 talloc_free(tmp_ctx);
315 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
316 if (rid_set_dn == NULL) {
317 talloc_free(tmp_ctx);
318 return ldb_module_oom(module);
321 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
322 talloc_free(tmp_ctx);
323 return ldb_module_oom(module);
326 /* grab a pool from the RID Manager object */
327 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent);
328 if (ret != LDB_SUCCESS) {
329 talloc_free(tmp_ctx);
333 /* create the RID Set object */
334 msg = ldb_msg_new(tmp_ctx);
335 msg->dn = rid_set_dn;
337 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
338 if (ret != LDB_SUCCESS) {
339 talloc_free(tmp_ctx);
343 ret = ridalloc_set_ridset_values(module, msg, &o, &n);
344 if (ret != LDB_SUCCESS) {
345 talloc_free(tmp_ctx);
349 /* we need this to go all the way to the top of the module
350 * stack, as we need all the extra attributes added (including
351 * complex ones like ntsecuritydescriptor). We must do this
352 * as system, otherwise a user might end up owning the RID
353 * set, and that would be bad... */
354 ret = dsdb_module_add(module, msg,
355 DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM
356 | DSDB_MODIFY_RELAX, parent);
357 if (ret != LDB_SUCCESS) {
358 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
359 ldb_dn_get_linearized(msg->dn),
361 talloc_free(tmp_ctx);
365 /* add the rIDSetReferences link */
366 msg = ldb_msg_new(tmp_ctx);
367 msg->dn = machine_dn;
369 /* we need the extended DN of the RID Set object for
370 * rIDSetReferences */
371 ret = dsdb_module_search_dn(module, msg, &res, rid_set_dn, no_attrs,
372 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, parent);
373 if (ret != LDB_SUCCESS) {
374 ldb_asprintf_errstring(ldb, "Failed to find extended DN of RID Set %s - %s",
375 ldb_dn_get_linearized(msg->dn),
377 talloc_free(tmp_ctx);
380 rid_set_dn = res->msgs[0]->dn;
383 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_extended_linearized(msg, rid_set_dn, 1));
384 if (ret != LDB_SUCCESS) {
385 talloc_free(tmp_ctx);
388 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
390 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
391 if (ret != LDB_SUCCESS) {
392 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
393 ldb_dn_get_linearized(msg->dn),
395 talloc_free(tmp_ctx);
399 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
401 talloc_free(tmp_ctx);
407 create a RID Set object for this DC
409 int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
410 struct ldb_dn **dn, struct ldb_request *parent)
412 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
413 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
415 struct ldb_context *ldb = ldb_module_get_ctx(module);
416 struct GUID fsmo_role_guid;
417 const struct GUID *our_ntds_guid;
420 /* work out who is the RID Manager */
421 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
422 if (ret != LDB_SUCCESS) {
423 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
425 talloc_free(tmp_ctx);
429 /* find the DN of the RID Manager */
430 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
431 if (ret != LDB_SUCCESS) {
432 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
434 talloc_free(tmp_ctx);
438 status = dsdb_get_extended_dn_guid(fsmo_role_dn, &fsmo_role_guid, "GUID");
439 if (!NT_STATUS_IS_OK(status)) {
440 talloc_free(tmp_ctx);
441 return ldb_operr(ldb_module_get_ctx(module));
444 our_ntds_guid = samdb_ntds_objectGUID(ldb_module_get_ctx(module));
445 if (!our_ntds_guid) {
446 talloc_free(tmp_ctx);
447 return ldb_operr(ldb_module_get_ctx(module));
450 if (!GUID_equal(&fsmo_role_guid, our_ntds_guid)) {
451 ret = ridalloc_poke_rid_manager(module);
452 if (ret != LDB_SUCCESS) {
453 ldb_asprintf_errstring(ldb,
454 "Request for remote creation of "
455 "RID Set for this DC failed: %s",
458 ldb_asprintf_errstring(ldb,
459 "Remote RID Set creation needed");
461 talloc_free(tmp_ctx);
462 return LDB_ERR_UNWILLING_TO_PERFORM;
465 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent);
466 talloc_free(tmp_ctx);
471 get a new RID pool for ourselves
472 also returns the first rid for the new pool
475 int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
477 TALLOC_CTX *tmp_ctx = talloc_new(module);
478 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
480 struct ldb_context *ldb = ldb_module_get_ctx(module);
483 /* work out who is the RID Manager */
484 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
485 if (ret != LDB_SUCCESS) {
486 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
488 talloc_free(tmp_ctx);
492 /* find the DN of the RID Manager */
493 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
494 if (ret != LDB_SUCCESS) {
495 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
497 talloc_free(tmp_ctx);
501 ret = samdb_dn_is_our_ntdsa(ldb, fsmo_role_dn, &is_us);
502 if (ret != LDB_SUCCESS) {
503 ldb_asprintf_errstring(ldb, "Failed to confirm if our ntdsDsa is %s: %s",
504 ldb_dn_get_linearized(fsmo_role_dn), ldb_errstring(ldb));
505 talloc_free(tmp_ctx);
510 ret = ridalloc_poke_rid_manager(module);
511 if (ret != LDB_SUCCESS) {
512 ldb_asprintf_errstring(ldb, "Request for remote refresh of RID Set allocation failed: %s",
515 ldb_asprintf_errstring(ldb, "Remote RID Set refresh needed");
517 talloc_free(tmp_ctx);
518 return LDB_ERR_UNWILLING_TO_PERFORM;
521 /* grab a pool from the RID Manager object */
522 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool, parent);
523 if (ret != LDB_SUCCESS) {
524 talloc_free(tmp_ctx);
528 talloc_free(tmp_ctx);
533 /* allocate a RID using our RID Set
534 If we run out of RIDs then allocate a new pool
535 either locally or by contacting the RID Manager
537 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_request *parent)
539 struct ldb_context *ldb;
541 struct ldb_dn *rid_set_dn;
542 struct ldb_result *res;
543 struct ldb_message *msg;
544 struct ridalloc_ridset_values oridset;
545 struct ridalloc_ridset_values nridset;
546 uint32_t prev_pool_lo, prev_pool_hi;
547 TALLOC_CTX *tmp_ctx = talloc_new(module);
550 ldb = ldb_module_get_ctx(module);
552 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
553 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
554 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn, parent);
556 if (ret != LDB_SUCCESS) {
557 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
559 talloc_free(tmp_ctx);
563 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
564 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
565 if (ret != LDB_SUCCESS) {
566 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
567 ldb_dn_get_linearized(rid_set_dn));
568 talloc_free(tmp_ctx);
572 ridalloc_get_ridset_values(res->msgs[0], &oridset);
573 if (oridset.alloc_pool == UINT64_MAX) {
574 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
575 ldb_dn_get_linearized(rid_set_dn));
576 talloc_free(tmp_ctx);
577 return LDB_ERR_OPERATIONS_ERROR;
583 * If we never used a pool, setup out first pool
585 if (nridset.prev_pool == UINT64_MAX ||
586 nridset.next_rid == UINT32_MAX) {
587 nridset.prev_pool = nridset.alloc_pool;
588 nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
592 * Now check if our current pool is still usable
594 nridset.next_rid += 1;
595 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
596 prev_pool_hi = nridset.prev_pool >> 32;
597 if (nridset.next_rid > prev_pool_hi) {
599 * We need a new pool, check if we already have a new one
600 * Otherwise we need to get a new pool.
602 if (nridset.alloc_pool == nridset.prev_pool) {
604 * if we are the RID Manager,
605 * we can get a new pool localy.
606 * Otherwise we fail the operation and
607 * ask async for a new pool.
609 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
610 if (ret != LDB_SUCCESS) {
611 ldb_asprintf_errstring(ldb, "NO RID values available: %s",
613 talloc_free(tmp_ctx);
619 * increment the rIDUsedPool attribute
621 * Note: w2k8r2 doesn't update this attribute,
622 * at least if it's itself the rid master.
624 nridset.used_pool += 1;
626 /* now use the new pool */
627 nridset.prev_pool = nridset.alloc_pool;
628 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
629 prev_pool_hi = nridset.prev_pool >> 32;
630 nridset.next_rid = prev_pool_lo;
633 if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
634 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
635 (unsigned)nridset.next_rid,
636 (unsigned)prev_pool_lo,
637 (unsigned)prev_pool_hi);
638 talloc_free(tmp_ctx);
639 return LDB_ERR_OPERATIONS_ERROR;
643 * if we are half-exhausted then try to get a new pool.
645 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2 &&
646 nridset.alloc_pool == nridset.prev_pool) {
648 * if we are the RID Manager,
649 * we can get a new pool localy.
650 * Otherwise we fail the operation and
651 * ask async for a new pool.
653 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
654 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
655 ldb_reset_err_string(ldb);
658 if (ret != LDB_SUCCESS) {
659 talloc_free(tmp_ctx);
667 msg = ldb_msg_new(tmp_ctx);
669 return ldb_module_oom(module);
671 msg->dn = rid_set_dn;
673 ret = ridalloc_set_ridset_values(module, msg,
675 if (ret != LDB_SUCCESS) {
676 talloc_free(tmp_ctx);
680 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
681 if (ret != LDB_SUCCESS) {
682 talloc_free(tmp_ctx);
686 talloc_free(tmp_ctx);
687 *rid = nridset.next_rid;
693 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
695 This is for the DRS server to allocate a RID Pool for another server.
697 Called by another server over DRS (which calls this extended
698 operation), it runs on the RID Manager only.
700 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
701 struct ldb_request *parent)
703 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
704 struct ldb_dn *rid_manager_dn;
705 TALLOC_CTX *tmp_ctx = talloc_new(module);
707 struct ldb_context *ldb = ldb_module_get_ctx(module);
708 struct ldb_result *res;
709 struct ldb_message *msg;
710 struct ridalloc_ridset_values oridset, nridset;
712 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn, parent);
713 if (ret != LDB_SUCCESS) {
714 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
715 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
716 talloc_free(tmp_ctx);
720 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
722 talloc_free(tmp_ctx);
723 return ldb_module_oom(module);
726 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
727 if (ret != LDB_SUCCESS) {
728 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
729 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
730 talloc_free(tmp_ctx);
734 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
735 if (ret != LDB_SUCCESS) {
736 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
738 talloc_free(tmp_ctx);
742 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn, parent);
743 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
744 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn, parent);
745 talloc_free(tmp_ctx);
749 if (ret != LDB_SUCCESS) {
750 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
751 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
752 talloc_free(tmp_ctx);
756 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
757 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
758 if (ret != LDB_SUCCESS) {
759 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
760 ldb_dn_get_linearized(rid_set_dn));
761 talloc_free(tmp_ctx);
765 ridalloc_get_ridset_values(res->msgs[0], &oridset);
766 if (oridset.alloc_pool == UINT64_MAX) {
767 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
768 ldb_dn_get_linearized(rid_set_dn));
769 talloc_free(tmp_ctx);
770 return LDB_ERR_OPERATIONS_ERROR;
775 if (exop->fsmo_info != 0) {
777 if (nridset.alloc_pool != exop->fsmo_info) {
778 /* it has already been updated */
779 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
780 (unsigned long long)exop->fsmo_info,
781 (unsigned long long)nridset.alloc_pool));
782 talloc_free(tmp_ctx);
787 /* grab a pool from the RID Manager object */
788 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &nridset.alloc_pool, parent);
789 if (ret != LDB_SUCCESS) {
790 talloc_free(tmp_ctx);
797 msg = ldb_msg_new(tmp_ctx);
799 return ldb_module_oom(module);
801 msg->dn = rid_set_dn;
803 ret = ridalloc_set_ridset_values(module, msg,
805 if (ret != LDB_SUCCESS) {
806 talloc_free(tmp_ctx);
810 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
811 if (ret != LDB_SUCCESS) {
812 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
813 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
814 talloc_free(tmp_ctx);
818 talloc_free(tmp_ctx);