[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Mar 23 08:20:01 UTC 2023


The branch, master has been updated
       via  e7ef43cead4 s4:dsdb/extended_dn_out: hide backlinks with DSDB_RMD_FLAG_HIDDEN_BL by default
       via  ad3694c491a s4:dsdb/extended_dn_out: use dsdb_dn_val_rmd_flags() instead of dsdb_dn_is_deleted_val()
       via  06fb5cdffdd s4:dsdb/extended_dn_out: make use of the existing have_reveal_control variable
       via  ea4f2b9f544 s4:dsdb/objectclass_attrs: allow all backlinks even if not allowed by the schema
       via  732bf8164df s4:dsdb/repl_meta_data: let replmd_process_backlink() set DSDB_RMD_FLAG_HIDDEN_BL is needed
       via  8ee7d232b10 s4:dsdb/common: rename DSDB_RMD_FLAG_INVISIBLE to DSDB_RMD_FLAG_HIDDEN_BL
       via  2340443c3be s4:dsdb/repl_meta_data: let replmd_process_backlink() use the source_dn variable
       via  c9fac2e912a s4:dsdb/repl_meta_data: let replmd_process_backlink() use dsdb_module_obj_by_guid()
       via  36bd0287ea7 s4:dsdb/util: split out dsdb_module_obj_by_guid() from dsdb_module_dn_by_guid()
       via  e519416e995 s4:dsdb/repl_meta_data: check replmd_add_backlink() result in replmd_modify_la_add()
       via  f9391ec448b s3:dsdb/repl_meta_data: fix possible memleak on error in replmd_modify_la_add()
       via  bd3596233f2 s4:dsdb/schema: remember if a backlink attribute is not allowed on class 'top'
       via  21f4317acb9 s4:dsdb/tests: let a test to demonstrate the behavior of invisible backlinks
       via  d43f6fb3004 s4:dsdb/tests: let linked_attributes.py use a container as testbase
       via  c6e1e5aae6b script/autobuild: Use logger.debug() for debug messages (visible with --verbose)
       via  0b29e12dc7a script/autobuild: Use --verbose to control python logger verbosity
       via  fdb7ec64432 script/autobuild: Use python logger to print times on log lines to aid in debugging.
      from  86b6353644d python:join: run domain adprep as part of join_provision_own_domain()

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e7ef43cead4ddab85e96b176c7c9123c28a033d2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 9 15:04:26 2023 +0100

    s4:dsdb/extended_dn_out: hide backlinks with DSDB_RMD_FLAG_HIDDEN_BL by default
    
    Backlinks which are not allowed by the schema are hidden by default,
    so we already set DSDB_RMD_FLAG_HIDDEN_BL on store, so we have a cheap
    way to hide the backlinks.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Mar 23 08:19:20 UTC 2023 on atb-devel-224

commit ad3694c491a6822cb5c571b5017b650a9d1e86c1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 9 15:04:26 2023 +0100

    s4:dsdb/extended_dn_out: use dsdb_dn_val_rmd_flags() instead of dsdb_dn_is_deleted_val()
    
    We now check for DSDB_RMD_FLAG_DELETED, as we'll check for
    DSDB_RMD_FLAG_HIDDEN_BL in the next step and it's better to
    call dsdb_dn_val_rmd_flags() just once.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 06fb5cdffdd1c5d7ac85746fd67cd8c30eb5ace4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 9 15:03:58 2023 +0100

    s4:dsdb/extended_dn_out: make use of the existing have_reveal_control variable
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ea4f2b9f544324d917d901e427b8629807ea9af1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 9 15:02:15 2023 +0100

    s4:dsdb/objectclass_attrs: allow all backlinks even if not allowed by the schema
    
    This only verifies internals store operations, adding invalid forward
    links is already checked in other places.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 732bf8164dff8fd3b5892a7858d8baedae6ed46e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 01:10:37 2023 +0100

    s4:dsdb/repl_meta_data: let replmd_process_backlink() set DSDB_RMD_FLAG_HIDDEN_BL is needed
    
    If we find that the backlink should not be visible on the given objectClass
    by default, we now set DSDB_RMD_FLAG_HIDDEN_BL.
    
    We'll evaluate that in the next commits in order to hide the
    backlink by default.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8ee7d232b1088f027b5f9d2bb4c11b15c3e9b0be
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 15 15:02:29 2023 +0100

    s4:dsdb/common: rename DSDB_RMD_FLAG_INVISIBLE to DSDB_RMD_FLAG_HIDDEN_BL
    
    DSDB_RMD_FLAG_INVISIBLE was introduced in commit
    00b39c70f57882a453a8d2e6b0f1f37fd39a2d2a, but never used.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2340443c3be8684e102c235c776f47498ecc50d3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 00:42:53 2023 +0100

    s4:dsdb/repl_meta_data: let replmd_process_backlink() use the source_dn variable
    
    We first create source_dn as trimmed down copy of bl->forward_dn
    and then only use it for debug messages.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c9fac2e912a30d92cceaea63ea684985a6d7c545
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 00:42:28 2023 +0100

    s4:dsdb/repl_meta_data: let replmd_process_backlink() use dsdb_module_obj_by_guid()
    
    This will simplify the following changes.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 36bd0287ea7d35b03c5cc0e77d00079268192212
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 00:38:06 2023 +0100

    s4:dsdb/util: split out dsdb_module_obj_by_guid() from dsdb_module_dn_by_guid()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e519416e995d8c91653eb01f7f603c602fd282fe
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 14:06:30 2023 +0100

    s4:dsdb/repl_meta_data: check replmd_add_backlink() result in replmd_modify_la_add()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f9391ec448b28fcb3b55b6f70bed980b0422ffb3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 21:04:56 2023 +0100

    s3:dsdb/repl_meta_data: fix possible memleak on error in replmd_modify_la_add()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit bd3596233f26cdc2e3c591bccf09b2cdceeac023
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 1 11:30:55 2023 +0100

    s4:dsdb/schema: remember if a backlink attribute is not allowed on class 'top'
    
    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 at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 21f4317acb9917e9f9394e6c44fcc5ba46f92dfb
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 15 12:16:30 2023 +0100

    s4:dsdb/tests: let a test to demonstrate the behavior of invisible backlinks
    
    msDS-KeyCredentialLink/msDS-KeyCredentialLink-BL are defined as linked attribute pair,
    but msDS-KeyCredentialLink-BL is not defined as allowed on any object class definition,
    still it's possible to create msDS-KeyCredentialLink attributes.
    
    msDS-KeyPrincipal/msDS-KeyPrincipalBL are also defined as linked attribute pair
    and msDS-KeyPrincipalBL is only allowed on object class 'user', but it's possible
    to create msDS-KeyPrincipal values pointing to non 'user' objects.
    
    The result is that 'user' objects have a visible msDS-KeyPrincipalBL, but
    the others don't have msDS-KeyPrincipalBL visible, by default.
    The backlinks are always visible if the backlink attributes are
    explicitly requested.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d43f6fb3004177adc16d1961d9371144ec245db2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 15 12:15:45 2023 +0100

    s4:dsdb/tests: let linked_attributes.py use a container as testbase
    
    The tests don't require an organizationalUnit as parent object
    and it makes it possible to create msDS-KeyCredential objects
    within the container in the next step.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12967
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c6e1e5aae6ba59dc604c46aec42c92eea927d611
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Mar 23 14:41:15 2023 +1300

    script/autobuild: Use logger.debug() for debug messages (visible with --verbose)
    
    Lots of the autobuild.py log outputs are really debugging, so should be
    controlled as such.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 0b29e12dc7a51c7c2cf3ea8cceffebd338497c83
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Mar 23 14:39:55 2023 +1300

    script/autobuild: Use --verbose to control python logger verbosity
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit fdb7ec64432daefd3664acde5ae640a440a8f871
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Mar 23 14:28:49 2023 +1300

    script/autobuild: Use python logger to print times on log lines to aid in debugging.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

-----------------------------------------------------------------------

Summary of changes:
 script/autobuild.py                                |  41 +++++---
 source4/dsdb/common/dsdb_dn.h                      |   7 +-
 source4/dsdb/samdb/ldb_modules/extended_dn_out.c   |  32 +++++-
 source4/dsdb/samdb/ldb_modules/objectclass_attrs.c |   8 ++
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    | 107 ++++++++++++++++++-
 source4/dsdb/samdb/ldb_modules/util.c              |  43 ++++++--
 source4/dsdb/schema/schema.h                       |   1 +
 source4/dsdb/schema/schema_set.c                   |  42 ++++++++
 source4/dsdb/tests/python/linked_attributes.py     | 114 +++++++++++++++++++--
 9 files changed, 361 insertions(+), 34 deletions(-)


Changeset truncated at 500 lines:

diff --git a/script/autobuild.py b/script/autobuild.py
index 492085a5bbb..e074c39d3c0 100755
--- a/script/autobuild.py
+++ b/script/autobuild.py
@@ -19,12 +19,17 @@ from email.mime.multipart import MIMEMultipart
 from sysconfig import get_path
 import platform
 
+import logging
+
 try:
     from waflib.Build import CACHE_SUFFIX
 except ImportError:
     sys.path.insert(0, "./third_party/waf")
     from waflib.Build import CACHE_SUFFIX
 
+logging.basicConfig(format='%(asctime)s %(message)s')
+logger = logging.getLogger('autobuild')
+logger.setLevel(logging.INFO)
 
 os.environ["PYTHONUNBUFFERED"] = "1"
 
@@ -104,6 +109,9 @@ if options.retry:
     if options.rebase is None:
         raise Exception('You can only use --retry if you also rebase')
 
+if options.verbose:
+    logger.setLevel(logging.DEBUG)
+
 if options.full_testbase is not None:
     testbase = options.full_testbase
 else:
@@ -1186,16 +1194,22 @@ if os.environ.get("AUTOBUILD_SKIP_SAMBA_O3", "0") == "1":
 
 
 def do_print(msg):
-    print("%s" % msg)
+    logger.info(msg)
+    sys.stdout.flush()
+    sys.stderr.flush()
+
+def do_debug(msg):
+    logger.debug(msg)
     sys.stdout.flush()
     sys.stderr.flush()
 
 
 def run_cmd(cmd, dir=".", show=None, output=False, checkfail=True):
     if show is None:
-        show = options.verbose
-    if show:
+        do_debug("Running: '%s' in '%s'" % (cmd, dir))
+    elif show:
         do_print("Running: '%s' in '%s'" % (cmd, dir))
+
     if output:
         out = check_output([cmd], shell=True, cwd=dir)
         return out.decode(encoding='utf-8', errors='backslashreplace')
@@ -1233,9 +1247,8 @@ class builder(object):
         self.next = 0
         self.stdout_path = "%s/%s.stdout" % (gitroot, self.tag)
         self.stderr_path = "%s/%s.stderr" % (gitroot, self.tag)
-        if options.verbose:
-            do_print("stdout for %s in %s" % (self.name, self.stdout_path))
-            do_print("stderr for %s in %s" % (self.name, self.stderr_path))
+        do_debug("stdout for %s in %s" % (self.name, self.stdout_path))
+        do_debug("stderr for %s in %s" % (self.name, self.stderr_path))
         run_cmd("rm -f %s %s" % (self.stdout_path, self.stderr_path))
         self.stdout = open(self.stdout_path, 'w')
         self.stderr = open(self.stderr_path, 'w')
@@ -1252,12 +1265,12 @@ class builder(object):
             assert "dependency" not in definition
 
     def mark_existing(self):
-        do_print('%s: Mark as existing dependency' % self.name)
+        do_debug('%s: Mark as existing dependency' % self.name)
         self.next = len(self.sequence)
         self.done = True
 
     def add_consumer(self, consumer):
-        do_print("%s: add consumer: %s" % (self.name, consumer.name))
+        do_debug("%s: add consumer: %s" % (self.name, consumer.name))
         consumer.producer = self
         consumer.test_source_dir = self.test_source_dir
         self.consumers.append(consumer)
@@ -1265,7 +1278,7 @@ class builder(object):
     def start_next(self):
         if self.producer is not None:
             if not self.producer.done:
-                do_print("%s: Waiting for producer: %s" % (self.name, self.producer.name))
+                do_debug("%s: Waiting for producer: %s" % (self.name, self.producer.name))
                 return
 
         if self.next == 0:
@@ -1355,9 +1368,9 @@ class buildlist(object):
 
         tasknames = implicit_tasknames.copy()
         tasknames.extend(given_tasknames)
-        do_print("given_tasknames: %s" % given_tasknames)
-        do_print("implicit_tasknames: %s" % implicit_tasknames)
-        do_print("tasknames: %s" % tasknames)
+        do_debug("given_tasknames: %s" % given_tasknames)
+        do_debug("implicit_tasknames: %s" % implicit_tasknames)
+        do_debug("tasknames: %s" % tasknames)
         self.tlist = [builder(n, tasks[n]) for n in tasknames]
 
         if options.retry:
@@ -1393,11 +1406,11 @@ class buildlist(object):
                     b.mark_existing()
 
         for b in self.tlist:
-            do_print("b.name=%s" % b.name)
+            do_debug("b.name=%s" % b.name)
             if "dependency" not in b.definition:
                 continue
             depname = b.definition["dependency"]
-            do_print("b.name=%s: dependency:%s" % (b.name, depname))
+            do_debug("b.name=%s: dependency:%s" % (b.name, depname))
             for p in self.tlist:
                 if p.name == depname:
                     p.add_consumer(b)
diff --git a/source4/dsdb/common/dsdb_dn.h b/source4/dsdb/common/dsdb_dn.h
index 8aadac7f2df..f98e3e79351 100644
--- a/source4/dsdb/common/dsdb_dn.h
+++ b/source4/dsdb/common/dsdb_dn.h
@@ -13,4 +13,9 @@ struct dsdb_dn {
 
 /* RMD_FLAGS component in a DN */
 #define DSDB_RMD_FLAG_DELETED     1
-#define DSDB_RMD_FLAG_INVISIBLE   2
+/*
+ * This is used on a backlink attribute
+ * if the backlink is not allowed on
+ * the objectClass
+ */
+#define DSDB_RMD_FLAG_HIDDEN_BL   2
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
index 53cbe345070..a8b4437354c 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
@@ -303,6 +303,7 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
 	 * interpret the list with) */
 	for (i = 0; ac->schema && i < msg->num_elements; i++) {
 		bool make_extended_dn;
+		bool bl_requested = true;
 		const struct dsdb_attribute *attribute;
 
 		attribute = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name);
@@ -338,23 +339,47 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
 			make_extended_dn = (strcmp(attribute->syntax->ldap_oid, DSDB_SYNTAX_OR_NAME) != 0);
 		}
 
+		if (attribute->linkID & 1 &&
+		    attribute->bl_maybe_invisible &&
+		    !have_reveal_control)
+		{
+			const char * const *attrs = ac->req->op.search.attrs;
+
+			if (attrs != NULL) {
+				bl_requested = is_attr_in_list(attrs,
+						attribute->lDAPDisplayName);
+			} else {
+				bl_requested = false;
+			}
+		}
+
 		for (k = 0, j = 0; j < msg->elements[i].num_values; j++) {
 			const char *dn_str;
 			struct ldb_dn *dn;
 			struct dsdb_dn *dsdb_dn = NULL;
 			struct ldb_val *plain_dn = &msg->elements[i].values[j];
 			bool is_deleted_objects = false;
+			uint32_t rmd_flags;
 
 			/* this is a fast method for detecting deleted
 			   linked attributes, working on the unparsed
 			   ldb_val */
-			if (dsdb_dn_is_deleted_val(plain_dn) && !have_reveal_control) {
+			rmd_flags = dsdb_dn_val_rmd_flags(plain_dn);
+			if (rmd_flags & DSDB_RMD_FLAG_DELETED && !have_reveal_control) {
 				/* it's a deleted linked attribute,
 				  and we don't have the reveal control */
 				/* we won't keep this one, so not incrementing k */
 				continue;
 			}
-
+			if (rmd_flags & DSDB_RMD_FLAG_HIDDEN_BL && !bl_requested) {
+				/*
+				 * Hidden backlinks are not revealed unless
+				 * requested.
+				 *
+				 * we won't keep this one, so not incrementing k
+				 */
+				continue;
+			}
 
 			dsdb_dn = dsdb_dn_parse_trusted(msg, ldb, plain_dn, attribute->syntax->ldap_oid);
 
@@ -402,8 +427,7 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
 					talloc_free(dsdb_dn);
 					return ldb_module_done(ac->req, NULL, NULL, ret);
 				}
-				if (remove_value &&
-				    !ldb_request_get_control(req, LDB_CONTROL_REVEAL_INTERNALS)) {
+				if (remove_value && !have_reveal_control) {
 					/* we show these with REVEAL
 					   to allow dbcheck to find and
 					   cleanup these orphaned links */
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
index 2a77353cdfc..da4217a2ff3 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
@@ -452,6 +452,14 @@ static int attr_handler2(struct oc_context *ac)
 			return ldb_operr(ldb);
 		}
 
+		if (attr->linkID & 1) {
+			/*
+			 * We need to allow backlinks on all objects
+			 * even if the schema doesn't allow it.
+			 */
+			continue;
+		}
+
 		/* We can use "str_list_check" with "strcmp" here since the
 		 * attribute information from the schema are always equal
 		 * up-down-cased. */
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index cb32d190dce..1975c01b91d 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -367,6 +367,8 @@ struct la_backlink {
 	struct ldb_dn *forward_dn;
 	struct GUID target_guid;
 	bool active;
+	bool bl_maybe_invisible;
+	bool bl_invisible;
 };
 
 /*
@@ -418,6 +420,52 @@ static int linked_attr_modify(struct ldb_module *module,
 	return ret;
 }
 
+static int replmd_backlink_invisible(struct ldb_module *module,
+				     struct ldb_message *msg,
+				     struct la_backlink *bl)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(module);
+	const struct dsdb_schema *schema = NULL;
+	TALLOC_CTX *frame = NULL;
+	struct ldb_message_element *oc_element = NULL;
+	const char **allowed_attrs = NULL;
+	bool bl_allowed;
+
+	if (!bl->active || !bl->bl_maybe_invisible || bl->bl_invisible) {
+		return LDB_SUCCESS;
+	}
+
+	schema = dsdb_get_schema(ldb, NULL);
+	if (schema == NULL) {
+		return ldb_module_operr(module);
+	}
+
+	oc_element = ldb_msg_find_element(msg, "objectClass");
+	if (oc_element == NULL) {
+		return ldb_module_operr(module);
+	}
+
+	frame = talloc_stackframe();
+
+	allowed_attrs = dsdb_full_attribute_list(frame,
+						 schema,
+						 oc_element,
+						 DSDB_SCHEMA_ALL);
+	if (allowed_attrs == NULL) {
+		TALLOC_FREE(frame);
+		return ldb_module_oom(module);
+	}
+
+	bl_allowed = str_list_check(allowed_attrs, bl->attr_name);
+	if (!bl_allowed) {
+		bl->bl_maybe_invisible = false;
+		bl->bl_invisible = true;
+	}
+
+	TALLOC_FREE(frame);
+	return LDB_SUCCESS;
+}
+
 /*
   process a backlinks we accumulated during a transaction, adding and
   deleting the backlinks from the target objects
@@ -425,19 +473,35 @@ static int linked_attr_modify(struct ldb_module *module,
 static int replmd_process_backlink(struct ldb_module *module, struct la_backlink *bl, struct ldb_request *parent)
 {
 	struct ldb_dn *target_dn, *source_dn;
+	struct ldb_message *old_msg = NULL;
+	const char * const empty_attrs[] = { NULL };
+	const char * const oc_attrs[] = { "objectClass", NULL };
+	const char * const *attrs = NULL;
+	uint32_t rmd_flags = 0;
 	int ret;
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
 	struct ldb_message *msg;
 	TALLOC_CTX *frame = talloc_stackframe();
 	char *dn_string;
 
+	if (bl->active && bl->bl_maybe_invisible) {
+		attrs = oc_attrs;
+	} else {
+		attrs = empty_attrs;
+	}
+
 	/*
 	  - find DN of target
 	  - find DN of source
 	  - construct ldb_message
               - either an add or a delete
 	 */
-	ret = dsdb_module_dn_by_guid(module, frame, &bl->target_guid, &target_dn, parent);
+	ret = dsdb_module_obj_by_guid(module,
+				      frame,
+				      &old_msg,
+				      &bl->target_guid,
+				      attrs,
+				      parent);
 	if (ret != LDB_SUCCESS) {
 		struct GUID_txt_buf guid_str;
 		DBG_WARNING("Failed to find target DN for linked attribute with GUID %s\n",
@@ -446,6 +510,17 @@ static int replmd_process_backlink(struct ldb_module *module, struct la_backlink
 		talloc_free(frame);
 		return LDB_SUCCESS;
 	}
+	target_dn = old_msg->dn;
+
+	ret = replmd_backlink_invisible(module, old_msg, bl);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(frame);
+		return ret;
+	}
+
+	if (bl->active && bl->bl_invisible) {
+		rmd_flags |= DSDB_RMD_FLAG_HIDDEN_BL;
+	}
 
 	msg = ldb_msg_new(frame);
 	if (msg == NULL) {
@@ -465,9 +540,28 @@ static int replmd_process_backlink(struct ldb_module *module, struct la_backlink
 		ldb_dn_extended_filter(source_dn, accept);
 	}
 
+	if (rmd_flags != 0) {
+		const char *flags_string = NULL;
+		struct ldb_val flagsv;
+
+		flags_string = talloc_asprintf(frame, "%u", rmd_flags);
+		if (flags_string == NULL) {
+			talloc_free(frame);
+			return ldb_module_oom(module);
+		}
+
+		flagsv = data_blob_string_const(flags_string);
+
+		ret = ldb_dn_set_extended_component(source_dn, "RMD_FLAGS", &flagsv);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(frame);
+			return ret;
+		}
+	}
+
 	/* construct a ldb_message for adding/deleting the backlink */
 	msg->dn = target_dn;
-	dn_string = ldb_dn_get_extended_linearized(frame, bl->forward_dn, 1);
+	dn_string = ldb_dn_get_extended_linearized(frame, source_dn, 1);
 	if (!dn_string) {
 		ldb_module_oom(module);
 		talloc_free(frame);
@@ -549,6 +643,8 @@ static int replmd_defer_add_backlink(struct ldb_module *module,
 	bl->forward_dn = talloc_steal(bl, forward_dn);
 	bl->target_guid = *target_guid;
 	bl->active = active;
+	bl->bl_maybe_invisible = target_attr->bl_maybe_invisible;
+	bl->bl_invisible = false;
 
 	DLIST_ADD(ac->la_backlinks, bl);
 
@@ -586,6 +682,8 @@ static int replmd_add_backlink(struct ldb_module *module,
 	bl.forward_dn = forward_dn;
 	bl.target_guid = *target_guid;
 	bl.active = active;
+	bl.bl_maybe_invisible = target_attr->bl_maybe_invisible;
+	bl.bl_invisible = false;
 
 	ret = replmd_process_backlink(module, &bl, parent);
 	return ret;
@@ -2719,6 +2817,7 @@ static int replmd_modify_la_add(struct ldb_module *module,
 				ret = really_parse_trusted_dn(tmp_ctx, ldb, next,
 							      schema_attr->syntax->ldap_oid);
 				if (ret != LDB_SUCCESS) {
+					talloc_free(tmp_ctx);
 					return ret;
 				}
 			}
@@ -2736,6 +2835,10 @@ static int replmd_modify_la_add(struct ldb_module *module,
 					  &dns[i].guid,
 					  true, schema_attr,
 					  parent);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			return ret;
+		}
 		/* Make the new linked attribute ldb_val. */
 		ret = replmd_build_la_val(new_values, &new_values[num_values],
 					  dns[i].dsdb_dn, &ac->our_invocation_id,
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
index c2949f0734d..69820983f88 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -255,14 +255,16 @@ int dsdb_module_search(struct ldb_module *module,
 }
 
 /*
-  find a DN given a GUID. This searches across all partitions
+  find an object given a GUID. This searches across all partitions
  */
-int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
-			   const struct GUID *guid, struct ldb_dn **dn,
-			   struct ldb_request *parent)
+int dsdb_module_obj_by_guid(struct ldb_module *module,
+			    TALLOC_CTX *mem_ctx,
+			    struct ldb_message **_msg,
+			    const struct GUID *guid,
+			    const char * const *attrs,
+			    struct ldb_request *parent)
 {
 	struct ldb_result *res;
-	const char *attrs[] = { NULL };
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 	int ret;
 
@@ -289,7 +291,36 @@ int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
-	*dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
+	*_msg = talloc_steal(mem_ctx, res->msgs[0]);
+
+	talloc_free(tmp_ctx);
+	return LDB_SUCCESS;
+}
+
+/*
+  find a DN given a GUID. This searches across all partitions
+ */
+int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+			   const struct GUID *guid, struct ldb_dn **dn,
+			   struct ldb_request *parent)
+{
+	struct ldb_message *msg = NULL;
+	const char *attrs[] = { NULL };
+	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+	int ret;
+
+	ret = dsdb_module_obj_by_guid(module,
+				      tmp_ctx,
+				      &msg,
+				      guid,
+				      attrs,
+				      parent);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(tmp_ctx);
+		return ret;
+	}
+
+	*dn = talloc_steal(mem_ctx, msg->dn);
 
 	talloc_free(tmp_ctx);
 	return LDB_SUCCESS;
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index 8e335830e3a..aaa2a9f9275 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -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 */
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
index 45faa0912ec..090f5468416 100644
--- a/source4/dsdb/schema/schema_set.c
+++ b/source4/dsdb/schema/schema_set.c
@@ -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;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list