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 void 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);
76 msg = imessaging_client_init(tmp_ctx, lpcfg_imessaging_path(tmp_ctx, lp_ctx),
77 ldb_get_event_context(ldb));
79 DEBUG(3,(__location__ ": Failed to create messaging context\n"));
84 server = irpc_servers_byname(msg, msg, "dreplsrv");
86 /* this means the drepl service is not running */
91 imessaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);
93 /* we don't care if the message got through */
98 static const char * const ridalloc_ridset_attrs[] = {
100 "rIDPreviousAllocationPool",
106 struct ridalloc_ridset_values {
113 static void ridalloc_get_ridset_values(struct ldb_message *msg, struct ridalloc_ridset_values *v)
115 v->alloc_pool = ldb_msg_find_attr_as_uint64(msg, "rIDAllocationPool", UINT64_MAX);
116 v->prev_pool = ldb_msg_find_attr_as_uint64(msg, "rIDPreviousAllocationPool", UINT64_MAX);
117 v->next_rid = ldb_msg_find_attr_as_uint(msg, "rIDNextRID", UINT32_MAX);
118 v->used_pool = ldb_msg_find_attr_as_uint(msg, "rIDUsedPool", UINT32_MAX);
121 static int ridalloc_set_ridset_values(struct ldb_module *module,
122 struct ldb_message *msg,
123 const struct ridalloc_ridset_values *o,
124 const struct ridalloc_ridset_values *n)
126 const uint32_t *o32, *n32;
127 const uint64_t *o64, *n64;
130 #define SETUP_PTRS(field, optr, nptr, max) do { \
133 if (o->field == max) { \
136 if (n->field == max) { \
139 if (o->field == n->field) { \
145 SETUP_PTRS(alloc_pool, o64, n64, UINT64_MAX);
146 ret = dsdb_msg_constrainted_update_uint64(module, msg,
149 if (ret != LDB_SUCCESS) {
153 SETUP_PTRS(prev_pool, o64, n64, UINT64_MAX);
154 ret = dsdb_msg_constrainted_update_uint64(module, msg,
155 "rIDPreviousAllocationPool",
157 if (ret != LDB_SUCCESS) {
161 SETUP_PTRS(next_rid, o32, n32, UINT32_MAX);
162 ret = dsdb_msg_constrainted_update_uint32(module, msg,
165 if (ret != LDB_SUCCESS) {
169 SETUP_PTRS(used_pool, o32, n32, UINT32_MAX);
170 ret = dsdb_msg_constrainted_update_uint32(module, msg,
173 if (ret != LDB_SUCCESS) {
182 allocate a new range of RIDs in the RID Manager object
184 static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool,
185 struct ldb_request *parent)
188 TALLOC_CTX *tmp_ctx = talloc_new(module);
189 const char *attrs[] = { "rIDAvailablePool", NULL };
190 uint64_t rid_pool, new_rid_pool, dc_pool;
191 uint32_t rid_pool_lo, rid_pool_hi;
192 struct ldb_result *res;
193 struct ldb_context *ldb = ldb_module_get_ctx(module);
194 const unsigned alloc_size = 500;
196 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
197 attrs, DSDB_FLAG_NEXT_MODULE, parent);
198 if (ret != LDB_SUCCESS) {
199 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
200 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
201 talloc_free(tmp_ctx);
205 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
206 rid_pool_lo = rid_pool & 0xFFFFFFFF;
207 rid_pool_hi = rid_pool >> 32;
208 if (rid_pool_lo >= rid_pool_hi) {
209 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
210 rid_pool_lo, rid_pool_hi);
211 talloc_free(tmp_ctx);
215 /* lower part of new pool is the low part of the rIDAvailablePool */
216 dc_pool = rid_pool_lo;
218 /* allocate 500 RIDs to this DC */
219 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
221 /* work out upper part of new pool */
222 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
224 /* and new rIDAvailablePool value */
225 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
227 ret = dsdb_module_constrainted_update_uint64(module, rid_manager_dn, "rIDAvailablePool",
228 &rid_pool, &new_rid_pool, parent);
229 if (ret != LDB_SUCCESS) {
230 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
232 talloc_free(tmp_ctx);
236 (*new_pool) = dc_pool;
237 talloc_free(tmp_ctx);
242 create a RID Set object for the specified DC
244 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
245 struct ldb_dn *rid_manager_dn,
246 struct ldb_dn *ntds_dn, struct ldb_dn **dn,
247 struct ldb_request *parent)
249 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
250 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
252 struct ldb_message *msg;
253 struct ldb_context *ldb = ldb_module_get_ctx(module);
254 static const struct ridalloc_ridset_values o = {
255 .alloc_pool = UINT64_MAX,
256 .prev_pool = UINT64_MAX,
257 .next_rid = UINT32_MAX,
258 .used_pool = UINT32_MAX,
260 struct ridalloc_ridset_values n = {
270 find the machine object for the DC
271 construct the RID Set DN
272 load rIDAvailablePool to find next available set
273 modify RID Manager object to update rIDAvailablePool
274 add the RID Set object
275 link to the RID Set object in machine object
278 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
280 talloc_free(tmp_ctx);
281 return ldb_module_oom(module);
284 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
285 if (ret != LDB_SUCCESS) {
286 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
287 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
288 talloc_free(tmp_ctx);
292 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
293 if (rid_set_dn == NULL) {
294 talloc_free(tmp_ctx);
295 return ldb_module_oom(module);
298 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
299 talloc_free(tmp_ctx);
300 return ldb_module_oom(module);
303 /* grab a pool from the RID Manager object */
304 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent);
305 if (ret != LDB_SUCCESS) {
306 talloc_free(tmp_ctx);
310 /* create the RID Set object */
311 msg = ldb_msg_new(tmp_ctx);
312 msg->dn = rid_set_dn;
314 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
315 if (ret != LDB_SUCCESS) {
316 talloc_free(tmp_ctx);
320 ret = ridalloc_set_ridset_values(module, msg, &o, &n);
321 if (ret != LDB_SUCCESS) {
322 talloc_free(tmp_ctx);
326 /* we need this to go all the way to the top of the module
327 * stack, as we need all the extra attributes added (including
328 * complex ones like ntsecuritydescriptor) */
329 ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent);
330 if (ret != LDB_SUCCESS) {
331 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
332 ldb_dn_get_linearized(msg->dn),
334 talloc_free(tmp_ctx);
338 /* add the rIDSetReferences link */
339 msg = ldb_msg_new(tmp_ctx);
340 msg->dn = machine_dn;
342 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
343 if (ret != LDB_SUCCESS) {
344 talloc_free(tmp_ctx);
347 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
349 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
350 if (ret != LDB_SUCCESS) {
351 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
352 ldb_dn_get_linearized(msg->dn),
354 talloc_free(tmp_ctx);
358 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
360 talloc_free(tmp_ctx);
366 create a RID Set object for this DC
368 static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
369 struct ldb_dn **dn, struct ldb_request *parent)
371 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
372 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
374 struct ldb_context *ldb = ldb_module_get_ctx(module);
376 /* work out who is the RID Manager */
377 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
378 if (ret != LDB_SUCCESS) {
379 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
381 talloc_free(tmp_ctx);
385 /* find the DN of the RID Manager */
386 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
387 if (ret != LDB_SUCCESS) {
388 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
390 talloc_free(tmp_ctx);
394 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
395 ridalloc_poke_rid_manager(module);
396 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
397 talloc_free(tmp_ctx);
398 return LDB_ERR_UNWILLING_TO_PERFORM;
401 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent);
402 talloc_free(tmp_ctx);
407 get a new RID pool for ourselves
408 also returns the first rid for the new pool
410 static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
412 TALLOC_CTX *tmp_ctx = talloc_new(module);
413 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
415 struct ldb_context *ldb = ldb_module_get_ctx(module);
417 /* work out who is the RID Manager */
418 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
419 if (ret != LDB_SUCCESS) {
420 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
422 talloc_free(tmp_ctx);
426 /* find the DN of the RID Manager */
427 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
428 if (ret != LDB_SUCCESS) {
429 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
431 talloc_free(tmp_ctx);
435 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
436 ridalloc_poke_rid_manager(module);
437 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
438 talloc_free(tmp_ctx);
439 return LDB_ERR_UNWILLING_TO_PERFORM;
442 /* grab a pool from the RID Manager object */
443 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool, parent);
444 if (ret != LDB_SUCCESS) {
445 talloc_free(tmp_ctx);
449 talloc_free(tmp_ctx);
454 /* allocate a RID using our RID Set
455 If we run out of RIDs then allocate a new pool
456 either locally or by contacting the RID Manager
458 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_request *parent)
460 struct ldb_context *ldb;
462 struct ldb_dn *rid_set_dn;
463 struct ldb_result *res;
464 struct ldb_message *msg;
465 struct ridalloc_ridset_values oridset;
466 struct ridalloc_ridset_values nridset;
467 uint32_t prev_pool_lo, prev_pool_hi;
468 TALLOC_CTX *tmp_ctx = talloc_new(module);
471 ldb = ldb_module_get_ctx(module);
473 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
474 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
475 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn, parent);
477 if (ret != LDB_SUCCESS) {
478 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
480 talloc_free(tmp_ctx);
484 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
485 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
486 if (ret != LDB_SUCCESS) {
487 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
488 ldb_dn_get_linearized(rid_set_dn));
489 talloc_free(tmp_ctx);
493 ridalloc_get_ridset_values(res->msgs[0], &oridset);
494 if (oridset.alloc_pool == UINT64_MAX) {
495 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
496 ldb_dn_get_linearized(rid_set_dn));
497 talloc_free(tmp_ctx);
498 return LDB_ERR_OPERATIONS_ERROR;
504 * If we never used a pool, setup out first pool
506 if (nridset.prev_pool == UINT64_MAX ||
507 nridset.next_rid == UINT32_MAX) {
508 nridset.prev_pool = nridset.alloc_pool;
509 nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
513 * Now check if our current pool is still usable
515 nridset.next_rid += 1;
516 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
517 prev_pool_hi = nridset.prev_pool >> 32;
518 if (nridset.next_rid > prev_pool_hi) {
520 * We need a new pool, check if we already have a new one
521 * Otherwise we need to get a new pool.
523 if (nridset.alloc_pool == nridset.prev_pool) {
525 * if we are the RID Manager,
526 * we can get a new pool localy.
527 * Otherwise we fail the operation and
528 * ask async for a new pool.
530 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
531 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
532 ridalloc_poke_rid_manager(module);
533 talloc_free(tmp_ctx);
536 if (ret != LDB_SUCCESS) {
537 talloc_free(tmp_ctx);
543 * increment the rIDUsedPool attribute
545 * Note: w2k8r2 doesn't update this attribute,
546 * at least if it's itself the rid master.
548 nridset.used_pool += 1;
550 /* now use the new pool */
551 nridset.prev_pool = nridset.alloc_pool;
552 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
553 prev_pool_hi = nridset.prev_pool >> 32;
554 nridset.next_rid = prev_pool_lo;
557 if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
558 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
559 (unsigned)nridset.next_rid,
560 (unsigned)prev_pool_lo,
561 (unsigned)prev_pool_hi);
562 talloc_free(tmp_ctx);
563 return LDB_ERR_OPERATIONS_ERROR;
567 * if we are half-exhausted then try to get a new pool.
569 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2) {
571 * if we are the RID Manager,
572 * we can get a new pool localy.
573 * Otherwise we fail the operation and
574 * ask async for a new pool.
576 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
577 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
578 ridalloc_poke_rid_manager(module);
581 if (ret != LDB_SUCCESS) {
582 talloc_free(tmp_ctx);
590 msg = ldb_msg_new(tmp_ctx);
592 return ldb_module_oom(module);
594 msg->dn = rid_set_dn;
596 ret = ridalloc_set_ridset_values(module, msg,
598 if (ret != LDB_SUCCESS) {
599 talloc_free(tmp_ctx);
603 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
604 if (ret != LDB_SUCCESS) {
605 talloc_free(tmp_ctx);
609 talloc_free(tmp_ctx);
610 *rid = nridset.next_rid;
616 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
618 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
619 struct ldb_request *parent)
621 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
622 struct ldb_dn *rid_manager_dn;
623 TALLOC_CTX *tmp_ctx = talloc_new(module);
625 struct ldb_context *ldb = ldb_module_get_ctx(module);
626 struct ldb_result *res;
627 struct ldb_message *msg;
628 struct ridalloc_ridset_values oridset, nridset;
630 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn, parent);
631 if (ret != LDB_SUCCESS) {
632 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
633 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
634 talloc_free(tmp_ctx);
638 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
640 talloc_free(tmp_ctx);
641 return ldb_module_oom(module);
644 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
645 if (ret != LDB_SUCCESS) {
646 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
647 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
648 talloc_free(tmp_ctx);
652 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
653 if (ret != LDB_SUCCESS) {
654 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
656 talloc_free(tmp_ctx);
660 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn, parent);
661 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
662 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn, parent);
663 talloc_free(tmp_ctx);
667 if (ret != LDB_SUCCESS) {
668 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
669 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
670 talloc_free(tmp_ctx);
674 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
675 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
676 if (ret != LDB_SUCCESS) {
677 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
678 ldb_dn_get_linearized(rid_set_dn));
679 talloc_free(tmp_ctx);
683 ridalloc_get_ridset_values(res->msgs[0], &oridset);
684 if (oridset.alloc_pool == UINT64_MAX) {
685 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
686 ldb_dn_get_linearized(rid_set_dn));
687 talloc_free(tmp_ctx);
688 return LDB_ERR_OPERATIONS_ERROR;
693 if (exop->fsmo_info != 0) {
695 if (nridset.alloc_pool != exop->fsmo_info) {
696 /* it has already been updated */
697 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
698 (unsigned long long)exop->fsmo_info,
699 (unsigned long long)nridset.alloc_pool));
700 talloc_free(tmp_ctx);
705 /* grab a pool from the RID Manager object */
706 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &nridset.alloc_pool, parent);
707 if (ret != LDB_SUCCESS) {
708 talloc_free(tmp_ctx);
715 msg = ldb_msg_new(tmp_ctx);
717 return ldb_module_oom(module);
719 msg->dn = rid_set_dn;
721 ret = ridalloc_set_ridset_values(module, msg,
723 if (ret != LDB_SUCCESS) {
724 talloc_free(tmp_ctx);
728 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
729 if (ret != LDB_SUCCESS) {
730 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
731 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
732 talloc_free(tmp_ctx);
736 talloc_free(tmp_ctx);