Handle schema reloading request.
authorAnatoliy Atanasov <anatoliy.atanasov@postpath.com>
Wed, 23 Jul 2008 06:59:17 +0000 (09:59 +0300)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 24 Jul 2008 01:54:30 +0000 (11:54 +1000)
The ldif for that operation looks like this:

dn:
changetype: Modify
add: schemaUpdateNow
schemaUpdateNow: 1

It uses the rootdse's object functional attribute schemaUpdateNow.
In rootdse_modify() this command is being recognized and it is send as extended operation with DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID.
In the partition module its dispatched to the schema_fsmo module.
The request is processed in the schema_fsmo module by schema_fsmo_extended().
(This used to be commit 39f9184ddf215f2b512319211c0a05702218ef87)

source4/dsdb/samdb/ldb_modules/partition.c
source4/dsdb/samdb/ldb_modules/rootdse.c
source4/dsdb/samdb/ldb_modules/schema_fsmo.c
source4/dsdb/samdb/samdb.h

index 22826e4f3346325a7d55122cbb9d7ab992bc49d7..9285d6d0d862e6e2d73b05f5db85d412ff356fed 100644 (file)
@@ -699,6 +699,50 @@ static int partition_extended_replicated_objects(struct ldb_module *module, stru
        return partition_replicate(module, req, ext->partition_dn);
 }
 
+static int partition_extended_schema_update_now(struct ldb_module *module, struct ldb_request *req)
+{
+       struct dsdb_control_current_partition *partition;
+       struct partition_private_data *data;
+       struct ldb_dn *schema_dn;
+       struct partition_context *ac;
+       struct ldb_module *backend;
+       int ret;
+
+       schema_dn = talloc_get_type(req->op.extended.data, struct ldb_dn);
+       if (!schema_dn) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "partition_extended: invalid extended data\n");
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
+
+       data = talloc_get_type(module->private_data, struct partition_private_data);
+       if (!data) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       partition = find_partition( data, schema_dn );
+       if (!partition) {
+               return ldb_next_request(module, req);
+       }
+
+       ac = partition_init_handle(req, module);
+       if (!ac) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       backend = make_module_for_next_request(req, module->ldb, partition->module);
+       if (!backend) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, false, partition);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       return ldb_next_request(backend, req);
+}
+
+
 /* extended */
 static int partition_extended(struct ldb_module *module, struct ldb_request *req)
 {
@@ -708,6 +752,11 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req
                return partition_extended_replicated_objects(module, req);
        }
 
+       /* forward schemaUpdateNow operation to schema_fsmo module*/
+       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) {
+               return partition_extended_schema_update_now( module, req );
+       }       
+
        /* 
         * as the extended operation has no dn
         * we need to send it to all partitions
index 75f99a139d797b17cbcc57be97fd36f1fd440818..97491a2ae3911825b1bbeece0625c5d16948c94c 100644 (file)
@@ -391,9 +391,50 @@ static int rootdse_init(struct ldb_module *module)
        return ldb_next_init(module);
 }
 
+static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
+{
+       struct ldb_result *ext_res;
+       int ret;
+       struct ldb_dn *schema_dn;
+       struct ldb_message_element *schemaUpdateNowAttr;
+       
+       /*
+               If dn is not "" we should let it pass through
+       */
+       if (!ldb_dn_is_null(req->op.mod.message->dn)) {
+               return ldb_next_request(module, req);
+       }
+       
+       /*
+               dn is empty so check for schemaUpdateNow attribute
+               "The type of modification and values specified in the LDAP modify operation do not matter." MSDN
+       */
+       schemaUpdateNowAttr = ldb_msg_find_element(req->op.mod.message, "schemaUpdateNow");
+       if (!schemaUpdateNowAttr) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       schema_dn = samdb_schema_dn(module->ldb);
+       if (!schema_dn) {
+               ldb_reset_err_string(module->ldb);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+                         "rootdse_modify: no schema dn present: (skip ldb_extended call)\n");
+               return ldb_next_request(module, req);
+       }
+
+       ret = ldb_extended(module->ldb, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, schema_dn, &ext_res);
+       if (ret != LDB_SUCCESS) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       talloc_free(ext_res);
+       return ret;
+}
+
 _PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = {
        .name                   = "rootdse",
-       .init_context           = rootdse_init,
-       .search                 = rootdse_search,
-       .request                = rootdse_request
+       .init_context   = rootdse_init,
+       .search         = rootdse_search,
+       .request                = rootdse_request,
+       .modify         = rootdse_modify
 };
index a3972287232600541bb5e28e961124d9f355873f..2acc5c0af4a6d29114a7515994f8582affd72290 100644 (file)
@@ -148,8 +148,70 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
        return ldb_next_request(module, req);
 }
 
+static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req)
+{
+       WERROR status;
+       struct ldb_dn *schema_dn;
+       struct dsdb_schema *schema;
+       char *error_string = NULL;
+       int ret;
+       TALLOC_CTX *mem_ctx;
+       
+       if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
+               return ldb_next_request(module, req);
+       }
+       
+       schema_dn = samdb_schema_dn(module->ldb);
+       if (!schema_dn) {
+               ldb_reset_err_string(module->ldb);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+                         "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
+               return ldb_next_request(module, req);
+       }
+       
+       mem_ctx = talloc_new(module);
+       if (!mem_ctx) {
+               ldb_oom(module->ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
+                                        lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
+                                        schema_dn, &schema, &error_string);
+
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ldb_reset_err_string(module->ldb);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+                         "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
+               talloc_free(mem_ctx);
+               return ldb_next_request(module, req);
+       }
+
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(module->ldb, 
+                                      "schema_fsmo_extended: dsdb_schema load failed: %s",
+                                      error_string);
+               talloc_free(mem_ctx);
+               return ldb_next_request(module, req);
+       }
+
+       /* Replace the old schema*/
+       ret = dsdb_set_schema(module->ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
+                             "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
+                             ret, ldb_strerror(ret));
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       talloc_free(mem_ctx);
+       return LDB_SUCCESS;
+}
+
 _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
        .name           = "schema_fsmo",
        .init_context   = schema_fsmo_init,
-       .add            = schema_fsmo_add
+       .add            = schema_fsmo_add,
+       .extended       = schema_fsmo_extended
 };
index 75aa819ccdd5809fc6dbe00a879e79d35c8fefbe..b8a3e16d465597b1acdbd8228c011bfb064a587f 100644 (file)
@@ -90,4 +90,6 @@ struct dsdb_pdc_fsmo {
        struct ldb_dn *master_dn;
 };
 
+#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
+
 #endif /* __SAMDB_H__ */