/* create a RID Set object for the specified DC */ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *rid_manager_dn, struct ldb_dn *ntds_dn, struct ldb_dn **dn) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *server_dn, *machine_dn, *rid_set_dn; int ret; uint64_t dc_pool; struct ldb_message *msg; struct ldb_context *ldb = ldb_module_get_ctx(module); /* steps: find the machine object for the DC construct the RID Set DN load rIDAvailablePool to find next available set modify RID Manager object to update rIDAvailablePool add the RID Set object link to the RID Set object in machine object */ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn); if (!server_dn) { ldb_module_oom(module); talloc_free(tmp_ctx); return LDB_ERR_OPERATIONS_ERROR; } ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s", ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn); if (rid_set_dn == NULL) { ldb_module_oom(module); return LDB_ERR_OPERATIONS_ERROR; } if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) { ldb_module_oom(module); return LDB_ERR_OPERATIONS_ERROR; } /* grab a pool from the RID Manager object */ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &dc_pool); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* create the RID Set object */ msg = ldb_msg_new(tmp_ctx); msg->dn = rid_set_dn; ret = ldb_msg_add_string(msg, "objectClass", "rIDSet"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = ldb_msg_add_fmt(msg, "rIDAllocationPool", "%llu", (unsigned long long)dc_pool); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* w2k8-r2 sets these to zero when first created */ ret = ldb_msg_add_fmt(msg, "rIDPreviousAllocationPool", "0"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = ldb_msg_add_fmt(msg, "rIDUsedPool", "0"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = ldb_msg_add_fmt(msg, "rIDNextRID", "0"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* we need this to go all the way to the top of the module * stack, as we need all the extra attributes added (including * complex ones like ntsecuritydescriptor) */ ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* add the rIDSetReferences link */ msg = ldb_msg_new(tmp_ctx); msg->dn = machine_dn; ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn)); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } msg->elements[0].flags = LDB_FLAG_MOD_ADD; ret = dsdb_module_modify(module, msg, 0); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } (*dn) = talloc_steal(mem_ctx, rid_set_dn); talloc_free(tmp_ctx); return LDB_SUCCESS; }
/* create a RID Set object for the specified DC */ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *rid_manager_dn, struct ldb_dn *ntds_dn, struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *server_dn, *machine_dn, *rid_set_dn; int ret; struct ldb_message *msg; struct ldb_context *ldb = ldb_module_get_ctx(module); static const struct ridalloc_ridset_values o = { .alloc_pool = UINT64_MAX, .prev_pool = UINT64_MAX, .next_rid = UINT32_MAX, .used_pool = UINT32_MAX, }; struct ridalloc_ridset_values n = { .alloc_pool = 0, .prev_pool = 0, .next_rid = 0, .used_pool = 0, }; /* steps: find the machine object for the DC construct the RID Set DN load rIDAvailablePool to find next available set modify RID Manager object to update rIDAvailablePool add the RID Set object link to the RID Set object in machine object */ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn); if (!server_dn) { talloc_free(tmp_ctx); return ldb_module_oom(module); } ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s", ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn); if (rid_set_dn == NULL) { talloc_free(tmp_ctx); return ldb_module_oom(module); } if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) { talloc_free(tmp_ctx); return ldb_module_oom(module); } /* grab a pool from the RID Manager object */ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* create the RID Set object */ msg = ldb_msg_new(tmp_ctx); msg->dn = rid_set_dn; ret = ldb_msg_add_string(msg, "objectClass", "rIDSet"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = ridalloc_set_ridset_values(module, msg, &o, &n); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* we need this to go all the way to the top of the module * stack, as we need all the extra attributes added (including * complex ones like ntsecuritydescriptor) */ ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* add the rIDSetReferences link */ msg = ldb_msg_new(tmp_ctx); msg->dn = machine_dn; ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn)); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } msg->elements[0].flags = LDB_FLAG_MOD_ADD; ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } (*dn) = talloc_steal(mem_ctx, rid_set_dn); talloc_free(tmp_ctx); return LDB_SUCCESS; } /* create a RID Set object for this DC */ static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *rid_manager_dn, *fsmo_role_dn; int ret; struct ldb_context *ldb = ldb_module_get_ctx(module); /* work out who is the RID Manager */ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s", ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* find the DN of the RID Manager */ ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s", ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) { ridalloc_poke_rid_manager(module); ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh"); talloc_free(tmp_ctx); return LDB_ERR_UNWILLING_TO_PERFORM; } ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent); talloc_free(tmp_ctx); return ret; }
/* create a RID Set object for the specified DC */ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *rid_manager_dn, struct ldb_dn *ntds_dn, struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *server_dn, *machine_dn, *rid_set_dn; int ret; struct ldb_message *msg; struct ldb_context *ldb = ldb_module_get_ctx(module); static const struct ridalloc_ridset_values o = { .alloc_pool = UINT64_MAX, .prev_pool = UINT64_MAX, .next_rid = UINT32_MAX, .used_pool = UINT32_MAX, }; struct ridalloc_ridset_values n = { .alloc_pool = 0, .prev_pool = 0, .next_rid = 0, .used_pool = 0, }; const char *no_attrs[] = { NULL }; struct ldb_result *res; /* steps: find the machine object for the DC construct the RID Set DN load rIDAvailablePool to find next available set modify RID Manager object to update rIDAvailablePool add the RID Set object link to the RID Set object in machine object */ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn); if (!server_dn) { talloc_free(tmp_ctx); return ldb_module_oom(module); } ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s", ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn); if (rid_set_dn == NULL) { talloc_free(tmp_ctx); return ldb_module_oom(module); } if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) { talloc_free(tmp_ctx); return ldb_module_oom(module); } /* grab a pool from the RID Manager object */ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* create the RID Set object */ msg = ldb_msg_new(tmp_ctx); msg->dn = rid_set_dn; ret = ldb_msg_add_string(msg, "objectClass", "rIDSet"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = ridalloc_set_ridset_values(module, msg, &o, &n); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* we need this to go all the way to the top of the module * stack, as we need all the extra attributes added (including * complex ones like ntsecuritydescriptor). We must do this * as system, otherwise a user might end up owning the RID * set, and that would be bad... */ ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM | DSDB_MODIFY_RELAX, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* add the rIDSetReferences link */ msg = ldb_msg_new(tmp_ctx); msg->dn = machine_dn; /* we need the extended DN of the RID Set object for * rIDSetReferences */ ret = dsdb_module_search_dn(module, msg, &res, rid_set_dn, no_attrs, DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find extended DN of RID Set %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } rid_set_dn = res->msgs[0]->dn; ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_extended_linearized(msg, rid_set_dn, 1)); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } msg->elements[0].flags = LDB_FLAG_MOD_ADD; ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } (*dn) = talloc_steal(mem_ctx, rid_set_dn); talloc_free(tmp_ctx); return LDB_SUCCESS; } /* create a RID Set object for this DC */ int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *rid_manager_dn, *fsmo_role_dn; int ret; struct ldb_context *ldb = ldb_module_get_ctx(module); struct GUID fsmo_role_guid; const struct GUID *our_ntds_guid; NTSTATUS status; /* work out who is the RID Manager */ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s", ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* find the DN of the RID Manager */ ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s", ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } status = dsdb_get_extended_dn_guid(fsmo_role_dn, &fsmo_role_guid, "GUID"); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return ldb_operr(ldb_module_get_ctx(module)); } our_ntds_guid = samdb_ntds_objectGUID(ldb_module_get_ctx(module)); if (!our_ntds_guid) { talloc_free(tmp_ctx); return ldb_operr(ldb_module_get_ctx(module)); } if (!GUID_equal(&fsmo_role_guid, our_ntds_guid)) { ret = ridalloc_poke_rid_manager(module); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Request for remote creation of " "RID Set for this DC failed: %s", ldb_errstring(ldb)); } else { ldb_asprintf_errstring(ldb, "Remote RID Set creation needed"); } talloc_free(tmp_ctx); return LDB_ERR_UNWILLING_TO_PERFORM; } ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent); talloc_free(tmp_ctx); return ret; }