s4:dsdb/schema: remember if a backlink attribute is not allowed on class 'top'
authorStefan Metzmacher <metze@samba.org>
Wed, 1 Mar 2023 10:30:55 +0000 (11:30 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 23 Mar 2023 07:16:34 +0000 (07:16 +0000)
Backlink attributes which are not "allowed" in objectClass 'top'
are always possible, but only visible by default based on the
real objectClass.

In order to avoid pay the cost for finding out if a backlink
should be visible or not, we remember a 'bool bl_maybe_invisible'
both on the forward link as well as the backlink dsdb_attribute.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/dsdb/schema/schema.h
source4/dsdb/schema/schema_set.c

index 8e335830e3a94a139c3e09a3e510709748a3dfa1..aaa2a9f9275e53eb187d80d2b0bc3216707444a5 100644 (file)
@@ -118,6 +118,7 @@ struct dsdb_attribute {
        bool systemOnly;
 
        bool one_way_link;
+       bool bl_maybe_invisible;
        enum dsdb_dn_format dn_format;
 
        /* internal stuff */
index 45faa0912ec648c59b8b93b3909c87c00e18c6ae..090f54684169a48750e1251a01d6fb86a7a4bab5 100644 (file)
@@ -397,11 +397,23 @@ wrong_mode:
 static void dsdb_setup_attribute_shortcuts(struct ldb_context *ldb, struct dsdb_schema *schema)
 {
        struct dsdb_attribute *attribute;
+       const struct dsdb_class *top_class = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+       const char **top_allowed_attrs = NULL;
+
+       top_class = dsdb_class_by_lDAPDisplayName(schema, "top");
+       if (top_class != NULL) {
+               top_allowed_attrs = dsdb_attribute_list(frame,
+                                                       top_class,
+                                                       DSDB_SCHEMA_ALL);
+       }
 
        /* setup fast access to one_way_link and DN format */
        for (attribute=schema->attributes; attribute; attribute=attribute->next) {
                attribute->dn_format = dsdb_dn_oid_to_format(attribute->syntax->ldap_oid);
 
+               attribute->bl_maybe_invisible = false;
+
                if (attribute->dn_format == DSDB_INVALID_DN) {
                        attribute->one_way_link = false;
                        continue;
@@ -419,6 +431,34 @@ static void dsdb_setup_attribute_shortcuts(struct ldb_context *ldb, struct dsdb_
                        attribute->one_way_link = true;
                        continue;
                }
+
+               if (attribute->linkID & 1) {
+                       const struct dsdb_attribute *fw_attr = NULL;
+                       bool in_top = false;
+
+                       if (top_allowed_attrs != NULL) {
+                               in_top = str_list_check(top_allowed_attrs,
+                                               attribute->lDAPDisplayName);
+                       }
+
+                       if (in_top) {
+                               continue;
+                       }
+
+                       attribute->bl_maybe_invisible = true;
+
+                       fw_attr = dsdb_attribute_by_linkID(schema,
+                                                       attribute->linkID - 1);
+                       if (fw_attr != NULL) {
+                               struct dsdb_attribute *_fw_attr =
+                                       discard_const_p(struct dsdb_attribute,
+                                                       fw_attr);
+                               _fw_attr->bl_maybe_invisible = true;
+                       }
+
+                       continue;
+               }
+
                /* handle attributes with a linkID but no backlink */
                if ((attribute->linkID & 1) == 0 &&
                    dsdb_attribute_by_linkID(schema, attribute->linkID + 1) == NULL) {
@@ -427,6 +467,8 @@ static void dsdb_setup_attribute_shortcuts(struct ldb_context *ldb, struct dsdb_
                }
                attribute->one_way_link = false;
        }
+
+       TALLOC_FREE(frame);
 }
 
 static int uint32_cmp(uint32_t c1, uint32_t c2)