Adds final schema consistency check before committing changes.
Aborts if corruption found.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12889
Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
}
talloc_free(ext_res);
- /* Save our updated prefixMap */
+ /* Save our updated prefixMap and check the schema is good. */
if (working_schema) {
+ struct ldb_result *ext_res_2;
+
werr = dsdb_write_prefixes_from_schema_to_ldb(working_schema,
ldb,
working_schema);
if (used_global_schema) {
dsdb_set_global_schema(ldb);
} else if (cur_schema ) {
- dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
+ dsdb_reference_schema(ldb,
+ cur_schema,
+ SCHEMA_MEMORY_ONLY);
}
DEBUG(0,("Failed to save updated prefixMap: %s\n",
win_errstr(werr)));
TALLOC_FREE(tmp_ctx);
return werr;
}
+
+ /*
+ * Use dsdb_schema_from_db through dsdb extended to check we
+ * can load the schema currently sitting in the transaction.
+ * We need this check because someone might have written to
+ * the schema or prefixMap before we started the transaction,
+ * which may have caused corruption.
+ */
+ ret = ldb_extended(ldb, DSDB_EXTENDED_SCHEMA_LOAD,
+ NULL, &ext_res_2);
+
+ if (ret != LDB_SUCCESS) {
+ if (used_global_schema) {
+ dsdb_set_global_schema(ldb);
+ } else if (cur_schema) {
+ dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
+ }
+ DEBUG(0,("Corrupt schema write attempt detected, "
+ "aborting schema modification operation.\n"
+ "This probably happened due to bad timing of "
+ "another schema edit: %s (%s)\n",
+ ldb_errstring(ldb),
+ ldb_strerror(ret)));
+ ldb_transaction_cancel(ldb);
+ TALLOC_FREE(tmp_ctx);
+ return WERR_FOOBAR;
+ }
}
ret = ldb_transaction_prepare_commit(ldb);
struct dsdb_schema *schema;
int ret;
- if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
- return ldb_next_request(module, req);
- }
- /* Force a refresh */
- schema = dsdb_get_schema(ldb, NULL);
+ if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_LOAD) == 0) {
- ret = dsdb_schema_set_indices_and_attributes(ldb,
- schema,
- SCHEMA_WRITE);
-
- if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb, "Failed to write new "
- "@INDEXLIST and @ATTRIBUTES "
- "records for updated schema: %s",
- ldb_errstring(ldb));
+ ret = dsdb_schema_from_db(module, req, 0, &schema);
+ if (ret == LDB_SUCCESS) {
+ return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+ }
return ret;
+
+ } else if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) {
+ /* Force a refresh */
+ schema = dsdb_get_schema(ldb, NULL);
+
+ ret = dsdb_schema_set_indices_and_attributes(ldb,
+ schema,
+ SCHEMA_WRITE);
+
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to write new "
+ "@INDEXLIST and @ATTRIBUTES "
+ "records for updated schema: %s",
+ ldb_errstring(ldb));
+ return ret;
+ }
+
+ return ldb_next_request(module, req);
+ } else {
+ /* Pass to next module, the partition one should finish the chain */
+ return ldb_next_request(module, req);
}
-
- /* Pass to next module, the partition one should finish the chain */
- return ldb_next_request(module, req);
}
static int schema_read_lock(struct ldb_module *module)
*/
#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
+#define DSDB_EXTENDED_SCHEMA_LOAD "1.3.6.1.4.1.7165.4.4.10"
+
#define DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID "1.3.6.1.4.1.7165.4.4.6"
#define DSDB_OPENLDAP_DEREFERENCE_CONTROL "1.3.6.1.4.1.4203.666.5.16"