summaryrefslogtreecommitdiffstats
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2014-04-03 14:50:05 +1300
committerAndrew Bartlett <abartlet@samba.org>2014-05-03 07:57:12 +0200
commitb19d80d0a97faffc165f068612f74d4ef8d7e5da (patch)
treefe2227c6f898ccfa7dd22715a9362152d8aa5947 /source4
parent4b324f7f08829ca3df0af291301d5272ae5cede1 (diff)
downloadsamba-b19d80d0a97faffc165f068612f74d4ef8d7e5da.tar.gz
samba-b19d80d0a97faffc165f068612f74d4ef8d7e5da.tar.xz
samba-b19d80d0a97faffc165f068612f74d4ef8d7e5da.zip
dsdb: Make it harder to corrupt the database by requiring DBCHECK or RELAX for final object deletion
This kind of deletion can cause us to then replicate back a partial object. We allow dbcheck to directly remove totally corrupt objects (missing an objectclass) by specifying both DBCHECK and RELAX, and the tombstone sweep after 180 days is done with the RELAX control. Andrew Bartlett Change-Id: Ic21f68e507ba9b65e035ca568430e35e2d001c7d Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/kcc/kcc_deleted.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c40
2 files changed, 32 insertions, 10 deletions
diff --git a/source4/dsdb/kcc/kcc_deleted.c b/source4/dsdb/kcc/kcc_deleted.c
index 63bb97c08d..331d4fbe67 100644
--- a/source4/dsdb/kcc/kcc_deleted.c
+++ b/source4/dsdb/kcc/kcc_deleted.c
@@ -128,7 +128,7 @@ NTSTATUS kccsrv_check_deleted(struct kccsrv_service *s, TALLOC_CTX *mem_ctx)
whenChanged = ldb_string_to_time(tstring);
}
if (t - whenChanged > tombstoneLifetime*60*60*24) {
- ret = dsdb_delete(s->samdb, res->msgs[i]->dn, DSDB_SEARCH_SHOW_DELETED);
+ ret = dsdb_delete(s->samdb, res->msgs[i]->dn, DSDB_SEARCH_SHOW_DELETED|DSDB_MODIFY_RELAX);
if (ret != LDB_SUCCESS) {
DEBUG(1,(__location__ ": Failed to remove deleted object %s\n",
ldb_dn_get_linearized(res->msgs[i]->dn)));
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index b01c956d1c..83dabdfdf3 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -2991,6 +2991,20 @@ static int replmd_delete_internals(struct ldb_module *module, struct ldb_request
return ldb_next_request(module, req);
}
+ /*
+ * We have to allow dbcheck to remove an object that
+ * is beyond repair, and to do so totally. This could
+ * mean we we can get a partial object from the other
+ * DC, causing havoc, so dbcheck suggests
+ * re-replication first. dbcheck sets both DBCHECK
+ * and RELAX in this situation.
+ */
+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)
+ && ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
+ /* really, really remove it */
+ return ldb_next_request(module, req);
+ }
+
tmp_ctx = talloc_new(ldb);
if (!tmp_ctx) {
ldb_oom(ldb);
@@ -3034,17 +3048,25 @@ static int replmd_delete_internals(struct ldb_module *module, struct ldb_request
}
if (next_deletion_state == OBJECT_REMOVED) {
- struct auth_session_info *session_info =
- (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
- if (security_session_user_level(session_info, NULL) != SECURITY_SYSTEM) {
- ldb_asprintf_errstring(ldb, "Refusing to delete deleted object %s",
- ldb_dn_get_linearized(old_msg->dn));
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ /*
+ * We have to prevent objects being deleted, even if
+ * the administrator really wants them gone, as
+ * without the tombstone, we can get a partial object
+ * from the other DC, causing havoc.
+ *
+ * The only other valid case is when the 180 day
+ * timeout has expired, when relax is specified.
+ */
+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
+ /* it is already deleted - really remove it this time */
+ talloc_free(tmp_ctx);
+ return ldb_next_request(module, req);
}
- /* it is already deleted - really remove it this time */
- talloc_free(tmp_ctx);
- return ldb_next_request(module, req);
+ ldb_asprintf_errstring(ldb, "Refusing to delete tombstone object %s. "
+ "This check is to prevent corruption of the replicated state.",
+ ldb_dn_get_linearized(old_msg->dn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
}
rdn_name = ldb_dn_get_rdn_name(old_dn);