[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Tue Feb 14 05:15:02 UTC 2017


The branch, master has been updated
       via  4f558c9 repl_meta_data: Remove the correct forward link for dn+binary attributes
       via  056b6b8 repl_meta_data: Add comment with some future improvements
       via  75d523f repl_meta_data: Always sort the links when upgrading them
       via  6ee0ace repl_meta_data: Bring replmd_check_upgrade_links() into get_parsed_dns_trusted()
       via  b6902fd python/tests: Add test for generated and duplicate mAPIIDs
       via  ec11d65 samldb: Allow automatic generation of mAPIIDs
       via  1c16e8a torture/drs: Add a test for dn+binary linked attributes
       via  bfe423a torture/drs: run repl_schema in vampire_2000_dc environment as well
       via  1983d07 selftest: add vampire_2000_dc environment
       via  305cdce python/tests: add test for generated and duplicate linkIDs
       via  373bd43 torture/drs: generate linkID for test rather than specifying
       via  35be7ee samldb: Allow automatic generation of linkIDs and prevent duplicates
      from  85d5b43 waf: Do not install the unit test binary for krb5samba

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


- Log -----------------------------------------------------------------
commit 4f558c9ad6f9b8a947e33207473579655708eed0
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Oct 12 15:51:37 2015 +1300

    repl_meta_data: Remove the correct forward link for dn+binary attributes
    
    The previous code assumed that only plain DNs could be linked attributes.
    
    We need to look over the list of attribute values and find the value
    that causes this particular backlink to exist, so we can remove it.
    
    We do not know (until we search) of the binary portion, so we must
    search over all the attribute values at this layer, using the
    parsed_dn_find() routine used elsewhere in this code.
    
    Found attempting to demote an RODC in a clone of a Windows 2012R2
    domain, due to the msDS-RevealedUsers attribute.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Tue Feb 14 06:14:35 CET 2017 on sn-devel-144

commit 056b6b8e5c5203d642cc2c9cbe2e9c36dff6bc56
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Feb 14 12:11:19 2017 +1300

    repl_meta_data: Add comment with some future improvements
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit 75d523f5792275b8aa357d0f266b0bc9b7a1c935
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Feb 14 12:08:35 2017 +1300

    repl_meta_data: Always sort the links when upgrading them
    
    This allows us to know that the output of get_parsed_dns_trusted() is sorted, as an
    upgraded attribute of FL2000 links would not otherwise be sorted in the DB
    
    This allows us to delete linked objects that have a forward link from a
    FL2000 style linked attribute once the DN+Binary patches land.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit 6ee0aceae17991d3eb665e9f19399be1a03b1ace
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Feb 14 11:59:13 2017 +1300

    repl_meta_data: Bring replmd_check_upgrade_links() into get_parsed_dns_trusted()
    
    This eliminates a lot of duplicate code and allows us to know that we will
    have a set of FL2003 style links in the parsed DNs to operate on
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit b6902fd637f22f2740d1ae1eb5ac73aadc9a0f30
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Feb 8 11:55:32 2017 +1300

    python/tests: Add test for generated and duplicate mAPIIDs
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ec11d65bef7aaea155fb40e87a74210166eca7dd
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Feb 8 11:40:32 2017 +1300

    samldb: Allow automatic generation of mAPIIDs
    
    This allows us to conform to MS-ADTS 3.1.1.2.3.2, where the OID
    1.2.840.113556.1.2.49 can be specified as the mAPIID of a new attribute
    in the schema in order to automatically assign it an unused mAPIID.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1c16e8abd28fd05ab169b7a6bc11f102264def3e
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Feb 3 10:34:14 2017 +1300

    torture/drs: Add a test for dn+binary linked attributes
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139

commit bfe423a6607e2b80d1fd946bcaf303c0be2b757b
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Feb 3 10:33:54 2017 +1300

    torture/drs: run repl_schema in vampire_2000_dc environment as well
    
    This will be necessary as linked attributes are handled differently in
    Windows 2000.
    
    We also only check msDS-IntId if we have a functional level of > Windows
    2000, as this attribute is not present on lower domain function levels.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139

commit 1983d078f62d1e4f6597ef549f576e72285b25a5
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Feb 8 09:16:41 2017 +1300

    selftest: add vampire_2000_dc environment
    
    This is the equivalent of vampire_dc, but using a domain functional
    level of DS_DOMAIN_FUNCTION_2000.
    
    Using this functional level is useful for tests involving replication
    and linked attributes, as they behave differently at it.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139
    Pair-programmed-with: Bob Campbell <bobcampbell at catalyst.net.nz>

commit 305cdcea8851d389aa7c6b9da69441c2aacee432
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Thu Feb 2 09:46:26 2017 +1300

    python/tests: add test for generated and duplicate linkIDs
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139

commit 373bd435425f85a0f24f9f14c36f76c51243a077
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Tue Feb 7 15:42:29 2017 +1300

    torture/drs: generate linkID for test rather than specifying
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139

commit 35be7ee8a49f000282859661fc6522c9d6c05020
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Feb 1 11:54:40 2017 +1300

    samldb: Allow automatic generation of linkIDs and prevent duplicates
    
    As per MS-ADTS 3.1.1.2.3.1, this allows specifying the OID
    1.2.840.113556.1.2.50 as the linkID of a new linked attribute in the
    schema in order to automatically assign it an unused even linkID.
    
    Specifying the attributeID or ldapDisplayName of an existing forward
    link will now also add the new linked attribute as the backlink of that
    existing link.
    
    This also prevents adding duplicate linkIDs. Previously, we could run
    into issues when trying to delete backlinks with duplicate linkIDs.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11139

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

Summary of changes:
 selftest/selftest.pl                            |   7 +
 selftest/target/Samba.pm                        |   1 +
 selftest/target/Samba4.pm                       |  46 ++-
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 257 +++++++++++------
 source4/dsdb/samdb/ldb_modules/samldb.c         | 290 ++++++++++++++++++-
 source4/dsdb/tests/python/ldap_schema.py        | 361 ++++++++++++++++++++++++
 source4/selftest/tests.py                       |  11 +-
 source4/torture/drs/python/repl_schema.py       |  91 +++++-
 source4/torture/drs/rpc/msds_intid.c            |   2 +-
 9 files changed, 944 insertions(+), 122 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index bfc8d7f..45e0ae0 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -811,6 +811,13 @@ my @exported_envvars = (
 	"VAMPIRE_DC_NETBIOSNAME",
 	"VAMPIRE_DC_NETBIOSALIAS",
 
+	# domain controller stuff for FL 2000 Vampired DC
+	"VAMPIRE_2000_DC_SERVER",
+	"VAMPIRE_2000_DC_SERVER_IP",
+	"VAMPIRE_2000_DC_SERVER_IPV6",
+	"VAMPIRE_2000_DC_NETBIOSNAME",
+	"VAMPIRE_2000_DC_NETBIOSALIAS",
+
 	"PROMOTED_DC_SERVER",
 	"PROMOTED_DC_SERVER_IP",
 	"PROMOTED_DC_SERVER_IPV6",
diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index 24484c9..e5c7f93 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -308,6 +308,7 @@ sub get_interface($)
     $interfaces{"fakednsforwarder1"} = 36;
     $interfaces{"fakednsforwarder2"} = 37;
     $interfaces{"s4member_dflt"} = 38;
+    $interfaces{"vampire2000dc"} = 39;
 
     # update lib/socket_wrapper/socket_wrapper.c
     #  #define MAX_WRAPPED_INTERFACES 40
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index dacdab4..8b5e699 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1246,15 +1246,20 @@ sub provision_promoted_dc($$$)
 
 sub provision_vampire_dc($$$)
 {
-	my ($self, $prefix, $dcvars) = @_;
-	print "PROVISIONING VAMPIRE DC...\n";
+	my ($self, $prefix, $dcvars, $fl) = @_;
+	print "PROVISIONING VAMPIRE DC @ FL $fl...\n";
+	my $name = "localvampiredc";
+
+	if ($fl == "2000") {
+	    $name = "vampire2000dc";
+	}
 
 	# We do this so that we don't run the provision.  That's the job of 'net vampire'.
 	my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
-					       "localvampiredc",
-					       "SAMBADOMAIN",
-					       "samba.example.com",
-					       "2008",
+					       $name,
+					       $dcvars->{DOMAIN},
+					       $dcvars->{REALM},
+					       $fl,
 					       $dcvars->{PASSWORD},
 					       $dcvars->{SERVER_IP},
 					       $dcvars->{SERVER_IPV6});
@@ -1299,11 +1304,17 @@ sub provision_vampire_dc($$$)
 		return undef;
 	}
 
-	$ret->{VAMPIRE_DC_SERVER} = $ret->{SERVER};
-	$ret->{VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP};
-	$ret->{VAMPIRE_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-	$ret->{VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-
+        if ($fl == "2000") {
+		$ret->{VAMPIRE_2000_DC_SERVER} = $ret->{SERVER};
+		$ret->{VAMPIRE_2000_DC_SERVER_IP} = $ret->{SERVER_IP};
+		$ret->{VAMPIRE_2000_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
+		$ret->{VAMPIRE_2000_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
+        } else {
+		$ret->{VAMPIRE_DC_SERVER} = $ret->{SERVER};
+		$ret->{VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP};
+		$ret->{VAMPIRE_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
+		$ret->{VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
+        }
 	$ret->{DC_SERVER} = $dcvars->{DC_SERVER};
 	$ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
 	$ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
@@ -2002,6 +2013,11 @@ sub setup_env($$$)
 		return $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
 	} elsif ($envname eq "fl2000dc") {
 		return $self->setup_fl2000dc("$path/fl2000dc");
+	} elsif ($envname eq "vampire_2000_dc") {
+		if (not defined($self->{vars}->{fl2000dc})) {
+			$self->setup_fl2000dc("$path/fl2000dc");
+		}
+		return $self->setup_vampire_dc("$path/vampire_2000_dc", $self->{vars}->{fl2000dc}, "2000");
 	} elsif ($envname eq "fl2003dc") {
 		if (not defined($self->{vars}->{ad_dc})) {
 			$self->setup_ad_dc("$path/ad_dc");
@@ -2021,7 +2037,7 @@ sub setup_env($$$)
 		if (not defined($self->{vars}->{ad_dc_ntvfs})) {
 			$self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
 		}
-		return $self->setup_vampire_dc("$path/vampire_dc", $self->{vars}->{ad_dc_ntvfs});
+		return $self->setup_vampire_dc("$path/vampire_dc", $self->{vars}->{ad_dc_ntvfs}, "2008");
 	} elsif ($envname eq "promoted_dc") {
 		if (not defined($self->{vars}->{ad_dc_ntvfs})) {
 			$self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
@@ -2211,11 +2227,11 @@ sub setup_fl2008r2dc($$$)
 	return $env;
 }
 
-sub setup_vampire_dc($$$)
+sub setup_vampire_dc($$$$)
 {
-	my ($self, $path, $dc_vars) = @_;
+	my ($self, $path, $dc_vars, $fl) = @_;
 
-	my $env = $self->provision_vampire_dc($path, $dc_vars);
+	my $env = $self->provision_vampire_dc($path, $dc_vars, $fl);
 
 	if (defined $env) {
 	        if (not defined($self->check_or_start($env, "single"))) {
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 6e041c7..e3bf032 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -101,8 +101,18 @@ struct replmd_replicated_request {
 	bool isDeleted;
 };
 
+struct parsed_dn {
+	struct dsdb_dn *dsdb_dn;
+	struct GUID guid;
+	struct ldb_val *v;
+};
+
 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete);
+static int replmd_check_upgrade_links(struct ldb_context *ldb,
+				      struct parsed_dn *dns, uint32_t count,
+				      struct ldb_message_element *el,
+				      const char *ldap_oid);
 
 enum urgent_situation {
 	REPL_URGENT_ON_CREATE = 1,
@@ -862,12 +872,6 @@ static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct ds
 			       const struct GUID *invocation_id, uint64_t seq_num,
 			       uint64_t local_usn, NTTIME nttime, uint32_t version, bool deleted);
 
-struct parsed_dn {
-	struct dsdb_dn *dsdb_dn;
-	struct GUID guid;
-	struct ldb_val *v;
-};
-
 static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx,
 			  struct ldb_message_element *el, struct parsed_dn **pdn,
 			  const char *ldap_oid, struct ldb_request *parent);
@@ -2073,6 +2077,9 @@ static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx,
  * GUID, even though the GUIDs might not be known. That works because we trust
  * the database to give us the elements like that if the
  * replmd_private->sorted_links flag is set.
+ *
+ * We also ensure that the links are in the Functional Level 2003
+ * linked attributes format.
  */
 static int get_parsed_dns_trusted(struct ldb_module *module,
 				  struct replmd_private *replmd_private,
@@ -2083,7 +2090,7 @@ static int get_parsed_dns_trusted(struct ldb_module *module,
 				  struct ldb_request *parent)
 {
 	unsigned int i;
-
+	int ret;
 	if (el == NULL) {
 		*pdn = NULL;
 		return LDB_SUCCESS;
@@ -2093,19 +2100,41 @@ static int get_parsed_dns_trusted(struct ldb_module *module,
 		/* We need to sort the list. This is the slow old path we want
 		   to avoid.
 		 */
-		return get_parsed_dns(module, mem_ctx, el, pdn, ldap_oid,
+		ret = get_parsed_dns(module, mem_ctx, el, pdn, ldap_oid,
 				      parent);
-	}
-	/* Here we get a list of 'struct parsed_dns' without the parsing */
-	*pdn = talloc_zero_array(mem_ctx, struct parsed_dn,
-				 el->num_values);
-	if (!*pdn) {
-		ldb_module_oom(module);
-		return LDB_ERR_OPERATIONS_ERROR;
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	} else {
+		/* Here we get a list of 'struct parsed_dns' without the parsing */
+		*pdn = talloc_zero_array(mem_ctx, struct parsed_dn,
+					 el->num_values);
+		if (!*pdn) {
+			ldb_module_oom(module);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		for (i = 0; i < el->num_values; i++) {
+			(*pdn)[i].v = &el->values[i];
+		}
 	}
 
-	for (i = 0; i < el->num_values; i++) {
-		(*pdn)[i].v = &el->values[i];
+	/*
+	 * This upgrades links to FL2003 style, and sorts the result
+	 * if that was needed.
+	 *
+	 * TODO: Add a database feature that asserts we have no FL2000
+	 *       style links to avoid this check or add a feature that
+	 *       uses a similar check to find sorted/unsorted links
+	 *       for an on-the-fly upgrade.
+	 */
+
+	ret = replmd_check_upgrade_links(ldb_module_get_ctx(module),
+					 *pdn, el->num_values,
+					 el,
+					 ldap_oid);
+	if (ret != LDB_SUCCESS) {
+		return ret;
 	}
 
 	return LDB_SUCCESS;
@@ -2208,10 +2237,10 @@ static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct d
 static int replmd_check_upgrade_links(struct ldb_context *ldb,
 				      struct parsed_dn *dns, uint32_t count,
 				      struct ldb_message_element *el,
-				      const struct GUID *invocation_id,
 				      const char *ldap_oid)
 {
 	uint32_t i;
+	const struct GUID *invocation_id = NULL;
 	for (i=0; i<count; i++) {
 		NTSTATUS status;
 		uint32_t version;
@@ -2243,6 +2272,14 @@ static int replmd_check_upgrade_links(struct ldb_context *ldb,
 			continue;
 		}
 
+		if (invocation_id == NULL) {
+			invocation_id = samdb_ntds_invocation_id(ldb);
+			if (invocation_id == NULL) {
+				return LDB_ERR_OPERATIONS_ERROR;
+			}
+		}
+
+
 		/* it's an old one that needs upgrading */
 		ret = replmd_update_la_val(el->values, dns[i].v,
 					   dns[i].dsdb_dn, dns[i].dsdb_dn,
@@ -2251,6 +2288,19 @@ static int replmd_check_upgrade_links(struct ldb_context *ldb,
 			return ret;
 		}
 	}
+
+	/*
+	 * This sort() is critical for the operation of
+	 * get_parsed_dns_trusted() because callers of this function
+	 * expect a sorted list, and FL2000 style links are not
+	 * sorted.  In particular, as well as the upgrade case,
+	 * get_parsed_dns_trusted() is called from
+	 * replmd_delete_remove_link() even in FL2000 mode
+	 *
+	 * We do not normally pay the cost of the qsort() due to the
+	 * early return in the RMD_VERSION found case.
+	 */
+	TYPESAFE_QSORT(dns, count, parsed_dn_compare);
 	return LDB_SUCCESS;
 }
 
@@ -2381,9 +2431,14 @@ static int replmd_modify_la_add(struct ldb_module *module,
 	const struct GUID *invocation_id;
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
 	NTTIME now;
-
 	unix_to_nt_time(&now, t);
 
+	invocation_id = samdb_ntds_invocation_id(ldb);
+	if (!invocation_id) {
+		talloc_free(tmp_ctx);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
 	/* get the DNs to be added, fully parsed.
 	 *
 	 * We need full parsing because they came off the wire and we don't
@@ -2407,20 +2462,6 @@ static int replmd_modify_la_add(struct ldb_module *module,
 		return ret;
 	}
 
-	invocation_id = samdb_ntds_invocation_id(ldb);
-	if (!invocation_id) {
-		talloc_free(tmp_ctx);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	ret = replmd_check_upgrade_links(ldb, old_dns, old_num_values,
-					 old_el, invocation_id,
-					 schema_attr->syntax->ldap_oid);
-	if (ret != LDB_SUCCESS) {
-		talloc_free(tmp_ctx);
-		return ret;
-	}
-
 	max_num_values = old_num_values + el->num_values;
 	if (max_num_values < old_num_values) {
 		DEBUG(0, ("we seem to have overflow in replmd_modify_la_add. "
@@ -2597,16 +2638,21 @@ static int replmd_modify_la_delete(struct ldb_module *module,
 	struct parsed_dn *dns, *old_dns;
 	TALLOC_CTX *tmp_ctx = NULL;
 	int ret;
-	const struct GUID *invocation_id;
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
 	struct ldb_control *vanish_links_ctrl = NULL;
 	bool vanish_links = false;
 	unsigned int num_to_delete = el->num_values;
 	uint32_t rmd_flags;
+	const struct GUID *invocation_id;
 	NTTIME now;
 
 	unix_to_nt_time(&now, t);
 
+	invocation_id = samdb_ntds_invocation_id(ldb);
+	if (!invocation_id) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
 	if (old_el == NULL || old_el->num_values == 0) {
 		/* there is nothing to delete... */
 		if (num_to_delete == 0) {
@@ -2637,20 +2683,6 @@ static int replmd_modify_la_delete(struct ldb_module *module,
 		return ret;
 	}
 
-	invocation_id = samdb_ntds_invocation_id(ldb);
-	if (!invocation_id) {
-		talloc_free(tmp_ctx);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	ret = replmd_check_upgrade_links(ldb, old_dns, old_el->num_values,
-					 old_el, invocation_id,
-					 schema_attr->syntax->ldap_oid);
-	if (ret != LDB_SUCCESS) {
-		talloc_free(tmp_ctx);
-		return ret;
-	}
-
 	if (parent) {
 		vanish_links_ctrl = ldb_request_get_control(parent, DSDB_CONTROL_REPLMD_VANISH_LINKS);
 		if (vanish_links_ctrl) {
@@ -2863,6 +2895,11 @@ static int replmd_modify_la_replace(struct ldb_module *module,
 
 	unix_to_nt_time(&now, t);
 
+	invocation_id = samdb_ntds_invocation_id(ldb);
+	if (!invocation_id) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
 	/*
 	 * The replace operation is unlike the replace and delete cases in that
 	 * we need to look at every existing link to see whether it is being
@@ -2908,13 +2945,8 @@ static int replmd_modify_la_replace(struct ldb_module *module,
 		return ret;
 	}
 
-	invocation_id = samdb_ntds_invocation_id(ldb);
-	if (!invocation_id) {
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
 	ret = replmd_check_upgrade_links(ldb, old_dns, old_num_values,
-					 old_el, invocation_id, ldap_oid);
+					 old_el, ldap_oid);
 	if (ret != LDB_SUCCESS) {
 		talloc_free(tmp_ctx);
 		return ret;
@@ -3625,7 +3657,9 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are
  */
 static int replmd_delete_remove_link(struct ldb_module *module,
 				     const struct dsdb_schema *schema,
+				     struct replmd_private *replmd_private,
 				     struct ldb_dn *dn,
+				     struct GUID *guid,
 				     struct ldb_message_element *el,
 				     const struct dsdb_attribute *sa,
 				     struct ldb_request *parent)
@@ -3636,14 +3670,19 @@ static int replmd_delete_remove_link(struct ldb_module *module,
 
 	for (i=0; i<el->num_values; i++) {
 		struct dsdb_dn *dsdb_dn;
-		NTSTATUS status;
 		int ret;
-		struct GUID guid2;
 		struct ldb_message *msg;
 		const struct dsdb_attribute *target_attr;
 		struct ldb_message_element *el2;
+		const char *dn_str;
 		struct ldb_val dn_val;
 		uint32_t dsdb_flags = 0;
+		const char *attrs[] = { NULL, NULL };
+		struct ldb_result *link_res;
+		struct ldb_message *link_msg;
+		struct ldb_message_element *link_el;
+		struct parsed_dn *link_dns;
+		struct parsed_dn *p = NULL, *unused = NULL;
 
 		if (dsdb_dn_is_deleted_val(&el->values[i])) {
 			continue;
@@ -3655,12 +3694,6 @@ static int replmd_delete_remove_link(struct ldb_module *module,
 			return LDB_ERR_OPERATIONS_ERROR;
 		}
 
-		status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid2, "GUID");
-		if (!NT_STATUS_IS_OK(status)) {
-			talloc_free(tmp_ctx);
-			return LDB_ERR_OPERATIONS_ERROR;
-		}
-
 		/* remove the link */
 		msg = ldb_msg_new(tmp_ctx);
 		if (!msg) {
@@ -3676,14 +3709,74 @@ static int replmd_delete_remove_link(struct ldb_module *module,
 		if (target_attr == NULL) {
 			continue;
 		}
+		attrs[0] = target_attr->lDAPDisplayName;
 
-		ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName, LDB_FLAG_MOD_DELETE, &el2);
+		ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName,
+					LDB_FLAG_MOD_DELETE, &el2);
 		if (ret != LDB_SUCCESS) {
 			ldb_module_oom(module);
 			talloc_free(tmp_ctx);
 			return LDB_ERR_OPERATIONS_ERROR;
 		}
-		dn_val = data_blob_string_const(ldb_dn_get_linearized(dn));
+
+		ret = dsdb_module_search_dn(module, tmp_ctx, &link_res,
+					    msg->dn, attrs,
+					    DSDB_FLAG_NEXT_MODULE |
+					    DSDB_SEARCH_SHOW_EXTENDED_DN,
+					    parent);
+
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			return ret;
+		}
+
+		link_msg = link_res->msgs[0];
+		link_el = ldb_msg_find_element(link_msg,
+					       target_attr->lDAPDisplayName);
+		if (link_el == NULL) {
+			talloc_free(tmp_ctx);
+			return LDB_ERR_NO_SUCH_ATTRIBUTE;
+		}
+
+		/*
+		 * This call 'upgrades' the links in link_dns, but we
+		 * do not commit the result back into the database, so
+		 * this is safe to call in FL2000 or on databases that
+		 * have been run at that level in the past.
+		 */
+		ret = get_parsed_dns_trusted(module, replmd_private, tmp_ctx,
+					     link_el, &link_dns,
+					     target_attr->syntax->ldap_oid, parent);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			return ret;
+		}
+
+		ret = parsed_dn_find(ldb, link_dns, link_el->num_values,
+				     guid, dn, &p, &unused,
+				     target_attr->syntax->ldap_oid);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			return ret;
+		}
+
+		if (p == NULL) {
+			ldb_asprintf_errstring(ldb_module_get_ctx(module),
+					       "Failed to find forward link on %s "
+					       "as %s to remove backlink %s on %s",
+					       ldb_dn_get_linearized(msg->dn),
+					       target_attr->lDAPDisplayName,
+					       sa->lDAPDisplayName,
+					       ldb_dn_get_linearized(dn));
+			talloc_free(tmp_ctx);
+			return LDB_ERR_NO_SUCH_ATTRIBUTE;
+		}
+
+
+		/* This needs to get the Binary DN, by first searching */
+		dn_str = dsdb_dn_get_linearized(tmp_ctx,
+						p->dsdb_dn);


-- 
Samba Shared Repository



More information about the samba-cvs mailing list