[Pkg-samba-maint] Bug#1035927: unblock: samba/2:4.17.8+dfsg-1

Michael Tokarev mjt at tls.msk.ru
Thu May 11 10:58:00 BST 2023


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock
X-Debbugs-Cc: samba at packages.debian.org, pkg-samba-maint at lists.alioth.debian.org
Control: affects -1 + src:samba

Please unblock package samba

[ Reason ]
This is a next upstream samba stable/bugfix release (4.17.8)
fixing a long number of various bugs all over the place, including
a security fix (additional changes addressing CVE-2020-25720).
It is definitely a good thing to have it all in bookworm.

[ Tests ]
First of all, samba upstream has an excellent testsuite ensuring
there's no regressions. Plus they pick changes for stable release
series very carefully.  This release is not an exception.
My basic local tests of basic samba file server and AD/DC functionality
does not reveal any issues either.

[ Risks ]
The risk of this update is quite low, due to the way
how the upstream stable release is being done.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
The debdiff is rather large due to big number of changes.
The complete changeset is available in git on salsa.d.o,
https://salsa.debian.org/samba-team/samba/-/commits/upstream/4.17.8+dfsg/

When preparing debdiff, I filtered all manpages (*.[15678] - this
goes for docs/manpages/ and ctdb/doc/, - unfortunately upstream
includes generated manpages in the source tarball, and those are
regenerated on every release with current timestamps. I'll strip
it all out from the orig source tarball in trixie.

The diffstat is still large. d/changelog is at the top.

unblock samba/2:4.17.8+dfsg-1


diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/debian/changelog samba-4.17.8+dfsg/debian/changelog
--- samba-4.17.7+dfsg/debian/changelog	2023-03-29 17:59:17.000000000 +0300
+++ samba-4.17.8+dfsg/debian/changelog	2023-05-11 10:52:40.000000000 +0300
@@ -1,3 +1,56 @@
+samba (2:4.17.8+dfsg-1) unstable; urgency=medium
+
+  * upstream stable/security/bugfix release, fixing the following issues:
+   * https://bugzilla.samba.org/show_bug.cgi?id=14810
+     CVE-2020-25720 Create Child permission should not allow
+     full write to all attributes (additional changes)
+   * https://bugzilla.samba.org/show_bug.cgi?id=15143
+     New filename parser doesn't check veto files smb.conf parameter
+   * https://bugzilla.samba.org/show_bug.cgi?id=15302
+     log flood: smbd_calculate_access_mask_fsp: Access denied: message
+     level should be lower (this was included in Debian package already)
+   * https://bugzilla.samba.org/show_bug.cgi?id=15306
+     Floating point exception (FPE) via cli_pull_send
+     at source3/libsmb/clireadwrite.c
+   * https://bugzilla.samba.org/show_bug.cgi?id=15313
+     Large directory optimization broken for non-lcomp path elements
+   * https://bugzilla.samba.org/show_bug.cgi?id=15317
+     winbindd idmap child contacts the domain controller without a need
+   * https://bugzilla.samba.org/show_bug.cgi?id=15318
+     idmap_autorid may fail to map sids of trusted domains for the
+   * https://bugzilla.samba.org/show_bug.cgi?id=15319
+     idmap_hash doesn't use ID_TYPE_BOTH for reverse mappings
+   * https://bugzilla.samba.org/show_bug.cgi?id=15323
+     net ads search -P doesn't work against servers in other domains
+   * https://bugzilla.samba.org/show_bug.cgi?id=15325
+     dsgetdcname: assumes local system uses IPv4
+   * https://bugzilla.samba.org/show_bug.cgi?id=15328
+     test_tstream_more_tcp_user_timeout_spin fails intermittently
+     on Rackspace GitLab runners
+   * https://bugzilla.samba.org/show_bug.cgi?id=15329
+     Reduce flapping of ridalloc test
+   * https://bugzilla.samba.org/show_bug.cgi?id=15329
+     Reduce flapping of ridalloc test
+   * https://bugzilla.samba.org/show_bug.cgi?id=15338
+     DS ACEs might be inherited to unrelated object classes
+   * https://bugzilla.samba.org/show_bug.cgi?id=15351
+     large_ldap test is unreliable
+   * https://bugzilla.samba.org/show_bug.cgi?id=15353
+     Temporary smbXsrv_tcon_global.tdb can't be parsed
+   * https://bugzilla.samba.org/show_bug.cgi?id=15354
+     mdssvc may crash when initializing
+   * https://bugzilla.samba.org/show_bug.cgi?id=15357
+     streams_depot fails to create streams
+   * https://bugzilla.samba.org/show_bug.cgi?id=15358
+     shadow_copy2 and streams_depot don't play well together
+   * https://bugzilla.samba.org/show_bug.cgi?id=15360
+     Setting veto files = /.*/ break listing directories
+   * https://bugzilla.samba.org/show_bug.cgi?id=15366
+     wbinfo -u fails on ad dc with >1000 users
+  * d/gbp.conf: switch debian-branch to "bookworm"
+
+ -- Michael Tokarev <mjt at tls.msk.ru>  Thu, 11 May 2023 10:52:40 +0300
+
 samba (2:4.17.7+dfsg-1) unstable; urgency=high
 
   * upstream stable/security/bugfix release, fixing the following issues:
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/debian/gbp.conf samba-4.17.8+dfsg/debian/gbp.conf
--- samba-4.17.7+dfsg/debian/gbp.conf	2023-03-12 12:11:49.000000000 +0300
+++ samba-4.17.8+dfsg/debian/gbp.conf	2023-05-11 10:36:28.000000000 +0300
@@ -1,4 +1,5 @@
 [DEFAULT]
 sign-tags = True
 pristine-tar = True
+debian-branch = bookworm
 upstream-branch = upstream_4.17
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/debian/patches/s3-smbd-open.c-smbd_calculate_access_mask_fsp-lower-.patch samba-4.17.8+dfsg/debian/patches/s3-smbd-open.c-smbd_calculate_access_mask_fsp-lower-.patch
--- samba-4.17.7+dfsg/debian/patches/s3-smbd-open.c-smbd_calculate_access_mask_fsp-lower-.patch	2023-03-09 12:37:58.000000000 +0300
+++ samba-4.17.8+dfsg/debian/patches/s3-smbd-open.c-smbd_calculate_access_mask_fsp-lower-.patch	1970-01-01 03:00:00.000000000 +0300
@@ -1,38 +0,0 @@
-From d1cfe6d143c5d6776cfa55efcd643c139b3a165f Mon Sep 17 00:00:00 2001
-From: Michael Tokarev <mjt at tls.msk.ru>
-Date: Wed, 8 Feb 2023 00:02:44 +0300
-Subject: s3/smbd/open.c:smbd_calculate_access_mask_fsp: lower "rejected by share acces" message from ERR to DEBUG
-
-Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
----
- source3/smbd/open.c | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
-diff --git a/source3/smbd/open.c b/source3/smbd/open.c
-index c24c55d6a76..73a087f94c3 100644
---- a/source3/smbd/open.c
-+++ b/source3/smbd/open.c
-@@ -3389,13 +3389,13 @@ NTSTATUS smbd_calculate_access_mask_fsp(struct files_struct *dirfsp,
- 	rejected_share_access = access_mask & ~(fsp->conn->share_access);
- 
- 	if (rejected_share_access) {
--		DBG_ERR("Access denied on file %s: "
--			"rejected by share access mask[0x%08X] "
--			"orig[0x%08X] mapped[0x%08X] reject[0x%08X]\n",
--			fsp_str_dbg(fsp),
--			fsp->conn->share_access,
--			orig_access_mask, access_mask,
--			rejected_share_access);
-+		DBG_DEBUG("Access denied on file %s: "
-+			  "rejected by share access mask[0x%08X] "
-+			  "orig[0x%08X] mapped[0x%08X] reject[0x%08X]\n",
-+			  fsp_str_dbg(fsp),
-+			  fsp->conn->share_access,
-+			  orig_access_mask, access_mask,
-+			  rejected_share_access);
- 		return NT_STATUS_ACCESS_DENIED;
- 	}
- 
--- 
-2.30.2
-
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/debian/patches/series samba-4.17.8+dfsg/debian/patches/series
--- samba-4.17.7+dfsg/debian/patches/series	2023-03-12 12:11:49.000000000 +0300
+++ samba-4.17.8+dfsg/debian/patches/series	2023-05-11 10:47:39.000000000 +0300
@@ -23,4 +23,3 @@
 meaningful-error-if-no-samba-ad-provision.patch
 meaningful-error-if-no-python3-markdown.patch
 ctdb-use-run-instead-of-var-run.patch
-s3-smbd-open.c-smbd_calculate_access_mask_fsp-lower-.patch
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/lib/tsocket/tests/test_tstream.c samba-4.17.8+dfsg/lib/tsocket/tests/test_tstream.c
--- samba-4.17.7+dfsg/lib/tsocket/tests/test_tstream.c	2022-12-15 19:09:31.713236300 +0300
+++ samba-4.17.8+dfsg/lib/tsocket/tests/test_tstream.c	2023-05-11 10:07:19.562420600 +0300
@@ -322,7 +322,7 @@
 	rc = write(sp->socket_client, TEST_STRING, sizeof(TEST_STRING));
 	assert_return_code(rc, errno);
 	sp->expected_errno = ETIMEDOUT;
-	sp->max_loops = 15;
+	sp->max_loops = 30;
 }
 
 static void test_tstream_server_spin_client_both_timer(struct tevent_context *ev,
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/libcli/security/create_descriptor.c samba-4.17.8+dfsg/libcli/security/create_descriptor.c
--- samba-4.17.7+dfsg/libcli/security/create_descriptor.c	2022-08-08 17:15:39.184190800 +0300
+++ samba-4.17.8+dfsg/libcli/security/create_descriptor.c	2023-05-11 10:07:19.566420800 +0300
@@ -78,7 +78,7 @@
 
 /* Not sure what this has to be,
 * and it does not seem to have any influence */
-static bool object_in_list(struct GUID *object_list, struct GUID *object)
+static bool object_in_list(const struct GUID *object_list, const struct GUID *object)
 {
 	size_t i;
 
@@ -107,7 +107,7 @@
 /* returns true if the ACE gontains generic information
  * that needs to be processed additionally */
  
-static bool desc_ace_has_generic(struct security_ace *ace)
+static bool desc_ace_has_generic(const struct security_ace *ace)
 {
 	if (ace->access_mask & SEC_GENERIC_ALL || ace->access_mask & SEC_GENERIC_READ ||
 	    ace->access_mask & SEC_GENERIC_WRITE || ace->access_mask & SEC_GENERIC_EXECUTE) {
@@ -155,12 +155,114 @@
 	}
 
 	for (i=0; i < acl->num_aces; i++) {
-		struct security_ace *ace = &acl->aces[i];
-		if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
-		    (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
-			struct GUID inherited_object = GUID_zero();
+		const struct security_ace *ace = &acl->aces[i];
+		const struct GUID *inherited_object = NULL;
+		const struct GUID *inherited_property = NULL;
+		struct security_ace *tmp_ace = NULL;
+		bool applies = false;
+		bool inherited_only = false;
+		bool expand_ace = false;
+		bool expand_only = false;
+
+		if (is_container && (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
+			applies = true;
+		} else if (!is_container && (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
+			applies = true;
+		}
+
+		if (!applies) {
+			/*
+			 * If the ace doesn't apply to the
+			 * current node, we should only keep
+			 * it as SEC_ACE_FLAG_OBJECT_INHERIT
+			 * on a container. We'll add
+			 * SEC_ACE_FLAG_INHERITED_ACE
+			 * and SEC_ACE_FLAG_INHERIT_ONLY below.
+			 *
+			 * Otherwise we should completely ignore it.
+			 */
+			if (!(ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
+				continue;
+			}
+		}
+
+		switch (ace->type) {
+		case SEC_ACE_TYPE_ACCESS_ALLOWED:
+		case SEC_ACE_TYPE_ACCESS_DENIED:
+		case SEC_ACE_TYPE_SYSTEM_AUDIT:
+		case SEC_ACE_TYPE_SYSTEM_ALARM:
+		case SEC_ACE_TYPE_ALLOWED_COMPOUND:
+			break;
+
+		case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+		case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+		case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+		case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+			if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
+				inherited_property = &ace->object.object.type.type;
+			}
+			if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
+				inherited_object = &ace->object.object.inherited_type.inherited_type;
+			}
+
+			if (inherited_object != NULL && !object_in_list(object_list, inherited_object)) {
+				/*
+				 * An explicit object class schemaId is given,
+				 * but doesn't belong to the current object.
+				 */
+				applies = false;
+			}
+
+			break;
+		}
+
+		if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+			if (!applies) {
+				/*
+				 * If the ACE doesn't apply to
+				 * the current object, we should
+				 * ignore it as it should not be
+				 * inherited any further
+				 */
+				continue;
+			}
+			/*
+			 * We should only keep the expanded version
+			 * of the ACE on the current object.
+			 */
+			expand_ace = true;
+			expand_only = true;
+		} else if (applies) {
+			/*
+			 * We check if should also add
+			 * the expanded version of the ACE
+			 * in addition, in case we should
+			 * expand generic access bits or
+			 * special sids.
+			 *
+			 * In that case we need to
+			 * keep the original ACE with
+			 * SEC_ACE_FLAG_INHERIT_ONLY.
+			 */
+			expand_ace = desc_ace_has_generic(ace);
+			if (expand_ace) {
+				inherited_only = true;
+			}
+		} else {
+			/*
+			 * If the ACE doesn't apply
+			 * to the current object,
+			 * we need to keep it with
+			 * SEC_ACE_FLAG_INHERIT_ONLY
+			 * in order to apply them to
+			 * grandchildren
+			 */
+			inherited_only = true;
+		}
 
-			tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces,
+		if (expand_ace) {
+			tmp_acl->aces = talloc_realloc(tmp_acl,
+						       tmp_acl->aces,
 						       struct security_ace,
 						       tmp_acl->num_aces+1);
 			if (tmp_acl->aces == NULL) {
@@ -168,60 +270,95 @@
 				return NULL;
 			}
 
-			tmp_acl->aces[tmp_acl->num_aces] = *ace;
-			tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERITED_ACE;
-			/* remove IO flag from the child's ace */
-			if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY &&
-			    !desc_ace_has_generic(ace)) {
-				tmp_acl->aces[tmp_acl->num_aces].flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
-			}
-
-			if (is_container && (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT))
-			    tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
-
-			switch (ace->type) {
-			case SEC_ACE_TYPE_ACCESS_ALLOWED:
-			case SEC_ACE_TYPE_ACCESS_DENIED:
-			case SEC_ACE_TYPE_SYSTEM_AUDIT:
-			case SEC_ACE_TYPE_SYSTEM_ALARM:
-			case SEC_ACE_TYPE_ALLOWED_COMPOUND:
-				break;
-
-			case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
-			case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
-			case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
-			case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
-				if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
-					inherited_object = ace->object.object.inherited_type.inherited_type;
-				}
+			tmp_ace = &tmp_acl->aces[tmp_acl->num_aces];
+			tmp_acl->num_aces++;
 
-				if (!object_in_list(object_list, &inherited_object)) {
-					tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
-				}
+			*tmp_ace = *ace;
 
-				break;
+			/*
+			 * Expand generic access bits as well as special
+			 * sids.
+			 */
+			desc_expand_generic(tmp_ace, owner, group);
+
+			/*
+			 * Expanded ACEs are marked as inherited,
+			 * but never inherited any further to
+			 * grandchildren.
+			 */
+			tmp_ace->flags |= SEC_ACE_FLAG_INHERITED_ACE;
+			tmp_ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
+			tmp_ace->flags &= ~SEC_ACE_FLAG_OBJECT_INHERIT;
+			tmp_ace->flags &= ~SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
+
+			/*
+			 * Expanded ACEs never have an explicit
+			 * object class schemaId, so clear it
+			 * if present.
+			 */
+			if (inherited_object != NULL) {
+				tmp_ace->object.object.flags &= ~SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT;
 			}
 
-			tmp_acl->num_aces++;
-			if (is_container) {
-				if (!(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) &&
-				    (desc_ace_has_generic(ace))) {
-					    tmp_acl->aces = talloc_realloc(tmp_acl,
-									   tmp_acl->aces,
-									   struct security_ace,
-									   tmp_acl->num_aces+1);
-					    if (tmp_acl->aces == NULL) {
-						    talloc_free(tmp_ctx);
-						    return NULL;
-					    }
-					    tmp_acl->aces[tmp_acl->num_aces] = *ace;
-					    desc_expand_generic(&tmp_acl->aces[tmp_acl->num_aces],
-								owner,
-								group);
-					    tmp_acl->aces[tmp_acl->num_aces].flags = SEC_ACE_FLAG_INHERITED_ACE;
-					    tmp_acl->num_aces++;
+			/*
+			 * If the ACE had an explicit object class
+			 * schemaId, but no attribute/propertySet
+			 * we need to downgrate the _OBJECT variants
+			 * to the normal ones.
+			 */
+			if (inherited_property == NULL) {
+				switch (tmp_ace->type) {
+				case SEC_ACE_TYPE_ACCESS_ALLOWED:
+				case SEC_ACE_TYPE_ACCESS_DENIED:
+				case SEC_ACE_TYPE_SYSTEM_AUDIT:
+				case SEC_ACE_TYPE_SYSTEM_ALARM:
+				case SEC_ACE_TYPE_ALLOWED_COMPOUND:
+					break;
+				case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+					tmp_ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+					break;
+				case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+					tmp_ace->type = SEC_ACE_TYPE_ACCESS_DENIED;
+					break;
+				case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+					tmp_ace->type = SEC_ACE_TYPE_SYSTEM_ALARM;
+					break;
+				case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+					tmp_ace->type = SEC_ACE_TYPE_SYSTEM_AUDIT;
+					break;
 				}
 			}
+
+			if (expand_only) {
+				continue;
+			}
+		}
+
+		tmp_acl->aces = talloc_realloc(tmp_acl,
+					       tmp_acl->aces,
+					       struct security_ace,
+					       tmp_acl->num_aces+1);
+		if (tmp_acl->aces == NULL) {
+			talloc_free(tmp_ctx);
+			return NULL;
+		}
+
+		tmp_ace = &tmp_acl->aces[tmp_acl->num_aces];
+		tmp_acl->num_aces++;
+
+		*tmp_ace = *ace;
+		tmp_ace->flags |= SEC_ACE_FLAG_INHERITED_ACE;
+
+		if (inherited_only) {
+			tmp_ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
+		} else {
+			tmp_ace->flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
+		}
+
+		if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+			tmp_ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
+			tmp_ace->flags &= ~SEC_ACE_FLAG_OBJECT_INHERIT;
+			tmp_ace->flags &= ~SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
 		}
 	}
 	if (tmp_acl->num_aces == 0) {
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/libcli/smb/smbXcli_base.c samba-4.17.8+dfsg/libcli/smb/smbXcli_base.c
--- samba-4.17.7+dfsg/libcli/smb/smbXcli_base.c	2022-08-23 17:45:49.516087300 +0300
+++ samba-4.17.8+dfsg/libcli/smb/smbXcli_base.c	2023-05-11 10:07:19.570420700 +0300
@@ -5088,6 +5088,17 @@
 	conn->smb2.server.system_time	= BVAL(body, 40);
 	conn->smb2.server.start_time	= BVAL(body, 48);
 
+	if (conn->smb2.server.max_trans_size == 0 ||
+	    conn->smb2.server.max_read_size == 0 ||
+	    conn->smb2.server.max_write_size == 0) {
+		/*
+		 * We can't connect to servers we can't
+		 * do any operations on.
+		 */
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
 	security_offset = SVAL(body, 56);
 	security_length = SVAL(body, 58);
 
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/libds/common/flags.h samba-4.17.8+dfsg/libds/common/flags.h
--- samba-4.17.7+dfsg/libds/common/flags.h	2023-03-20 12:04:29.063923100 +0300
+++ samba-4.17.8+dfsg/libds/common/flags.h	2023-05-11 10:07:19.570420700 +0300
@@ -237,6 +237,20 @@
 /* wellknown GUIDs for optional directory features */
 #define DS_GUID_FEATURE_RECYCLE_BIN		      "766ddcd8-acd0-445e-f3b9-a7f9b6744f2a"
 
+/* GUIDs for AD schema attributes and classes */
+#define DS_GUID_SCHEMA_ATTR_DEPARTMENT                "bf96794f-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_DNS_HOST_NAME             "72e39547-7b18-11d1-adef-00c04fd8d5cd"
+#define DS_GUID_SCHEMA_ATTR_INSTANCE_TYPE             "bf96798c-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_MS_SFU_30                 "16c5d1d3-35c2-4061-a870-a5cefda804f0"
+#define DS_GUID_SCHEMA_ATTR_NT_SECURITY_DESCRIPTOR    "bf9679e3-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_PRIMARY_GROUP_ID          "bf967a00-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_SERVICE_PRINCIPAL_NAME    "f3a64788-5306-11d1-a9c5-0000f80367c1"
+#define DS_GUID_SCHEMA_ATTR_USER_ACCOUNT_CONTROL      "bf967a68-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_USER_PASSWORD             "bf967a6e-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_CLASS_COMPUTER                 "bf967a86-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_CLASS_MANAGED_SERVICE_ACCOUNT  "ce206244-5827-4a86-ba1c-1c0c386c1b64"
+#define DS_GUID_SCHEMA_CLASS_USER                     "bf967aba-0de6-11d0-a285-00aa003049e2"
+
 /* dsHeuristics character indexes see MS-ADTS 7.1.1.2.4.1.2 */
 
 #define DS_HR_SUPFIRSTLASTANR                     0x00000001
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/python/samba/join.py samba-4.17.8+dfsg/python/samba/join.py
--- samba-4.17.7+dfsg/python/samba/join.py	2022-10-19 15:14:56.008195900 +0300
+++ samba-4.17.8+dfsg/python/samba/join.py	2023-05-11 10:07:19.578420900 +0300
@@ -50,6 +50,7 @@
 from collections import OrderedDict
 from samba.common import get_string
 from samba.netcmd import CommandError
+from samba import dsdb
 
 
 class DCJoinException(Exception):
@@ -937,6 +938,10 @@
         """Replicate the SAM."""
 
         ctx.logger.info("Starting replication")
+
+        # A global transaction is started so that linked attributes
+        # are applied at the very end, once all partitions are
+        # replicated.  This helps get all cross-partition links.
         ctx.local_samdb.transaction_start()
         try:
             source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id())
@@ -1057,7 +1062,21 @@
             ctx.local_samdb.transaction_cancel()
             raise
         else:
+
+            # This is a special case, we have completed a full
+            # replication so if a link comes to us that points to a
+            # deleted object, and we asked for all objects already, we
+            # just have to ignore it, the chance to re-try the
+            # replication with GET_TGT has long gone.  This can happen
+            # if the object is deleted and sent to us after the link
+            # was sent, as we are processing all links in the
+            # transaction_commit().
+            if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+                ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME,
+                                                   1)
             ctx.local_samdb.transaction_commit()
+            ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME,
+                                               0)
             ctx.logger.info("Committed SAM database")
 
         # A large replication may have caused our LDB connection to the
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/selftest/target/Samba3.pm samba-4.17.8+dfsg/selftest/target/Samba3.pm
--- samba-4.17.7+dfsg/selftest/target/Samba3.pm	2023-03-09 12:18:38.349811600 +0300
+++ samba-4.17.8+dfsg/selftest/target/Samba3.pm	2023-05-11 10:07:19.582420800 +0300
@@ -1974,6 +1974,10 @@
 	path = $veto_sharedir
 	delete veto files = yes
 
+[veto_files_nohidden]
+	path = $veto_sharedir
+	veto files = /.*/
+
 [veto_files]
 	path = $veto_sharedir
 	veto files = /veto_name*/
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/lib/util.c samba-4.17.8+dfsg/source3/lib/util.c
--- samba-4.17.7+dfsg/source3/lib/util.c	2022-08-08 17:15:39.360192000 +0300
+++ samba-4.17.8+dfsg/source3/lib/util.c	2023-05-11 10:07:19.582420800 +0300
@@ -748,6 +748,11 @@
 		return False;
 	}
 
+	/* Do not reject path components if namelist is set to '.*' */
+	if (ISDOT(name) || ISDOTDOT(name)) {
+		return false;
+	}
+
 	DEBUG(8, ("is_in_path: %s\n", name));
 
 	/* Get the last component of the unix name. */
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/libsmb/dsgetdcname.c samba-4.17.8+dfsg/source3/libsmb/dsgetdcname.c
--- samba-4.17.7+dfsg/source3/libsmb/dsgetdcname.c	2022-08-08 17:15:39.380192000 +0300
+++ samba-4.17.8+dfsg/source3/libsmb/dsgetdcname.c	2023-05-11 10:07:19.586420800 +0300
@@ -551,14 +551,20 @@
 		return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 	}
 
+	/* Check for integer wrap. */
+	if (numdcs + numdcs < numdcs) {
+		TALLOC_FREE(dcs);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 	/*
-	 * We're only returning one address per
-	 * DC name, so just allocate size numdcs.
+	 * We're only returning up to 2 addresses per
+	 * DC name, so just allocate size numdcs x 2.
 	 */
 
 	dclist = talloc_zero_array(mem_ctx,
 				   struct ip_service_name,
-				   numdcs);
+				   numdcs * 2);
 	if (!dclist) {
 		TALLOC_FREE(dcs);
 		return NT_STATUS_NO_MEMORY;
@@ -571,17 +577,16 @@
 	ret_count = 0;
 	for (i = 0; i < numdcs; i++) {
 		size_t j;
+		bool have_v4_addr = false;
+		bool have_v6_addr = false;
 
 		if (dcs[i].num_ips == 0) {
 			continue;
 		}
 
-		dclist[ret_count].hostname =
-			talloc_move(dclist, &dcs[i].hostname);
-
 		/*
-		 * Pick the first IPv4 address,
-		 * if none pick the first address.
+		 * Pick up to 1 address from each address
+		 * family (IPv4, IPv6).
 		 *
 		 * This is different from the previous
 		 * code which picked a 'next ip' address
@@ -589,8 +594,11 @@
 		 * Too complex to maintain :-(.
 		 */
 		for (j = 0; j < dcs[i].num_ips; j++) {
-			if (dcs[i].ss_s[j].ss_family == AF_INET) {
+			if ((dcs[i].ss_s[j].ss_family == AF_INET && !have_v4_addr) ||
+			    (dcs[i].ss_s[j].ss_family == AF_INET6 && !have_v6_addr)) {
 				bool ok;
+				dclist[ret_count].hostname =
+					talloc_strdup(dclist, dcs[i].hostname);
 				ok = sockaddr_storage_to_samba_sockaddr(
 					&dclist[ret_count].sa,
 					&dcs[i].ss_s[j]);
@@ -599,22 +607,17 @@
 					TALLOC_FREE(dclist);
 					return NT_STATUS_INVALID_PARAMETER;
 				}
-				break;
-			}
-		}
-		if (j == dcs[i].num_ips) {
-			/* No IPv4- use the first IPv6 addr. */
-			bool ok;
-			ok = sockaddr_storage_to_samba_sockaddr(
-					&dclist[ret_count].sa,
-					&dcs[i].ss_s[0]);
-			if (!ok) {
-				TALLOC_FREE(dcs);
-				TALLOC_FREE(dclist);
-				return NT_STATUS_INVALID_PARAMETER;
+				ret_count++;
+				if (dcs[i].ss_s[j].ss_family == AF_INET) {
+					have_v4_addr = true;
+				} else {
+					have_v6_addr = true;
+				}
+				if (have_v4_addr && have_v6_addr) {
+					break;
+				}
 			}
 		}
-		ret_count++;
 	}
 
 	TALLOC_FREE(dcs);
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/modules/vfs_shadow_copy2.c samba-4.17.8+dfsg/source3/modules/vfs_shadow_copy2.c
--- samba-4.17.7+dfsg/source3/modules/vfs_shadow_copy2.c	2022-08-08 17:29:11.357506800 +0300
+++ samba-4.17.8+dfsg/source3/modules/vfs_shadow_copy2.c	2023-05-11 10:07:19.590421000 +0300
@@ -1521,15 +1521,22 @@
 	if (fsp->base_fsp != NULL) {
 		struct smb_filename *base_fname = fsp->base_fsp->fsp_name;
 
-		SMB_ASSERT(is_named_stream(smb_fname_in));
+		if (smb_fname_in->base_name[0] == '/') {
+			/*
+			 * Special-case stream names from streams_depot
+			 */
+			result = cp_smb_filename(mem_ctx, smb_fname_in);
+		} else {
 
-		result = synthetic_smb_fname(
-			mem_ctx,
-			base_fname->base_name,
-			smb_fname_in->stream_name,
-			&smb_fname_in->st,
-			smb_fname_in->twrp,
-			smb_fname_in->flags);
+			SMB_ASSERT(is_named_stream(smb_fname_in));
+
+			result = synthetic_smb_fname(mem_ctx,
+						     base_fname->base_name,
+						     smb_fname_in->stream_name,
+						     &smb_fname_in->st,
+						     smb_fname_in->twrp,
+						     smb_fname_in->flags);
+		}
 	} else {
 		result = full_path_from_dirfsp_atname(
 			mem_ctx, dirfsp, smb_fname_in);
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/modules/vfs_streams_depot.c samba-4.17.8+dfsg/source3/modules/vfs_streams_depot.c
--- samba-4.17.7+dfsg/source3/modules/vfs_streams_depot.c	2022-08-08 17:29:11.357506800 +0300
+++ samba-4.17.8+dfsg/source3/modules/vfs_streams_depot.c	2023-05-11 10:07:19.590421000 +0300
@@ -690,7 +690,7 @@
 	SMB_ASSERT(dirfsp == NULL);
 	SMB_ASSERT(VALID_STAT(fsp->base_fsp->fsp_name->st));
 
-	create_it = (how->mode & O_CREAT);
+	create_it = (how->flags & O_CREAT);
 
 	/* Determine the stream name, and then open it. */
 	status = stream_smb_fname(
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/rpc_server/rpcd_mdssvc.c samba-4.17.8+dfsg/source3/rpc_server/rpcd_mdssvc.c
--- samba-4.17.7+dfsg/source3/rpc_server/rpcd_mdssvc.c	2022-08-08 17:15:39.448192600 +0300
+++ samba-4.17.8+dfsg/source3/rpc_server/rpcd_mdssvc.c	2023-05-11 10:07:19.590421000 +0300
@@ -16,6 +16,7 @@
  */
 
 #include "includes.h"
+#include "source3/locking/proto.h"
 #include "rpc_worker.h"
 #include "librpc/gen_ndr/ndr_mdssvc.h"
 #include "librpc/gen_ndr/ndr_mdssvc_scompat.h"
@@ -38,9 +39,16 @@
 	void *private_data)
 {
 	static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL };
+	bool ok;
 
 	lp_load_with_shares(get_dyn_CONFIGFILE());
 
+	ok = posix_locking_init(false);
+	if (!ok) {
+		DBG_ERR("posix_locking_init() failed\n");
+		exit(1);
+	}
+
 	ep_servers[0] = mdssvc_get_ep_server();
 
 	*_ep_servers = ep_servers;
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/script/tests/test_veto_files.sh samba-4.17.8+dfsg/source3/script/tests/test_veto_files.sh
--- samba-4.17.7+dfsg/source3/script/tests/test_veto_files.sh	2022-08-16 23:15:21.280624400 +0300
+++ samba-4.17.8+dfsg/source3/script/tests/test_veto_files.sh	2023-05-11 10:07:19.590421000 +0300
@@ -22,13 +22,21 @@
 SMBCLIENT=${6}
 shift 6
 SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+# Used by test_smbclient()
+# shellcheck disable=2034
+smbclient="$VALGRIND ${SMBCLIENT}"
 ADDARGS="$@"
 
 incdir=$(dirname "$0")/../../../testprogs/blackbox
 . "$incdir"/subunit.sh
+. "${incdir}/common_test_fns.inc"
 
 failed=0
 
+TMPDIR=${PREFIX_ABS}/$(basename "${0}")
+mkdir -p "${TMPDIR}" || exit 1
+cd "${TMPDIR}" || exit 1
+
 #
 # Cleanup function.
 #
@@ -41,6 +49,8 @@
 		rm -rf "$SHAREPATH/veto_name_dir\"mangle"
 		rm -f "$SHAREPATH/veto_name_file"
 		rm -f "$SHAREPATH/veto_name_file\"mangle"
+		rm -f "${SHAREPATH}/regular_file"
+		rm -f "${SHAREPATH}/.hidden_file"
 	)
 }
 
@@ -51,7 +61,7 @@
 {
 	filename1="$1"
 	expected_error="$2"
-	tmpfile=$PREFIX/smbclient_interactive_prompt_commands
+	tmpfile=${TMPDIR}/smbclient_interactive_prompt_commands
 	cat >"$tmpfile" <<EOF
 get $filename1 got_file
 quit
@@ -84,6 +94,42 @@
 	fi
 }
 
+smbclient_create_expect_error()
+{
+	filename="$1.$$"
+	expected_error="$2"
+	tmpfile=${TMPDIR}/smbclient_interactive_prompt_commands
+	cat >"$tmpfile" <<EOF
+put $tmpfile $filename
+quit
+EOF
+
+	cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/veto_files -I$SERVER_IP < $tmpfile 2>&1'
+	eval echo "$cmd"
+	out=$(eval "$cmd")
+	ret=$?
+	rm -f "$tmpfile"
+	rm -f "$SHAREPATH/$filename"
+
+	if [ $ret != 0 ]; then
+		printf "%s\n" "$out"
+		printf "failed accessing veto_files share with error %s\n" "$ret"
+		return 1
+	fi
+
+	if [ "$expected_error" = "NT_STATUS_OK" ]; then
+		printf "%s" "$out" | grep -c "NT_STATUS_" && false
+	else
+		printf "%s" "$out" | grep "$expected_error"
+	fi
+	ret=$?
+	if [ $ret != 0 ]; then
+		printf "%s\n" "$out"
+		printf "failed - should get %s doing \"put %s\"\n" "$expected_error" "$filename"
+		return 1
+	fi
+}
+
 #
 # Using the share "[veto_files]" ensure we
 # cannot fetch a veto'd file or file in a veto'd directory.
@@ -133,6 +179,35 @@
 	return 0
 }
 
+test_create_veto_file()
+{
+	# Test creating files
+	smbclient_create_expect_error "veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+	smbclient_create_expect_error "veto_name_dir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+	smbclient_create_expect_error "dir1/veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+
+	return 0
+}
+
+do_cleanup
+
+echo "regular_file" > "${SHAREPATH}/regular_file"
+echo "hidden_file" > "${SHAREPATH}/.hidden_file"
+
+test_smbclient "download regular file" \
+	"get regular_file" "//${SERVER}/veto_files_nohidden" \
+	-U"${USERNAME}%${PASSWORD}" ||
+	failed=$((failed + 1))
+rm -f regular_file
+test_smbclient_expect_failure "hidden file can't be downloaded" \
+	"get .hidden_file" "//${SERVER}/veto_files_nohidden" \
+	-U"${USERNAME}%${PASSWORD}" ||
+	failed=$((failed + 1))
+test_smbclient "list files" \
+	"ls" "//${SERVER}/veto_files_nohidden" \
+	-U"${USERNAME}%${PASSWORD}" ||
+	failed=$((failed + 1))
+
 do_cleanup
 
 # Using hash2, veto_name_file\"mangle == VHXE5P~M
@@ -194,8 +269,11 @@
 mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/testdir"
 touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/testdir/file_inside_dir"
 
+testit "create_veto_file" test_create_veto_file || failed=$((failed + 1))
 testit "get_veto_file" test_get_veto_file || failed=$(("$failed" + 1))
 
 do_cleanup
 
+cd "${PREFIX_ABS}" && rm -rf ${TMPDIR}
+
 exit "$failed"
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/script/tests/test_wbinfo_u_large_ad.sh samba-4.17.8+dfsg/source3/script/tests/test_wbinfo_u_large_ad.sh
--- samba-4.17.7+dfsg/source3/script/tests/test_wbinfo_u_large_ad.sh	1970-01-01 03:00:00.000000000 +0300
+++ samba-4.17.8+dfsg/source3/script/tests/test_wbinfo_u_large_ad.sh	2023-05-11 10:07:19.590421000 +0300
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+LDBMODIFY="$VALGRIND ${LDBMODIFY:-$BINDIR/ldbmodify} $CONFIGURATION"
+LDBSEARCH="$VALGRIND ${LDBSEARCH:-$BINDIR/ldbsearch} $CONFIGURATION"
+WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo} $CONFIGURATION"
+
+NUM_USERS=1234
+
+BASE_DN=$($LDBSEARCH -H ldap://$DC_SERVER -b "" --scope=base defaultNamingContext | awk '/^defaultNamingContext/ {print $2}')
+
+incdir=$(dirname $0)/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+seq -w 1 "$NUM_USERS" |
+    xargs -INUM echo -e "dn:cn=large_ad_NUM,cn=users,$BASE_DN\nchangetype:add\nobjectclass:user\nsamaccountname:large_ad_NUM\n" |
+    $LDBMODIFY -H ldap://$DC_SERVER -U "$DOMAIN\Administrator%$DC_PASSWORD"
+
+testit_grep_count \
+    "Make sure $NUM_USERS $DOMAIN users are returned" \
+    "$DOMAIN/large_ad_" \
+    "$NUM_USERS" \
+    ${WBINFO} -u || failed=$(expr $failed + 1)
+
+seq -w 1 "$NUM_USERS" |
+    xargs -INUM echo -e "dn:cn=large_ad_NUM,cn=users,$BASE_DN\nchangetype:delete\n" |
+    $LDBMODIFY -H ldap://$DC_SERVER -U "$DOMAIN\Administrator%$DC_PASSWORD"
+
+testok $0 $failed
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/script/tests/test_zero_readsize.sh samba-4.17.8+dfsg/source3/script/tests/test_zero_readsize.sh
--- samba-4.17.7+dfsg/source3/script/tests/test_zero_readsize.sh	1970-01-01 03:00:00.000000000 +0300
+++ samba-4.17.8+dfsg/source3/script/tests/test_zero_readsize.sh	2023-05-11 10:07:19.590421000 +0300
@@ -0,0 +1,101 @@
+#!/usr/bin/env bash
+#
+# Test setting smb2 max read = 0.
+#
+# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15306
+#
+
+if [ $# -lt 6 ]; then
+	cat <<EOF
+Usage: $0 SERVERCONFFILE SMBCLIENT SMBCONTROL SERVER SHARE PREFIX
+EOF
+        exit 1
+fi
+
+CONF=${1}
+shift 1
+SMBCLIENT=${1}
+shift 1
+SMBCONTROL=${1}
+shift 1
+SERVER=${1}
+shift 1
+SHARE=${1}
+shift 1
+PREFIX=${1}
+shift 1
+
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$@"
+
+incdir=$(dirname "$0")/../../../testprogs/blackbox
+. "$incdir"/subunit.sh
+
+failed=0
+
+#
+# Setup function
+#
+do_setup()
+{
+	rm -f "${PREFIX}/zero_read_testfile"
+	rm -f "${PREFIX}/zero_read_testfile_get"
+	dd if=/dev/zero of="${PREFIX}/zero_read_testfile" bs=1024 count=1
+	global_inject_conf="$(dirname "${SERVERCONFFILE}")/global_inject.conf"
+	echo "smb2 max read = 0" >"$global_inject_conf"
+	${SMBCONTROL} ${CONF} smbd reload-config
+}
+
+do_cleanup()
+{
+	rm -f "${PREFIX}/zero_read_testfile"
+	rm -f "${PREFIX}/zero_read_testfile_get"
+	global_inject_conf="$(dirname "${SERVERCONFFILE}")/global_inject.conf"
+	rm "$global_inject_conf"
+	${SMBCONTROL} ${CONF} smbd reload-config
+}
+
+test_smb2_zero_readsize()
+{
+	local tmpfile="$PREFIX/smbclient.in.$$"
+
+	cat >"$tmpfile" <<EOF
+lcd $PREFIX
+put zero_read_testfile zero_read_testfile_put
+get zero_read_testfile_put zero_read_testfile_get
+del zero_read_testfile_put
+quit
+EOF
+
+	local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/$SHARE -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
+	eval echo "$cmd"
+	out=$(eval "$cmd")
+	ret=$?
+
+	# Check for smbclient error.
+	# We should have failed the protocol negotiation, returning 1.
+	if [ $ret != 1 ]; then
+                echo "smbclient protocol negotiation succeeded (should have failed) zero read testfile $ret"
+                echo "$out"
+                return 1
+        fi
+
+	# We should get NT_STATUS_INVALID_NETWORK_RESPONSE
+	echo "$out" | grep NT_STATUS_INVALID_NETWORK_RESPONSE
+	ret=$?
+	if [ $ret -ne 0 ]; then
+                echo "Should get NT_STATUS_INVALID_NETWORK_RESPONSE"
+                echo "$out"
+                return 1
+        fi
+	rm "$tmpfile"
+	return 0
+}
+
+do_setup
+
+testit "smb2_zero_readsize" test_smb2_zero_readsize || failed=$((failed + 1))
+
+do_cleanup
+
+testok "$0" "$failed"
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/filename.c samba-4.17.8+dfsg/source3/smbd/filename.c
--- samba-4.17.7+dfsg/source3/smbd/filename.c	2023-03-09 12:18:38.357810700 +0300
+++ samba-4.17.8+dfsg/source3/smbd/filename.c	2023-05-11 10:07:19.594421000 +0300
@@ -840,7 +840,7 @@
 	if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
 		DBG_DEBUG("veto files rejecting last component %s\n",
 			  smb_fname_str_dbg(smb_fname_rel));
-		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+		return NT_STATUS_NETWORK_OPEN_RESTRICTION;
 	}
 
 	status = openat_pathref_fsp(dirfsp, smb_fname_rel);
@@ -906,7 +906,7 @@
 			DBG_DEBUG("veto files rejecting last component %s\n",
 				  smb_fname_str_dbg(smb_fname_rel));
 			TALLOC_FREE(cache_key.data);
-			return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+			return NT_STATUS_NETWORK_OPEN_RESTRICTION;
 		}
 
 		status = openat_pathref_fsp(dirfsp, smb_fname_rel);
@@ -936,7 +936,7 @@
 		if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
 			DBG_DEBUG("veto files rejecting last component %s\n",
 				smb_fname_str_dbg(smb_fname_rel));
-			return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+			return NT_STATUS_NETWORK_OPEN_RESTRICTION;
 		}
 
 		status = openat_pathref_fsp(dirfsp, smb_fname_rel);
@@ -1153,6 +1153,14 @@
 		char *substitute = NULL;
 		size_t unparsed = 0;
 
+		status = normalize_filename_case(conn, dirname, ucf_flags);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("normalize_filename_case %s failed: %s\n",
+				dirname,
+				nt_errstr(status));
+			goto fail;
+		}
+
 		status = openat_pathref_dirfsp_nosymlink(
 			mem_ctx,
 			conn,
@@ -1341,6 +1349,10 @@
 		goto done;
 	}
 
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_OPEN_RESTRICTION)) {
+		/* A vetoed file, pretend it's not there  */
+		status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+	}
 	if (!NT_STATUS_IS_OK(status)) {
 		goto fail;
 	}
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/globals.h samba-4.17.8+dfsg/source3/smbd/globals.h
--- samba-4.17.7+dfsg/source3/smbd/globals.h	2023-01-26 20:45:01.657668600 +0300
+++ samba-4.17.8+dfsg/source3/smbd/globals.h	2023-05-11 10:07:19.594421000 +0300
@@ -648,6 +648,8 @@
 NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon, uint64_t vuid);
 NTSTATUS smb1srv_tcon_table_init(struct smbXsrv_connection *conn);
 NTSTATUS smb1srv_tcon_create(struct smbXsrv_connection *conn,
+			     uint32_t session_global_id,
+			     const char *share_name,
 			     NTTIME now,
 			     struct smbXsrv_tcon **_tcon);
 NTSTATUS smb1srv_tcon_lookup(struct smbXsrv_connection *conn,
@@ -656,6 +658,9 @@
 NTSTATUS smb1srv_tcon_disconnect_all(struct smbXsrv_client *client);
 NTSTATUS smb2srv_tcon_table_init(struct smbXsrv_session *session);
 NTSTATUS smb2srv_tcon_create(struct smbXsrv_session *session,
+			     uint32_t session_global_id,
+			     uint8_t encryption_flags,
+			     const char *share_name,
 			     NTTIME now,
 			     struct smbXsrv_tcon **_tcon);
 NTSTATUS smb2srv_tcon_lookup(struct smbXsrv_session *session,
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/open.c samba-4.17.8+dfsg/source3/smbd/open.c
--- samba-4.17.7+dfsg/source3/smbd/open.c	2022-09-06 17:22:03.302113000 +0300
+++ samba-4.17.8+dfsg/source3/smbd/open.c	2023-05-11 10:07:19.598420900 +0300
@@ -3389,7 +3389,7 @@
 	rejected_share_access = access_mask & ~(fsp->conn->share_access);
 
 	if (rejected_share_access) {
-		DBG_ERR("Access denied on file %s: "
+		DBG_INFO("Access denied on file %s: "
 			"rejected by share access mask[0x%08X] "
 			"orig[0x%08X] mapped[0x%08X] reject[0x%08X]\n",
 			fsp_str_dbg(fsp),
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/smb1_service.c samba-4.17.8+dfsg/source3/smbd/smb1_service.c
--- samba-4.17.7+dfsg/source3/smbd/smb1_service.c	2022-08-08 17:15:39.484192800 +0300
+++ samba-4.17.8+dfsg/source3/smbd/smb1_service.c	2023-05-11 10:07:19.598420900 +0300
@@ -48,17 +48,43 @@
 {
 	const struct loadparm_substitution *lp_sub =
 		loadparm_s3_global_substitution();
+	uint32_t session_global_id;
+	char *share_name = NULL;
 	struct smbXsrv_tcon *tcon;
 	NTSTATUS status;
 	struct connection_struct *conn;
 
-	status = smb1srv_tcon_create(req->xconn, now, &tcon);
+	session_global_id = req->session->global->session_global_id;
+	share_name = lp_servicename(talloc_tos(), lp_sub, snum);
+	if (share_name == NULL) {
+		*pstatus = NT_STATUS_NO_MEMORY;
+		return NULL;
+	}
+
+	if ((lp_max_connections(snum) > 0)
+	    && (count_current_connections(lp_const_servicename(snum), true) >=
+		lp_max_connections(snum))) {
+
+		DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n",
+			  lp_max_connections(snum),
+			  lp_const_servicename(snum), share_name);
+		TALLOC_FREE(share_name);
+		*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
+		return NULL;
+	}
+
+	status = smb1srv_tcon_create(req->xconn,
+				     session_global_id,
+				     share_name,
+				     now, &tcon);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
-			 nt_errstr(status)));
+		DEBUG(0,("make_connection_smb1: Couldn't find free tcon for [%s] - %s\n",
+			 share_name, nt_errstr(status)));
+		TALLOC_FREE(share_name);
 		*pstatus = status;
 		return NULL;
 	}
+	TALLOC_FREE(share_name);
 
 	conn = conn_new(req->sconn);
 	if (!conn) {
@@ -83,24 +109,10 @@
 		return NULL;
 	}
 
-	tcon->global->share_name = lp_servicename(tcon->global, lp_sub, SNUM(conn));
-	if (tcon->global->share_name == NULL) {
-		conn_free(conn);
-		TALLOC_FREE(tcon);
-		*pstatus = NT_STATUS_NO_MEMORY;
-		return NULL;
-	}
-	tcon->global->session_global_id =
-		req->session->global->session_global_id;
-
 	tcon->compat = talloc_move(tcon, &conn);
 	tcon->status = NT_STATUS_OK;
 
-	*pstatus = smbXsrv_tcon_update(tcon);
-	if (!NT_STATUS_IS_OK(*pstatus)) {
-		TALLOC_FREE(tcon);
-		return NULL;
-	}
+	*pstatus = NT_STATUS_OK;
 
 	return tcon->compat;
 }
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/smb2_service.c samba-4.17.8+dfsg/source3/smbd/smb2_service.c
--- samba-4.17.7+dfsg/source3/smbd/smb2_service.c	2022-08-23 17:45:49.528087900 +0300
+++ samba-4.17.8+dfsg/source3/smbd/smb2_service.c	2023-05-11 10:07:19.598420900 +0300
@@ -646,21 +646,6 @@
 	 * in the logs. */
 	widelinks_warning(snum);
 
-	/*
-	 * Enforce the max connections parameter.
-	 */
-
-	if ((lp_max_connections(snum) > 0)
-	    && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
-		lp_max_connections(snum))) {
-
-		DBG_WARNING("Max connections (%d) exceeded for %s\n",
-			  lp_max_connections(snum),
-			  lp_const_servicename(snum));
-		status = NT_STATUS_INSUFFICIENT_RESOURCES;
-		goto err_root_exit;
-	}
-
 	/* Invoke VFS make connection hook - this must be the first
 	   filesystem operation that we do. */
 
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/smb2_tcon.c samba-4.17.8+dfsg/source3/smbd/smb2_tcon.c
--- samba-4.17.7+dfsg/source3/smbd/smb2_tcon.c	2022-08-08 17:15:39.492193000 +0300
+++ samba-4.17.8+dfsg/source3/smbd/smb2_tcon.c	2023-05-11 10:07:19.598420900 +0300
@@ -217,6 +217,9 @@
 	bool encryption_required = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
 	bool guest_session = false;
 	bool require_signed_tcon = false;
+	uint32_t session_global_id;
+	char *share_name = NULL;
+	uint8_t encryption_flags = 0;
 
 	*disconnect = false;
 
@@ -328,17 +331,39 @@
 		}
 	}
 
-	/* create a new tcon as child of the session */
-	status = smb2srv_tcon_create(req->session, now, &tcon);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
-
 	if (encryption_desired) {
-		tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
+		encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
 	}
 	if (encryption_required) {
-		tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED;
+		encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED;
+	}
+
+	session_global_id = req->session->global->session_global_id;
+	share_name = lp_servicename(talloc_tos(), lp_sub, snum);
+	if (share_name == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if ((lp_max_connections(snum) > 0)
+	    && (count_current_connections(lp_const_servicename(snum), true) >=
+		lp_max_connections(snum))) {
+
+		DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n",
+			  lp_max_connections(snum),
+			  lp_const_servicename(snum), share_name);
+		TALLOC_FREE(share_name);
+		return NT_STATUS_INSUFFICIENT_RESOURCES;
+	}
+
+	/* create a new tcon as child of the session */
+	status = smb2srv_tcon_create(req->session,
+				     session_global_id,
+				     encryption_flags,
+				     share_name,
+				     now, &tcon);
+	TALLOC_FREE(share_name);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
 	}
 
 	compat_conn = make_connection_smb2(req,
@@ -350,27 +375,10 @@
 		return status;
 	}
 
-	tcon->global->share_name = lp_servicename(tcon->global,
-						  lp_sub,
-						  SNUM(compat_conn));
-	if (tcon->global->share_name == NULL) {
-		conn_free(compat_conn);
-		TALLOC_FREE(tcon);
-		return NT_STATUS_NO_MEMORY;
-	}
-	tcon->global->session_global_id =
-		req->session->global->session_global_id;
-
 	tcon->compat = talloc_move(tcon, &compat_conn);
 
 	tcon->status = NT_STATUS_OK;
 
-	status = smbXsrv_tcon_update(tcon);
-	if (!NT_STATUS_IS_OK(status)) {
-		TALLOC_FREE(tcon);
-		return status;
-	}
-
 	if (IS_PRINT(tcon->compat)) {
 		*out_share_type = SMB2_SHARE_TYPE_PRINT;
 	} else if (IS_IPC(tcon->compat)) {
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/smbd/smbXsrv_tcon.c samba-4.17.8+dfsg/source3/smbd/smbXsrv_tcon.c
--- samba-4.17.7+dfsg/source3/smbd/smbXsrv_tcon.c	2022-08-23 17:45:49.528087900 +0300
+++ samba-4.17.8+dfsg/source3/smbd/smbXsrv_tcon.c	2023-05-11 10:07:19.602421000 +0300
@@ -738,6 +738,9 @@
 				    enum protocol_types protocol,
 				    struct server_id server_id,
 				    NTTIME now,
+				    uint32_t session_global_id,
+				    uint8_t encryption_flags,
+				    const char *share_name,
 				    struct smbXsrv_tcon **_tcon)
 {
 	struct db_record *local_rec = NULL;
@@ -767,6 +770,14 @@
 	}
 	tcon->global = global;
 
+	global->session_global_id = session_global_id;
+	global->encryption_flags = encryption_flags;
+	global->share_name = talloc_strdup(global, share_name);
+	if (global->share_name == NULL) {
+		TALLOC_FREE(tcon);
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	if (protocol >= PROTOCOL_SMB2_02) {
 		uint64_t id = global->tcon_global_id;
 
@@ -1100,14 +1111,21 @@
 }
 
 NTSTATUS smb1srv_tcon_create(struct smbXsrv_connection *conn,
+			     uint32_t session_global_id,
+			     const char *share_name,
 			     NTTIME now,
 			     struct smbXsrv_tcon **_tcon)
 {
 	struct server_id id = messaging_server_id(conn->client->msg_ctx);
+	const uint8_t encryption_flags = 0;
 
 	return smbXsrv_tcon_create(conn->client->tcon_table,
 				   conn->protocol,
-				   id, now, _tcon);
+				   id, now,
+				   session_global_id,
+				   encryption_flags,
+				   share_name,
+				   _tcon);
 }
 
 NTSTATUS smb1srv_tcon_lookup(struct smbXsrv_connection *conn,
@@ -1156,6 +1174,9 @@
 }
 
 NTSTATUS smb2srv_tcon_create(struct smbXsrv_session *session,
+			     uint32_t session_global_id,
+			     uint8_t encryption_flags,
+			     const char *share_name,
 			     NTTIME now,
 			     struct smbXsrv_tcon **_tcon)
 {
@@ -1163,7 +1184,11 @@
 
 	return smbXsrv_tcon_create(session->tcon_table,
 				   PROTOCOL_SMB2_02,
-				   id, now, _tcon);
+				   id, now,
+				   session_global_id,
+				   encryption_flags,
+				   share_name,
+				   _tcon);
 }
 
 NTSTATUS smb2srv_tcon_lookup(struct smbXsrv_session *session,
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/utils/net_ads.c samba-4.17.8+dfsg/source3/utils/net_ads.c
--- samba-4.17.7+dfsg/source3/utils/net_ads.c	2022-12-15 19:09:31.745236600 +0300
+++ samba-4.17.8+dfsg/source3/utils/net_ads.c	2023-05-11 10:07:19.602421000 +0300
@@ -710,7 +710,15 @@
 			TALLOC_FREE(ads);
 			return ADS_ERROR(LDAP_NO_MEMORY);
 		}
-       }
+	} else if (ads->auth.realm == NULL) {
+		const char *c_realm = cli_credentials_get_realm(c->creds);
+
+		ads->auth.realm = talloc_strdup(ads, c_realm);
+		if (ads->auth.realm == NULL) {
+			TALLOC_FREE(ads);
+			return ADS_ERROR(LDAP_NO_MEMORY);
+		}
+	}
 
 	status = ads_connect(ads);
 
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/winbindd/idmap_autorid.c samba-4.17.8+dfsg/source3/winbindd/idmap_autorid.c
--- samba-4.17.7+dfsg/source3/winbindd/idmap_autorid.c	2022-08-08 17:15:39.520193000 +0300
+++ samba-4.17.8+dfsg/source3/winbindd/idmap_autorid.c	2023-05-11 10:07:19.602421000 +0300
@@ -697,9 +697,10 @@
 {
 	struct idmap_tdb_common_context *commoncfg;
 	NTSTATUS ret;
-	int i;
-	int num_tomap = 0;
-	int num_mapped = 0;
+	size_t i;
+	size_t num_tomap = 0;
+	size_t num_mapped = 0;
+	size_t num_required = 0;
 
 	/* initialize the status to avoid surprise */
 	for (i = 0; ids[i]; i++) {
@@ -713,6 +714,12 @@
 
 	for (i = 0; ids[i]; i++) {
 		ret = idmap_autorid_sid_to_id(commoncfg, dom, ids[i]);
+		if (NT_STATUS_EQUAL(ret, NT_STATUS_SOME_NOT_MAPPED) &&
+		    ids[i]->status == ID_REQUIRE_TYPE)
+		{
+			num_required++;
+			continue;
+		}
 		if ((!NT_STATUS_IS_OK(ret)) &&
 		    (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
 			struct dom_sid_buf buf;
@@ -729,6 +736,8 @@
 
 	if (num_tomap == num_mapped) {
 		return NT_STATUS_OK;
+	} else if (num_required > 0) {
+		return STATUS_SOME_UNMAPPED;
 	} else if (num_mapped == 0) {
 		return NT_STATUS_NONE_MAPPED;
 	}
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/winbindd/idmap_hash/idmap_hash.c samba-4.17.8+dfsg/source3/winbindd/idmap_hash/idmap_hash.c
--- samba-4.17.7+dfsg/source3/winbindd/idmap_hash/idmap_hash.c	2022-08-08 17:15:39.520193000 +0300
+++ samba-4.17.8+dfsg/source3/winbindd/idmap_hash/idmap_hash.c	2023-05-11 10:07:19.602421000 +0300
@@ -25,6 +25,7 @@
 #include "ads.h"
 #include "nss_info.h"
 #include "../libcli/security/dom_sid.h"
+#include "libsmb/samlogon_cache.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
@@ -60,13 +61,16 @@
 }
 
 /*********************************************************************
- Hash a Relative ID to a 20 bit number
+ Hash a Relative ID to a 19 bit number
  ********************************************************************/
 
 static uint32_t hash_rid(uint32_t rid)
 {
-	/* 20 bits for the rid which allows us to support
-	   the first 100K users/groups in a domain */
+	/*
+	 * 19 bits for the rid which allows us to support
+	 * the first 50K users/groups in a domain
+	 *
+	 */
 
 	return (rid & 0x0007FFFF);
 }
@@ -79,8 +83,13 @@
 {
 	uint32_t return_id = 0;
 
-	/* shift the hash_domain 19 bits to the left and OR with the
-	   hash_rid */
+	/*
+	 * shift the hash_domain 19 bits to the left and OR with the
+	 * hash_rid
+	 *
+	 * This will generate a 31 bit number out of
+	 * 12 bit domain and 19 bit rid.
+	 */
 
 	return_id = ((h_domain<<19) | h_rid);
 
@@ -123,14 +132,6 @@
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	/* If the domain SID hash table has been initialized, assume
-	   that we completed this function previously */
-
-	if (dom->private_data != NULL) {
-		nt_status = NT_STATUS_OK;
-		goto done;
-	}
-
 	if (!wcache_tdc_fetch_list(&dom_list, &num_domains)) {
 		nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
 		BAIL_ON_NTSTATUS_ERROR(nt_status);
@@ -183,135 +184,224 @@
 /*********************************************************************
  ********************************************************************/
 
+static NTSTATUS idmap_hash_id_to_sid(struct sid_hash_table *hashed_domains,
+				     struct idmap_domain *dom,
+				     struct id_map *id)
+{
+	uint32_t h_domain = 0, h_rid = 0;
+
+	id->status = ID_UNMAPPED;
+
+	separate_hashes(id->xid.id, &h_domain, &h_rid);
+
+	/*
+	 * If the domain hash doesn't find a SID in the table,
+	 * skip it
+	 */
+	if (hashed_domains[h_domain].sid == NULL) {
+		/* keep ID_UNMAPPED */
+		return NT_STATUS_OK;
+	}
+
+	id->xid.type = ID_TYPE_BOTH;
+	sid_compose(id->sid, hashed_domains[h_domain].sid, h_rid);
+	id->status = ID_MAPPED;
+
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS unixids_to_sids(struct idmap_domain *dom,
 				struct id_map **ids)
 {
 	struct sid_hash_table *hashed_domains = talloc_get_type_abort(
 		dom->private_data, struct sid_hash_table);
-	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-	int i;
-
-	if (!ids) {
-		nt_status = NT_STATUS_INVALID_PARAMETER;
-		BAIL_ON_NTSTATUS_ERROR(nt_status);
-	}
+	size_t i;
+	size_t num_tomap = 0;
+	size_t num_mapped = 0;
 
-	/* initialize the status to avoid suprise */
+	/* initialize the status to avoid surprise */
 	for (i = 0; ids[i]; i++) {
 		ids[i]->status = ID_UNKNOWN;
+		num_tomap++;
 	}
 
-	nt_status = idmap_hash_initialize(dom);
-	BAIL_ON_NTSTATUS_ERROR(nt_status);
-
 	for (i=0; ids[i]; i++) {
-		uint32_t h_domain, h_rid;
-
-		ids[i]->status = ID_UNMAPPED;
-
-		separate_hashes(ids[i]->xid.id, &h_domain, &h_rid);
+		NTSTATUS ret;
 
-		/* Make sure the caller allocated memor for us */
-
-		if (!ids[i]->sid) {
-			nt_status = NT_STATUS_INVALID_PARAMETER;
-			BAIL_ON_NTSTATUS_ERROR(nt_status);
+		ret = idmap_hash_id_to_sid(hashed_domains, dom, ids[i]);
+		if (!NT_STATUS_IS_OK(ret)) {
+			/* some fatal error occurred, log it */
+			DBG_NOTICE("Unexpected error resolving an ID "
+				   "(%d): %s\n", ids[i]->xid.id,
+				   nt_errstr(ret));
+			return ret;
 		}
 
-		/* If the domain hash doesn't find a SID in the table,
-		   skip it */
-
-		if (!hashed_domains[h_domain].sid)
-			continue;
+		if (ids[i]->status == ID_MAPPED) {
+			num_mapped++;
+		}
+	}
 
-		sid_compose(ids[i]->sid, hashed_domains[h_domain].sid, h_rid);
-		ids[i]->status = ID_MAPPED;
+	if (num_tomap == num_mapped) {
+		return NT_STATUS_OK;
+	} else if (num_mapped == 0) {
+		return NT_STATUS_NONE_MAPPED;
 	}
 
-done:
-	return nt_status;
+	return STATUS_SOME_UNMAPPED;
 }
 
 /*********************************************************************
  ********************************************************************/
 
-static NTSTATUS sids_to_unixids(struct idmap_domain *dom,
-				struct id_map **ids)
+static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains,
+				     struct idmap_domain *dom,
+				     struct id_map *id)
 {
-	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-	int i;
+	struct dom_sid sid;
+	uint32_t rid;
+	uint32_t h_domain, h_rid;
+
+	id->status = ID_UNMAPPED;
+
+	sid_copy(&sid, id->sid);
+	sid_split_rid(&sid, &rid);
+
+	h_domain = hash_domain_sid(&sid);
+	h_rid = hash_rid(rid);
+
+	/* Check that both hashes are non-zero*/
+	if (h_domain == 0) {
+		/* keep ID_UNMAPPED */
+		return NT_STATUS_OK;
+	}
+	if (h_rid == 0) {
+		/* keep ID_UNMAPPED */
+		return NT_STATUS_OK;
+	}
 
-	if (!ids) {
-		nt_status = NT_STATUS_INVALID_PARAMETER;
-		BAIL_ON_NTSTATUS_ERROR(nt_status);
+	/*
+	 * If the domain hash already exists find a SID in the table,
+	 * just return the mapping.
+	 */
+	if (hashed_domains[h_domain].sid != NULL) {
+		goto return_mapping;
 	}
 
-	/* initialize the status to avoid suprise */
-	for (i = 0; ids[i]; i++) {
-		ids[i]->status = ID_UNKNOWN;
+	/*
+	 * Check of last resort: A domain is valid if a user from that
+	 * domain has recently logged in. The samlogon_cache these
+	 * days also stores the domain sid.
+	 */
+	if (netsamlogon_cache_have(&sid)) {
+		/*
+		 * The domain is valid, so we'll
+		 * remember it in order to
+		 * allow reverse mappings to work.
+		 */
+		goto remember_domain;
+	}
+
+	if (id->xid.type == ID_TYPE_NOT_SPECIFIED) {
+		/*
+		 * idmap_hash used to bounce back the requested type,
+		 * which was ID_TYPE_UID, ID_TYPE_GID or
+		 * ID_TYPE_NOT_SPECIFIED before as the winbindd parent
+		 * always used a lookupsids.  When the lookupsids
+		 * failed because of an unknown domain, the idmap child
+		 * weren't requested at all and the caller sees
+		 * ID_TYPE_NOT_SPECIFIED.
+		 *
+		 * Now that the winbindd parent will pass ID_TYPE_BOTH
+		 * in order to indicate that the domain exists.
+		 * We should ask the parent to fallback to lookupsids
+		 * if the domain is not known yet.
+		 */
+		id->status = ID_REQUIRE_TYPE;
+		return NT_STATUS_OK;
 	}
 
-	nt_status = idmap_hash_initialize(dom);
-	BAIL_ON_NTSTATUS_ERROR(nt_status);
+	/*
+	 * Now we're sure the domain exist, remember
+	 * the domain in order to return reverse mappings
+	 * in future.
+	 */
+remember_domain:
+	hashed_domains[h_domain].sid = dom_sid_dup(hashed_domains, &sid);
+	if (hashed_domains[h_domain].sid == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
 
-	for (i=0; ids[i]; i++) {
-		struct dom_sid sid;
-		uint32_t rid;
-		uint32_t h_domain, h_rid;
-
-		ids[i]->status = ID_UNMAPPED;
-
-		if (ids[i]->xid.type == ID_TYPE_NOT_SPECIFIED) {
-			/*
-			 * idmap_hash used to bounce back the requested type,
-			 * which was ID_TYPE_UID, ID_TYPE_GID or
-			 * ID_TYPE_NOT_SPECIFIED before as the winbindd parent
-			 * always used a lookupsids.  When the lookupsids
-			 * failed because of an unknown domain, the idmap child
-			 * weren't requested at all and the caller sees
-			 * ID_TYPE_NOT_SPECIFIED.
-			 *
-			 * Now that the winbindd parent will pass ID_TYPE_BOTH
-			 * in order to indicate that the domain exists.
-			 * We should ask the parent to fallback to lookupsids
-			 * if the domain is not known yet.
-			 */
-			ids[i]->status = ID_REQUIRE_TYPE;
-			continue;
-		}
+	/*
+	 * idmap_hash used to bounce back the requested type,
+	 * which was ID_TYPE_UID, ID_TYPE_GID or
+	 * ID_TYPE_NOT_SPECIFIED before as the winbindd parent
+	 * always used a lookupsids.
+	 *
+	 * This module should have supported ID_TYPE_BOTH since
+	 * samba-4.1.0, similar to idmap_rid and idmap_autorid.
+	 *
+	 * Now that the winbindd parent will pass ID_TYPE_BOTH
+	 * in order to indicate that the domain exists, it's
+	 * better to always return ID_TYPE_BOTH instead of a
+	 * random mix of ID_TYPE_UID, ID_TYPE_GID or
+	 * ID_TYPE_BOTH.
+	 */
+return_mapping:
+	id->xid.type = ID_TYPE_BOTH;
+	id->xid.id = combine_hashes(h_domain, h_rid);
+	id->status = ID_MAPPED;
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS sids_to_unixids(struct idmap_domain *dom,
+				struct id_map **ids)
+{
+	struct sid_hash_table *hashed_domains = talloc_get_type_abort(
+		dom->private_data, struct sid_hash_table);
+	size_t i;
+	size_t num_tomap = 0;
+	size_t num_mapped = 0;
+	size_t num_required = 0;
 
-		sid_copy(&sid, ids[i]->sid);
-		sid_split_rid(&sid, &rid);
+	/* initialize the status to avoid surprise */
+	for (i = 0; ids[i]; i++) {
+		ids[i]->status = ID_UNKNOWN;
+		num_tomap++;
+	}
 
-		h_domain = hash_domain_sid(&sid);
-		h_rid = hash_rid(rid);
+	for (i=0; ids[i]; i++) {
+		NTSTATUS ret;
 
-		/* Check that both hashes are non-zero*/
+		ret = idmap_hash_sid_to_id(hashed_domains, dom, ids[i]);
+		if (!NT_STATUS_IS_OK(ret)) {
+			struct dom_sid_buf buf;
+			/* some fatal error occurred, log it */
+			DBG_NOTICE("Unexpected error resolving a SID "
+				   "(%s): %s\n",
+				   dom_sid_str_buf(ids[i]->sid, &buf),
+				   nt_errstr(ret));
+			return ret;
+		}
 
-		if (h_domain && h_rid) {
-			/*
-			 * idmap_hash used to bounce back the requested type,
-			 * which was ID_TYPE_UID, ID_TYPE_GID or
-			 * ID_TYPE_NOT_SPECIFIED before as the winbindd parent
-			 * always used a lookupsids.
-			 *
-			 * This module should have supported ID_TYPE_BOTH since
-			 * samba-4.1.0, similar to idmap_rid and idmap_autorid.
-			 *
-			 * Now that the winbindd parent will pass ID_TYPE_BOTH
-			 * in order to indicate that the domain exists, it's
-			 * better to always return ID_TYPE_BOTH instead of a
-			 * random mix of ID_TYPE_UID, ID_TYPE_GID or
-			 * ID_TYPE_BOTH.
-			 */
-			ids[i]->xid.type = ID_TYPE_BOTH;
-			ids[i]->xid.id = combine_hashes(h_domain, h_rid);
-			ids[i]->status = ID_MAPPED;
+		if (ids[i]->status == ID_MAPPED) {
+			num_mapped++;
+		}
+		if (ids[i]->status == ID_REQUIRE_TYPE) {
+			num_required++;
 		}
 	}
 
-done:
-	return nt_status;
+	if (num_tomap == num_mapped) {
+		return NT_STATUS_OK;
+	} else if (num_required > 0) {
+		return STATUS_SOME_UNMAPPED;
+	} else if (num_mapped == 0) {
+		return NT_STATUS_NONE_MAPPED;
+	}
+
+	return STATUS_SOME_UNMAPPED;
 }
 
 /*********************************************************************
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/winbindd/winbindd_dual.c samba-4.17.8+dfsg/source3/winbindd/winbindd_dual.c
--- samba-4.17.7+dfsg/source3/winbindd/winbindd_dual.c	2022-08-08 17:15:39.524193300 +0300
+++ samba-4.17.8+dfsg/source3/winbindd/winbindd_dual.c	2023-05-11 10:07:19.606421000 +0300
@@ -1810,13 +1810,6 @@
 		}
 	}
 
-	/*
-	 * We are in idmap child, bring primary domain online.
-	 */
-	if (is_idmap_child(child)) {
-		set_domain_online_request(primary_domain);
-	}
-
 	/* We might be in the idmap child...*/
 	if (child->domain && !(child->domain->internal) &&
 	    lp_winbind_offline_logon()) {
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source3/winbindd/winbindd_samr.c samba-4.17.8+dfsg/source3/winbindd/winbindd_samr.c
--- samba-4.17.7+dfsg/source3/winbindd/winbindd_samr.c	2022-08-08 17:15:39.532193200 +0300
+++ samba-4.17.8+dfsg/source3/winbindd/winbindd_samr.c	2023-05-11 10:07:19.606421000 +0300
@@ -914,8 +914,6 @@
 	struct rpc_pipe_client *samr_pipe = NULL;
 	struct dcerpc_binding_handle *h = NULL;
 	struct policy_handle dom_pol = { .handle_type = 0, };
-	struct lsa_Strings lsa_names = { .count = 0, };
-	struct samr_Ids samr_types = { .count = 0, };
 	enum lsa_SidType *types = NULL;
 	char **names = NULL;
 	const char *domain_name = NULL;
@@ -997,49 +995,73 @@
 	}
 	h = samr_pipe->binding_handle;
 
-	status = dcerpc_samr_LookupRids(
-		h,
-		tmp_ctx,
-		&dom_pol,
-		num_rids,
-		rids,
-		&lsa_names,
-		&samr_types,
-		&result);
-
-	if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
-		retry = true;
-		goto again;
-	}
+	/*
+	 * Magic number 1000 comes from samr.idl
+	 */
+
+	for (i = 0; i < num_rids; i += 1000) {
+		uint32_t num_lookup_rids = MIN(num_rids - i, 1000);
+		struct lsa_Strings lsa_names = {
+			.count = 0,
+		};
+		struct samr_Ids samr_types = {
+			.count = 0,
+		};
+		uint32_t j;
+
+		status = dcerpc_samr_LookupRids(h,
+						tmp_ctx,
+						&dom_pol,
+						num_lookup_rids,
+						&rids[i],
+						&lsa_names,
+						&samr_types,
+						&result);
+
+		if (!retry &&
+		    reset_connection_on_error(domain, samr_pipe, status)) {
+			retry = true;
+			goto again;
+		}
 
-	if (!NT_STATUS_IS_OK(status)) {
-		DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
-			  nt_errstr(status));
-		goto fail;
-	}
-	if (!NT_STATUS_IS_OK(result) &&
-	    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
-		DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
-			  nt_errstr(result));
-		status = result;
-		goto fail;
-	}
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
+				  nt_errstr(status));
+			goto fail;
+		}
+		if (!NT_STATUS_IS_OK(result) &&
+		    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
+			DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
+				  nt_errstr(result));
+			status = result;
+			goto fail;
+		}
 
-	for (i=0; i<num_rids; i++) {
-		types[i] = samr_types.ids[i];
-		names[i] = talloc_move(
-			names,
-			discard_const_p(char *, &lsa_names.names[i].string));
-
-		if (names[i] != NULL) {
-			char *normalized = NULL;
-			NTSTATUS nstatus = normalize_name_map(
-				names, domain_name, names[i], &normalized);
-			if (NT_STATUS_IS_OK(nstatus) ||
-			    NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
-				names[i] = normalized;
+		for (j = 0; j < num_lookup_rids; j++) {
+			uint32_t dst = i + j;
+
+			types[dst] = samr_types.ids[j];
+			names[dst] = talloc_move(
+				names,
+				discard_const_p(char *,
+						&lsa_names.names[j].string));
+			if (names[dst] != NULL) {
+				char *normalized = NULL;
+				NTSTATUS nstatus =
+					normalize_name_map(names,
+							   domain_name,
+							   names[dst],
+							   &normalized);
+				if (NT_STATUS_IS_OK(nstatus) ||
+				    NT_STATUS_EQUAL(nstatus,
+						    NT_STATUS_FILE_RENAMED)) {
+					names[dst] = normalized;
+				}
 			}
 		}
+
+		TALLOC_FREE(samr_types.ids);
+		TALLOC_FREE(lsa_names.names);
 	}
 
 done:
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source4/dsdb/pydsdb.c samba-4.17.8+dfsg/source4/dsdb/pydsdb.c
--- samba-4.17.7+dfsg/source4/dsdb/pydsdb.c	2023-03-20 12:04:29.087923300 +0300
+++ samba-4.17.8+dfsg/source4/dsdb/pydsdb.c	2023-05-11 10:07:19.606421000 +0300
@@ -1755,5 +1755,20 @@
 	ADD_DSDB_STRING(DS_GUID_SYSTEMS_CONTAINER);
 	ADD_DSDB_STRING(DS_GUID_USERS_CONTAINER);
 
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_DEPARTMENT);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_DNS_HOST_NAME);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_INSTANCE_TYPE);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_MS_SFU_30);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_NT_SECURITY_DESCRIPTOR);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_PRIMARY_GROUP_ID);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_SERVICE_PRINCIPAL_NAME);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_USER_ACCOUNT_CONTROL);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_USER_PASSWORD);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_COMPUTER);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_MANAGED_SERVICE_ACCOUNT);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_USER);
+
+	ADD_DSDB_STRING(DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME);
+
 	return m;
 }
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c samba-4.17.8+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
--- samba-4.17.7+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c	2022-08-08 17:15:39.556193400 +0300
+++ samba-4.17.8+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c	2023-05-11 10:07:19.606421000 +0300
@@ -7533,6 +7533,16 @@
 						  source_dn,
 						  target_dn);
 	if (is_in_same_nc) {
+		/*
+		 * We allow the join.py code to point out that all
+		 * replication is completed, so failing now would just
+		 * trigger errors, rather than trigger a GET_TGT
+		 */
+		int *finished_full_join_ptr =
+			talloc_get_type(ldb_get_opaque(ldb,
+						       DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME),
+					int);
+		bool finished_full_join = finished_full_join_ptr && *finished_full_join_ptr;
 
 		/*
 		 * if the target is already be up-to-date there's no point in
@@ -7540,7 +7550,8 @@
 		 * on a one-way link was deleted. We ignore the link rather
 		 * than failing the replication cycle completely
 		 */
-		if (dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) {
+		if (finished_full_join
+		    || dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) {
 			*ignore_link = true;
 			DBG_WARNING("%s is %s "
 				    "but up to date. Ignoring link from %s\n",
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source4/dsdb/samdb/samdb.h samba-4.17.8+dfsg/source4/dsdb/samdb/samdb.h
--- samba-4.17.7+dfsg/source4/dsdb/samdb/samdb.h	2023-03-20 12:03:45.135653300 +0300
+++ samba-4.17.8+dfsg/source4/dsdb/samdb/samdb.h	2023-05-11 10:07:19.606421000 +0300
@@ -360,6 +360,8 @@
 
 #define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG"
 
+#define DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME "DSDB_FULL_JOIN_REPLICATION_COMPLETED"
+
 #define DSDB_ACL_CHECKS_DIRSYNC_FLAG 0x1
 #define DSDB_SAMDB_MINIMUM_ALLOWED_RID   1000
 
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source4/dsdb/tests/python/large_ldap.py samba-4.17.8+dfsg/source4/dsdb/tests/python/large_ldap.py
--- samba-4.17.7+dfsg/source4/dsdb/tests/python/large_ldap.py	2023-03-20 12:03:44.451649000 +0300
+++ samba-4.17.8+dfsg/source4/dsdb/tests/python/large_ldap.py	2023-05-11 10:07:19.610421000 +0300
@@ -146,6 +146,14 @@
                 "sAMAccountName": user_name,
                 "jpegPhoto": b'a' * (2 * 1024 * 1024)})
 
+            ace = "(OD;;RP;{6bc69afa-7bd9-4184-88f5-28762137eb6a};;S-1-%d)" % x
+            dn = ldb.Dn(cls.ldb, "cn=" + user_name + "," + str(cls.ou_dn))
+
+            # add an ACE that denies access to the above random attr
+            # for a not-existing user.  This makes each SD distinct
+            # and so will slow SD parsing.
+            cls.sd_utils.dacl_add_ace(dn, ace)
+
     @classmethod
     def tearDownClass(cls):
         # Remake the connection for tear-down (old Samba drops the socket)
@@ -290,19 +298,9 @@
                       session_info=system_session(lp),
                       lp=lp)
 
-        for x in range(200):
-            user_name = self.USER_NAME + format(x, "03")
-            ace = "(OD;;RP;{6bc69afa-7bd9-4184-88f5-28762137eb6a};;S-1-%d)" % x
-            dn = ldb.Dn(self.ldb, "cn=" + user_name + "," + str(self.ou_dn))
-
-            # add an ACE that denies access to the above random attr
-            # for a not-existing user.  This makes each SD distinct
-            # and so will slow SD parsing.
-            self.sd_utils.dacl_add_ace(dn, ace)
-
         # Create a large search expression that will take a long time to
         # evaluate.
-        expression = f'(jpegPhoto=*X*)' * 1000
+        expression = '(jpegPhoto=*X*)' * 2000
         expression = f'(|{expression})'
 
         # Perform the LDAP search.
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source4/selftest/tests.py samba-4.17.8+dfsg/source4/selftest/tests.py
--- samba-4.17.7+dfsg/source4/selftest/tests.py	2023-03-20 12:04:29.107923500 +0300
+++ samba-4.17.8+dfsg/source4/selftest/tests.py	2023-05-11 10:07:19.610421000 +0300
@@ -666,6 +666,17 @@
 plantestsuite("samba4.blackbox.net_ads_dns(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_net_ads_dns.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$USERNAME', '$PASSWORD'])
 plantestsuite("samba4.blackbox.samba-tool_ntacl(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_samba-tool_ntacl.sh"), '$PREFIX', '$DOMSID'])
 
+env = "ad_member:local"
+plantestsuite("samba4.blackbox.net_ads_search_server_P.primary", env,
+              [os.path.join(bbdir, "test_net_ads_search_server.sh"),
+              '$DC_SERVER', '$REALM'])
+plantestsuite("samba4.blackbox.net_ads_search_server_P.trust_e_both", env,
+              [os.path.join(bbdir, "test_net_ads_search_server.sh"),
+              '$TRUST_E_BOTH_SERVER', '$TRUST_E_BOTH_REALM'])
+plantestsuite("samba4.blackbox.net_ads_search_server_P.trust_f_both", env,
+              [os.path.join(bbdir, "test_net_ads_search_server.sh"),
+              '$TRUST_F_BOTH_SERVER', '$TRUST_F_BOTH_REALM'])
+
 if have_gnutls_fips_mode_support:
     plantestsuite("samba4.blackbox.weak_crypto.client", "ad_dc", [os.path.join(bbdir, "test_weak_crypto.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc"])
     plantestsuite("samba4.blackbox.test_weak_disable_ntlmssp_ldap", "ad_member:local", [os.path.join(bbdir, "test_weak_disable_ntlmssp_ldap.sh"),'$DC_USERNAME', '$DC_PASSWORD'])
@@ -841,6 +852,11 @@
 
     planpythontestsuite(env + ":local", "samba.tests.ntlm_auth")
 
+plantestsuite(
+    "samba.wbinfo_u_large_ad.(ad_dc:local)",
+    "ad_dc:local",
+    [os.path.join(samba3srcdir, "script/tests/test_wbinfo_u_large_ad.sh")])
+
 for env in ["ktest"]:
     planpythontestsuite(env + ":local", "samba.tests.ntlm_auth_krb5")
 
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/source4/torture/drs/python/ridalloc_exop.py samba-4.17.8+dfsg/source4/torture/drs/python/ridalloc_exop.py
--- samba-4.17.7+dfsg/source4/torture/drs/python/ridalloc_exop.py	2022-08-08 17:15:40.444200000 +0300
+++ samba-4.17.8+dfsg/source4/torture/drs/python/ridalloc_exop.py	2023-05-11 10:07:19.610421000 +0300
@@ -46,6 +46,7 @@
 from samba.dbchecker import dbcheck
 from samba.ndr import ndr_pack
 from samba.dcerpc import security
+from samba import drs_utils, dsdb
 
 
 class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase):
@@ -676,3 +677,137 @@
         finally:
             self._test_force_demote(fsmo_owner['dns_name'], "RIDALLOCTEST7")
             shutil.rmtree(targetdir, ignore_errors=True)
+
+    def test_replicate_against_deleted_objects_transaction(self):
+        """Not related to RID allocation, but uses the infrastructure here.
+        Do a join, create a link between two objects remotely, but
+        remove the target locally.  Show that we need to set a magic
+        opaque if there is an outer transaction.
+
+        """
+        fsmo_dn = ldb.Dn(self.ldb_dc1, "CN=RID Manager$,CN=System," + self.ldb_dc1.domain_dn())
+        (fsmo_owner, fsmo_not_owner) = self._determine_fSMORoleOwner(fsmo_dn)
+
+        test_user4 = "ridalloctestuser4"
+        test_group = "ridalloctestgroup1"
+
+        self.ldb_dc1.newuser(test_user4, "P at ssword!")
+
+        self.addCleanup(self.ldb_dc1.deleteuser, test_user4)
+
+        self.ldb_dc1.newgroup(test_group)
+        self.addCleanup(self.ldb_dc1.deletegroup, test_group)
+
+        targetdir = self._test_join(self.dnsname_dc1, "RIDALLOCTEST8")
+        try:
+            # Connect to the database
+            ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb")
+            lp = self.get_loadparm()
+
+            new_ldb = SamDB(ldb_url,
+                            session_info=system_session(lp), lp=lp)
+
+            destination_dsa_guid = misc.GUID(new_ldb.get_ntds_GUID())
+
+            repl = drs_utils.drs_Replicate(f'ncacn_ip_tcp:{self.dnsname_dc1}[seal]',
+                                           lp,
+                                           self.get_credentials(),
+                                           new_ldb,
+                                           destination_dsa_guid)
+
+            source_dsa_invocation_id = misc.GUID(self.ldb_dc1.invocation_id)
+
+            # Add the link on the remote DC
+            self.ldb_dc1.add_remove_group_members(test_group, [test_user4])
+
+            # Starting a transaction overrides, currently the logic
+            # inside repl.replicatate to retry with GET_TGT which in
+            # turn tells the repl_meta_data module that the most up to
+            # date info is already available
+            new_ldb.transaction_start()
+            repl.replicate(self.ldb_dc1.domain_dn(),
+                           source_dsa_invocation_id,
+                           destination_dsa_guid)
+
+            # Delete the user locally, before applying the links.
+            # This simulates getting the delete in the replciation
+            # stream.
+            new_ldb.deleteuser(test_user4)
+
+            # This fails as the user has been deleted locally but a remote link is sent
+            self.assertRaises(ldb.LdbError, new_ldb.transaction_commit)
+
+            new_ldb.transaction_start()
+            repl.replicate(self.ldb_dc1.domain_dn(),
+                           source_dsa_invocation_id,
+                           destination_dsa_guid)
+
+            # Delete the user locally (the previous transaction
+            # doesn't apply), before applying the links.  This
+            # simulates getting the delete in the replciation stream.
+            new_ldb.deleteuser(test_user4)
+
+            new_ldb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME,
+                                       1)
+
+            # This should now work
+            try:
+                new_ldb.transaction_commit()
+            except ldb.LdbError as e:
+                self.fail(f"Failed to replicate despite setting opaque with {e.args[1]}")
+
+        finally:
+            self._test_force_demote(self.dnsname_dc1, "RIDALLOCTEST8")
+            shutil.rmtree(targetdir, ignore_errors=True)
+
+    def test_replicate_against_deleted_objects_normal(self):
+        """Not related to RID allocation, but uses the infrastructure here.
+        Do a join, create a link between two objects remotely, but
+        remove the target locally.  .
+
+        """
+        fsmo_dn = ldb.Dn(self.ldb_dc1, "CN=RID Manager$,CN=System," + self.ldb_dc1.domain_dn())
+        (fsmo_owner, fsmo_not_owner) = self._determine_fSMORoleOwner(fsmo_dn)
+
+        test_user5 = "ridalloctestuser5"
+        test_group2 = "ridalloctestgroup2"
+
+        self.ldb_dc1.newuser(test_user5, "P at ssword!")
+        self.addCleanup(self.ldb_dc1.deleteuser, test_user5)
+
+        self.ldb_dc1.newgroup(test_group2)
+        self.addCleanup(self.ldb_dc1.deletegroup, test_group2)
+
+        targetdir = self._test_join(self.dnsname_dc1, "RIDALLOCTEST9")
+        try:
+            # Connect to the database
+            ldb_url = "tdb://%s" % os.path.join(targetdir, "private/sam.ldb")
+            lp = self.get_loadparm()
+
+            new_ldb = SamDB(ldb_url,
+                            session_info=system_session(lp), lp=lp)
+
+            destination_dsa_guid = misc.GUID(new_ldb.get_ntds_GUID())
+
+            repl = drs_utils.drs_Replicate(f'ncacn_ip_tcp:{self.dnsname_dc1}[seal]',
+                                           lp,
+                                           self.get_credentials(),
+                                           new_ldb,
+                                           destination_dsa_guid)
+
+            source_dsa_invocation_id = misc.GUID(self.ldb_dc1.invocation_id)
+
+            # Add the link on the remote DC
+            self.ldb_dc1.add_remove_group_members(test_group2, [test_user5])
+
+            # Delete the user locally
+            new_ldb.deleteuser(test_user5)
+
+            # Confirm replication copes with a link to a locally deleted user
+            repl.replicate(self.ldb_dc1.domain_dn(),
+                           source_dsa_invocation_id,
+                           destination_dsa_guid)
+
+        finally:
+            self._test_force_demote(self.dnsname_dc1, "RIDALLOCTEST9")
+            shutil.rmtree(targetdir, ignore_errors=True)
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/testprogs/blackbox/test_net_ads_search_server.sh samba-4.17.8+dfsg/testprogs/blackbox/test_net_ads_search_server.sh
--- samba-4.17.7+dfsg/testprogs/blackbox/test_net_ads_search_server.sh	1970-01-01 03:00:00.000000000 +0300
+++ samba-4.17.8+dfsg/testprogs/blackbox/test_net_ads_search_server.sh	2023-05-11 10:07:19.610421000 +0300
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+if [ $# -lt 2 ]; then
+cat <<EOF
+Usage: $0 SERVER REALM
+EOF
+exit 1;
+fi
+
+SERVER=$1
+REALM=$2
+shift 2
+
+failed=0
+. `dirname $0`/subunit.sh
+
+samba_net="$BINDIR/net"
+
+DN=$(echo "${REALM}" | tr '[:upper:]' '[:lower:]' | sed -e 's!^!DC=!' -e 's!\.!,DC=!g')
+testit_grep_count \
+	"net_ads_search.ntlmssp" \
+	"distinguishedName: ${DN}" \
+	1 \
+	$samba_net ads search --use-kerberos=off -P \
+	--server "${SERVER}.${REALM}" \
+	'(objectClass=domain)' distinguishedName || \
+	failed=$((failed + 1))
+testit_grep_count \
+	"net_ads_search.krb5" \
+	"distinguishedName: ${DN}" \
+	1 \
+	$samba_net ads search --use-kerberos=required -P \
+	--server "${SERVER}.${REALM}" \
+	'(objectClass=domain)' distinguishedName || \
+	failed=$((failed + 1))
+
+exit $failed
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/VERSION samba-4.17.8+dfsg/VERSION
--- samba-4.17.7+dfsg/VERSION	2023-03-29 16:22:38.841019400 +0300
+++ samba-4.17.8+dfsg/VERSION	2023-05-11 10:07:19.562420600 +0300
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=17
-SAMBA_VERSION_RELEASE=7
+SAMBA_VERSION_RELEASE=8
 
 ########################################################
 # If a official release has a serious bug              #
diff -Nru --exclude '*.[1578]' samba-4.17.7+dfsg/WHATSNEW.txt samba-4.17.8+dfsg/WHATSNEW.txt
--- samba-4.17.7+dfsg/WHATSNEW.txt	2023-03-29 16:22:38.825019600 +0300
+++ samba-4.17.8+dfsg/WHATSNEW.txt	2023-05-11 10:07:19.562420600 +0300
@@ -1,4 +1,83 @@
                    ==============================
+                   Release Notes for Samba 4.17.8
+                            May 11, 2023
+                   ==============================
+
+
+This is the latest stable release of the Samba 4.17 release series.
+
+
+Changes since 4.17.7
+--------------------
+
+o  Jeremy Allison <jra at samba.org>
+   * BUG 15302: log flood: smbd_calculate_access_mask_fsp: Access denied:
+     message level should be lower.
+   * BUG 15306: Floating point exception (FPE) via cli_pull_send at
+     source3/libsmb/clireadwrite.c.
+
+o  Andrew Bartlett <abartlet at samba.org>
+   * BUG 15328: test_tstream_more_tcp_user_timeout_spin fails intermittently on
+     Rackspace GitLab runners.
+   * BUG 15329: Reduce flapping of ridalloc test.
+   * BUG 15351: large_ldap test is unreliable.
+
+o  Ralph Boehme <slow at samba.org>
+   * BUG 15143: New filename parser doesn't check veto files smb.conf parameter.
+   * BUG 15354: mdssvc may crash when initializing.
+
+o  Volker Lendecke <vl at samba.org>
+   * BUG 15313: Large directory optimization broken for non-lcomp path elements.
+   * BUG 15357: streams_depot fails to create streams.
+   * BUG 15358: shadow_copy2 and streams_depot don't play well together.
+   * BUG 15366: wbinfo -u fails on ad dc with >1000 users.
+
+o  Stefan Metzmacher <metze at samba.org>
+   * BUG 15317: winbindd idmap child contacts the domain controller without a
+     need.
+   * BUG 15318: idmap_autorid may fail to map sids of trusted domains for the
+     first time.
+   * BUG 15319: idmap_hash doesn't use ID_TYPE_BOTH for reverse mappings.
+   * BUG 15323: net ads search -P doesn't work against servers in other domains.
+   * BUG 15338: DS ACEs might be inherited to unrelated object classes.
+   * BUG 15353: Temporary smbXsrv_tcon_global.tdb can't be parsed.
+
+o  Andreas Schneider <asn at samba.org>
+   * BUG 15360: Setting veto files = /.*/ break listing directories.
+
+o  Joseph Sutton <josephsutton at catalyst.net.nz>
+   * BUG 14810: CVE-2020-25720 [SECURITY] Create Child permission should not
+     allow full write to all attributes (additional changes).
+   * BUG 15329: Reduce flapping of ridalloc test.
+
+o  Nathaniel W. Turner <nturner at exagrid.com>
+   * BUG 15325: dsgetdcname: assumes local system uses IPv4.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical:matrix.org matrix room, or
+#samba-technical IRC channel on irc.libera.chat.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the Samba 4.1 and newer product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+                   ==============================
                    Release Notes for Samba 4.17.7
                            March 29, 2023
                    ==============================
@@ -67,8 +146,7 @@
 ======================================================================
 
 
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
                    ==============================
                    Release Notes for Samba 4.17.6
                            March 09, 2023



More information about the Pkg-samba-maint mailing list