summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/common/dsdb_dn.h5
-rw-r--r--source4/dsdb/common/util.c48
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c66
-rw-r--r--source4/lib/ldb-samba/ldif_handlers.c2
-rw-r--r--source4/rpc_server/drsuapi/getncchanges.c2
5 files changed, 83 insertions, 40 deletions
diff --git a/source4/dsdb/common/dsdb_dn.h b/source4/dsdb/common/dsdb_dn.h
index 53e10535c8..b713bdd27b 100644
--- a/source4/dsdb/common/dsdb_dn.h
+++ b/source4/dsdb/common/dsdb_dn.h
@@ -15,3 +15,8 @@ struct dsdb_dn {
#define DSDB_SYNTAX_BINARY_DN "1.2.840.113556.1.4.903"
#define DSDB_SYNTAX_STRING_DN "1.2.840.113556.1.4.904"
#define DSDB_SYNTAX_OR_NAME "1.2.840.113556.1.4.1221"
+
+
+/* RMD_FLAGS component in a DN */
+#define DSDB_RMD_FLAG_DELETED 1
+#define DSDB_RMD_FLAG_INVISIBLE 2
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 5d9ec1182f..b8ba26a4ec 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -2895,17 +2895,51 @@ NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const cha
}
/*
+ return RMD_FLAGS directly from a ldb_dn
+ returns 0 if not found
+ */
+uint32_t dsdb_dn_rmd_flags(struct ldb_dn *dn)
+{
+ const struct ldb_val *v;
+ char buf[32];
+ v = ldb_dn_get_extended_component(dn, "RMD_FLAGS");
+ if (!v || v->length > sizeof(buf)-1) return 0;
+ strncpy(buf, (const char *)v->data, v->length);
+ buf[v->length] = 0;
+ return strtoul(buf, NULL, 10);
+}
+
+/*
+ return RMD_FLAGS directly from a ldb_val for a DN
+ returns 0 if RMD_FLAGS is not found
+ */
+uint32_t dsdb_dn_val_rmd_flags(struct ldb_val *val)
+{
+ const char *p;
+ uint32_t flags;
+ char *end;
+
+ if (val->length < 13) {
+ return 0;
+ }
+ p = memmem(val->data, val->length-2, "<RMD_FLAGS=", 11);
+ if (!p) {
+ return 0;
+ }
+ flags = strtoul(p+11, &end, 10);
+ if (!end || *end != '>') {
+ /* it must end in a > */
+ return 0;
+ }
+ return flags;
+}
+
+/*
return true if a ldb_val containing a DN in storage form is deleted
*/
bool dsdb_dn_is_deleted_val(struct ldb_val *val)
{
- /* this relies on the sort order and exact format of
- linearized extended DNs */
- if (val->length >= 12 &&
- strncmp((const char *)val->data, "<DELETED=1>;", 12) == 0) {
- return true;
- }
- return false;
+ return (dsdb_dn_val_rmd_flags(val) & DSDB_RMD_FLAG_DELETED) != 0;
}
/*
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 202b74e8b4..890eb91d6d 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -1204,7 +1204,7 @@ static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx,
/*
build a new extended DN, including all meta data fields
- DELETED = 1 or missing
+ RMD_FLAGS = DSDB_RMD_FLAG_* bits
RMD_ADDTIME = originating_add_time
RMD_INVOCID = originating_invocation_id
RMD_CHANGETIME = originating_change_time
@@ -1217,15 +1217,16 @@ static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct ds
uint64_t local_usn, NTTIME nttime, uint32_t version, bool deleted)
{
struct ldb_dn *dn = dsdb_dn->dn;
- const char *tstring, *usn_string;
+ const char *tstring, *usn_string, *flags_string;
struct ldb_val tval;
struct ldb_val iid;
struct ldb_val usnv, local_usnv;
- struct ldb_val vers;
+ struct ldb_val vers, flagsv;
NTSTATUS status;
int ret;
const char *dnstring;
char *vstring;
+ uint32_t rmd_flags = deleted?DSDB_RMD_FLAG_DELETED:0;
tstring = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)nttime);
if (!tstring) {
@@ -1246,6 +1247,9 @@ static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct ds
local_usnv = data_blob_string_const(usn_string);
vstring = talloc_asprintf(mem_ctx, "%lu", (unsigned long)version);
+ if (!vstring) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
vers = data_blob_string_const(vstring);
status = GUID_to_ndr_blob(invocation_id, dn, &iid);
@@ -1253,13 +1257,13 @@ static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct ds
return LDB_ERR_OPERATIONS_ERROR;
}
- if (deleted) {
- struct ldb_val dv;
- dv = data_blob_string_const("1");
- ret = ldb_dn_set_extended_component(dn, "DELETED", &dv);
- } else {
- ret = ldb_dn_set_extended_component(dn, "DELETED", NULL);
+ flags_string = talloc_asprintf(mem_ctx, "%u", rmd_flags);
+ if (!flags_string) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
+ flagsv = data_blob_string_const(flags_string);
+
+ ret = ldb_dn_set_extended_component(dn, "RMD_FLAGS", &flagsv);
if (ret != LDB_SUCCESS) return ret;
ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", &tval);
if (ret != LDB_SUCCESS) return ret;
@@ -1325,17 +1329,18 @@ static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct d
uint32_t version, bool deleted)
{
struct ldb_dn *dn = dsdb_dn->dn;
- const char *tstring, *usn_string;
+ const char *tstring, *usn_string, *flags_string;
struct ldb_val tval;
struct ldb_val iid;
struct ldb_val usnv, local_usnv;
- struct ldb_val vers;
+ struct ldb_val vers, flagsv;
const struct ldb_val *old_addtime;
uint32_t old_version;
NTSTATUS status;
int ret;
const char *dnstring;
char *vstring;
+ uint32_t rmd_flags = deleted?DSDB_RMD_FLAG_DELETED:0;
tstring = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)nttime);
if (!tstring) {
@@ -1360,13 +1365,13 @@ static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct d
return LDB_ERR_OPERATIONS_ERROR;
}
- if (deleted) {
- struct ldb_val dv;
- dv = data_blob_string_const("1");
- ret = ldb_dn_set_extended_component(dn, "DELETED", &dv);
- } else {
- ret = ldb_dn_set_extended_component(dn, "DELETED", NULL);
+ flags_string = talloc_asprintf(mem_ctx, "%u", rmd_flags);
+ if (!flags_string) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
+ flagsv = data_blob_string_const(flags_string);
+
+ ret = ldb_dn_set_extended_component(dn, "RMD_FLAGS", &flagsv);
if (ret != LDB_SUCCESS) return ret;
/* get the ADDTIME from the original */
@@ -1484,9 +1489,9 @@ static int replmd_modify_la_add(struct ldb_module *module,
} else {
/* this is only allowed if the GUID was
previously deleted. */
- const struct ldb_val *v;
- v = ldb_dn_get_extended_component(p->dsdb_dn->dn, "DELETED");
- if (v == NULL) {
+ uint32_t rmd_flags = dsdb_dn_rmd_flags(p->dsdb_dn->dn);
+
+ if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
ldb_asprintf_errstring(ldb, "Attribute %s already exists for target GUID %s",
el->name, GUID_string(tmp_ctx, p->guid));
talloc_free(tmp_ctx);
@@ -1595,7 +1600,7 @@ static int replmd_modify_la_delete(struct ldb_module *module,
for (i=0; i<el->num_values; i++) {
struct parsed_dn *p = &dns[i];
struct parsed_dn *p2;
- const struct ldb_val *v;
+ uint32_t rmd_flags;
p2 = parsed_dn_find(old_dns, old_el->num_values, p->guid, NULL);
if (!p2) {
@@ -1603,8 +1608,8 @@ static int replmd_modify_la_delete(struct ldb_module *module,
el->name, GUID_string(tmp_ctx, p->guid));
return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
- v = ldb_dn_get_extended_component(p2->dsdb_dn->dn, "DELETED");
- if (v) {
+ rmd_flags = dsdb_dn_rmd_flags(p2->dsdb_dn->dn);
+ if (rmd_flags & DSDB_RMD_FLAG_DELETED) {
ldb_asprintf_errstring(ldb, "Attribute %s already deleted for target GUID %s",
el->name, GUID_string(tmp_ctx, p->guid));
return LDB_ERR_NO_SUCH_ATTRIBUTE;
@@ -1616,14 +1621,14 @@ static int replmd_modify_la_delete(struct ldb_module *module,
*/
for (i=0; i<old_el->num_values; i++) {
struct parsed_dn *p = &old_dns[i];
- const struct ldb_val *v;
+ uint32_t rmd_flags;
if (el->num_values && parsed_dn_find(dns, el->num_values, p->guid, NULL) == NULL) {
continue;
}
- v = ldb_dn_get_extended_component(p->dsdb_dn->dn, "DELETED");
- if (v != NULL) continue;
+ rmd_flags = dsdb_dn_rmd_flags(p->dsdb_dn->dn);
+ if (rmd_flags & DSDB_RMD_FLAG_DELETED) continue;
ret = replmd_update_la_val(old_el->values, p->v, p->dsdb_dn, p->dsdb_dn,
invocation_id, seq_num, seq_num, now, 0, true);
@@ -1710,10 +1715,9 @@ static int replmd_modify_la_replace(struct ldb_module *module,
for (i=0; i<old_num_values; i++) {
struct parsed_dn *old_p = &old_dns[i];
struct parsed_dn *p;
- const struct ldb_val *v;
+ uint32_t rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
- v = ldb_dn_get_extended_component(old_p->dsdb_dn->dn, "DELETED");
- if (v) continue;
+ if (rmd_flags & DSDB_RMD_FLAG_DELETED) continue;
ret = replmd_add_backlink(module, schema, msg_guid, old_dns[i].guid, false, schema_attr, false);
if (ret != LDB_SUCCESS) {
@@ -3519,7 +3523,7 @@ linked_attributes[0]:
struct GUID invocation_id = GUID_zero();
uint32_t version = 0;
NTTIME change_time = 0;
- bool was_active = ldb_dn_get_extended_component(pdn->dsdb_dn->dn, "DELETED") == NULL;
+ uint32_t rmd_flags = dsdb_dn_rmd_flags(pdn->dsdb_dn->dn);
dsdb_get_extended_dn_guid(pdn->dsdb_dn->dn, &invocation_id, "RMD_INVOCID");
dsdb_get_extended_dn_uint32(pdn->dsdb_dn->dn, &version, "RMD_VERSION");
@@ -3545,7 +3549,7 @@ linked_attributes[0]:
return ret;
}
- if (was_active) {
+ if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
/* remove the existing backlink */
ret = replmd_add_backlink(module, schema, &la->identifier->guid, &guid, false, attr, false);
if (ret != LDB_SUCCESS) {
diff --git a/source4/lib/ldb-samba/ldif_handlers.c b/source4/lib/ldb-samba/ldif_handlers.c
index 7ddc8e57a7..4611eba3f1 100644
--- a/source4/lib/ldb-samba/ldif_handlers.c
+++ b/source4/lib/ldb-samba/ldif_handlers.c
@@ -870,7 +870,7 @@ static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
.write_clear_fn = ldif_write_objectGUID,
.write_hex_fn = extended_dn_write_hex
},{
- .name = "DELETED",
+ .name = "RMD_FLAGS",
.read_fn = ldb_handler_copy,
.write_clear_fn = ldb_handler_copy,
.write_hex_fn = ldb_handler_copy
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index a41d116b6a..437dc87ae8 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -256,7 +256,7 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx,
la->identifier = get_object_identifier(*la_list, msg);
W_ERROR_HAVE_NO_MEMORY(la->identifier);
- active = ldb_dn_get_extended_component(dsdb_dn->dn, "DELETED")?false:true;
+ active = (dsdb_dn_rmd_flags(dsdb_dn->dn) & DSDB_RMD_FLAG_DELETED) == 0;
la->attid = sa->attributeID_id;
la->flags = active?DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE:0;