diff options
-rw-r--r-- | source4/dsdb/common/dsdb_dn.h | 5 | ||||
-rw-r--r-- | source4/dsdb/common/util.c | 48 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 66 | ||||
-rw-r--r-- | source4/lib/ldb-samba/ldif_handlers.c | 2 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/getncchanges.c | 2 |
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; |