uint64_t seq_num;
bool is_urgent;
+ bool is_recycled_in_schema;
+ bool is_recycled_tested;
};
enum urgent_situation {
{
int ret = LDB_ERR_OTHER;
bool retb, disallow_move_on_delete;
+ bool add_recycled = false;
struct ldb_dn *old_dn, *new_dn;
const char *rdn_name;
const struct ldb_val *rdn_value, *new_rdn_value;
case OBJECT_TOMBSTONE:
/* we also mark it as recycled, meaning this object can't be
- recovered (we are stripping its attributes) */
- if (functional_level >= DS_DOMAIN_FUNCTION_2008_R2) {
+ recovered (we are stripping its attributes).
+ This is done only if we have this schema object of course ...
+ This behavior is identical to the one of Windows 2008R2 which
+ always set the isRecycled attribute if the recycle-bin is
+ not activated and what ever the forest level is.
+ */
+ if (functional_level < DS_DOMAIN_FUNCTION_2008_R2) {
+ if (dsdb_attribute_by_lDAPDisplayName(schema, "isRecycled") != NULL) {
+ add_recycled = true;
+ }
+ } else {
+ add_recycled = true;
+ }
+
+ if (add_recycled) {
ret = ldb_msg_add_string(msg, "isRecycled", "TRUE");
if (ret != LDB_SUCCESS) {
DEBUG(0,(__location__ ": Failed to add isRecycled string to the msg\n"));
struct replPropertyMetaDataBlob *md;
struct ldb_val md_value;
unsigned int i;
+ bool is_deleted = false;
+ bool is_recycled = false;
+ bool rcbin_enabled = false;
int ret;
/*
return replmd_replicated_request_error(ar, ret);
}
+ if (!ar->is_recycled_tested) {
+ if (dsdb_attribute_by_lDAPDisplayName(ar->schema, "isRecycled") != NULL) {
+ ar->is_recycled_in_schema = true;
+ }
+ ar->is_recycled_tested = true;
+ }
+
+ if (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008_R2) {
+ ret = dsdb_recyclebin_enabled(ar->module, &rcbin_enabled);
+ if (ret != LDB_SUCCESS) {
+ return replmd_replicated_request_error(ar, ret);
+ }
+ }
+
+
/* remove any message elements that have zero values */
for (i=0; i<msg->num_elements; i++) {
struct ldb_message_element *el = &msg->elements[i];
+ if (ldb_attr_cmp(el->name, "isDeleted") == 0) {
+ is_deleted = true;
+ }
+
+ if (ldb_attr_cmp(el->name, "isRecycled") == 0) {
+ is_recycled = true;
+ }
+
if (el->num_values == 0) {
DEBUG(4,(__location__ ": Removing attribute %s with num_values==0\n",
el->name));
}
}
+ if (is_deleted && ar->is_recycled_in_schema && !is_recycled && !rcbin_enabled) {
+ /*
+ * The object is deleted and we have the isRecycled attribute in
+ * the schema but it is missing on the object and the recycle-bin is not activated
+ * so we mark the object as deleted because it means that it comes from a
+ * pre windows 2008R2 server or from a Samba DC before changes related to isRecycled.*/
+
+ const struct dsdb_attribute *sa;
+ time_t t = time(NULL);
+ NTTIME now;
+ struct replPropertyMetaData1 *m;
+ const struct GUID *our_invocation_id;
+ const struct ldb_val* v;
+
+ v = ldb_dn_get_rdn_val(msg->dn);
+ if (!v || strcmp((char*)v->data, "Deleted Objects") == 0) {
+ goto noadd;
+ }
+
+ our_invocation_id = samdb_ntds_invocation_id(ldb);
+ if (!our_invocation_id) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ "replmd_add: unable to find invocationId\n");
+ return replmd_replicated_request_error(ar, LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ unix_to_nt_time(&now, t);
+
+ ret = ldb_msg_add_string(msg, "isRecycled", "TRUE");
+ if (ret != LDB_SUCCESS) {
+ return replmd_replicated_request_error(ar, ret);
+ }
+
+ md->ctr.ctr1.count++;
+ md->ctr.ctr1.array = talloc_realloc(ar, md->ctr.ctr1.array,
+ struct replPropertyMetaData1,
+ md->ctr.ctr1.count);
+
+ /* rdn is at the end so shift it to end first */
+ m = &md->ctr.ctr1.array[md->ctr.ctr1.count - 2];
+ md->ctr.ctr1.array[md->ctr.ctr1.count - 1] = *m;
+
+ /* Allocate a new entry in the replPropertyMetadata */
+ sa = dsdb_attribute_by_lDAPDisplayName(ar->schema, "isRecycled");
+
+ m->attid = sa->attributeID_id;
+ m->version = 1;
+ m->originating_change_time = now;
+ m->originating_invocation_id = *our_invocation_id;
+ m->originating_usn = ar->seq_num;
+ m->local_usn = ar->seq_num;
+ }
+noadd:
+
/*
* the meta data array is already sorted by the caller
*/