s4/schema: Move msDS-IntId implementation to samldb.c module
authorKamen Mazdrashki <kamen.mazdrashki@postpath.com>
Tue, 23 Feb 2010 23:45:26 +0000 (01:45 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 24 Feb 2010 01:01:51 +0000 (12:01 +1100)
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>
source4/dsdb/samdb/ldb_modules/samldb.c
source4/dsdb/samdb/ldb_modules/schema_data.c

index 9d79776e6689f8ca1b1496e803489f1b9983f2aa..6420e05ba89fd81dd4c0456a936d3eeab45c5971 100644 (file)
@@ -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");
index 8125a46cbb080873602e658b7bd8e710eec41577..d15c6756751dd0ea56a709db2aa0d3a99675f68f 100644 (file)
@@ -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
 };