mirror of
https://github.com/samba-team/samba.git
synced 2025-03-09 08:58:35 +03:00
s4/schema: Move msDS-IntId implementation to samldb.c module
msDS-IntId attribute should be replicated, so it must be implemented in a module that is before repl_meta_data module (thanks abartlet for pointing this out). Signed-off-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
2523b20349
commit
fffdce62fc
@ -689,6 +689,81 @@ static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
|
||||
return ldb_next_request(ac->module, req);
|
||||
}
|
||||
|
||||
/**
|
||||
* msDS-IntId attributeSchema attribute handling
|
||||
* during LDB_ADD request processing
|
||||
*/
|
||||
static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
|
||||
{
|
||||
int ret;
|
||||
bool id_exists;
|
||||
uint32_t msds_intid;
|
||||
uint32_t system_flags;
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_result *ldb_res;
|
||||
struct ldb_dn *schema_dn;
|
||||
|
||||
ldb = ldb_module_get_ctx(ac->module);
|
||||
schema_dn = ldb_get_schema_basedn(ldb);
|
||||
|
||||
/* replicated update should always go through */
|
||||
if (ldb_request_get_control(ac->req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* msDS-IntId is handled by system and should never be
|
||||
* passed by clients */
|
||||
if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
|
||||
return LDB_ERR_UNWILLING_TO_PERFORM;
|
||||
}
|
||||
|
||||
/* do not generate msDS-IntId if Relax control is passed */
|
||||
if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* check Functional Level */
|
||||
if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* check systemFlags for SCHEMA_BASE_OBJECT flag */
|
||||
system_flags = ldb_msg_find_attr_as_uint(ac->msg, "systemFlags", 0);
|
||||
if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* Generate new value for msDs-IntId
|
||||
* Value should be in 0x80000000..0xBFFFFFFF range */
|
||||
msds_intid = generate_random() % 0X3FFFFFFF;
|
||||
msds_intid += 0x80000000;
|
||||
|
||||
/* probe id values until unique one is found */
|
||||
do {
|
||||
msds_intid++;
|
||||
if (msds_intid > 0xBFFFFFFF) {
|
||||
msds_intid = 0x80000001;
|
||||
}
|
||||
|
||||
ret = dsdb_module_search(ac->module, ac,
|
||||
&ldb_res,
|
||||
schema_dn, LDB_SCOPE_ONELEVEL, NULL, 0,
|
||||
"(msDS-IntId=%d)", msds_intid);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
ldb_debug_set(ldb, LDB_DEBUG_ERROR,
|
||||
__location__": Searching for msDS-IntId=%d failed - %s\n",
|
||||
msds_intid,
|
||||
ldb_errstring(ldb));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
id_exists = (ldb_res->count > 0);
|
||||
|
||||
talloc_free(ldb_res);
|
||||
} while(id_exists);
|
||||
|
||||
return ldb_msg_add_fmt(ac->msg, "msDS-IntId", "%d", msds_intid);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* samldb_add_entry (async)
|
||||
@ -870,6 +945,10 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
|
||||
}
|
||||
}
|
||||
|
||||
/* handle msDS-IntID attribute */
|
||||
ret = samldb_add_handle_msDS_IntId(ac);
|
||||
if (ret != LDB_SUCCESS) return ret;
|
||||
|
||||
ret = samldb_add_step(ac, samldb_add_entry);
|
||||
if (ret != LDB_SUCCESS) return ret;
|
||||
|
||||
@ -1763,6 +1842,14 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
|
||||
return LDB_ERR_UNWILLING_TO_PERFORM;
|
||||
}
|
||||
|
||||
/* msDS-IntId is not allowed to be modified
|
||||
* except when modification comes from replication */
|
||||
if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
|
||||
if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
|
||||
return LDB_ERR_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: do not modify original request, create a new one */
|
||||
|
||||
el = ldb_msg_find_element(req->op.mod.message, "groupType");
|
||||
|
@ -92,37 +92,6 @@ struct schema_data_search_data {
|
||||
const struct dsdb_schema *schema;
|
||||
};
|
||||
|
||||
/* context to be used during async operations */
|
||||
struct schema_data_context {
|
||||
struct ldb_module *module;
|
||||
struct ldb_request *req;
|
||||
|
||||
const struct dsdb_schema *schema;
|
||||
};
|
||||
|
||||
/* Create new context using
|
||||
* ldb_request as memory context */
|
||||
static int _schema_data_context_new(struct ldb_module *module,
|
||||
struct ldb_request *req,
|
||||
struct schema_data_context **pac)
|
||||
{
|
||||
struct schema_data_context *ac;
|
||||
struct ldb_context *ldb;
|
||||
|
||||
ldb = ldb_module_get_ctx(module);
|
||||
|
||||
*pac = ac = talloc_zero(req, struct schema_data_context);
|
||||
if (ac == NULL) {
|
||||
ldb_oom(ldb);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
ac->module = module;
|
||||
ac->req = req;
|
||||
ac->schema = dsdb_get_schema(ldb);
|
||||
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
static int schema_data_init(struct ldb_module *module)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
@ -163,57 +132,6 @@ static int schema_data_init(struct ldb_module *module)
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Generate new value for msDs-IntId
|
||||
* Value should be in 0x80000000..0xBFFFFFFF range
|
||||
* Generated value is added ldb_msg */
|
||||
static int _schema_data_gen_msds_intid(struct schema_data_context *ac,
|
||||
struct ldb_message *ldb_msg)
|
||||
{
|
||||
uint32_t id;
|
||||
|
||||
/* generate random num in 0x80000000..0xBFFFFFFF */
|
||||
id = generate_random() % 0X3FFFFFFF;
|
||||
id += 0x80000000;
|
||||
|
||||
/* make sure id is unique and adjust if not */
|
||||
while (dsdb_attribute_by_attributeID_id(ac->schema, id)) {
|
||||
id++;
|
||||
if (id > 0xBFFFFFFF) {
|
||||
id = 0x80000001;
|
||||
}
|
||||
}
|
||||
|
||||
/* add generated msDS-IntId value to ldb_msg */
|
||||
return ldb_msg_add_fmt(ldb_msg, "msDS-IntId", "%d", id);
|
||||
}
|
||||
|
||||
static int _schema_data_add_callback(struct ldb_request *req,
|
||||
struct ldb_reply *ares)
|
||||
{
|
||||
struct schema_data_context *ac;
|
||||
|
||||
ac = talloc_get_type(req->context, struct schema_data_context);
|
||||
|
||||
if (!ares) {
|
||||
return ldb_module_done(ac->req, NULL, NULL,
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
}
|
||||
if (ares->error != LDB_SUCCESS) {
|
||||
return ldb_module_done(ac->req, ares->controls,
|
||||
ares->response, ares->error);
|
||||
}
|
||||
|
||||
if (ares->type != LDB_REPLY_DONE) {
|
||||
talloc_free(ares);
|
||||
return ldb_module_done(ac->req, NULL, NULL,
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
}
|
||||
|
||||
return ldb_module_done(ac->req, ares->controls,
|
||||
ares->response, ares->error);
|
||||
}
|
||||
|
||||
static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
@ -251,11 +169,6 @@ static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
|
||||
governsID = ldb_msg_find_ldb_val(req->op.add.message, "governsID");
|
||||
|
||||
if (attributeID) {
|
||||
/* Sanity check for not allowed attributes */
|
||||
if (ldb_msg_find_ldb_val(req->op.add.message, "msDS-IntId")) {
|
||||
return LDB_ERR_UNWILLING_TO_PERFORM;
|
||||
}
|
||||
|
||||
oid_attr = "attributeID";
|
||||
oid = talloc_strndup(req, (const char *)attributeID->data, attributeID->length);
|
||||
} else if (governsID) {
|
||||
@ -290,67 +203,6 @@ 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)
|
||||
&& !(ldb_msg_find_attr_as_uint(req->op.add.message, "systemFlags", 0) & SYSTEM_FLAG_SCHEMA_BASE_OBJECT)) {
|
||||
struct ldb_message *msg;
|
||||
struct schema_data_context *ac;
|
||||
struct ldb_request *add_req;
|
||||
|
||||
if (_schema_data_context_new(module, req, &ac) != LDB_SUCCESS) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/* we have to copy the message as the caller might have it as a const */
|
||||
msg = ldb_msg_copy_shallow(ac, req->op.add.message);
|
||||
if (msg == NULL) {
|
||||
ldb_oom(ldb);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/* generate unique value for msDS-IntId attr value */
|
||||
if (_schema_data_gen_msds_intid(ac, msg) != LDB_SUCCESS) {
|
||||
ldb_debug_set(ldb, LDB_DEBUG_ERROR,
|
||||
"_schema_data_gen_msds_intid() failed to generate msDS-IntId value\n");
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ldb_build_add_req(&add_req, ldb, ac,
|
||||
msg,
|
||||
req->controls,
|
||||
ac, _schema_data_add_callback,
|
||||
req);
|
||||
|
||||
return ldb_next_request(module, add_req);
|
||||
}
|
||||
|
||||
return ldb_next_request(module, req);
|
||||
}
|
||||
|
||||
static int schema_data_modify(struct ldb_module *module, struct ldb_request *req)
|
||||
{
|
||||
/* special objects should always go through */
|
||||
if (ldb_dn_is_special(req->op.mod.message->dn)) {
|
||||
return ldb_next_request(module, req);
|
||||
}
|
||||
|
||||
/* replicated update should always go through */
|
||||
if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
|
||||
return ldb_next_request(module, req);
|
||||
}
|
||||
|
||||
/* msDS-IntId is not allowed to be modified */
|
||||
if (ldb_msg_find_ldb_val(req->op.mod.message, "msDS-IntId")) {
|
||||
return LDB_ERR_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
|
||||
/* go on with the call chain */
|
||||
return ldb_next_request(module, req);
|
||||
}
|
||||
|
||||
@ -609,6 +461,5 @@ _PUBLIC_ const struct ldb_module_ops ldb_schema_data_module_ops = {
|
||||
.name = "schema_data",
|
||||
.init_context = schema_data_init,
|
||||
.add = schema_data_add,
|
||||
.modify = schema_data_modify,
|
||||
.search = schema_data_search
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user