summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_data.c147
1 files changed, 133 insertions, 14 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/schema_data.c b/source4/dsdb/samdb/ldb_modules/schema_data.c
index cc609581e4..2e99113953 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_data.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_data.c
@@ -92,6 +92,37 @@ 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;
@@ -132,6 +163,57 @@ 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;
@@ -187,23 +269,60 @@ static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
status = dsdb_schema_pfm_find_oid(schema->prefixmap, oid, NULL);
- if (W_ERROR_IS_OK(status)) {
- return ldb_next_request(module, req);
- } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
- ldb_debug_set(ldb, LDB_DEBUG_ERROR,
- "schema_data_add: failed to map %s[%s]: %s\n",
- oid_attr, oid, win_errstr(status));
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ if (!W_ERROR_IS_OK(status)) {
+ /* check for internal errors */
+ if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ "schema_data_add: failed to map %s[%s]: %s\n",
+ oid_attr, oid, win_errstr(status));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ /* Update prefixMap and save it */
+ status = dsdb_create_prefix_mapping(ldb, schema, oid);
+ if (!W_ERROR_IS_OK(status)) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ "schema_data_add: failed to create prefix mapping for %s[%s]: %s\n",
+ oid_attr, oid, win_errstr(status));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
}
- status = dsdb_create_prefix_mapping(ldb, schema, oid);
- if (!W_ERROR_IS_OK(status)) {
- ldb_debug_set(ldb, LDB_DEBUG_ERROR,
- "schema_data_add: failed to create prefix mapping for %s[%s]: %s\n",
- oid_attr, oid, win_errstr(status));
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ /* 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);