patch schemaUpdateNow

Anatoliy Atanasov anatoliy.atanasov at postpath.com
Mon Jul 21 11:09:08 GMT 2008


Hi Andrew,

Here is a patch for reloading the schema when schemaUpdateNow happens.

Regards,
Anatoliy



-------------- next part --------------
diff --git a/source/dsdb/samdb/ldb_modules/partition.c b/source/dsdb/samdb/ldb_modules/partition.c
index 22826e4..5cac3e5 100644
--- a/source/dsdb/samdb/ldb_modules/partition.c
+++ b/source/dsdb/samdb/ldb_modules/partition.c
@@ -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) == 0) {
+		return partition_extended_schema_update_now( module, req );
+	}	
+
 	/* 
 	 * as the extended operation has no dn
 	 * we need to send it to all partitions
diff --git a/source/dsdb/samdb/ldb_modules/rootdse.c b/source/dsdb/samdb/ldb_modules/rootdse.c
index 75f99a1..889ec3a 100644
--- a/source/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source/dsdb/samdb/ldb_modules/rootdse.c
@@ -391,9 +391,49 @@ 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
+	*/
+	if (!ldb_dn_is_null(req->op.mod.message->dn)) {
+		return ldb_next_request(module, req);
+	}
+	
+	/*
+		"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, 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
 };
diff --git a/source/dsdb/samdb/ldb_modules/schema_fsmo.c b/source/dsdb/samdb/ldb_modules/schema_fsmo.c
index a397228..b06aed2 100644
--- a/source/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source/dsdb/samdb/ldb_modules/schema_fsmo.c
@@ -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) != 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
 };
diff --git a/source/dsdb/samdb/samdb.h b/source/dsdb/samdb/samdb.h
index 75aa819..5a5fe3c 100644
--- a/source/dsdb/samdb/samdb.h
+++ b/source/dsdb/samdb/samdb.h
@@ -90,4 +90,6 @@ struct dsdb_pdc_fsmo {
 	struct ldb_dn *master_dn;
 };
 
+#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW "1.3.6.1.4.1.7165.4.4.2"
+
 #endif /* __SAMDB_H__ */


More information about the samba-technical mailing list