s4-dsdb: switched to using RMD_FLAGS instead of DELETED in extended DNs
authorAndrew Tridgell <tridge@samba.org>
Fri, 1 Jan 2010 21:14:52 +0000 (08:14 +1100)
committerAndrew Tridgell <tridge@samba.org>
Fri, 1 Jan 2010 21:16:57 +0000 (08:16 +1100)
This allows for more flags in the future

source4/dsdb/common/dsdb_dn.h
source4/dsdb/common/util.c
source4/dsdb/samdb/ldb_modules/repl_meta_data.c
source4/lib/ldb-samba/ldif_handlers.c
source4/rpc_server/drsuapi/getncchanges.c

index 53e10535c84500d7d347e08e7c98a28240dc443d..b713bdd27b9a76cd7196a159d4fe1ea58af38335 100644 (file)
@@ -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
index 5d9ec1182f8e1007672a7b9d832941f3b9fd5575..b8ba26a4ec41dc85546ca235bba6c337b30d6b74 100644 (file)
@@ -2894,18 +2894,52 @@ NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const cha
        return NT_STATUS_OK;
 }
 
+/*
+  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;
 }
 
 /*
index 202b74e8b496171b5d071f514d168387e94606ab..890eb91d6d4d90ad3e0b8552126afb9f252e4f40 100644 (file)
@@ -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) {
index 7ddc8e57a750c0a967f126e92cca302fe58d1a17..4611eba3f11ced083836217d0dc98bcf1c2c1e44 100644 (file)
@@ -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
index a41d116b6aad1193649ce8245acf9303f1c56b35..437dc87ae893a1d6cacf46947d85fa802c087080 100644 (file)
@@ -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;