summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Campbell <bobcampbell@catalyst.net.nz>2016-09-05 10:48:13 +1200
committerKarolin Seeger <kseeger@samba.org>2016-10-20 10:45:28 +0200
commitc6578c38a96ee3df5c0c222dd910c1d852ad95aa (patch)
treeaf69f5f53dae78f3887567beaf29f7b8fb569380
parent7dbb5decf27bb9e6619c9a5f65a0461256f11d60 (diff)
downloadsamba-c6578c38a96ee3df5c0c222dd910c1d852ad95aa.tar.gz
dsdb: refactor part of garbage_collect_tombstones into new function
Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> Signed-off-by: Bob Campbell <bobcampbell@catalyst.net.nz> Signed-off-by: Garming Sam <garming@catalyst.net.nz> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12382 Reviewed-by: Andrew Bartlett <abartlet@samba.org> (cherry picked from commit 2dfedffb740ecfe898945a9fc47b24e3c8328d7e)
-rw-r--r--source4/dsdb/kcc/garbage_collect_tombstones.c385
1 files changed, 216 insertions, 169 deletions
diff --git a/source4/dsdb/kcc/garbage_collect_tombstones.c b/source4/dsdb/kcc/garbage_collect_tombstones.c
index 8d2ea8b477a..62e98137adf 100644
--- a/source4/dsdb/kcc/garbage_collect_tombstones.c
+++ b/source4/dsdb/kcc/garbage_collect_tombstones.c
@@ -33,6 +33,209 @@
#include "lib/ldb-samba/ldb_matching_rules.h"
#include "lib/util/time.h"
+static NTSTATUS garbage_collect_tombstones_part(TALLOC_CTX *mem_ctx,
+ struct ldb_context *samdb,
+ struct dsdb_ldb_dn_list_node *part,
+ char *filter,
+ unsigned int *num_links_removed,
+ unsigned int *num_objects_removed,
+ struct dsdb_schema *schema,
+ const char **attrs,
+ char **error_string,
+ NTTIME expunge_time_nttime)
+{
+ int ret;
+ struct ldb_dn *do_dn;
+ struct ldb_result *res;
+ unsigned int i, j, k;
+ uint32_t flags;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = dsdb_get_deleted_objects_dn(samdb, tmp_ctx, part->dn, &do_dn);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(tmp_ctx);
+ /* some partitions have no Deleted Objects
+ container */
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(1, ("Doing a full scan on %s and looking for deleted objects\n",
+ ldb_dn_get_linearized(part->dn)));
+
+ flags = DSDB_SEARCH_SHOW_RECYCLED |
+ DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
+ DSDB_SEARCH_REVEAL_INTERNALS;
+ ret = dsdb_search(samdb, tmp_ctx, &res, part->dn, LDB_SCOPE_SUBTREE,
+ attrs, flags, "%s", filter);
+
+ if (ret != LDB_SUCCESS) {
+ *error_string = talloc_asprintf(mem_ctx,
+ "Failed to search for deleted "
+ "objects in %s: %s",
+ ldb_dn_get_linearized(do_dn),
+ ldb_errstring(samdb));
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ for (i=0; i<res->count; i++) {
+ struct ldb_message *cleanup_msg = NULL;
+ unsigned int num_modified = 0;
+
+ bool isDeleted = ldb_msg_find_attr_as_bool(res->msgs[i],
+ "isDeleted", false);
+ if (isDeleted) {
+ if (ldb_dn_compare(do_dn, res->msgs[i]->dn) == 0) {
+ /* Skip the Deleted Object Container */
+ continue;
+ }
+
+ ret = dsdb_delete(samdb, res->msgs[i]->dn,
+ DSDB_SEARCH_SHOW_RECYCLED
+ |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)));
+ } else {
+ DEBUG(4,("Removed deleted object %s\n",
+ ldb_dn_get_linearized(res->
+ msgs[i]->dn)));
+ (*num_objects_removed)++;
+ }
+ continue;
+ }
+
+ /* This must have a linked attribute */
+
+ /*
+ * From MS-ADTS 3.1.1.1.9 DCs, usn Counters, and
+ * the Originating Update Stamp
+ *
+ * "A link value r is deleted, but exists as a
+ * tombstone, if r.stamp.timeDeleted ≠ 0. When
+ * the current time minus r.stamp.timeDeleted
+ * exceeds the tombstone lifetime, the link
+ * value r is garbage-collected; that is,
+ * removed from its containing forward link
+ * attribute. "
+ */
+
+ for (j=0; j < res->msgs[i]->num_elements; j++) {
+ struct ldb_message_element *element = NULL;
+ /* TODO this is O(log n) per attribute with deleted values */
+ const struct dsdb_attribute *attrib = NULL;
+
+ element = &res->msgs[i]->elements[j];
+ attrib = dsdb_attribute_by_lDAPDisplayName(schema,
+ element->name);
+
+ /* This avoids parsing isDeleted as a link */
+ if (attrib->linkID == 0 || ((attrib->linkID & 1) == 1)) {
+ continue;
+ }
+
+ for (k = 0; k < element->num_values; k++) {
+ struct ldb_val *value = &element->values[k];
+ uint64_t whenChanged = 0;
+ NTSTATUS status;
+ struct dsdb_dn *dn;
+ struct ldb_message_element *cleanup_elem = NULL;
+ char *guid_search_str = NULL;
+ char *guid_buf_str = NULL;
+ struct ldb_val cleanup_val;
+ struct GUID_txt_buf buf_guid;
+ struct GUID guid;
+ const struct ldb_val *guid_blob;
+
+ if (dsdb_dn_is_deleted_val(value) == false) {
+ continue;
+ }
+
+ dn = dsdb_dn_parse(tmp_ctx, samdb,
+ &element->values[k],
+ attrib->syntax->ldap_oid);
+ if (dn == NULL) {
+ DEBUG(1, ("Failed to parse linked attribute blob of "
+ "%s on %s while expunging expired links\n",
+ element->name,
+ ldb_dn_get_linearized(res->msgs[i]->dn)));
+ continue;
+ }
+
+ status = dsdb_get_extended_dn_uint64(dn->dn,
+ &whenChanged,
+ "RMD_CHANGETIME");
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Error: RMD_CHANGETIME is missing on a forward link.\n"));
+ talloc_free(dn);
+ continue;
+ }
+
+ if (whenChanged >= expunge_time_nttime) {
+ talloc_free(dn);
+ continue;
+ }
+
+ guid_blob = ldb_dn_get_extended_component(dn->dn, "GUID");
+ status = GUID_from_ndr_blob(guid_blob, &guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Error: Invalid GUID on link target.\n"));
+ talloc_free(dn);
+ continue;
+ }
+
+ guid_buf_str = GUID_buf_string(&guid, &buf_guid);
+ guid_search_str = talloc_asprintf(mem_ctx,
+ "<GUID=%s>",
+ guid_buf_str);
+ cleanup_val = data_blob_string_const(guid_search_str);
+
+ talloc_free(dn);
+
+ if (cleanup_msg == NULL) {
+ cleanup_msg = ldb_msg_new(mem_ctx);
+ if (cleanup_msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ cleanup_msg->dn = res->msgs[i]->dn;
+ }
+
+ ret = ldb_msg_add_value(cleanup_msg,
+ element->name,
+ &cleanup_val,
+ &cleanup_elem);
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ cleanup_elem->flags = LDB_FLAG_MOD_DELETE;
+ num_modified++;
+ }
+ }
+
+ if (num_modified > 0) {
+ ret = dsdb_modify(samdb, cleanup_msg,
+ DSDB_REPLMD_VANISH_LINKS);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1,(__location__ ": Failed to remove deleted object %s\n",
+ ldb_dn_get_linearized(res->msgs[i]->dn)));
+ } else {
+ DEBUG(4,("Removed deleted object %s\n",
+ ldb_dn_get_linearized(res->msgs[i]->dn)));
+ *num_links_removed = *num_links_removed + num_modified;
+ }
+
+ }
+ }
+
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
/*
* Per MS-ADTS 3.1.1.5.5 Delete Operation
*
@@ -58,11 +261,9 @@ NTSTATUS dsdb_garbage_collect_tombstones(TALLOC_CTX *mem_ctx,
unsigned int *num_links_removed,
char **error_string)
{
- int ret;
-
const char **attrs = NULL;
char *filter = NULL;
-
+ NTSTATUS status;
unsigned int i;
struct dsdb_attribute *next_attr;
unsigned int num_link_attrs;
@@ -117,178 +318,24 @@ NTSTATUS dsdb_garbage_collect_tombstones(TALLOC_CTX *mem_ctx,
attrs[i] = "isDeleted";
attrs[i+1] = NULL;
- filter = talloc_asprintf_append(filter, "(&(isDeleted=TRUE)(whenChanged<=%s)))", expunge_time_string);
+ filter = talloc_asprintf_append(filter,
+ "(&(isDeleted=TRUE)(whenChanged<=%s)))",
+ expunge_time_string);
if (filter == NULL) {
return NT_STATUS_NO_MEMORY;
}
- schema = dsdb_get_schema(samdb, mem_ctx);
-
for (; part != NULL; part = part->next) {
- struct ldb_dn *do_dn;
- struct ldb_result *res;
- unsigned int j, k;
- uint32_t flags;
- TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
- if (!tmp_ctx) {
- return NT_STATUS_NO_MEMORY;
- }
-
- ret = dsdb_get_deleted_objects_dn(samdb, tmp_ctx, part->dn, &do_dn);
- if (ret != LDB_SUCCESS) {
- TALLOC_FREE(tmp_ctx);
- /* some partitions have no Deleted Objects
- container */
- continue;
- }
-
- DEBUG(1, ("Doing a full scan on %s and looking for deleted objects\n",
- ldb_dn_get_linearized(part->dn)));
-
- flags = DSDB_SEARCH_SHOW_RECYCLED |
- DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
- DSDB_SEARCH_REVEAL_INTERNALS;
- ret = dsdb_search(samdb, tmp_ctx, &res, part->dn, LDB_SCOPE_SUBTREE,
- attrs, flags, "%s", filter);
-
- if (ret != LDB_SUCCESS) {
- *error_string = talloc_asprintf(mem_ctx, "Failed to search for deleted objects in %s: %s",
- ldb_dn_get_linearized(do_dn),
- ldb_errstring(samdb));
- TALLOC_FREE(tmp_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ status = garbage_collect_tombstones_part(mem_ctx, samdb, part,
+ filter,
+ num_links_removed,
+ num_objects_removed,
+ schema, attrs,
+ error_string,
+ expunge_time_nttime);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
-
- for (i=0; i<res->count; i++) {
- struct ldb_message *cleanup_msg = NULL;
- unsigned int num_modified = 0;
-
- bool isDeleted = ldb_msg_find_attr_as_bool(res->msgs[i], "isDeleted", false);
- if (isDeleted) {
- if (ldb_dn_compare(do_dn, res->msgs[i]->dn) == 0) {
- /* Skip the Deleted Object Container */
- continue;
- }
-
- ret = dsdb_delete(samdb, res->msgs[i]->dn, DSDB_SEARCH_SHOW_RECYCLED|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)));
- } else {
- DEBUG(4,("Removed deleted object %s\n",
- ldb_dn_get_linearized(res->msgs[i]->dn)));
- (*num_objects_removed)++;
- }
- continue;
- }
-
- /* This must have a linked attribute */
-
- /*
- * From MS-ADTS 3.1.1.1.9 DCs, usn Counters, and the Originating Update Stamp
- *
- * "A link value r is deleted, but exists as a
- * tombstone, if r.stamp.timeDeleted ≠ 0. When
- * the current time minus r.stamp.timeDeleted
- * exceeds the tombstone lifetime, the link
- * value r is garbage-collected; that is,
- * removed from its containing forward link
- * attribute. "
- */
-
- for (j=0; j < res->msgs[i]->num_elements; j++) {
- struct ldb_message_element *element = &res->msgs[i]->elements[j];
- /* TODO this is O(log n) per attribute with deleted values */
- const struct dsdb_attribute *attrib
- = dsdb_attribute_by_lDAPDisplayName(schema, element->name);
-
- /* This avoids parsing isDeleted as a link */
- if (attrib->linkID == 0 || ((attrib->linkID & 1) == 1)) {
- continue;
- }
-
- for (k = 0; k < element->num_values; k++) {
- struct ldb_val *value = &element->values[k];
- uint64_t whenChanged = 0;
- NTSTATUS status;
- struct dsdb_dn *dn;
- struct ldb_message_element *cleanup_elem = NULL;
- char *guid_search_str = NULL, *guid_buf_str = NULL;
- struct ldb_val cleanup_val;
- struct GUID_txt_buf buf_guid;
- struct GUID guid;
- const struct ldb_val *guid_blob;
-
- if (dsdb_dn_is_deleted_val(value) == false) {
- continue;
- }
-
- dn = dsdb_dn_parse(tmp_ctx, samdb, &element->values[k],
- attrib->syntax->ldap_oid);
- if (dn == NULL) {
- DEBUG(1, ("Failed to parse linked attribute blob of %s on %s while expunging expired links\n", element->name,
- ldb_dn_get_linearized(res->msgs[i]->dn)));
- continue;
- }
-
- status = dsdb_get_extended_dn_uint64(dn->dn, &whenChanged, "RMD_CHANGETIME");
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Error: RMD_CHANGETIME is missing on a forward link.\n"));
- talloc_free(dn);
- continue;
- }
-
- if (whenChanged >= expunge_time_nttime) {
- talloc_free(dn);
- continue;
- }
-
- guid_blob = ldb_dn_get_extended_component(dn->dn, "GUID");
- status = GUID_from_ndr_blob(guid_blob, &guid);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Error: Invalid GUID on link target.\n"));
- talloc_free(dn);
- continue;
- }
-
- guid_buf_str = GUID_buf_string(&guid, &buf_guid);
- guid_search_str = talloc_asprintf(mem_ctx, "<GUID=%s>", guid_buf_str);
- cleanup_val = data_blob_string_const(guid_search_str);
-
- talloc_free(dn);
-
- if (cleanup_msg == NULL) {
- cleanup_msg = ldb_msg_new(mem_ctx);
- if (cleanup_msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- cleanup_msg->dn = res->msgs[i]->dn;
- }
-
- ret = ldb_msg_add_value(cleanup_msg, element->name, &cleanup_val, &cleanup_elem);
- if (ret != LDB_SUCCESS) {
- return NT_STATUS_NO_MEMORY;
- }
- cleanup_elem->flags = LDB_FLAG_MOD_DELETE;
- num_modified++;
- }
- }
-
- if (num_modified > 0) {
- ret = dsdb_modify(samdb, cleanup_msg, DSDB_REPLMD_VANISH_LINKS);
- if (ret != LDB_SUCCESS) {
- DEBUG(1,(__location__ ": Failed to remove deleted object %s\n",
- ldb_dn_get_linearized(res->msgs[i]->dn)));
- } else {
- DEBUG(4,("Removed deleted object %s\n",
- ldb_dn_get_linearized(res->msgs[i]->dn)));
- *num_links_removed = *num_links_removed + num_modified;
- }
-
- }
- }
- TALLOC_FREE(tmp_ctx);
-
}
return NT_STATUS_OK;