summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r--source4/dsdb/samdb/ldb_modules/acl.c38
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk23
-rw-r--r--source4/dsdb/samdb/ldb_modules/instancetype.c3
-rw-r--r--source4/dsdb/samdb/ldb_modules/lazy_commit.c13
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c12
-rw-r--r--source4/dsdb/samdb/ldb_modules/pdc_fsmo.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c12
-rw-r--r--source4/dsdb/samdb/ldb_modules/ridalloc.c646
-rw-r--r--source4/dsdb/samdb/ldb_modules/samba3sid.c197
-rw-r--r--source4/dsdb/samdb/ldb_modules/samba_dsdb.c77
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c684
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_data.c5
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_load.c8
-rw-r--r--source4/dsdb/samdb/ldb_modules/show_deleted.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/tests/samba3sam.py17
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.c192
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.h5
17 files changed, 1212 insertions, 728 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index a3298362f3..a779821107 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -35,10 +35,10 @@
#include "ldb_module.h"
#include "auth/auth.h"
#include "libcli/security/security.h"
-#include "librpc/gen_ndr/ndr_security.h"
#include "dsdb/samdb/samdb.h"
#include "librpc/gen_ndr/ndr_security.h"
#include "param/param.h"
+#include "dsdb/samdb/ldb_modules/util.h"
struct extended_access_check_attribute {
const char *oa_name;
@@ -53,7 +53,7 @@ struct acl_private {
struct acl_context {
struct ldb_module *module;
struct ldb_request *req;
- enum security_user_level user_type;
+ bool am_system;
bool allowedAttributes;
bool allowedAttributesEffective;
bool allowedChildClasses;
@@ -70,14 +70,6 @@ bool is_root_base_dn(struct ldb_context *ldb, struct ldb_dn *dn_to_check)
return (result==0);
}
-static enum security_user_level what_is_user(struct ldb_module *module)
-{
- struct ldb_context *ldb = ldb_module_get_ctx(module);
- struct auth_session_info *session_info
- = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
- return security_session_user_level(session_info);
-}
-
static struct security_token *acl_user_token(struct ldb_module *module)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
@@ -309,7 +301,7 @@ static int acl_check_access_on_attribute(struct ldb_module *module,
struct security_descriptor *sd,
struct dom_sid *rp_sid,
uint32_t access,
- struct dsdb_attribute *attr)
+ const struct dsdb_attribute *attr)
{
int ret;
NTSTATUS status;
@@ -370,7 +362,7 @@ static int acl_check_access_on_class(struct ldb_module *module,
uint32_t access_granted;
struct object_tree *root = NULL;
struct object_tree *new_node = NULL;
- struct GUID *guid;
+ const struct GUID *guid;
const struct dsdb_schema *schema = dsdb_get_schema(ldb);
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
struct security_token *token = acl_user_token(module);
@@ -450,7 +442,7 @@ static int acl_allowedAttributes(struct ldb_module *module,
struct ldb_control *as_system = ldb_request_get_control(ac->req,
LDB_CONTROL_AS_SYSTEM_OID);
ldb_msg_remove_attr(msg, "allowedAttributesEffective");
- if (ac->user_type == SECURITY_SYSTEM || as_system) {
+ if (ac->am_system || as_system) {
for (i=0; attr_list && attr_list[i]; i++) {
ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
}
@@ -468,7 +460,7 @@ static int acl_allowedAttributes(struct ldb_module *module,
return ret;
}
for (i=0; attr_list && attr_list[i]; i++) {
- struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
+ const struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
attr_list[i]);
if (!attr) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -566,7 +558,7 @@ static int acl_childClassesEffective(struct ldb_module *module,
struct dom_sid *sid = NULL;
int i, j, ret;
- if (ac->user_type == SECURITY_SYSTEM || as_system) {
+ if (ac->am_system || as_system) {
return acl_childClasses(module, sd_msg, msg, "allowedChildClassesEffective");
}
@@ -650,7 +642,7 @@ static int acl_sDRightsEffective(struct ldb_module *module,
if (ret != LDB_SUCCESS) {
return ret;
}
- if (ac->user_type == SECURITY_SYSTEM || as_system) {
+ if (ac->am_system || as_system) {
flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_SACL | SECINFO_DACL;
}
else {
@@ -707,7 +699,7 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req)
struct object_tree *new_node = NULL;
struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
@@ -773,7 +765,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
{
DEBUG(10, ("ldb:acl_modify: %s\n", req->op.mod.message->elements[0].name));
}
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
if (ldb_dn_is_special(req->op.mod.message->dn)) {
@@ -901,7 +893,7 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn)));
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
@@ -955,7 +947,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
};
DEBUG(10, ("ldb:acl_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)));
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
if (ldb_dn_is_special(req->op.rename.olddn)) {
@@ -1135,7 +1127,7 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares)
}
}
if (data && data->password_attrs) {
- if (ac->user_type != SECURITY_SYSTEM) {
+ if (!ac->am_system) {
for (i = 0; data->password_attrs[i]; i++) {
ldb_msg_remove_attr(ares->message, data->password_attrs[i]);
}
@@ -1173,7 +1165,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req)
ac->module = module;
ac->req = req;
- ac->user_type = what_is_user(module);
+ ac->am_system = dsdb_module_am_system(module);
ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes");
ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective");
ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses");
@@ -1183,7 +1175,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req)
/* replace any attributes in the parse tree that are private,
so we don't allow a search for 'userPassword=penguin',
just as we would not allow that attribute to be returned */
- if (ac->user_type != SECURITY_SYSTEM) {
+ if (ac->am_system) {
/* FIXME: We should copy the tree and keep the original unmodified. */
/* remove password attributes */
if (data && data->password_attrs) {
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk
index 6128dc9d65..f9f1714358 100644
--- a/source4/dsdb/samdb/ldb_modules/config.mk
+++ b/source4/dsdb/samdb/ldb_modules/config.mk
@@ -1,9 +1,11 @@
################################################
# Start SUBSYSTEM DSDB_MODULE_HELPERS
[SUBSYSTEM::DSDB_MODULE_HELPERS]
-PRIVATE_DEPENDENCIES = LIBLDB LIBNDR SAMDB_SCHEMA
+PRIVATE_DEPENDENCIES = LIBLDB LIBNDR SAMDB_SCHEMA MESSAGING
-DSDB_MODULE_HELPERS_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/util.o
+DSDB_MODULE_HELPERS_OBJ_FILES = \
+ $(dsdbsrcdir)/samdb/ldb_modules/util.o \
+ $(dsdbsrcdir)/samdb/ldb_modules/ridalloc.o
$(eval $(call proto_header_template,$(dsdbsrcdir)/samdb/ldb_modules/util_proto.h,$(DSDB_MODULE_HELPERS_OBJ_FILES:.o=.c)))
@@ -135,13 +137,26 @@ SUBSYSTEM = LIBLDB
INIT_FUNCTION = LDB_MODULE(samba3sam)
PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB SMBPASSWD \
NSS_WRAPPER LIBSECURITY NDR_SECURITY
-# End MODULE ldb_samldb
+# End MODULE ldb_samba3sam
################################################
ldb_samba3sam_OBJ_FILES = \
$(dsdbsrcdir)/samdb/ldb_modules/samba3sam.o
################################################
+# Start MODULE ldb_samba3sid
+[MODULE::ldb_samba3sid]
+SUBSYSTEM = LIBLDB
+INIT_FUNCTION = LDB_MODULE(samba3sid)
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB SMBPASSWD \
+ NSS_WRAPPER LIBSECURITY NDR_SECURITY
+# End MODULE ldb_samba3sid
+################################################
+
+ldb_samba3sid_OBJ_FILES = \
+ $(dsdbsrcdir)/samdb/ldb_modules/samba3sid.o
+
+################################################
# Start MODULE ldb_simple_ldap_map
[MODULE::ldb_simple_ldap_map]
SUBSYSTEM = LIBLDB
@@ -337,7 +352,7 @@ ldb_subtree_delete_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/subtree_delete.o
[MODULE::ldb_linked_attributes]
INIT_FUNCTION = LDB_MODULE(linked_attributes)
CFLAGS = -Ilib/ldb/include
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB DSDB_MODULE_HELPERS
SUBSYSTEM = LIBLDB
# End MODULE ldb_linked_attributes
################################################
diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c
index b17f40e82a..0a297d587a 100644
--- a/source4/dsdb/samdb/ldb_modules/instancetype.c
+++ b/source4/dsdb/samdb/ldb_modules/instancetype.c
@@ -36,6 +36,7 @@
#include "librpc/gen_ndr/ndr_misc.h"
#include "dsdb/samdb/samdb.h"
#include "../libds/common/flags.h"
+#include "dsdb/samdb/ldb_modules/util.h"
struct it_context {
struct ldb_module *module;
@@ -143,7 +144,7 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_build_add_req(&down_req, ldb, req,
msg,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
if (ret != LDB_SUCCESS) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/lazy_commit.c b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
index 0502b2efa1..b4eaf50d51 100644
--- a/source4/dsdb/samdb/ldb_modules/lazy_commit.c
+++ b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
@@ -28,6 +28,7 @@
*/
#include "ldb_module.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
{
@@ -47,28 +48,28 @@ static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
req->op.search.tree,
req->op.search.attrs,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_ADD:
ret = ldb_build_add_req(&new_req, ldb_module_get_ctx(module), req,
req->op.add.message,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_MODIFY:
ret = ldb_build_mod_req(&new_req, ldb_module_get_ctx(module), req,
req->op.mod.message,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_DELETE:
ret = ldb_build_del_req(&new_req, ldb_module_get_ctx(module), req,
req->op.del.dn,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_RENAME:
@@ -76,7 +77,7 @@ static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
req->op.rename.olddn,
req->op.rename.newdn,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_EXTENDED:
@@ -85,7 +86,7 @@ static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
req->op.extended.oid,
req->op.extended.data,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
default:
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 01ae0a10a7..59e7fab393 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -39,7 +39,6 @@ struct part_request {
struct partition_context {
struct ldb_module *module;
struct ldb_request *req;
- bool got_success;
struct part_request *part_req;
int num_requests;
@@ -160,7 +159,7 @@ static int partition_req_callback(struct ldb_request *req,
}
}
- if (ares->error != LDB_SUCCESS && !ac->got_success) {
+ if (ares->error != LDB_SUCCESS) {
return ldb_module_done(ac->req, ares->controls,
ares->response, ares->error);
}
@@ -182,9 +181,6 @@ static int partition_req_callback(struct ldb_request *req,
return ldb_module_send_entry(ac->req, ares->message, ares->controls);
case LDB_REPLY_DONE:
- if (ares->error == LDB_SUCCESS) {
- ac->got_success = true;
- }
if (ac->req->operation == LDB_EXTENDED) {
/* FIXME: check for ares->response, replmd does not fill it ! */
if (ares->response) {
@@ -205,7 +201,7 @@ static int partition_req_callback(struct ldb_request *req,
/* this was the last one, call callback */
return ldb_module_done(ac->req, ares->controls,
ares->response,
- ac->got_success?LDB_SUCCESS:ares->error);
+ ares->error);
}
/* not the last, now call the next one */
@@ -528,9 +524,7 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req)
*/
if (ldb_dn_compare(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
match = true;
- if (req->op.search.scope == LDB_SCOPE_BASE) {
- stop = true;
- }
+ stop = true;
}
if (!match &&
(ldb_dn_compare_base(req->op.search.base, data->partitions[i]->ctrl->dn) == 0 &&
diff --git a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
index 796ecaf7bc..00d9a30fd3 100644
--- a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
@@ -75,8 +75,8 @@ static int pdc_fsmo_init(struct ldb_module *module)
return ldb_next_init(module);
} else if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "pdc_fsmo_init: failed to search the domain object: %d:%s",
- ret, ldb_strerror(ret));
+ "pdc_fsmo_init: failed to search the domain object: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 890eb91d6d..b4caac4c8d 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -672,7 +672,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
/* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
if (control) {
- allow_add_guid = 1;
+ allow_add_guid = true;
}
/* do not manipulate our control entries */
@@ -2667,10 +2667,12 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar)
break;
}
- DEBUG(1,("Discarding older DRS attribute update to %s on %s from %s\n",
- msg->elements[i-removed_attrs].name,
- ldb_dn_get_linearized(msg->dn),
- GUID_string(ar, &rmd->ctr.ctr1.array[i].originating_invocation_id)));
+ if (rmd->ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType) {
+ DEBUG(1,("Discarding older DRS attribute update to %s on %s from %s\n",
+ msg->elements[i-removed_attrs].name,
+ ldb_dn_get_linearized(msg->dn),
+ GUID_string(ar, &rmd->ctr.ctr1.array[i].originating_invocation_id)));
+ }
/* we don't want to apply this change so remove the attribute */
ldb_msg_remove_element(msg, &msg->elements[i-removed_attrs]);
diff --git a/source4/dsdb/samdb/ldb_modules/ridalloc.c b/source4/dsdb/samdb/ldb_modules/ridalloc.c
new file mode 100644
index 0000000000..a64062fcdc
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/ridalloc.c
@@ -0,0 +1,646 @@
+/*
+ RID allocation helper functions
+
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Andrew Tridgell 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: RID allocation logic
+ *
+ * Description: manage RID Set and RID Manager objects
+ *
+ */
+
+#include "includes.h"
+#include "ldb_module.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "lib/messaging/irpc.h"
+#include "param/param.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+
+/*
+ Note: the RID allocation attributes in AD are very badly named. Here
+ is what we think they really do:
+
+ in RID Set object:
+ - rIDPreviousAllocationPool: the pool which a DC is currently
+ pulling RIDs from. Managed by client DC
+
+ - rIDAllocationPool: the pool that the DC will switch to next,
+ when rIDPreviousAllocationPool is exhausted. Managed by RID Manager.
+
+ - rIDNextRID: the last RID allocated by this DC. Managed by client DC
+
+ in RID Manager object:
+ - rIDAvailablePool: the pool where the RID Manager gets new rID
+ pools from when it gets a EXOP_RID_ALLOC getncchanges call (or
+ locally when the DC is the RID Manager)
+ */
+
+
+/*
+ make a IRPC call to the drepl task to ask it to get the RID
+ Manager to give us another RID pool.
+
+ This function just sends the message to the drepl task then
+ returns immediately. It should be called well before we
+ completely run out of RIDs
+ */
+static void ridalloc_poke_rid_manager(struct ldb_module *module)
+{
+ struct messaging_context *msg;
+ struct server_id *server;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+
+ msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, lp_ctx),
+ lp_iconv_convenience(lp_ctx),
+ ldb_get_event_context(ldb));
+ if (!msg) {
+ DEBUG(3,(__location__ ": Failed to create messaging context\n"));
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ server = irpc_servers_byname(msg, msg, "dreplsrv");
+ if (!server) {
+ /* this means the drepl service is not running */
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ messaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);
+
+ /* we don't care if the message got through */
+ talloc_free(tmp_ctx);
+}
+
+
+/*
+ allocate a new range of RIDs in the RID Manager object
+ */
+static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool)
+{
+ int ret;
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ const char *attrs[] = { "rIDAvailablePool", NULL };
+ uint64_t rid_pool, new_rid_pool, dc_pool;
+ uint32_t rid_pool_lo, rid_pool_hi;
+ struct ldb_result *res;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ const unsigned alloc_size = 500;
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
+ ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
+ rid_pool_lo = rid_pool & 0xFFFFFFFF;
+ rid_pool_hi = rid_pool >> 32;
+ if (rid_pool_lo >= rid_pool_hi) {
+ ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
+ rid_pool_lo, rid_pool_hi);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* lower part of new pool is the low part of the rIDAvailablePool */
+ dc_pool = rid_pool_lo;
+
+ /* allocate 500 RIDs to this DC */
+ rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
+
+ /* work out upper part of new pool */
+ dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
+
+ /* and new rIDAvailablePool value */
+ new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
+
+ ret = dsdb_module_constrainted_update_integer(module, rid_manager_dn, "rIDAvailablePool",
+ rid_pool, new_rid_pool);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ (*new_pool) = dc_pool;
+ 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)
+{
+ 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 this DC
+ */
+static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+ struct ldb_dn **dn)
+{
+ 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);
+ 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);
+ 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);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ refresh a RID Set object for the specified DC
+ also returns the first RID for the new pool
+ */
+static int ridalloc_refresh_rid_set_ntds(struct ldb_module *module,
+ struct ldb_dn *rid_manager_dn,
+ struct ldb_dn *ntds_dn, uint64_t *new_pool)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ int ret;
+
+ /* grab a pool from the RID Manager object */
+ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ 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;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
+ ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDAllocationPool", *new_pool);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+/*
+ get a new RID pool for ourselves
+ also returns the first rid for the new pool
+ */
+static int ridalloc_refresh_own_pool(struct ldb_module *module, uint64_t *new_pool)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ 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);
+ 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);
+ 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_refresh_rid_set_ntds(module, rid_manager_dn, fsmo_role_dn, new_pool);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
+/* allocate a RID using our RID Set
+ If we run out of RIDs then allocate a new pool
+ either locally or by contacting the RID Manager
+*/
+int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
+{
+ struct ldb_context *ldb;
+ static const char * const attrs[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
+ "rIDNextRID" , "rIDUsedPool", NULL };
+ int ret;
+ struct ldb_dn *rid_set_dn;
+ struct ldb_result *res;
+ uint64_t alloc_pool, prev_alloc_pool;
+ uint32_t prev_alloc_pool_lo, prev_alloc_pool_hi;
+ uint32_t rid_used_pool;
+ int prev_rid;
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+
+ (*rid) = 0;
+ ldb = ldb_module_get_ctx(module);
+
+ ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
+ if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
+ }
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
+ ldb_dn_get_linearized(rid_set_dn));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
+ alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+ prev_rid = ldb_msg_find_attr_as_int(res->msgs[0], "rIDNextRID", 0);
+ rid_used_pool = ldb_msg_find_attr_as_int(res->msgs[0], "rIDUsedPool", 0);
+ if (alloc_pool == 0) {
+ ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
+ ldb_dn_get_linearized(rid_set_dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
+ prev_alloc_pool_hi = prev_alloc_pool >> 32;
+ if (prev_rid >= prev_alloc_pool_hi) {
+ if (prev_alloc_pool == 0) {
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDPreviousAllocationPool", alloc_pool);
+ } else {
+ ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
+ prev_alloc_pool, alloc_pool);
+ }
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ prev_alloc_pool = alloc_pool;
+ prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
+ prev_alloc_pool_hi = prev_alloc_pool >> 32;
+
+ /* update the rIDUsedPool attribute */
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDUsedPool", rid_used_pool+1);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDUsedPool on %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ (*rid) = prev_alloc_pool_lo;
+ }
+
+ /* see if we are still out of RIDs, and if so then ask
+ the RID Manager to give us more */
+ if (prev_rid >= prev_alloc_pool_hi) {
+ uint64_t new_pool;
+ ret = ridalloc_refresh_own_pool(module, &new_pool);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
+ prev_alloc_pool, new_pool);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ prev_alloc_pool = new_pool;
+ prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
+ prev_alloc_pool_hi = prev_alloc_pool >> 32;
+ (*rid) = prev_alloc_pool_lo;
+ } else {
+ /* despite the name, rIDNextRID is the value of the last user
+ * added by this DC, not the next available RID */
+ if (*rid == 0) {
+ (*rid) = prev_rid + 1;
+ }
+ }
+
+ if (*rid < prev_alloc_pool_lo || *rid > prev_alloc_pool_hi) {
+ ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
+ (unsigned)*rid, (unsigned)prev_alloc_pool_lo,
+ (unsigned)prev_alloc_pool_hi);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* now modify the RID Set to use up this RID using a
+ * constrained delete/add if possible */
+ if (prev_rid == 0) {
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDNextRID", *rid);
+ } else {
+ ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDNextRID", prev_rid, *rid);
+ }
+
+ /* if we are half-exhausted then ask the repl task to start
+ * getting another one */
+ if (*rid > (prev_alloc_pool_hi + prev_alloc_pool_lo)/2) {
+ ridalloc_poke_rid_manager(module);
+ }
+
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
+
+
+/*
+ called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
+ */
+int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop)
+{
+ struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
+ struct ldb_dn *rid_manager_dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ uint64_t new_pool;
+
+ ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
+ GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ 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, __location__ ": Failed to find serverReference in %s - %s",
+ ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+
+ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
+ if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
+ ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (exop->fsmo_info != 0) {
+ const char *attrs[] = { "rIDAllocationPool", NULL };
+ struct ldb_result *res;
+ uint64_t alloc_pool;
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
+ ldb_dn_get_linearized(rid_set_dn));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+ if (alloc_pool != exop->fsmo_info) {
+ /* it has already been updated */
+ DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
+ (unsigned long long)exop->fsmo_info,
+ (unsigned long long)alloc_pool));
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+ }
+ }
+
+ ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, ntds_dn, &new_pool);
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/source4/dsdb/samdb/ldb_modules/samba3sid.c b/source4/dsdb/samdb/ldb_modules/samba3sid.c
new file mode 100644
index 0000000000..76848eb258
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/samba3sid.c
@@ -0,0 +1,197 @@
+/*
+ samba3sid module
+
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Andrew Tridgell 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ add objectSID to users and groups using samba3 nextRid method
+ */
+
+#include "includes.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "ldb_module.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "../lib/util/util_ldb.h"
+#include "ldb_wrap.h"
+#include "param/param.h"
+
+/*
+ RID algorithm from pdb_ldap.c in source3/passdb/
+ (loosely based on Volkers code)
+ */
+static int samba3sid_next_sid(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx, char **sid)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ struct ldb_result *res;
+ const char *attrs[] = { "sambaNextRid", "sambaNextUserRid",
+ "sambaNextGroupRid", "sambaSID", NULL };
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ int sambaNextRid, sambaNextGroupRid, sambaNextUserRid;
+ struct ldb_message *msg;
+ int rid;
+ const char *sambaSID;
+
+ ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
+ attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
+ "(&(objectClass=sambaDomain)(sambaDomainName=%s))",
+ lp_sam_name(ldb_get_opaque(ldb, "loadparm")));
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": Failed to find domain object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ if (res->count != 1) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": Expected exactly 1 domain object - got %u",
+ res->count);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg = res->msgs[0];
+
+ sambaNextRid = ldb_msg_find_attr_as_uint(msg, "sambaNextRid", -1);
+ sambaNextUserRid = ldb_msg_find_attr_as_uint(msg, "sambaNextUserRid", -1);
+ sambaNextGroupRid = ldb_msg_find_attr_as_uint(msg, "sambaNextGroupRid", -1);
+ sambaSID = ldb_msg_find_attr_as_string(msg, "sambaSID", NULL);
+
+ if (sambaSID == NULL) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": No sambaSID in %s",
+ ldb_dn_get_linearized(msg->dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* choose the highest of the 3 - see pdb_ldap.c for an
+ * explanation */
+ rid = sambaNextRid;
+ if (sambaNextUserRid > rid) {
+ rid = sambaNextUserRid;
+ }
+ if (sambaNextGroupRid > rid) {
+ rid = sambaNextGroupRid;
+ }
+ if (rid == -1) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": No sambaNextRid in %s",
+ ldb_dn_get_linearized(msg->dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* sambaNextRid is actually the previous RID .... */
+ rid += 1;
+
+ (*sid) = talloc_asprintf(tmp_ctx, "%s-%d", sambaSID, rid);
+ if (!*sid) {
+ ldb_module_oom(module);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_module_constrainted_update_integer(module, msg->dn,
+ "sambaNextRid",
+ sambaNextRid, rid);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": Failed to update sambaNextRid - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ talloc_steal(mem_ctx, *sid);
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+
+/* add */
+static int samba3sid_add(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb;
+ int ret;
+ const struct ldb_message *msg = req->op.add.message;
+ struct ldb_message *new_msg;
+ char *sid;
+ struct ldb_request *new_req;
+
+ ldb = ldb_module_get_ctx(module);
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.add.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ if (!samdb_find_attribute(ldb, msg, "objectclass", "posixAccount") &&
+ !samdb_find_attribute(ldb, msg, "objectclass", "posixGroup")) {
+ /* its not a user or a group */
+ return ldb_next_request(module, req);
+ }
+
+ if (ldb_msg_find_element(msg, "sambaSID")) {
+ /* a SID was supplied */
+ return ldb_next_request(module, req);
+ }
+
+ new_msg = ldb_msg_copy_shallow(req, req->op.add.message);
+ if (!new_msg) {
+ ldb_module_oom(module);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = samba3sid_next_sid(module, new_msg, &sid);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_msg_add_steal_string(new_msg, "sambaSID", sid);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_build_add_req(&new_req, ldb, req,
+ new_msg,
+ req->controls,
+ req, dsdb_next_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_next_request(module, new_req);
+}
+
+_PUBLIC_ const struct ldb_module_ops ldb_samba3sid_module_ops = {
+ .name = "samba3sid",
+ .add = samba3sid_add,
+};
+
diff --git a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
index a461a94806..44526128f1 100644
--- a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
+++ b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
@@ -138,53 +138,6 @@ static int prepare_modules_line(struct ldb_context *ldb,
-/*
- initialise the invocationID for a standalone server
- */
-static int initialise_invocation_id(struct ldb_module *module, struct GUID *guid)
-{
- struct ldb_message *msg;
- struct ldb_context *ldb = ldb_module_get_ctx(module);
- int ret;
-
- *guid = GUID_random();
-
- msg = ldb_msg_new(module);
- if (msg == NULL) {
- ldb_module_oom(module);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- msg->dn = ldb_dn_new(msg, ldb, "@SAMBA_DSDB");
- if (!msg->dn) {
- ldb_module_oom(module);
- talloc_free(msg);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ret = dsdb_msg_add_guid(msg, guid, "invocationID");
- if (ret != LDB_SUCCESS) {
- ldb_module_oom(module);
- talloc_free(msg);
- return ret;
- }
- msg->elements[0].flags = LDB_FLAG_MOD_ADD;
-
- ret = ldb_modify(ldb, msg);
- if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb, "Failed to setup standalone invocationID - %s",
- ldb_errstring(ldb));
- talloc_free(msg);
- return ret;
- }
-
- DEBUG(1,("Initialised standalone invocationID to %s\n",
- GUID_string(msg, guid)));
-
- talloc_free(msg);
-
- return LDB_SUCCESS;
-}
-
-
static int samba_dsdb_init(struct ldb_module *module)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
@@ -258,7 +211,7 @@ static int samba_dsdb_init(struct ldb_module *module)
static const char *openldap_backend_modules[] = {
"entryuuid", "paged_searches", NULL };
- static const char *samba_dsdb_attrs[] = { "backendType", "serverRole", "invocationID", NULL };
+ static const char *samba_dsdb_attrs[] = { "backendType", "serverRole", NULL };
const char *backendType, *serverRole;
if (!tmp_ctx) {
@@ -293,34 +246,6 @@ static int samba_dsdb_init(struct ldb_module *module)
return ret;
}
- if (strcmp(serverRole, "standalone") == 0 ||
- strcmp(serverRole, "member server") == 0) {
- struct GUID *guid;
-
- guid = talloc(module, struct GUID);
- if (!guid) {
- ldb_module_oom(module);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *guid = samdb_result_guid(res->msgs[0], "invocationID");
- if (GUID_all_zero(guid)) {
- ret = initialise_invocation_id(module, guid);
- if (ret != LDB_SUCCESS) {
- talloc_free(tmp_ctx);
- return ret;
- }
- }
-
- /* cache the domain_sid in the ldb. See the matching
- * code in samdb_ntds_invocation_id() */
- ret = ldb_set_opaque(ldb, "cache.invocation_id", guid);
- if (ret != LDB_SUCCESS) {
- talloc_free(tmp_ctx);
- return ret;
- }
- }
-
backend_modules = NULL;
if (strcasecmp(backendType, "ldb") == 0) {
extended_dn_module = extended_dn_module_ldb;
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 17a99c74c7..ccf76aaef2 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -59,12 +59,6 @@ struct samldb_ctx {
/* the resulting message */
struct ldb_message *msg;
- /* used to find parent domain */
- struct ldb_dn *check_dn;
- struct ldb_dn *domain_dn;
- struct dom_sid *domain_sid;
- uint32_t next_rid;
-
/* holds the entry SID */
struct dom_sid *sid;
@@ -175,139 +169,6 @@ static int samldb_next_step(struct samldb_ctx *ac)
}
}
-/*
- * samldb_get_parent_domain (async)
- */
-
-static int samldb_get_parent_domain(struct samldb_ctx *ac);
-
-static int samldb_get_parent_domain_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- const char *nextRid;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if ((ac->domain_dn != NULL) || (ac->domain_sid != NULL)) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain object!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- nextRid = ldb_msg_find_attr_as_string(ares->message,
- "nextRid", NULL);
- if (nextRid == NULL) {
- ldb_asprintf_errstring(ldb,
- "While looking for domain above %s attribute nextRid not found in %s!",
- ldb_dn_get_linearized(
- ac->req->op.add.message->dn),
- ldb_dn_get_linearized(ares->message->dn));
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- ac->next_rid = strtol(nextRid, NULL, 0);
-
- ac->domain_sid = samdb_result_dom_sid(ac, ares->message,
- "objectSid");
- if (ac->domain_sid == NULL) {
- ldb_set_errstring(ldb,
- "Unable to get the parent domain SID!");
- ret = LDB_ERR_CONSTRAINT_VIOLATION;
- break;
- }
- ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
- if ((ac->domain_dn == NULL) || (ac->domain_sid == NULL)) {
- /* not found -> retry */
- ret = samldb_get_parent_domain(ac);
- } else {
- /* found, go on */
- ret = samldb_next_step(ac);
- }
- break;
- }
-
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* Find a domain object in the parents of a particular DN. */
-static int samldb_get_parent_domain(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- static const char * const attrs[] = { "objectSid", "nextRid", NULL };
- struct ldb_request *req;
- struct ldb_dn *dn;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->check_dn == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- dn = ldb_dn_get_parent(ac, ac->check_dn);
- if (dn == NULL) {
- ldb_set_errstring(ldb,
- "Unable to find parent domain object!");
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- ac->check_dn = dn;
-
- ret = ldb_build_search_req(&req, ldb, ac,
- dn, LDB_SCOPE_BASE,
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain))",
- attrs,
- NULL,
- ac, samldb_get_parent_domain_callback,
- ac->req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- return ldb_next_request(ac->module, req);
-}
-
-
static int samldb_generate_samAccountName(struct ldb_message *msg)
{
char *name;
@@ -395,7 +256,7 @@ static int samldb_check_samAccountName(struct samldb_ctx *ac)
}
ret = ldb_build_search_req(&req, ldb, ac,
- ac->domain_dn, LDB_SCOPE_SUBTREE,
+ samdb_base_dn(ldb), LDB_SCOPE_SUBTREE,
filter, NULL,
NULL,
ac, samldb_check_samAccountName_callback,
@@ -464,134 +325,45 @@ static int samldb_check_samAccountType(struct samldb_ctx *ac)
return samldb_next_step(ac);
}
-
-/*
- * samldb_get_sid_domain (async)
- */
-
-static int samldb_get_sid_domain_callback(struct ldb_request *req,
- struct ldb_reply *ares)
+static bool samldb_msg_add_sid(struct ldb_message *msg,
+ const char *name,
+ const struct dom_sid *sid)
{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- const char *nextRid;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if (ac->next_rid != 0) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain object!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- nextRid = ldb_msg_find_attr_as_string(ares->message,
- "nextRid", NULL);
- if (nextRid == NULL) {
- ldb_asprintf_errstring(ldb,
- "Attribute nextRid not found in %s!",
- ldb_dn_get_linearized(ares->message->dn));
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- ac->next_rid = strtol(nextRid, NULL, 0);
-
- ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
- if (ac->next_rid == 0) {
- ldb_asprintf_errstring(ldb,
- "Unable to get nextRid from domain entry!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- /* found, go on */
- ret = samldb_next_step(ac);
- break;
- }
+ struct ldb_val v;
+ enum ndr_err_code ndr_err;
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
+ ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
+ (ndr_push_flags_fn_t)ndr_push_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return false;
}
-
- return LDB_SUCCESS;
+ return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
}
-/* Find a domain object in the parents of a particular DN. */
-static int samldb_get_sid_domain(struct samldb_ctx *ac)
+
+/* allocate a SID using our RID Set */
+static int samldb_allocate_sid(struct samldb_ctx *ac)
{
- struct ldb_context *ldb;
- static const char * const attrs[] = { "nextRid", NULL };
- struct ldb_request *req;
- char *filter;
+ uint32_t rid;
int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->sid == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ ret = ridalloc_allocate_rid(ac->module, &rid);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- ac->domain_sid = dom_sid_dup(ac, ac->sid);
- if (!ac->domain_sid) {
+ ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
+ if (ac->sid == NULL) {
+ ldb_module_oom(ac->module);
return LDB_ERR_OPERATIONS_ERROR;
}
- /* get the domain component part of the provided SID */
- ac->domain_sid->num_auths--;
- filter = talloc_asprintf(ac,
- "(&(objectSid=%s)"
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain)))",
- ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
- if (filter == NULL) {
+ if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ldb_build_search_req(&req, ldb, ac,
- ldb_get_default_basedn(ldb),
- LDB_SCOPE_SUBTREE,
- filter, attrs,
- NULL,
- ac, samldb_get_sid_domain_callback,
- ac->req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ac->next_rid = 0;
- return ldb_next_request(ac->module, req);
+ return samldb_next_step(ac);
}
/*
@@ -722,161 +494,6 @@ static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
}
-static bool samldb_msg_add_sid(struct ldb_message *msg,
- const char *name,
- const struct dom_sid *sid)
-{
- struct ldb_val v;
- enum ndr_err_code ndr_err;
-
- ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
- (ndr_push_flags_fn_t)ndr_push_dom_sid);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return false;
- }
- return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
-}
-
-static int samldb_new_sid(struct samldb_ctx *ac)
-{
-
- if (ac->domain_sid == NULL || ac->next_rid == 0) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->sid = dom_sid_add_rid(ac, ac->domain_sid, ac->next_rid + 1);
- if (ac->sid == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- return samldb_next_step(ac);
-}
-
-/*
- * samldb_notice_sid_callback (async)
- */
-
-static int samldb_notice_sid_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
- if (ares->type != LDB_REPLY_DONE) {
- ldb_set_errstring(ldb,
- "Invalid reply type!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
-
- ret = samldb_next_step(ac);
-
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* If we are adding new users/groups, we need to update the nextRid
- * attribute to be 'above' the new/incoming RID. Attempt to do it
- * atomically. */
-static int samldb_notice_sid(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- uint32_t old_id, new_id;
- struct ldb_request *req;
- struct ldb_message *msg;
- struct ldb_message_element *els;
- struct ldb_val *vals;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
- old_id = ac->next_rid;
- new_id = ac->sid->sub_auths[ac->sid->num_auths - 1];
-
- if (old_id >= new_id) {
- /* no need to update the domain nextRid attribute */
- return samldb_next_step(ac);
- }
-
- /* we do a delete and add as a single operation. That prevents
- a race, in case we are not actually on a transaction db */
- msg = ldb_msg_new(ac);
- if (msg == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- els = talloc_array(msg, struct ldb_message_element, 2);
- if (els == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- vals = talloc_array(msg, struct ldb_val, 2);
- if (vals == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- msg->dn = ac->domain_dn;
- msg->num_elements = 2;
- msg->elements = els;
-
- els[0].num_values = 1;
- els[0].values = &vals[0];
- els[0].flags = LDB_FLAG_MOD_DELETE;
- els[0].name = talloc_strdup(msg, "nextRid");
- if (!els[0].name) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- els[1].num_values = 1;
- els[1].values = &vals[1];
- els[1].flags = LDB_FLAG_MOD_ADD;
- els[1].name = els[0].name;
-
- vals[0].data = (uint8_t *)talloc_asprintf(vals, "%u", old_id);
- if (!vals[0].data) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- vals[0].length = strlen((char *)vals[0].data);
-
- vals[1].data = (uint8_t *)talloc_asprintf(vals, "%u", new_id);
- if (!vals[1].data) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- vals[1].length = strlen((char *)vals[1].data);
-
- ret = ldb_build_mod_req(&req, ldb, ac,
- msg, NULL,
- ac, samldb_notice_sid_callback,
- ac->req);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- return ldb_next_request(ac->module, req);
-}
-
/*
* samldb_set_defaultObjectCategory_callback (async)
*/
@@ -1142,11 +759,6 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
ldb = ldb_module_get_ctx(ac->module);
- /* search for a parent domain objet */
- ac->check_dn = ac->req->op.add.message->dn;
- ret = samldb_add_step(ac, samldb_get_parent_domain);
- if (ret != LDB_SUCCESS) return ret;
-
/* Add informations for the different account types */
ac->type = type;
if (strcmp(ac->type, "user") == 0) {
@@ -1174,9 +786,11 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
ret = samdb_find_or_add_attribute(ldb, ac->msg,
"pwdLastSet", "0");
if (ret != LDB_SUCCESS) return ret;
- ret = samdb_find_or_add_attribute(ldb, ac->msg,
- "primaryGroupID", "513");
- if (ret != LDB_SUCCESS) return ret;
+ if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
+ ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
+ "primaryGroupID", DOMAIN_RID_USERS);
+ if (ret != LDB_SUCCESS) return ret;
+ }
ret = samdb_find_or_add_attribute(ldb, ac->msg,
"accountExpires", "9223372036854775807");
if (ret != LDB_SUCCESS) return ret;
@@ -1287,20 +901,21 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
struct loadparm_context);
- sid_generator = lp_sid_generator(lp_ctx);
- if (sid_generator == SID_GENERATOR_INTERNAL) {
- /* check if we have a valid SID */
- ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
- if ( ! ac->sid) {
- ret = samldb_add_step(ac, samldb_new_sid);
- if (ret != LDB_SUCCESS) return ret;
- } else {
- ret = samldb_add_step(ac, samldb_get_sid_domain);
+ /* don't allow objectSID to be specified without the RELAX control */
+ ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
+ if (ac->sid && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
+ !dsdb_module_am_system(ac->module)) {
+ ldb_asprintf_errstring(ldb, "No SID may be specified in user/group creation for %s",
+ ldb_dn_get_linearized(ac->msg->dn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ if ( ! ac->sid) {
+ sid_generator = lp_sid_generator(lp_ctx);
+ if (sid_generator == SID_GENERATOR_INTERNAL) {
+ ret = samldb_add_step(ac, samldb_allocate_sid);
if (ret != LDB_SUCCESS) return ret;
}
-
- ret = samldb_add_step(ac, samldb_notice_sid);
- if (ret != LDB_SUCCESS) return ret;
}
/* finally proceed with adding the entry */
@@ -1310,144 +925,6 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
return samldb_first_step(ac);
}
-/*
- * samldb_foreign_notice_sid (async)
- */
-
-static int samldb_foreign_notice_sid_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- const char *nextRid;
- const char *name;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if (ac->next_rid != 0) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain object!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- nextRid = ldb_msg_find_attr_as_string(ares->message,
- "nextRid", NULL);
- if (nextRid == NULL) {
- ldb_asprintf_errstring(ldb,
- "While looking for foreign SID %s attribute nextRid not found in %s",
- dom_sid_string(ares, ac->sid),
- ldb_dn_get_linearized(ares->message->dn));
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- ac->next_rid = strtol(nextRid, NULL, 0);
-
- ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
-
- name = samdb_result_string(ares->message, "name", NULL);
- ldb_debug(ldb, LDB_DEBUG_TRACE,
- "NOTE (strange but valid): Adding foreign SID "
- "record with SID %s, but this domain (%s) is "
- "not foreign in the database\n",
- dom_sid_string(ares, ac->sid), name);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
-
- /* if this is a fake foreign SID, notice the SID */
- if (ac->domain_dn) {
- ret = samldb_notice_sid(ac);
- break;
- }
-
- /* found, go on */
- ret = samldb_next_step(ac);
- break;
- }
-
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* Find a domain object in the parents of a particular DN. */
-static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- static const char * const attrs[3] = { "nextRid", "name", NULL };
- struct ldb_request *req;
- NTSTATUS status;
- char *filter;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->sid == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- status = dom_sid_split_rid(ac, ac->sid, &ac->domain_sid, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
-
- filter = talloc_asprintf(ac,
- "(&(objectSid=%s)"
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain)))",
- ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
- if (filter == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = ldb_build_search_req(&req, ldb, ac,
- ldb_get_default_basedn(ldb),
- LDB_SCOPE_SUBTREE,
- filter, attrs,
- NULL,
- ac, samldb_foreign_notice_sid_callback,
- ac->req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- return ldb_next_request(ac->module, req);
-}
-
-
static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
{
struct ldb_context *ldb;
@@ -1455,8 +932,6 @@ static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
ldb = ldb_module_get_ctx(ac->module);
- ac->next_rid = 0;
-
ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
if (ac->sid == NULL) {
ac->sid = dom_sid_parse_talloc(ac->msg,
@@ -1474,10 +949,6 @@ static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
}
}
- /* check if we need to notice this SID */
- ret = samldb_add_step(ac, samldb_foreign_notice_sid);
- if (ret != LDB_SUCCESS) return ret;
-
/* finally proceed with adding the entry */
ret = samldb_add_step(ac, samldb_add_entry);
if (ret != LDB_SUCCESS) return ret;
@@ -2313,6 +1784,20 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
el2->flags = LDB_FLAG_MOD_REPLACE;
}
+ el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
+ if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
+ struct samldb_ctx *ac;
+
+ ac = samldb_ctx_init(module, req);
+ if (ac == NULL)
+ return LDB_ERR_OPERATIONS_ERROR;
+
+ req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
+ req->op.mod.message);
+
+ return samldb_prim_group_change(ac);
+ }
+
el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
uint32_t user_account_control;
@@ -2340,21 +1825,18 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
}
el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
el2->flags = LDB_FLAG_MOD_REPLACE;
- }
- }
-
- el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
- if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
- struct samldb_ctx *ac;
- ac = samldb_ctx_init(module, req);
- if (ac == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
-
- req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
- req->op.mod.message);
-
- return samldb_prim_group_change(ac);
+ /* DCs have primaryGroupID of DOMAIN_RID_DCS */
+ if (!ldb_msg_find_element(msg, "primaryGroupID")) {
+ ret = samdb_msg_add_uint(ldb, msg, msg,
+ "primaryGroupID", DOMAIN_RID_DCS);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ el2 = ldb_msg_find_element(msg, "primaryGroupID");
+ el2->flags = LDB_FLAG_MOD_REPLACE;
+ }
+ }
}
el = ldb_msg_find_element(req->op.mod.message, "member");
@@ -2392,17 +1874,41 @@ static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
return samldb_prim_group_users_check(ac);
}
+static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct dsdb_fsmo_extended_op *exop;
+ int ret;
+
+ exop = talloc_get_type(req->op.extended.data, struct dsdb_fsmo_extended_op);
+ if (!exop) {
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_extended_allocate_rid_pool: invalid extended data\n");
+ return LDB_ERR_PROTOCOL_ERROR;
+ }
+
+ ret = ridalloc_allocate_rid_pool_fsmo(module, exop);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+}
-static int samldb_init(struct ldb_module *module)
+static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
{
- return ldb_next_init(module);
+ if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
+ return samldb_extended_allocate_rid_pool(module, req);
+ }
+
+ return ldb_next_request(module, req);
}
+
_PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
.name = "samldb",
- .init_context = samldb_init,
.add = samldb_add,
.modify = samldb_modify,
- .del = samldb_delete
+ .del = samldb_delete,
+ .extended = samldb_extended
};
diff --git a/source4/dsdb/samdb/ldb_modules/schema_data.c b/source4/dsdb/samdb/ldb_modules/schema_data.c
index 2e99113953..8125a46cbb 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_data.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_data.c
@@ -290,6 +290,11 @@ static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
}
}
+ /* bypass further processing if CONTROL_RELAX is set */
+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
+ return ldb_next_request(module, req);
+ }
+
/* generate and add msDS-IntId attr value */
if (attributeID
&& (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2003)
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index c72911fe89..6c11df21ce 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -181,8 +181,8 @@ static int schema_load_init(struct ldb_module *module)
ret = dsdb_set_schema(ldb, schema);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "schema_load_init: dsdb_set_schema() failed: %d:%s",
- ret, ldb_strerror(ret));
+ "schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
}
@@ -240,8 +240,8 @@ static int schema_load_extended(struct ldb_module *module, struct ldb_request *r
ret = dsdb_set_schema(ldb, schema);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "schema_load_extended: dsdb_set_schema() failed: %d:%s",
- ret, ldb_strerror(ret));
+ "schema_load_extended: dsdb_set_schema() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
}
diff --git a/source4/dsdb/samdb/ldb_modules/show_deleted.c b/source4/dsdb/samdb/ldb_modules/show_deleted.c
index 666d28053c..93463ae95f 100644
--- a/source4/dsdb/samdb/ldb_modules/show_deleted.c
+++ b/source4/dsdb/samdb/ldb_modules/show_deleted.c
@@ -32,7 +32,7 @@
#include "includes.h"
#include "ldb/include/ldb_module.h"
#include "dsdb/samdb/samdb.h"
-
+#include "dsdb/samdb/ldb_modules/util.h"
static int show_deleted_search(struct ldb_module *module, struct ldb_request *req)
{
@@ -83,7 +83,7 @@ static int show_deleted_search(struct ldb_module *module, struct ldb_request *re
new_tree,
req->op.search.attrs,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
if (ret != LDB_SUCCESS) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
index 2478043eb4..cc1a86ed4a 100644
--- a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
+++ b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
@@ -29,6 +29,8 @@ from samba import Ldb, substitute_var
from samba.tests import LdbTestCase, TestCaseInTempDir, cmdline_loadparm
import samba.dcerpc.security
import samba.ndr
+from samba.auth import system_session
+from samba import param
datadir = os.path.join(os.path.dirname(__file__),
"../../../../../testdata/samba3")
@@ -49,7 +51,7 @@ class MapBaseTestCase(TestCaseInTempDir):
"@TO": "sambaDomainName=TESTS," + s3.basedn})
ldb.add({"dn": "@MODULES",
- "@LIST": "rootdse,paged_results,server_sort,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,partition"})
+ "@LIST": "rootdse,paged_results,server_sort,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,samba3sid,partition"})
ldb.add({"dn": "@PARTITION",
"partition": ["%s" % (s4.basedn_casefold),
@@ -58,6 +60,9 @@ class MapBaseTestCase(TestCaseInTempDir):
"modules": "*:"})
def setUp(self):
+ cmdline_loadparm.set("sid generator", "backend")
+ cmdline_loadparm.set("workgroup", "TESTS")
+ cmdline_loadparm.set("netbios name", "TESTS")
super(MapBaseTestCase, self).setUp()
def make_dn(basedn, rdn):
@@ -75,7 +80,7 @@ class MapBaseTestCase(TestCaseInTempDir):
"""Simple helper class that contains data for a specific SAM
connection."""
def __init__(self, basedn, dn):
- self.db = Ldb(lp=cmdline_loadparm)
+ self.db = Ldb(lp=cmdline_loadparm, session_info=system_session())
self.basedn = basedn
self.basedn_casefold = ldb.Dn(self.db, basedn).get_casefold()
self.substvars = {"BASEDN": self.basedn}
@@ -124,13 +129,13 @@ class Samba3SamTestCase(MapBaseTestCase):
def setUp(self):
super(Samba3SamTestCase, self).setUp()
- ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
self.samba3.setup_data("samba3.ldif")
ldif = read_datafile("provision_samba3sam.ldif")
ldb.add_ldif(self.samba4.subst(ldif))
self.setup_modules(ldb, self.samba3, self.samba4)
del ldb
- self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
def test_search_non_mapped(self):
"""Looking up by non-mapped attribute"""
@@ -291,12 +296,12 @@ class MapTestCase(MapBaseTestCase):
def setUp(self):
super(MapTestCase, self).setUp()
- ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
ldif = read_datafile("provision_samba3sam.ldif")
ldb.add_ldif(self.samba4.subst(ldif))
self.setup_modules(ldb, self.samba3, self.samba4)
del ldb
- self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
def test_map_search(self):
"""Running search tests on mapped data."""
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
index 32b79a6701..46252cb279 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -26,6 +26,7 @@
#include "dsdb/samdb/ldb_modules/util.h"
#include "dsdb/samdb/samdb.h"
#include "util.h"
+#include "libcli/security/security.h"
/*
add a set of controls to a ldb_request structure based on a set of
@@ -214,6 +215,8 @@ int dsdb_module_search(struct ldb_module *module,
if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
const struct ldb_module_ops *ops = ldb_module_get_ops(module);
ret = ops->search(module, req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), req);
} else {
ret = ldb_next_request(module, req);
}
@@ -332,6 +335,8 @@ int dsdb_module_modify(struct ldb_module *module,
if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
const struct ldb_module_ops *ops = ldb_module_get_ops(module);
ret = ops->modify(module, mod_req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), mod_req);
} else {
ret = ldb_next_request(module, mod_req);
}
@@ -380,6 +385,8 @@ int dsdb_module_rename(struct ldb_module *module,
if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
const struct ldb_module_ops *ops = ldb_module_get_ops(module);
ret = ops->rename(module, req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), req);
} else {
ret = ldb_next_request(module, req);
}
@@ -391,6 +398,54 @@ int dsdb_module_rename(struct ldb_module *module,
return ret;
}
+/*
+ a ldb_add request operating on modules below the
+ current module
+ */
+int dsdb_module_add(struct ldb_module *module,
+ const struct ldb_message *message,
+ uint32_t dsdb_flags)
+{
+ struct ldb_request *req;
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+
+ ret = ldb_build_add_req(&req, ldb, tmp_ctx,
+ message,
+ NULL,
+ NULL,
+ ldb_op_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_request_add_controls(module, req, dsdb_flags);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* Run the new request */
+ if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
+ const struct ldb_module_ops *ops = ldb_module_get_ops(module);
+ ret = ops->add(module, req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), req);
+ } else {
+ ret = ldb_next_request(module, req);
+ }
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
{
const struct dsdb_class *last_class = NULL;
@@ -446,3 +501,140 @@ int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
return LDB_SUCCESS;
}
+
+
+/*
+ find a 'reference' DN that points at another object
+ (eg. serverReference, rIDManagerReference etc)
+ */
+int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
+ const char *attribute, struct ldb_dn **dn)
+{
+ const char *attrs[2];
+ struct ldb_result *res;
+ int ret;
+
+ attrs[0] = attribute;
+ attrs[1] = NULL;
+
+ ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
+ mem_ctx, res->msgs[0], attribute);
+ if (!*dn) {
+ talloc_free(res);
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ }
+
+ talloc_free(res);
+ return LDB_SUCCESS;
+}
+
+/*
+ find the RID Manager$ DN via the rIDManagerReference attribute in the
+ base DN
+ */
+int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
+{
+ return dsdb_module_reference_dn(module, mem_ctx,
+ samdb_base_dn(ldb_module_get_ctx(module)),
+ "rIDManagerReference", dn);
+}
+
+
+/*
+ update an integer attribute safely via a constrained delete/add
+ */
+int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
+ const char *attr, uint64_t old_val, uint64_t new_val)
+{
+ struct ldb_message *msg;
+ struct ldb_message_element *el;
+ struct ldb_val v1, v2;
+ int ret;
+ char *vstring;
+
+ msg = ldb_msg_new(module);
+ msg->dn = dn;
+
+ ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ el->num_values = 1;
+ el->values = &v1;
+ vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
+ if (!vstring) {
+ ldb_module_oom(module);
+ talloc_free(msg);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ v1 = data_blob_string_const(vstring);
+
+ ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ el->num_values = 1;
+ el->values = &v2;
+ vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
+ if (!vstring) {
+ ldb_module_oom(module);
+ talloc_free(msg);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ v2 = data_blob_string_const(vstring);
+
+ ret = dsdb_module_modify(module, msg, 0);
+ talloc_free(msg);
+ return ret;
+}
+
+/*
+ used to chain to the callers callback
+ */
+int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
+
+ talloc_steal(up_req, req);
+ return up_req->callback(up_req, ares);
+}
+
+
+/*
+ set an integer attribute
+ */
+int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
+ const char *attr, uint64_t new_val)
+{
+ struct ldb_message *msg;
+ int ret;
+
+ msg = ldb_msg_new(module);
+ msg->dn = dn;
+
+ ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
+
+ ret = dsdb_module_modify(module, msg, 0);
+ talloc_free(msg);
+ return ret;
+}
+
+bool dsdb_module_am_system(struct ldb_module *module)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct auth_session_info *session_info
+ = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
+ return security_session_user_level(session_info) == SECURITY_SYSTEM;
+}
diff --git a/source4/dsdb/samdb/ldb_modules/util.h b/source4/dsdb/samdb/ldb_modules/util.h
index add39e110a..53ed9bd48e 100644
--- a/source4/dsdb/samdb/ldb_modules/util.h
+++ b/source4/dsdb/samdb/ldb_modules/util.h
@@ -19,9 +19,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-struct dsdb_schema; /* predeclare schema struct */
+/* predeclare some structures used by utility functions */
+struct dsdb_schema;
struct GUID;
struct dsdb_attribute;
+struct dsdb_fsmo_extended_op;
#include "dsdb/samdb/ldb_modules/util_proto.h"
@@ -32,3 +34,4 @@ struct dsdb_attribute;
#define DSDB_SEARCH_SHOW_EXTENDED_DN 0x0010
#define DSDB_MODIFY_RELAX 0x0020
#define DSDB_FLAG_OWN_MODULE 0x0040
+#define DSDB_FLAG_TOP_MODULE 0x0080