samba/SOURCES/redhat-4.22.patch
2026-03-17 01:40:40 -04:00

3335 lines
113 KiB
Diff

From b0ff8644c06b01252bdbac6a31c77c5781d4b5a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Tue, 29 Jul 2025 11:19:07 +0200
Subject: [PATCH 01/38] selftest: Add the short name for localvampiredc to
hosts file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15905
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
(cherry picked from commit 5d2f60ae5aa96751b74901ae5384291ef338b152)
---
selftest/target/Samba4.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 9da339f6239..af0434a8e6b 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -878,7 +878,7 @@ nogroup:x:65534:nobody
my $hostname = lc($ctx->{hostname});
open(HOSTS, ">>$ctx->{nsswrap_hosts}");
- if ($hostname eq "localdc") {
+ if ($hostname eq "localdc" || $hostname eq "localvampiredc") {
print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n";
print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n";
} else {
--
2.53.0
From 03431792b4707e50afc8f9e356f08a91f4fb67c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Mon, 4 Aug 2025 11:20:54 +0200
Subject: [PATCH 02/38] tests: Add test for 'net ads join' to a preferred DC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15905
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
(cherry picked from commit 36f6ac547c09f492d1dcab11570e8bcbd377cf26)
---
selftest/knownfail | 1 +
source4/selftest/tests.py | 1 +
.../test_net_ads_join_to_preferred_dc.sh | 61 +++++++++++++++++++
3 files changed, 63 insertions(+)
create mode 100755 testprogs/blackbox/test_net_ads_join_to_preferred_dc.sh
diff --git a/selftest/knownfail b/selftest/knownfail
index ab2d79d7114..7c0e9dd00e7 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -335,6 +335,7 @@
^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_security_descriptor.*
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_dangling_multi_valued_clean
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_missing
+^samba4.blackbox.net_ads_join.join
# We currently don't send referrals for LDAP modify of non-replicated attrs
^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.*
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 9c5e85e428a..14a41ba77ed 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -902,6 +902,7 @@ plantestsuite("samba4.blackbox.rfc2307_mapping",
plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', r"CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX/chgdcpass', "aes256-cts-hmac-sha1-96", '$PREFIX/chgdcpass', smbclient3])
plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass'])
plantestsuite("samba4.blackbox.net_ads", "ad_dc:client", [os.path.join(bbdir, "test_net_ads.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS'])
+plantestsuite("samba4.blackbox.net_ads_join", "vampire_dc:client", [os.path.join(bbdir, "test_net_ads_join_to_preferred_dc.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX'])
plantestsuite("samba4.blackbox.net_offlinejoin", "ad_dc:client", [os.path.join(bbdir, "test_net_offline.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS'])
plantestsuite("samba4.blackbox.client_etypes_all(ad_dc:client)", "ad_dc:client", [os.path.join(bbdir, "test_client_etypes.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS', 'all', '17_18_23'])
plantestsuite("samba4.blackbox.client_etypes_legacy(ad_dc:client)", "ad_dc:client", [os.path.join(bbdir, "test_client_etypes.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS', 'legacy', '23'])
diff --git a/testprogs/blackbox/test_net_ads_join_to_preferred_dc.sh b/testprogs/blackbox/test_net_ads_join_to_preferred_dc.sh
new file mode 100755
index 00000000000..1bebc2f4dbe
--- /dev/null
+++ b/testprogs/blackbox/test_net_ads_join_to_preferred_dc.sh
@@ -0,0 +1,61 @@
+if [ $# -lt 4 ]; then
+ cat <<EOF
+Usage: test_net_ads.sh DC_SERVER DC_USERNAME DC_PASSWORD BASEDIR
+EOF
+ exit 1
+fi
+
+DC_SERVER=$1
+DC_USERNAME=$2
+DC_PASSWORD=$3
+BASEDIR=$4
+
+HOSTNAME=$(dd if=/dev/urandom bs=1 count=32 2>/dev/null | sha1sum | cut -b 1-10)
+
+RUNDIR=$(pwd)
+cd $BASEDIR
+WORKDIR=$(mktemp -d -p .)
+WORKDIR=$(basename $WORKDIR)
+cp -a client/* $WORKDIR/
+sed -ri "s@(dir|directory) = (.*)/client/@\1 = \2/$WORKDIR/@" $WORKDIR/client.conf
+sed -ri "s/netbios name = .*/netbios name = $HOSTNAME/" $WORKDIR/client.conf
+rm -f $WORKDIR/private/secrets.tdb
+cd $RUNDIR
+
+failed=0
+
+net_tool="$BINDIR/net --configfile=$BASEDIR/$WORKDIR/client.conf --option=security=ads"
+
+# Load test functions
+. $(dirname $0)/subunit.sh
+. "$(dirname "${0}")/common_test_fns.inc"
+
+# This test is run in environment with two DCs ('localdc' and 'localvampiredc')
+# The 'net ads join' has these two steps:
+# 1. create machine account at DC ('-S' points to 'localvampiredc')
+# 2. create keytab and sync the KVNO from a DC
+#
+# It must be ensured that in step #2 the keytab code contacts the same DC
+# ('localvampiredc'). The configuration below tries to break it.
+# We disable [SAF/DOMAIN/...] and [SAFJOIN/DOMAIN/...] by setting TTL to '-1'
+# And via setting 'password server' to 'localdc' we manage that
+# get_dc_list() returns 'localdc' instead of 'localvampiredc'
+#
+# As long as the keytab code is not explicitly told to use the same DC as join,
+# we get failure:
+# gensec_gse_client_prepare_ccache: Kinit for F0D26C71F6$@SAMBA.EXAMPLE.COM to access ldap/localdc.samba.example.com failed: Client not found in Kerberos database: NT_STATUS_LOGON_FAILURE
+
+cat <<EOF >>$BASEDIR/$WORKDIR/client.conf
+sync machine password to keytab = $BASEDIR/keytab:account_name:machine_password:sync_kvno
+password server = $DC_SERVER
+saf: join ttl = -1
+saf: ttl = -1
+EOF
+
+testit "join" $VALGRIND $net_tool ads join -S$SERVER -U$DC_USERNAME%$DC_PASSWORD || failed=$(expr $failed + 1)
+
+testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=$(expr $failed + 1)
+
+rm -rf $BASEDIR/$WORKDIR
+
+exit $failed
--
2.53.0
From 5cff37091161976a979752351003c9c1deb0d39f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Mon, 28 Jul 2025 10:43:36 +0200
Subject: [PATCH 03/38] s3:net: Pass down the server from cmdline to
sync_pw2keytabs()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This makes sure that during 'net ads join' the keytab create code
- sync_pw2keytabs() talks to the same DC at what the machine account
was created.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15905
Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Pair-Programmed-With: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): Pavel Filipensky <pfilipensky@samba.org>
Autobuild-Date(master): Fri Sep 5 13:38:33 UTC 2025 on atb-devel-224
(cherry picked from commit 5d1d3a8b568b5a07ed1ed537d20aa93820cecc14)
---
selftest/knownfail | 1 -
source3/include/secrets.h | 25 ++++++++++++++----------
source3/libads/ads_proto.h | 2 +-
source3/libads/kerberos_keytab.c | 24 ++++++++++++++++++++---
source3/libads/trusts_util.c | 15 ++++++++------
source3/libads/util.c | 10 ++++++----
source3/libnet/libnet_join.c | 2 +-
source3/passdb/machine_account_secrets.c | 10 ++++++----
source3/utils/net.c | 10 ++++++----
source3/utils/net_ads.c | 2 +-
10 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/selftest/knownfail b/selftest/knownfail
index 7c0e9dd00e7..ab2d79d7114 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -335,7 +335,6 @@
^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_security_descriptor.*
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_dangling_multi_valued_clean
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_missing
-^samba4.blackbox.net_ads_join.join
# We currently don't send referrals for LDAP modify of non-replicated attrs
^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.*
diff --git a/source3/include/secrets.h b/source3/include/secrets.h
index a454c8bb8ff..061b9c6ef34 100644
--- a/source3/include/secrets.h
+++ b/source3/include/secrets.h
@@ -125,12 +125,15 @@ char *secrets_domain_info_string(TALLOC_CTX *mem_ctx, const struct secrets_domai
NTSTATUS secrets_fetch_or_upgrade_domain_info(const char *domain,
TALLOC_CTX *mem_ctx,
struct secrets_domain_info1 **pinfo);
-NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname,
- const char *cleartext_unix,
- TALLOC_CTX *mem_ctx,
- struct secrets_domain_info1 **pinfo,
- struct secrets_domain_info1_change **pprev,
- NTSTATUS (*sync_pw2keytabs_fn)(void));
+NTSTATUS secrets_prepare_password_change(
+ const char *domain,
+ const char *dcname,
+ const char *cleartext_unix,
+ TALLOC_CTX *mem_ctx,
+ struct secrets_domain_info1 **pinfo,
+ struct secrets_domain_info1_change **pprev,
+ NTSTATUS (*sync_pw2keytabs_fn)(const char *),
+ const char *opt_host);
NTSTATUS secrets_failed_password_change(const char *change_server,
NTSTATUS local_status,
NTSTATUS remote_status,
@@ -139,10 +142,12 @@ NTSTATUS secrets_defer_password_change(const char *change_server,
NTSTATUS local_status,
NTSTATUS remote_status,
const struct secrets_domain_info1 *info);
-NTSTATUS secrets_finish_password_change(const char *change_server,
- NTTIME change_time,
- const struct secrets_domain_info1 *info,
- NTSTATUS (*sync_pw2keytabs_fn)(void));
+NTSTATUS secrets_finish_password_change(
+ const char *change_server,
+ NTTIME change_time,
+ const struct secrets_domain_info1 *info,
+ NTSTATUS (*sync_pw2keytabs_fn)(const char *),
+ const char *prefer_dc);
bool secrets_delete_machine_password_ex(const char *domain, const char *realm);
bool secrets_delete_domain_sid(const char *domain);
char *secrets_fetch_prev_machine_password(const char *domain);
diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 8440c35e46d..2e67eef155c 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -230,6 +230,6 @@ struct spn_struct {
/* parse a windows style SPN, returns NULL if parsing fails */
struct spn_struct *parse_spn(TALLOC_CTX *ctx, const char *srvprinc);
-NTSTATUS sync_pw2keytabs(void);
+NTSTATUS sync_pw2keytabs(const char *prefer_dc);
#endif /* _LIBADS_ADS_PROTO_H_ */
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 49a892e5a55..1d4f9c12e1d 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -84,6 +84,7 @@ struct pw2kt_global_state {
char *ad_upn;
char *ad_sam_account;
char **ad_spn_array;
+ const char *prefer_dc;
size_t ad_num_spns;
/* This is from secrets.db */
struct secrets_domain_info1 *info;
@@ -869,8 +870,11 @@ static ADS_STATUS pw2kt_get_dc_info(struct pw2kt_global_state *state)
int count;
bool ok;
TALLOC_CTX *tmp_ctx = talloc_stackframe();
- ADS_STRUCT *ads = ads_init(
- tmp_ctx, lp_realm(), lp_workgroup(), NULL, ADS_SASL_SIGN);
+ ADS_STRUCT *ads = ads_init(tmp_ctx,
+ lp_realm(),
+ lp_workgroup(),
+ state->prefer_dc,
+ ADS_SASL_SIGN);
if (ads == NULL) {
DBG_ERR("ads_init() failed\n");
@@ -1029,7 +1033,20 @@ static bool pw2kt_default_keytab_name(char *name_str, size_t name_size)
return true;
}
-NTSTATUS sync_pw2keytabs(void)
+/**
+ * @internal
+ *
+ * @brief Sync machine password from secrets to keytab
+ *
+ * @param prefer_dc The DC we should talk to. This is especially important
+ * during domain join. Pass NULL if we should pick a random
+ * one.
+ *
+ * @return An NTSTATUS error code.
+ *
+ * @see NT_STATUS_IS_OK()
+ */
+NTSTATUS sync_pw2keytabs(const char *prefer_dc)
{
TALLOC_CTX *frame = talloc_stackframe();
const struct loadparm_substitution *lp_sub =
@@ -1055,6 +1072,7 @@ NTSTATUS sync_pw2keytabs(void)
TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
}
+ state->prefer_dc = prefer_dc;
lp_ptr = lp_sync_machine_password_to_keytab();
if (lp_ptr == NULL) {
diff --git a/source3/libads/trusts_util.c b/source3/libads/trusts_util.c
index 6a39f32f350..c51c556e86b 100644
--- a/source3/libads/trusts_util.c
+++ b/source3/libads/trusts_util.c
@@ -360,10 +360,11 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
&info,
&prev,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ NULL /* opt_host */);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n",
domain));
@@ -610,10 +611,11 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
prev->password->change_time,
info,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ prev->password->change_server);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n",
domain));
@@ -759,10 +761,11 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
info->next_change->change_time,
info,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ info->next_change->change_server);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("secrets_finish_password_change() failed for domain %s!\n",
domain));
diff --git a/source3/libads/util.c b/source3/libads/util.c
index 243dd09f3d0..360e556ab9b 100644
--- a/source3/libads/util.c
+++ b/source3/libads/util.c
@@ -59,10 +59,11 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
&info,
&prev,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ ads->auth.kdc_server);
if (!NT_STATUS_IS_OK(status)) {
return ADS_ERROR_NT(status);
}
@@ -138,10 +139,11 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
now,
info,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ ads->auth.kdc_server);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_NT(status);
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 5796c68e2e0..cb997dcbe23 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -867,7 +867,7 @@ static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx,
static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx,
struct libnet_JoinCtx *r)
{
- NTSTATUS ntstatus = sync_pw2keytabs();
+ NTSTATUS ntstatus = sync_pw2keytabs(r->in.dc_name);
return NT_STATUS_IS_OK(ntstatus);
}
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index 0679535f026..568d77a3892 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -1674,7 +1674,8 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname,
TALLOC_CTX *mem_ctx,
struct secrets_domain_info1 **pinfo,
struct secrets_domain_info1_change **pprev,
- NTSTATUS (*sync_pw2keytabs_fn)(void))
+ NTSTATUS (*sync_pw2keytabs_fn)(const char *),
+ const char *opt_host)
{
TALLOC_CTX *frame = talloc_stackframe();
struct db_context *db = NULL;
@@ -1770,7 +1771,7 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname,
}
if (prev == NULL && sync_pw2keytabs_fn != NULL) {
- status = sync_pw2keytabs_fn();
+ status = sync_pw2keytabs_fn(opt_host);
if (!NT_STATUS_IS_OK(status)) {
DBG_ERR("Sync of machine password failed.\n");
dbwrap_transaction_cancel(db);
@@ -2023,7 +2024,8 @@ NTSTATUS secrets_defer_password_change(const char *change_server,
NTSTATUS secrets_finish_password_change(const char *change_server,
NTTIME change_time,
const struct secrets_domain_info1 *cookie,
- NTSTATUS (*sync_pw2keytabs_fn)(void))
+ NTSTATUS (*sync_pw2keytabs_fn)(const char *),
+ const char *prefer_dc)
{
const char *domain = cookie->domain_info.name.string;
TALLOC_CTX *frame = talloc_stackframe();
@@ -2102,7 +2104,7 @@ NTSTATUS secrets_finish_password_change(const char *change_server,
}
if (sync_pw2keytabs_fn != NULL) {
- status = sync_pw2keytabs_fn();
+ status = sync_pw2keytabs_fn(prefer_dc);
if (!NT_STATUS_IS_OK(status)) {
DBG_ERR("Sync of machine password failed.\n");
TALLOC_FREE(frame);
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 7ce93ced79e..ecabd980d0c 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -235,10 +235,11 @@ static int net_changesecretpw(struct net_context *c, int argc,
&info,
&prev,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ c->opt_host);
if (!NT_STATUS_IS_OK(status)) {
d_fprintf(stderr,
_("Unable to write the machine account password in the secrets database"));
@@ -261,10 +262,11 @@ static int net_changesecretpw(struct net_context *c, int argc,
now,
info,
#ifdef HAVE_ADS
- sync_pw2keytabs);
+ sync_pw2keytabs,
#else
- NULL);
+ NULL,
#endif
+ c->opt_host);
if (!NT_STATUS_IS_OK(status)) {
d_fprintf(stderr,
_("Unable to write the machine account password in the secrets database"));
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 46531210411..753b957e43f 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -2965,7 +2965,7 @@ static int net_ads_keytab_create(struct net_context *c, int argc, const char **a
net_use_krb_machine_account(c);
}
- ntstatus = sync_pw2keytabs();
+ ntstatus = sync_pw2keytabs(c->opt_host);
ret = NT_STATUS_IS_OK(ntstatus) ? 0 : 1;
return ret;
}
--
2.53.0
From 5b23ab3845597dcfcf33e2c0a7d7af820d3167a5 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Wed, 13 Aug 2025 17:02:16 +0200
Subject: [PATCH 04/38] smbtorture: fix locking offset in
test_fruit_locking_conflict()
AD_FILELOCK_RSRC_DENY_WR = AD_FILELOCK_BASE + 6
= (0x7FFFFFFFFFFFFFFF - 9) + 6
= 0x7FFFFFFFFFFFFFFC
No change in behaviour though, just stumpled across it.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 3052839636f185307edb8832de9bdba4b2e2c83c)
---
source4/torture/vfs/fruit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index 6bad4e409c6..e9ff4a57e66 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -8002,7 +8002,7 @@ static bool test_fruit_locking_conflict(struct torture_context *tctx,
/* Add AD_FILELOCK_RSRC_DENY_WR lock. */
el = (struct smb2_lock_element) {
- .offset = 0xfffffffffffffffc,
+ .offset = 0x7ffffffffffffffc,
.length = 1,
.flags = SMB2_LOCK_FLAG_EXCLUSIVE,
};
--
2.53.0
From 9c7228f46c3955b0e1a3c91fd42da6f2ea864cb8 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 1 Aug 2025 17:28:04 +0200
Subject: [PATCH 05/38] smbd: don't use sticky write times on POSIX handles
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 795a8c0e84f2bf2b70c8070737183e33f4254a54)
---
source3/smbd/dosmode.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 9a8ecf6e0a7..ab45f9edbb9 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -1279,6 +1279,10 @@ bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
{
bool ok;
+ if (fsp->fsp_flags.posix_open) {
+ return true;
+ }
+
if (is_omit_timespec(&mtime)) {
return true;
}
--
2.53.0
From ec9f60e4eda3162aec63ada4ec49574e99362989 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 19 Sep 2025 00:20:43 +0200
Subject: [PATCH 06/38] smbtorture: add test vfs.fruit.readonly-exclusive-lock
Verify macOS clients get Windows byterange lock behavour by trying to set an
exclusive lock on a file opened in read-only mode.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 777db5b50689d28c53d6b0116818601fd8e52aa8)
---
source4/torture/vfs/fruit.c | 92 +++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index e9ff4a57e66..02f7acd0fea 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -7839,6 +7839,97 @@ done:
return ret;
}
+/*
+ test exclusive byte range lock on read-only file
+*/
+static bool test_readonly_exclusive_lock(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ bool ret = true;
+ struct smb2_handle h;
+ struct smb2_create create;
+ struct smb2_lock lock;
+ struct smb2_lock_element lock_element;
+ const char *fname = "readonly_lock_test.txt";
+
+ torture_comment(tctx, "Testing exclusive lock on read-only opened file\n");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ /* Clean up any existing file */
+ smb2_util_unlink(tree, fname);
+
+ /* Create the file first with write access to ensure it exists */
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_RIGHTS_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE;
+ create.in.create_disposition = NTCREATEX_DISP_CREATE;
+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ create.in.security_flags = 0;
+ create.in.fname = fname;
+
+ status = smb2_create(tree, tctx, &create);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Write some data to the file */
+ status = smb2_util_write(tree, create.out.file.handle, "test data", 0, 9);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Close the file */
+ status = smb2_util_close(tree, create.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Now open the file read-only */
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ create.in.security_flags = 0;
+ create.in.fname = fname;
+
+ status = smb2_create(tree, tctx, &create);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ h = create.out.file.handle;
+
+ torture_comment(tctx, "File opened read-only successfully\n");
+
+ /* Attempt to set an exclusive byte-range lock */
+ ZERO_STRUCT(lock);
+ ZERO_STRUCT(lock_element);
+
+ lock.in.lock_count = 1;
+ lock.in.lock_sequence = 0;
+ lock.in.file.handle = h;
+ lock.in.locks = &lock_element;
+
+ lock_element.offset = 0;
+ lock_element.length = 100;
+ lock_element.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+
+ torture_comment(tctx, "Attempting to set exclusive lock on read-only file\n");
+
+ status = smb2_lock(tree, &lock);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+done:
+ /* Close the file */
+ smb2_util_close(tree, h);
+
+ /* Clean up */
+ smb2_util_unlink(tree, fname);
+
+ return ret;
+}
+
/*
* Note: This test depends on "vfs objects = catia fruit streams_xattr". For
* some tests torture must be run on the host it tests and takes an additional
@@ -7885,6 +7976,7 @@ struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream);
torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo);
torture_suite_add_1smb2_test(suite, "delete_trigger_convert_sharing_violation", test_delete_trigger_convert_sharing_violation);
+ torture_suite_add_1smb2_test(suite, "readonly-exclusive-lock", test_readonly_exclusive_lock);
return suite;
}
--
2.53.0
From 87e6e2d0cdb78cfe9b372732439706d94a5ea7a2 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 19 Sep 2025 06:43:57 +0200
Subject: [PATCH 07/38] smbtorture: add test vfs.fruit.case_insensitive_find
Verifies case insensitive directory scanning works.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 68ed6279335cfac13a624ae8a7738dac3d9b0d1a)
---
source4/torture/vfs/fruit.c | 85 ++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index 02f7acd0fea..a6f86cd5edf 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -7930,6 +7930,89 @@ done:
return ret;
}
+/*
+ * Test case-insensitive file finding with AAPL extensions
+ * Add this function to source4/torture/vfs/fruit.c
+ */
+
+static bool test_case_insensitive_find(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ bool ret = true;
+ const char *fname = "TestFile.txt";
+ const char *fname_upper = "TESTFILE.TXT";
+ struct smb2_handle testdirh;
+ struct smb2_handle h1;
+ struct smb2_create create;
+ struct smb2_find f;
+ union smb_search_data *d;
+ uint_t count;
+
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed");
+
+ /* Enable AAPL extensions */
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret, ret, done,
+ "enable_aapl failed");
+
+ /* Create test file */
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_RIGHTS_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE;
+ create.in.create_disposition = NTCREATEX_DISP_CREATE;
+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ create.in.fname = talloc_asprintf(tctx, "%s\\%s", BASEDIR, fname);
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ talloc_asprintf(tctx, "failed to create %s", fname));
+ h1 = create.out.file.handle;
+
+ /* Close the file */
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "failed to close test file");
+
+ /* Search for file using different case */
+ f = (struct smb2_find) {
+ .in.file.handle = testdirh,
+ .in.pattern = fname_upper,
+ .in.max_response_size = 0x1000,
+ .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
+ };
+
+ status = smb2_find_level(tree, tctx, &f, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ talloc_asprintf(tctx, "smb2_find_level failed searching for %s", fname_upper));
+
+ /* Verify we found exactly one file */
+ torture_assert_int_equal_goto(tctx, count, 1, ret, done,
+ talloc_asprintf(tctx, "Expected 1 file, got %u", count));
+
+ /* Verify the filename matches our original file (case may differ) */
+ torture_assert_str_equal_goto(tctx,
+ d[0].id_both_directory_info.name.s, fname, ret, done,
+ talloc_asprintf(tctx, "Found file name '%s' doesn't match expected '%s'",
+ d[0].directory_info.name.s, fname));
+
+ torture_comment(tctx, "Case-insensitive find test passed: "
+ "searched for '%s', found '%s'\n",
+ fname_upper, d[0].id_both_directory_info.name.s);
+
+done:
+ smb2_util_close(tree, testdirh);
+ smb2_deltree(tree, BASEDIR);
+ return ret;
+}
+
/*
* Note: This test depends on "vfs objects = catia fruit streams_xattr". For
* some tests torture must be run on the host it tests and takes an additional
@@ -7977,7 +8060,7 @@ struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo);
torture_suite_add_1smb2_test(suite, "delete_trigger_convert_sharing_violation", test_delete_trigger_convert_sharing_violation);
torture_suite_add_1smb2_test(suite, "readonly-exclusive-lock", test_readonly_exclusive_lock);
-
+ torture_suite_add_1smb2_test(suite, "case_insensitive_find", test_case_insensitive_find);
return suite;
}
--
2.53.0
From 98e1a3b39cb3e4fa03ac8340338179cd85df18f3 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Mon, 10 Mar 2025 15:01:42 +0100
Subject: [PATCH 08/38] vfs_fruit: add option "fruit:posix_opens = yes|no"
(default: yes)
Tags alls opens as POSIX by setting fsp_flags.posix_open to true.
POSIX handles have different behaviour compared to Windows:
Behaviour | POSIX | Windows | macOS |fruit:posix_opens = yes
-----------------------------------+------------+----------------------------------------
Deleting files with open handles | yes | no | yes | yes
Moving directories with open files | yes | no | yes | yes
Byterange locks behaviour | POSIX-ish | Window-ish | POSIX-ish | POSIX-ish
Sticky writetime | no | yes | no | no
Case sensitive | no | yes | yes | yes
Streams allowed | no | yes | yes | yes
macOS follows POSIX for the first four, but needs case insensitive behaviour
and needs streams.
By carefully setting fsp_flags.posix_open to true *after* going through the path
resolution logic, but before opens are added to locking.tdb, with
"fruit:posix_opens = yes" we get closest to macOS semantics.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(backported from commit e86f0c2de80e2409bfe3fc12df24e94470988e3c)
[slow@samba.org: conflict due to optino veto_localized only present in master]
---
docs-xml/manpages/vfs_fruit.8.xml | 15 +++++++++++++
selftest/knownfail.d/samba3.vfs.fruit | 2 ++
source3/include/vfs.h | 18 ++++++++++++++++
source3/modules/vfs_fruit.c | 31 ++++++++++++++++++++++-----
4 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/docs-xml/manpages/vfs_fruit.8.xml b/docs-xml/manpages/vfs_fruit.8.xml
index 9e27030b660..21c2e76de8d 100644
--- a/docs-xml/manpages/vfs_fruit.8.xml
+++ b/docs-xml/manpages/vfs_fruit.8.xml
@@ -426,6 +426,21 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>fruit:posix_opens = yes | no</term>
+ <listitem>
+
+ <para>When <parameter>fruit:posix_opens</parameter> is set to
+ <parameter>yes</parameter>, vfs_fruit will internally translate
+ all filesystem semantics to use POSIX behaviour instead of Windows
+ behaviour. As Macs are closer to POSIX than Windows with regard
+ to filesystem semantics, this improves access semantics for
+ a lot of corner cases.</para>
+ <para>The default is <emphasis>yes</emphasis>.</para>
+
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit
index 6307e2b3404..b774b0503e7 100644
--- a/selftest/knownfail.d/samba3.vfs.fruit
+++ b/selftest/knownfail.d/samba3.vfs.fruit
@@ -1,2 +1,4 @@
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\)
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\)
+^samba3.vfs.fruit.*readonly-exclusive-lock\(.*\)
+^samba3.vfs.fruit.*case_insensitive_find\(.*\)
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 581148fa053..cab809de5d3 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -462,6 +462,15 @@ typedef struct files_struct {
bool lock_failure_seen : 1;
bool encryption_required : 1;
bool fstat_before_close : 1;
+ /*
+ * For POSIX clients struct files_struct.fsp_flags.posix_open
+ * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will
+ * always be set to the same value.
+ *
+ * For macOS clients vfs_fruit with fruit:posix_open=yes, we
+ * deliberately set both flags to fsp_flags.posix_open=true
+ * while SMB_FILENAME_POSIX_PATH will not be set.
+ */
bool posix_open : 1;
bool posix_append : 1;
} fsp_flags;
@@ -886,6 +895,15 @@ struct smb_filename {
struct fsp_smb_fname_link *fsp_link;
};
+/*
+ * For POSIX clients struct files_struct.fsp_flags.posix_open
+ * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will
+ * always be set to the same value.
+ *
+ * For macOS clients vfs_fruit with fruit:posix_open=yes, we
+ * deliberately set both flags to fsp_flags.posix_open=true
+ * while SMB_FILENAME_POSIX_PATH will not be set.
+ */
#define SMB_FILENAME_POSIX_PATH 0x01
enum vfs_translate_direction {
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index ba744e52a96..ce9cba2525c 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -125,6 +125,7 @@ struct fruit_config_data {
bool use_aapl; /* config from smb.conf */
bool use_copyfile;
bool readdir_attr_enabled;
+ bool posix_opens;
bool unix_info_enabled;
bool copyfile_enabled;
bool veto_appledouble;
@@ -339,6 +340,9 @@ static int init_fruit_config(vfs_handle_struct *handle)
config->use_copyfile = lp_parm_bool(-1, FRUIT_PARAM_TYPE_NAME,
"copyfile", false);
+ config->posix_opens = lp_parm_bool(
+ SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "posix_opens", true);
+
config->aapl_zero_file_id =
lp_parm_bool(SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME,
"zero_file_id", true);
@@ -1754,16 +1758,27 @@ static int fruit_openat(vfs_handle_struct *handle,
files_struct *fsp,
const struct vfs_open_how *how)
{
+ struct fruit_config_data *config = NULL;
int fd;
+ SMB_VFS_HANDLE_GET_DATA(handle, config,
+ struct fruit_config_data, return -1);
+
DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
if (!is_named_stream(smb_fname)) {
- return SMB_VFS_NEXT_OPENAT(handle,
- dirfsp,
- smb_fname,
- fsp,
- how);
+ fd = SMB_VFS_NEXT_OPENAT(handle,
+ dirfsp,
+ smb_fname,
+ fsp,
+ how);
+ if (fd == -1) {
+ return -1;
+ }
+ if (config->posix_opens && global_fruit_config.nego_aapl) {
+ fsp->fsp_flags.posix_open = true;
+ }
+ return fd;
}
if (how->resolve != 0) {
@@ -1798,7 +1813,13 @@ static int fruit_openat(vfs_handle_struct *handle,
DBG_DEBUG("Path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd);
/* Prevent reopen optimisation */
+ if (fd == -1) {
+ return -1;
+ }
fsp->fsp_flags.have_proc_fds = false;
+ if (config->posix_opens && global_fruit_config.nego_aapl) {
+ fsp->fsp_flags.posix_open = true;
+ }
return fd;
}
--
2.53.0
From 1549f90eccfe838fe984cebe0c02f768b50666f2 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Thu, 18 Sep 2025 23:44:34 +0200
Subject: [PATCH 09/38] smbd: hang posix brl per-handle check on the pathname
For the SMB3 POSIX client both posix_open=true and (fsp->fsp_name->flags &
SMB_FILENAME_POSIX_PATH) will always be the case, so this is no change in
behaviour for that case.
However, for the macOS client fruit will carefully setup both flags as
posix_open=true but SMB_FILENAME_POSIX_PATH will not be set.
This is a deliberate hack to give the macOS client POSIX behaviour for some
operations, but not for others, while also allowing the POSIX-ified macOS client
to continue to get case insensitive behavour.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 75fa416f911f1f30aae8bdf14b423140874acaa0)
---
selftest/knownfail.d/samba3.vfs.fruit | 1 -
source3/smbd/smb2_lock.c | 16 +++++++++++++++-
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit
index b774b0503e7..b51c887c212 100644
--- a/selftest/knownfail.d/samba3.vfs.fruit
+++ b/selftest/knownfail.d/samba3.vfs.fruit
@@ -1,4 +1,3 @@
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\)
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\)
-^samba3.vfs.fruit.*readonly-exclusive-lock\(.*\)
^samba3.vfs.fruit.*case_insensitive_find\(.*\)
diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c
index 8591b2fbd2c..73a341eff79 100644
--- a/source3/smbd/smb2_lock.c
+++ b/source3/smbd/smb2_lock.c
@@ -381,8 +381,22 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
for (i=0; i<in_lock_count; i++) {
bool invalid = false;
- bool posix_handle = fsp->fsp_flags.posix_open;
+ bool posix_handle = fsp->fsp_name->flags &
+ SMB_FILENAME_POSIX_PATH;
+ /*
+ * For POSIX clients struct files_struct.fsp_flags.posix_open
+ * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will
+ * always be set to the same value.
+ *
+ * For macOS clients vfs_fruit with fruit:posix_open=yes, we
+ * deliberately set both flags to fsp_flags.posix_open=true
+ * while SMB_FILENAME_POSIX_PATH will not be set.
+ *
+ * By deliberately checking the fsp_name flag here instead of
+ * the fsp flag, Byterange Lock processing uses Windows
+ * behaviour for macOS clients which is what we want.
+ */
switch (in_locks[i].flags) {
case SMB2_LOCK_FLAG_SHARED:
case SMB2_LOCK_FLAG_EXCLUSIVE:
--
2.53.0
From fe490422b79c74fc789358c191d157d31761be68 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Thu, 18 Sep 2025 20:35:22 +0200
Subject: [PATCH 10/38] smbd: hang directory pattern matching case sensitivity
on the pathname
For the SMB3 POSIX client both posix_open=true and (fsp->fsp_name->flags &
SMB_FILENAME_POSIX_PATH) will always be the case, so this is no change in
behaviour for that case.
However, for the macOS client fruit will carefully setup both flags as
posix_open=true but SMB_FILENAME_POSIX_PATH will not be set.
This is a deliberate hack to give the macOS client POSIX behaviour for some
operations, but not for others, while also allowing the POSIX-ified macOS client
to continue to get case insensitive behavour.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit b3132202cf787cc9fb061e39eaf1509157f53953)
---
selftest/knownfail.d/samba3.vfs.fruit | 1 -
source3/smbd/dir.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit
index b51c887c212..6307e2b3404 100644
--- a/selftest/knownfail.d/samba3.vfs.fruit
+++ b/selftest/knownfail.d/samba3.vfs.fruit
@@ -1,3 +1,2 @@
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\)
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\)
-^samba3.vfs.fruit.*case_insensitive_find\(.*\)
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index afc9c74dfdd..c72fd4349d2 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -1171,7 +1171,7 @@ static NTSTATUS OpenDir_fsp(
goto fail;
}
dir_hnd->fsp = fsp;
- if (fsp->fsp_flags.posix_open) {
+ if (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) {
dir_hnd->case_sensitive = true;
} else {
dir_hnd->case_sensitive = conn->case_sensitive;
--
2.53.0
From 68d6be8e2c68385797b9c9f51d87b601a9eace33 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Sat, 6 Sep 2025 08:48:44 +0200
Subject: [PATCH 11/38] vfs_fruit: ignore Set-ACL requests with zero ACEs
Workaround for a new behaviour in latest macOS versions.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(backported from commit a112978ed1240c399eb90e4472d5c43d867c49d9)
[slow@samba.org: conflict due to option veto_localized present only in master]
---
docs-xml/manpages/vfs_fruit.8.xml | 18 ++++++++++++++++++
source3/modules/vfs_fruit.c | 18 ++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/docs-xml/manpages/vfs_fruit.8.xml b/docs-xml/manpages/vfs_fruit.8.xml
index 21c2e76de8d..13748c110fb 100644
--- a/docs-xml/manpages/vfs_fruit.8.xml
+++ b/docs-xml/manpages/vfs_fruit.8.xml
@@ -441,6 +441,24 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>fruit:ignore_zero_aces = yes | no</term>
+ <listitem>
+
+ <para>When <parameter>fruit:ignore_zero_aces</parameter> is
+ enabled, attempts to modify filesystem permissions fail if the ACL
+ sent over the wire contains no ACEs. This is completely valid
+ client behaviour, but it means subsequently no further access is
+ possible to the file, unless permissions get fixed by an
+ administrator.</para>
+ <para>This problematic behaviour has been reported for latest
+ macOS versions and this new option allows to work around
+ it.</para>
+ <para>The default is <emphasis>yes</emphasis>.</para>
+
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index ce9cba2525c..213d4cc3eeb 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -137,6 +137,7 @@ struct fruit_config_data {
bool wipe_intentionally_left_blank_rfork;
bool delete_empty_adfiles;
bool validate_afpinfo;
+ bool ignore_zero_aces;
/*
* Additional options, all enabled by default,
@@ -343,6 +344,11 @@ static int init_fruit_config(vfs_handle_struct *handle)
config->posix_opens = lp_parm_bool(
SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "posix_opens", true);
+ config->ignore_zero_aces = lp_parm_bool(SNUM(handle->conn),
+ FRUIT_PARAM_TYPE_NAME,
+ "ignore_zero_aces",
+ true);
+
config->aapl_zero_file_id =
lp_parm_bool(SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME,
"zero_file_id", true);
@@ -4626,6 +4632,7 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
uint32_t security_info_sent,
const struct security_descriptor *orig_psd)
{
+ struct fruit_config_data *config = NULL;
NTSTATUS status;
bool do_chmod;
mode_t ms_nfs_mode = 0;
@@ -4633,6 +4640,10 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
struct security_descriptor *psd = NULL;
uint32_t orig_num_aces = 0;
+ SMB_VFS_HANDLE_GET_DATA(handle, config,
+ struct fruit_config_data,
+ return NT_STATUS_UNSUCCESSFUL);
+
if (orig_psd->dacl != NULL) {
orig_num_aces = orig_psd->dacl->num_aces;
}
@@ -4644,6 +4655,13 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
DBG_DEBUG("%s\n", fsp_str_dbg(fsp));
+ if (config->ignore_zero_aces && (psd->dacl->num_aces == 0)) {
+ /*
+ * Just ignore Set-ACL requests with zero ACEs.
+ */
+ return NT_STATUS_OK;
+ }
+
status = check_ms_nfs(handle, fsp, psd, &ms_nfs_mode, &do_chmod);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("fruit_fset_nt_acl: check_ms_nfs failed%s\n", fsp_str_dbg(fsp)));
--
2.53.0
From 73d2494edfc58bd8c8806c7ca6aeb38bb2310cee Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 14 Nov 2025 14:55:12 +0100
Subject: [PATCH 12/38] vfs_fruit: psd->dacl can be NULL, use orig_num_aces
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Tue Nov 18 10:13:44 UTC 2025 on atb-devel-224
(cherry picked from commit 0de67cf0748139920006a4dd65cb77c874c3595f)
Autobuild-User(v4-23-test): Jule Anger <janger@samba.org>
Autobuild-Date(v4-23-test): Wed Nov 26 11:26:55 UTC 2025 on atb-devel-224
(cherry picked from commit b3f2445aef48e855f689de864d770fc2130f0ecc)
---
source3/modules/vfs_fruit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 213d4cc3eeb..795f79ce09c 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -4655,7 +4655,7 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
DBG_DEBUG("%s\n", fsp_str_dbg(fsp));
- if (config->ignore_zero_aces && (psd->dacl->num_aces == 0)) {
+ if (config->ignore_zero_aces && (orig_num_aces == 0)) {
/*
* Just ignore Set-ACL requests with zero ACEs.
*/
--
2.53.0
From 0b0e342500042b80dedda6c5bd1d9d2598f710ca Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Tue, 2 Dec 2025 14:02:08 +0100
Subject: [PATCH 13/38] Revert "ldb: User hexchars_upper from replace.h"
This reverts commit 542cf01bfe530a83dfbc8a606d182c0a5a622059.
We shouldn't put a hard requirement for libreplace in libldb! We do not need
libreplace on Linux until we start using hexbytes_upper.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15961
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
(cherry picked from commit 1bb25c0e01d35b1adb3137cb193de27f5c5a65f0)
Autobuild-User(v4-23-test): Jule Anger <janger@samba.org>
Autobuild-Date(v4-23-test): Thu Dec 11 17:00:21 UTC 2025 on atb-devel-224
---
lib/ldb/common/ldb_dn.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c
index 5b8c0f4f580..389da444904 100644
--- a/lib/ldb/common/ldb_dn.c
+++ b/lib/ldb/common/ldb_dn.c
@@ -232,10 +232,15 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
case '\0': {
/* any others get \XX form */
unsigned char v;
+ /*
+ * Do not use libreplace for this. We don't want to have
+ * a hard requirement for it.
+ */
+ const char *hexbytes = "0123456789ABCDEF";
v = (const unsigned char)c;
*d++ = '\\';
- *d++ = hexchars_upper[v>>4];
- *d++ = hexchars_upper[v&0xF];
+ *d++ = hexbytes[v>>4];
+ *d++ = hexbytes[v&0xF];
break;
}
default:
@@ -2100,7 +2105,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
unsigned int i;
struct ldb_val v2;
const struct ldb_dn_extended_syntax *ext_syntax;
-
+
if ( ! ldb_dn_validate(dn)) {
return LDB_ERR_OTHER;
}
--
2.53.0
From d8558ac294e7c622e6bb1239635e4e17f5f6e8cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Mon, 19 Jan 2026 14:33:52 +0100
Subject: [PATCH 14/38] s3:libads: Reset ads->config.flags in ads_disconnect()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is doing the same thing in ads_disconnect() as commit
a26f535 Clear previous CLDAP ping flags when reusing the ADS_STRUCT
did in ads_current_time()
In this case we:
1) found cached ADS_STRUCT which already has ads->config.flags set:
lookup_groupmem()
ads_cached_connection()
ads_cached_connection_reuse()
2) started search which immediately timeouts (the cached conn. was dead)
ads_do_search_retry_internal()
ldap_search_with_timeout() - IO_TIMEOUT
3) Retry loop finds a new DC and tries to connect
ads_do_search_retry_internal()
ads_disconnect()
ads_find_dc()
ads_try_connect()
netlogon_pings()
check_cldap_reply_required_flags()
4) check_cldap_reply_required_flags() fails since ads->config.flags
(stored possibly long time ago) contain:
NBT_SERVER_CLOSEST 0x00000080
which is misinterpreted as:
DS_PDC_REQUIRED 0x00000080
the newly found DC is not PDC (we asked for DS_ONLY_LDAP_NEEDED)
and since previous DC had NBT_SERVER_CLOSEST we want DS_PDC_REQUIRED
and fail.
We should anyway avoid mixing independent namespaces NBT_* and DS_*
in the same flag.
Next commit will do that.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15972
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 9f3a35991feb01a8d2c2b69fa0b914bbc637a809)
---
source3/libads/ldap.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 49fa1d47298..8dde09e3551 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1261,6 +1261,7 @@ void ads_disconnect(ADS_STRUCT *ads)
if (ads->ldap_wrap_data.mem_ctx) {
talloc_free(ads->ldap_wrap_data.mem_ctx);
}
+ ads->config.flags = 0;
ads_zero_ldap(ads);
ZERO_STRUCT(ads->ldap_tls_data);
ZERO_STRUCT(ads->ldap_wrap_data);
--
2.53.0
From 37cbf09ec9b9bacd2c9e8fd50bd4b80046388d9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Sun, 18 Jan 2026 01:04:11 +0100
Subject: [PATCH 15/38] s3:libads: Separate use of ads->config.flags for NBT_*
and DS_* values
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use of ads->config.flags is overloaded.
It is used to:
- pass DS_* flags down to cldap_netlogon()
- store the server_type from NETLOGON_SAM_LOGON_RESPONSE
Both cases use different values and cannot be combined.
E.g. flags mess up with value 0x00000080
NBT_SERVER_CLOSEST 0x00000080
DS_PDC_REQUIRED 0x00000080
Let's create two separate flags
nbt_server_type server_flags; /* NBT_* cldap flags identifying the services. */
uint32 required_flags; /* DS_* - Netlogon flags */
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15972
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Pavel Filipensky <pfilipensky@samba.org>
Autobuild-Date(master): Thu Jan 22 09:14:25 UTC 2026 on atb-devel-224
(cherry picked from commit 7483903575eab97773a992149d64511d5ec6f256)
---
source3/libads/ldap.c | 46 ++++++++++++++++++----------------
source3/librpc/idl/ads.idl | 4 ++-
source3/libsmb/namequery_dc.c | 4 ++-
source3/winbindd/winbindd_cm.c | 6 ++---
4 files changed, 33 insertions(+), 27 deletions(-)
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 8dde09e3551..ac57489d1eb 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -237,7 +237,7 @@ bool ads_sitename_match(ADS_STRUCT *ads)
bool ads_closest_dc(ADS_STRUCT *ads)
{
- if (ads->config.flags & NBT_SERVER_CLOSEST) {
+ if (ads->config.server_flags & NBT_SERVER_CLOSEST) {
DEBUG(10,("ads_closest_dc: NBT_SERVER_CLOSEST flag set\n"));
return True;
}
@@ -344,7 +344,7 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
sitename_store(cldap_reply->dns_domain, cldap_reply->client_site);
/* Leave this until last so that the flags are not clobbered */
- ads->config.flags = cldap_reply->server_type;
+ ads->config.server_flags = cldap_reply->server_type;
ret = true;
@@ -379,7 +379,8 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
ok = ads_cldap_netlogon_5(frame,
ss,
ads->server.realm,
- ads->config.flags | DS_ONLY_LDAP_NEEDED,
+ ads->config.required_flags |
+ DS_ONLY_LDAP_NEEDED,
&cldap_reply);
if (!ok) {
DBG_NOTICE("ads_cldap_netlogon_5(%s, %s) failed.\n",
@@ -490,20 +491,21 @@ again:
return status;
}
- status = netlogon_pings(frame, /* mem_ctx */
- lp_client_netlogon_ping_protocol(), /* proto */
- ts_list, /* servers */
- num_requests, /* num_servers */
- (struct netlogon_ping_filter){
- .ntversion = nt_version,
- .domain = ads->server.realm,
- .acct_ctrl = -1,
- .required_flags = ads->config.flags |
- DS_ONLY_LDAP_NEEDED,
- },
- 1, /* wanted_servers */
- endtime, /* timeout */
- &responses);
+ status = netlogon_pings(
+ frame, /* mem_ctx */
+ lp_client_netlogon_ping_protocol(), /* proto */
+ ts_list, /* servers */
+ num_requests, /* num_servers */
+ (struct netlogon_ping_filter){
+ .ntversion = nt_version,
+ .domain = ads->server.realm,
+ .acct_ctrl = -1,
+ .required_flags = ads->config.required_flags |
+ DS_ONLY_LDAP_NEEDED,
+ },
+ 1, /* wanted_servers */
+ endtime, /* timeout */
+ &responses);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netlogon_pings(realm=%s, num_requests=%zu) "
"for count[%zu] - %s\n",
@@ -1261,7 +1263,7 @@ void ads_disconnect(ADS_STRUCT *ads)
if (ads->ldap_wrap_data.mem_ctx) {
talloc_free(ads->ldap_wrap_data.mem_ctx);
}
- ads->config.flags = 0;
+ ads->config.server_flags = 0;
ads_zero_ldap(ads);
ZERO_STRUCT(ads->ldap_tls_data);
ZERO_STRUCT(ads->ldap_wrap_data);
@@ -3726,10 +3728,10 @@ ADS_STATUS ads_current_time(ADS_STRUCT *ads)
}
/*
- * Reset ads->config.flags as it can contain the flags
+ * Reset flags as it can contain the flags
* returned by the previous CLDAP ping when reusing the struct.
*/
- ads_s->config.flags = 0;
+ ads_s->config.server_flags = 0;
status = ads_connect_simple_anon(ads_s);
if ( !ADS_ERR_OK(status))
@@ -3815,10 +3817,10 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32_t *val)
}
/*
- * Reset ads->config.flags as it can contain the flags
+ * Reset flags as it can contain the flags
* returned by the previous CLDAP ping when reusing the struct.
*/
- ads_s->config.flags = 0;
+ ads_s->config.server_flags = 0;
status = ads_connect_simple_anon(ads_s);
if ( !ADS_ERR_OK(status))
diff --git a/source3/librpc/idl/ads.idl b/source3/librpc/idl/ads.idl
index 381447a1a29..20941e90346 100644
--- a/source3/librpc/idl/ads.idl
+++ b/source3/librpc/idl/ads.idl
@@ -6,6 +6,7 @@
*/
import "nbt.idl";
+import "netlogon.idl";
cpp_quote("#include <system/network.h>")
@@ -51,7 +52,8 @@ interface ads
} ads_auth;
typedef [nopull,nopush] struct {
- nbt_server_type flags; /* cldap flags identifying the services. */
+ nbt_server_type server_flags; /* NBT_* cldap flags identifying the services. */
+ netr_DsRGetDCName_flags required_flags; /* DS_* - Netlogon flags */
string workgroup;
string realm;
string bind_path;
diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c
index 3a2f22129b8..3d771d77b8d 100644
--- a/source3/libsmb/namequery_dc.c
+++ b/source3/libsmb/namequery_dc.c
@@ -109,7 +109,9 @@ static bool ads_dc_name(const char *domain,
}
#ifdef HAVE_ADS
- if (is_our_primary_domain(domain) && (ads->config.flags & NBT_SERVER_KDC)) {
+ if (is_our_primary_domain(domain) &&
+ (ads->config.server_flags & NBT_SERVER_KDC))
+ {
if (ads_closest_dc(ads)) {
/* We're going to use this KDC for this realm/domain.
If we are using sites, then force the krb5 libs
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 2c18aeba060..45b68ebe561 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -1061,7 +1061,7 @@ static bool dcip_check_name_ads(const struct winbindd_domain *domain,
ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto out;
}
- ads->config.flags |= request_flags;
+ ads->config.required_flags |= request_flags;
ads->server.no_fallback = true;
ads_status = ads_connect_cldap_only(ads);
@@ -1077,9 +1077,9 @@ static bool dcip_check_name_ads(const struct winbindd_domain *domain,
}
namecache_store(name, 0x20, 1, sa);
- DBG_DEBUG("CLDAP flags = 0x%"PRIx32"\n", ads->config.flags);
+ DBG_DEBUG("CLDAP flags = 0x%" PRIx32 "\n", ads->config.server_flags);
- if (domain->primary && (ads->config.flags & NBT_SERVER_KDC)) {
+ if (domain->primary && (ads->config.server_flags & NBT_SERVER_KDC)) {
if (ads_closest_dc(ads)) {
char *sitename = sitename_fetch(tmp_ctx,
ads->config.realm);
--
2.53.0
From e02f1dca11cbee015923d9e8c141a727dc1c02d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Thu, 22 Jan 2026 14:27:09 +0100
Subject: [PATCH 16/38] s3:libads: Allocate cli_credentials on a stackframe
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This fixes:
ERROR: talloc_free with references at ../../source3/libads/ldap_utils.c:158
What happens:
* `struct cli_credentials *creds` is allocated on `ads` talloc context
* gensec_set_credentials() creates a talloc_reference to `creds`
* TALLOC_FREE(creds) sees two parents and complains
All other code is using temporary talloc_stackframe() for `creds`.
Do it here as well.
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Fri Jan 23 11:20:28 UTC 2026 on atb-devel-224
---
source3/libads/ldap_utils.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/source3/libads/ldap_utils.c b/source3/libads/ldap_utils.c
index 9d6d962a2bc..d01afa69697 100644
--- a/source3/libads/ldap_utils.c
+++ b/source3/libads/ldap_utils.c
@@ -99,6 +99,7 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind
struct cli_credentials *creds = NULL;
char *cred_name = NULL;
NTSTATUS ntstatus;
+ TALLOC_CTX *frame = talloc_stackframe();
if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) &&
ads->config.ldap_page_size >= (lp_ldap_page_size() / 4) &&
@@ -119,18 +120,20 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind
DBG_NOTICE("Search for %s in <%s> failed: %s\n",
expr, bp, ads_errstr(status));
SAFE_FREE(bp);
+ TALLOC_FREE(frame);
return status;
}
ntstatus = ads->auth.reconnect_state->fn(ads,
ads->auth.reconnect_state->private_data,
- ads, &creds);
+ frame, &creds);
if (!NT_STATUS_IS_OK(ntstatus)) {
DBG_WARNING("Failed to get creds for realm(%s): %s\n",
ads->server.realm, nt_errstr(ntstatus));
DBG_WARNING("Search for %s in <%s> failed: %s\n",
expr, bp, ads_errstr(status));
SAFE_FREE(bp);
+ TALLOC_FREE(frame);
return status;
}
@@ -151,11 +154,11 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind
* callers depend on it being around.
*/
ads_disconnect(ads);
- TALLOC_FREE(creds);
+ TALLOC_FREE(frame);
SAFE_FREE(bp);
return status;
}
- TALLOC_FREE(creds);
+ TALLOC_FREE(frame);
*res = NULL;
--
2.53.0
From 2bdf2b96a818a64d7c420f0fb675530959602188 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@samba.org>
Date: Mon, 26 Jan 2026 13:36:02 +0100
Subject: [PATCH 17/38] s3:rpc_client: Fix memory leak opening local named pipe
If no local server name was passed to rpc_pipe_open_local_np() then
get_myname() was called with NULL talloc context instead of the
current stackframe.
This was causing an increase of memory usage on busy servers with long-living
rpcd_* workers.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15979
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Noel Power <noel.power@suse.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Tue Jan 27 10:13:40 UTC 2026 on atb-devel-224
(cherry picked from commit 24dc455362fb49ef81c99d95880e106a234ce29a)
---
source3/rpc_client/cli_pipe.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 23adbbc62fa..91afccd7fb2 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -3624,7 +3624,7 @@ NTSTATUS rpc_pipe_open_local_np(
}
if (local_server_name == NULL) {
- local_server_name = get_myname(result);
+ local_server_name = get_myname(frame);
}
if (local_server_addr != NULL) {
--
2.53.0
From 17c104ea4171aa002df0e7f69e61312898c7fad5 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 4 Apr 2025 10:27:50 +0200
Subject: [PATCH 18/38] lib:cmdline: Make sure --use-krb5-ccache sets the
ccache
Pair-Programmed-With: Alexander Bokovoy <ab@samba.org>
Signed-off-by: Alexander Bokovoy <ab@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
---
lib/cmdline/cmdline.c | 79 ++++++++++++++++++++++++++++++-------------
1 file changed, 55 insertions(+), 24 deletions(-)
diff --git a/lib/cmdline/cmdline.c b/lib/cmdline/cmdline.c
index 161ba8874bf..5902628cc15 100644
--- a/lib/cmdline/cmdline.c
+++ b/lib/cmdline/cmdline.c
@@ -16,6 +16,7 @@
*/
#include "includes.h"
+#include "auth/credentials/credentials.h"
#include "lib/param/param.h"
#include "dynconfig/dynconfig.h"
#include "auth/gensec/gensec.h"
@@ -930,6 +931,7 @@ static struct poptOption popt_common_connection[] = {
static bool skip_password_callback;
static bool machine_account_pending;
+static char *krb5_ccache = NULL;
static void popt_common_credentials_callback(poptContext popt_ctx,
enum poptCallbackReason reason,
@@ -1004,6 +1006,31 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
CRED_SPECIFIED);
}
+ /*
+ * If --use-krb5-ccache was passed on the command line we need
+ * to overwrite the values set by cli_credentials_guess().
+ */
+ if (krb5_ccache != NULL) {
+ const char *error_string = NULL;
+ int rc;
+
+ rc = cli_credentials_set_ccache(creds,
+ lp_ctx,
+ krb5_ccache,
+ CRED_SPECIFIED,
+ &error_string);
+ SAFE_FREE(krb5_ccache);
+ if (rc != 0) {
+ fprintf(stderr,
+ "Error setting krb5 credentials cache: "
+ "'%s'"
+ " - %s\n",
+ krb5_ccache,
+ error_string);
+ exit(1);
+ }
+ }
+
if (cli_credentials_get_kerberos_state(creds) ==
CRED_USE_KERBEROS_REQUIRED)
{
@@ -1023,10 +1050,10 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
skip_password_callback = true;
}
}
- if (!skip_password_callback) {
- (void)cli_credentials_get_password_and_obtained(creds,
- &password_obtained);
- }
+
+ (void)cli_credentials_get_password_and_obtained(
+ creds, &password_obtained);
+
if (!skip_password_callback &&
password_obtained < CRED_CALLBACK) {
ok = cli_credentials_set_cmdline_callbacks(creds);
@@ -1038,6 +1065,15 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
}
}
+ /*
+ * If the user specified a password on the command line always
+ * do a kinit!
+ */
+ if (password_obtained == CRED_SPECIFIED) {
+ cli_credentials_invalidate_ccache(creds,
+ CRED_SPECIFIED);
+ }
+
return;
}
@@ -1138,9 +1174,6 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
break;
}
case OPT_USE_KERBEROS_CCACHE: {
- const char *error_string = NULL;
- int rc;
-
if (arg == NULL) {
fprintf(stderr,
"Failed to parse --use-krb5-ccache=CCACHE: "
@@ -1148,26 +1181,24 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
exit(1);
}
- ok = cli_credentials_set_kerberos_state(creds,
- CRED_USE_KERBEROS_REQUIRED,
- CRED_SPECIFIED);
- if (!ok) {
- fprintf(stderr,
- "Failed to set Kerberos state to %s!\n", arg);
- exit(1);
+ /*
+ * Remember the value and handle it in
+ * POPT_CALLBACK_REASON_POST.
+ */
+ if (arg[0] != '\0') {
+ krb5_ccache = strdup(arg);
+ if (krb5_ccache == NULL) {
+ fprintf(stderr, "Failed allocate memory\n");
+ exit(1);
+ }
}
- rc = cli_credentials_set_ccache(creds,
- lp_ctx,
- arg,
- CRED_SPECIFIED,
- &error_string);
- if (rc != 0) {
+ ok = cli_credentials_set_kerberos_state(
+ creds, CRED_USE_KERBEROS_REQUIRED, CRED_SPECIFIED);
+ if (!ok) {
fprintf(stderr,
- "Error reading krb5 credentials cache: '%s'"
- " - %s\n",
- arg,
- error_string);
+ "Failed to set Kerberos state to %s!\n",
+ arg);
exit(1);
}
--
2.53.0
From d36e10471ddbd2175da53c046e3e62b9cdb576fd Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 11 Apr 2025 10:56:43 +0200
Subject: [PATCH 19/38] lib:cmdline: POPT_CALLBACK_REASON_POST should handle if
we skip the password callback
It is already checking if there is a valid ccache and disabling the callback.
In case of IAKerb we specify a ccache but might to fill one with a krbtgt.
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Tue Apr 15 12:54:57 UTC 2025 on atb-devel-224
---
lib/cmdline/cmdline.c | 5 ++++-
testprogs/blackbox/test_client_kerberos.sh | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/lib/cmdline/cmdline.c b/lib/cmdline/cmdline.c
index 5902628cc15..e434d65a2ef 100644
--- a/lib/cmdline/cmdline.c
+++ b/lib/cmdline/cmdline.c
@@ -1202,7 +1202,10 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
exit(1);
}
- skip_password_callback = true;
+ /*
+ * The password callback will be skipped, if we have a valid
+ * ccache. This is handled in POPT_CALLBACK_REASON_POST.
+ */
break;
}
case OPT_USE_WINBIND_CCACHE:
diff --git a/testprogs/blackbox/test_client_kerberos.sh b/testprogs/blackbox/test_client_kerberos.sh
index 54554ea3290..395b5bc989a 100755
--- a/testprogs/blackbox/test_client_kerberos.sh
+++ b/testprogs/blackbox/test_client_kerberos.sh
@@ -147,7 +147,7 @@ testit "test rpcclient kerberos" \
failed=$(expr $failed + 1)
cmd='echo ${PASSWORD} | $samba_rpcclient ncacn_np:${SERVER} -U${USERNAME} --use-krb5-ccache=$KRB5CCNAME --configfile=${CONFIGURATION} -c getusername 2>&1'
-testit_expect_failure "test rpcclient kerberos interactive (negative test)" \
+testit "test rpcclient kerberos interactive" \
test_rpc_getusername ||
failed=$(expr $failed + 1)
--
2.53.0
From c4369a82dffbc550b8740fca70aba57bc46400d4 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 25 Apr 2025 11:30:14 +0200
Subject: [PATCH 20/38] auth:creds: Make sure when parsing username that realm
is uppercase
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
---
auth/credentials/credentials.c | 7 +++++++
auth/credentials/tests/test_creds.c | 2 +-
python/samba/tests/credentials.py | 4 ++--
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c
index a88a458f82b..c31470a81d2 100644
--- a/auth/credentials/credentials.c
+++ b/auth/credentials/credentials.c
@@ -1030,6 +1030,8 @@ _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials,
}
if ((p = strchr_m(uname,'@'))) {
+ char *x = NULL;
+
/*
* We also need to set username and domain
* in order to undo the effect of
@@ -1038,6 +1040,11 @@ _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials,
cli_credentials_set_username(credentials, uname, obtained);
cli_credentials_set_domain(credentials, "", obtained);
+ /* Make sure the realm is uppercase */
+ for (x = p + 1; x[0] != '\0'; x++) {
+ *x = toupper_m(*x);
+ }
+
cli_credentials_set_principal(credentials, uname, obtained);
*p = 0;
cli_credentials_set_realm(credentials, p+1, obtained);
diff --git a/auth/credentials/tests/test_creds.c b/auth/credentials/tests/test_creds.c
index fa8755e0a40..4abb7e4b90c 100644
--- a/auth/credentials/tests/test_creds.c
+++ b/auth/credentials/tests/test_creds.c
@@ -219,7 +219,7 @@ static void torture_creds_parse_string(void **state)
usr_obtained = cli_credentials_get_username_obtained(creds);
assert_int_equal(usr_obtained, CRED_SPECIFIED);
- assert_string_equal(creds->principal, "wurst@brot.realm");
+ assert_string_equal(creds->principal, "wurst@BROT.REALM");
princ_obtained = cli_credentials_get_principal_obtained(creds);
assert_int_equal(princ_obtained, CRED_SPECIFIED);
diff --git a/python/samba/tests/credentials.py b/python/samba/tests/credentials.py
index f9781f8ba03..bc132681c48 100644
--- a/python/samba/tests/credentials.py
+++ b/python/samba/tests/credentials.py
@@ -403,7 +403,7 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
self.assertEqual(creds.get_username(), "user@samba.org")
self.assertEqual(creds.get_domain(), "")
self.assertEqual(creds.get_realm(), "SAMBA.ORG")
- self.assertEqual(creds.get_principal(), "user@samba.org")
+ self.assertEqual(creds.get_principal(), "user@SAMBA.ORG")
self.assertEqual(creds.is_anonymous(), False)
self.assertEqual(creds.authentication_requested(), True)
@@ -445,7 +445,7 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
self.assertEqual(creds.get_domain(), "")
self.assertEqual(creds.get_password(), "pass")
self.assertEqual(creds.get_realm(), "SAMBA.ORG")
- self.assertEqual(creds.get_principal(), "user@samba.org")
+ self.assertEqual(creds.get_principal(), "user@SAMBA.ORG")
self.assertEqual(creds.is_anonymous(), False)
self.assertEqual(creds.authentication_requested(), True)
--
2.53.0
From 0673310878659d01fb250243c427d36b6cda105c Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 4 Apr 2025 13:32:41 +0200
Subject: [PATCH 21/38] auth:creds: Always store the ccache name
This will allow us to specify the cache as one to fill with credentials.
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
---
auth/credentials/credentials_internal.h | 1 +
auth/credentials/credentials_krb5.c | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/auth/credentials/credentials_internal.h b/auth/credentials/credentials_internal.h
index cda361e1dd0..72ec390ad7e 100644
--- a/auth/credentials/credentials_internal.h
+++ b/auth/credentials/credentials_internal.h
@@ -74,6 +74,7 @@ struct cli_credentials {
DATA_BLOB nt_response;
DATA_BLOB nt_session_key;
+ const char *ccache_name;
struct ccache_container *ccache;
struct gssapi_creds_container *client_gss_creds;
struct keytab_container *keytab;
diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index ce76b10361d..7d8b744b3e2 100644
--- a/auth/credentials/credentials_krb5.c
+++ b/auth/credentials/credentials_krb5.c
@@ -293,6 +293,14 @@ _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred,
return 0;
}
+ if (name != NULL) {
+ cred->ccache_name = talloc_strdup(cred, name);
+ if (cred->ccache_name == NULL) {
+ (*error_string) = error_message(ENOMEM);
+ return ENOMEM;
+ }
+ }
+
ccc = talloc(cred, struct ccache_container);
if (!ccc) {
(*error_string) = error_message(ENOMEM);
--
2.53.0
From d1ab591115e1d09e89eb2e960ca989a1f14fe62d Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 4 Apr 2025 13:33:19 +0200
Subject: [PATCH 22/38] auth:creds: Add cli_credentials_get_out_ccache_name()
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
---
auth/credentials/credentials.h | 1 +
auth/credentials/credentials_krb5.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index cae6a94b450..9f945726440 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -262,6 +262,7 @@ int cli_credentials_set_ccache(struct cli_credentials *cred,
const char *name,
enum credentials_obtained obtained,
const char **error_string);
+const char *cli_credentials_get_out_ccache_name(struct cli_credentials *cred);
bool cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained);
bool cli_credentials_parse_password_fd(struct cli_credentials *credentials,
int fd, enum credentials_obtained obtained);
diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index 7d8b744b3e2..6c61eca7b4b 100644
--- a/auth/credentials/credentials_krb5.c
+++ b/auth/credentials/credentials_krb5.c
@@ -280,6 +280,11 @@ static int cli_credentials_set_from_ccache(struct cli_credentials *cred,
return 0;
}
+_PUBLIC_ const char *cli_credentials_get_out_ccache_name(struct cli_credentials *cred)
+{
+ return cred->ccache_name;
+}
+
_PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred,
struct loadparm_context *lp_ctx,
const char *name,
--
2.53.0
From 843a279c4fd93bf312ab242f7dc9569e65ffdcd5 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 4 Apr 2025 13:37:21 +0200
Subject: [PATCH 23/38] librpc:gse: Implement storing tickets into an emtpy
ccache
smbclient //server/share --krb5-use-ccache=/tmp/foo
Will write the ticket to the specified ccache.
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
---
source3/librpc/crypto/gse.c | 65 ++++++++++++++++++++++++++++++
wscript_configure_embedded_heimdal | 1 +
wscript_configure_system_heimdal | 9 +++++
wscript_configure_system_mitkrb5 | 7 ++++
4 files changed, 82 insertions(+)
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index e6f96d2464e..d29122c9ce6 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -632,6 +632,71 @@ init_sec_context_done:
goto done;
}
+ /*
+ * In case we have a ccache specified on the command line we probably
+ * want to use it to store credentials we got it.
+ */
+#ifdef HAVE_GSS_KEY_VALUE_SET_DESC
+ if (NT_STATUS_IS_OK(status)) {
+ struct cli_credentials *creds = gensec_get_credentials(
+ gensec_security);
+ bool ccache_valid = false;
+ enum credentials_obtained ccache_obtained = CRED_UNINITIALISED;
+
+ ccache_valid = cli_credentials_get_ccache_name_obtained(
+ creds, gse_ctx, NULL, &ccache_obtained);
+ /*
+ * In case we don't have a valid ccache yet, try to create it if
+ * one has been specified.
+ */
+ if (!ccache_valid) {
+ gss_key_value_set_desc store;
+ const char *ccache_name =
+ cli_credentials_get_out_ccache_name(creds);
+
+ if (ccache_name == NULL) {
+ goto done;
+ }
+
+ store.elements = talloc_zero_array(
+ mem_ctx,
+ struct gss_key_value_element_struct,
+ 1);
+ if (store.elements == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ store.count = 1;
+ store.elements[0] =
+ (struct gss_key_value_element_struct){
+ .key = "ccache",
+ .value = ccache_name,
+ };
+
+ /*
+ * We attempt to store the cred into the ccache. It
+ * might fail but we don't need to act on it for the
+ * purpose of the authentication.
+ */
+ gss_maj = gss_store_cred_into(&gss_min,
+ gse_ctx->creds,
+ GSS_C_INITIATE,
+ GSS_C_NO_OID,
+ /* overwrite_cred = */ 1,
+ /* default_cred = */ 1,
+ &store,
+ NULL,
+ NULL);
+ if (gss_maj != 0) {
+ DBG_ERR("Failed to store Kerberos credentials "
+ "into ccache: %s\n",
+ ccache_name);
+ }
+ }
+ }
+#endif /* HAVE_GSS_KEY_VALUE_SET_DESC */
+
/* we may be told to return nothing */
if (out_data.length) {
blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
diff --git a/wscript_configure_embedded_heimdal b/wscript_configure_embedded_heimdal
index c1488e5506e..325b1b11d4b 100644
--- a/wscript_configure_embedded_heimdal
+++ b/wscript_configure_embedded_heimdal
@@ -15,3 +15,4 @@ conf.RECURSE('third_party/heimdal_build')
conf.define('HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG', 1)
conf.define('HAVE_KRB5_INIT_CREDS_STEP', 1)
+conf.define('HAVE_GSS_KEY_VALUE_SET_DESC', 1)
diff --git a/wscript_configure_system_heimdal b/wscript_configure_system_heimdal
index c320a76ea17..6256bbac4e6 100644
--- a/wscript_configure_system_heimdal
+++ b/wscript_configure_system_heimdal
@@ -66,3 +66,12 @@ conf.CHECK_FUNCS('''
''',
lib='krb5',
headers='krb5.h')
+
+# gss_key_value_set_desc is not part of system heimdal in the build image. Maybe
+# the distro we use is too old.
+conf.CHECK_CODE(
+ "gss_key_value_set_desc",
+ "HAVE_GSS_KEY_VALUE_SET_DESC",
+ headers="gssapi/gssapi.h",
+ lib="gssapi",
+)
diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
index 58b9fb802d0..87cd6e9a1b8 100644
--- a/wscript_configure_system_mitkrb5
+++ b/wscript_configure_system_mitkrb5
@@ -344,6 +344,13 @@ conf.CHECK_CODE('''
headers='krb5.h', lib='krb5', execute=False,
msg="Checking whether krb5_creds have flags property")
+conf.CHECK_CODE(
+ "gss_key_value_set_desc",
+ "HAVE_GSS_KEY_VALUE_SET_DESC",
+ headers="gssapi/gssapi_ext.h",
+ lib="gssapi",
+)
+
# Check for MIT KDC
if conf.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'):
Logs.info("Looking for MIT KDC")
--
2.53.0
From cc930a27882a5ad2878ceb5dfd7eac2f164c98b1 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 25 Apr 2025 17:32:16 +0200
Subject: [PATCH 24/38] lib:cmdline: Check if we have a valid default ccache
If you don't specify anything, and we have a valid ccache then try to
use it!
> smbclient -L //samba1.earth.milkyway.site
Anonymous login successful
Sharename Type Comment
--------- ---- -------
print$ Disk Printer Drivers
IPC$ IPC IPC Service (Samba 4.22.1)
SMB1 disabled -- no workgroup available
In case the user specifies a principal, it will ask for a password:
> bin/smbclient -L //samba1.earth.milkyway.site -Ualice1@EARTH.MILKYWAY.SITE
Password for [alice1@EARTH.MILKYWAY.SITE]:
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
---
lib/cmdline/cmdline.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/cmdline/cmdline.c b/lib/cmdline/cmdline.c
index e434d65a2ef..f96ca88f95b 100644
--- a/lib/cmdline/cmdline.c
+++ b/lib/cmdline/cmdline.c
@@ -1031,8 +1031,8 @@ static void popt_common_credentials_callback(poptContext popt_ctx,
}
}
- if (cli_credentials_get_kerberos_state(creds) ==
- CRED_USE_KERBEROS_REQUIRED)
+ if (cli_credentials_get_kerberos_state(creds) !=
+ CRED_USE_KERBEROS_DISABLED)
{
enum credentials_obtained ccache_obtained =
CRED_UNINITIALISED;
--
2.53.0
From 5bb7e14a4e23626383467f25b34f5d4d1b01ab91 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Tue, 5 Aug 2025 09:15:43 +0200
Subject: [PATCH 25/38] docs-xml: Update documentation for --use-kerberos and
--use-krb5-ccache
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Tue Aug 5 11:49:35 UTC 2025 on atb-devel-224
---
docs-xml/build/DTD/samba.entities | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/docs-xml/build/DTD/samba.entities b/docs-xml/build/DTD/samba.entities
index cefddacd9b7..65d597ae8ff 100644
--- a/docs-xml/build/DTD/samba.entities
+++ b/docs-xml/build/DTD/samba.entities
@@ -764,10 +764,19 @@
<term>--use-kerberos=desired|required|off</term>
<listitem>
<para>
- This parameter determines whether Samba client tools
- will try to authenticate using Kerberos. For Kerberos
- authentication you need to use dns names instead of IP
- addresses when connecting to a service.
+ This parameter determines whether Samba client tools
+ will try to authenticate using Kerberos. For Kerberos
+ authentication you should use DNS names instead of IP
+ addresses when connecting to a service.
+
+ By default Samba client tools will try to use the
+ default Kerberos credential cache (ccache).
+ In case the ccache does not exist or -U|--user option
+ was specified, clients will ask to enter a password and
+ will obtain a Kerberos ticket (kinit) for you.
+
+ If you want to use an alternative Kerberos credentical
+ cache, use the --use-krb5-ccache option.
</para>
<para>
@@ -789,7 +798,7 @@
</para>
<para>
- This will set --use-kerberos=required too.
+ This will enforce --use-kerberos=required.
</para>
</listitem>
</varlistentry>
--
2.53.0
From b5cf950c9bdca697bdba6dfbceccabcb18a62a49 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Tue, 2 Dec 2025 17:17:33 +0100
Subject: [PATCH 26/38] s3-selftest: mention in-memory ccache usage when
nothing is provided
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15840
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
source3/script/tests/test_net_ads_kerberos.sh | 2 ++
1 file changed, 2 insertions(+)
diff --git a/source3/script/tests/test_net_ads_kerberos.sh b/source3/script/tests/test_net_ads_kerberos.sh
index 8a3c9ef2bc7..92d3996d078 100755
--- a/source3/script/tests/test_net_ads_kerberos.sh
+++ b/source3/script/tests/test_net_ads_kerberos.sh
@@ -30,6 +30,7 @@ KRB5CCNAME="FILE:$KRB5CCNAME_PATH"
## Test "net ads kerberos kinit" variants
#################################################
+#simply uses in memory ccache
testit "net_ads_kerberos_kinit" \
"$VALGRIND" "$BINDIR"/net ads kerberos kinit \
-U"$USERNAME"%"$PASSWORD" "$ADDARGS" \
@@ -50,6 +51,7 @@ rm -f "$KRB5CCNAME_PATH"
# --use-krb5-ccache=${KRB5CCNAME} \
# || failed=$((failed + 1))
+#simply uses in memory ccache
testit "net_ads_kerberos_kinit (-P)" \
"$VALGRIND" "$BINDIR"/net ads kerberos kinit \
-P "$ADDARGS" \
--
2.53.0
From a95b0b800022286db1a8680a5ea98aa0e4253020 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Tue, 2 Dec 2025 17:18:41 +0100
Subject: [PATCH 27/38] s3-selftest: verify KRB5CCNAME presence after kinit
using klist
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15840
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
source3/script/tests/test_net_ads_kerberos.sh | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/source3/script/tests/test_net_ads_kerberos.sh b/source3/script/tests/test_net_ads_kerberos.sh
index 92d3996d078..c53520cf733 100755
--- a/source3/script/tests/test_net_ads_kerberos.sh
+++ b/source3/script/tests/test_net_ads_kerberos.sh
@@ -14,6 +14,12 @@ PREFIX="$4"
shift 4
ADDARGS="$*"
+if [ -x $(which klist) ]; then
+ KLIST=$(which klist);
+else
+ KLIST="test -e";
+fi
+
incdir=$(dirname "$0")/../../../testprogs/blackbox
. "$incdir"/subunit.sh
@@ -41,6 +47,9 @@ testit "net_ads_kerberos_kinit (KRB5CCNAME env set)" \
"$VALGRIND" "$BINDIR"/net ads kerberos kinit \
-U"$USERNAME"%"$PASSWORD" "$ADDARGS" \
|| failed=$((failed + 1))
+testit "klist env $KRB5CCNAME" \
+ "$KLIST" "$KRB5CCNAME" \
+ || failed=$((failed +1))
unset KRB5CCNAME
rm -f "$KRB5CCNAME_PATH"
@@ -62,6 +71,9 @@ testit "net_ads_kerberos_kinit (-P and KRB5CCNAME env set)" \
"$VALGRIND" "$BINDIR"/net ads kerberos kinit \
-P "$ADDARGS" \
|| failed=$((failed + 1))
+testit "klist env $KRB5CCNAME" \
+ "$KLIST" "$KRB5CCNAME" \
+ || failed=$((failed +1))
unset KRB5CCNAME
rm -f "$KRB5CCNAME_PATH"
--
2.53.0
From 9743315e50823c1e8d884ba62167c5e8d62a3a40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Tue, 2 Dec 2025 17:01:31 +0100
Subject: [PATCH 28/38] s3-selftest: Activate "net ads kerberos kinit" tests
with --use-krb5-ccache
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15840
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
selftest/knownfail | 2 ++
source3/script/tests/test_net_ads_kerberos.sh | 30 +++++++++++--------
2 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/selftest/knownfail b/selftest/knownfail
index ab2d79d7114..76f1dae605d 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -338,3 +338,5 @@
# We currently don't send referrals for LDAP modify of non-replicated attrs
^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.*
+
+^samba3.blackbox.net_ads_kerberos.*.klist.*--use-krb5-ccache.*
diff --git a/source3/script/tests/test_net_ads_kerberos.sh b/source3/script/tests/test_net_ads_kerberos.sh
index c53520cf733..b7933bab6a6 100755
--- a/source3/script/tests/test_net_ads_kerberos.sh
+++ b/source3/script/tests/test_net_ads_kerberos.sh
@@ -53,12 +53,15 @@ testit "klist env $KRB5CCNAME" \
unset KRB5CCNAME
rm -f "$KRB5CCNAME_PATH"
-# --use-krb5-ccache is not working
-#testit "net_ads_kerberos_kinit (with --use-krb5-ccache)" \
-# $VALGRIND $BINDIR/net ads kerberos kinit \
-# -U$USERNAME%$PASSWORD $ADDARGS \
-# --use-krb5-ccache=${KRB5CCNAME} \
-# || failed=$((failed + 1))
+testit "net_ads_kerberos_kinit (with --use-krb5-ccache)" \
+ "$VALGRIND" "$BINDIR"/net ads kerberos kinit \
+ -U"$USERNAME"%"$PASSWORD" "$ADDARGS" \
+ --use-krb5-ccache="${KRB5CCNAME_PATH}" \
+ || failed=$((failed + 1))
+testit "klist --use-krb5-ccache $KRB5CCNAME_PATH" \
+ "$KLIST" "$KRB5CCNAME_PATH" \
+ || failed=$((failed +1))
+rm -f "$KRB5CCNAME_PATH"
#simply uses in memory ccache
testit "net_ads_kerberos_kinit (-P)" \
@@ -77,12 +80,15 @@ testit "klist env $KRB5CCNAME" \
unset KRB5CCNAME
rm -f "$KRB5CCNAME_PATH"
-# --use-krb5-ccache is not working
-#testit "net_ads_kerberos_kinit (-P with --use-krb5-ccache)" \
-# $VALGRIND $BINDIR/net ads kerberos kinit \
-# -P $ADDARGS \
-# --use-krb5-ccache=${KRB5CCNAME} \
-# || failed=$((failed + 1))
+testit "net_ads_kerberos_kinit (-P with --use-krb5-ccache)" \
+ "$VALGRIND" "$BINDIR"/net ads kerberos kinit \
+ -P "$ADDARGS" \
+ --use-krb5-ccache="${KRB5CCNAME_PATH}" \
+ || failed=$((failed + 1))
+testit "klist --use-krb5-ccache $KRB5CCNAME_PATH" \
+ "$KLIST" "$KRB5CCNAME_PATH" \
+ || failed=$((failed +1))
+rm -f "$KRB5CCNAME_PATH"
#################################################
--
2.53.0
From a90df88fbce5e9ead92093edfe51e5f6014216b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Tue, 2 Dec 2025 16:56:44 +0100
Subject: [PATCH 29/38] s3-net: properly setup krb5 ccache name via
--use-krb5-ccache
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15840
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
selftest/knownfail | 2 --
source3/utils/net.c | 19 ++++++++++++-------
source3/utils/net_ads.c | 4 ++++
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/selftest/knownfail b/selftest/knownfail
index 76f1dae605d..ab2d79d7114 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -338,5 +338,3 @@
# We currently don't send referrals for LDAP modify of non-replicated attrs
^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.*
-
-^samba3.blackbox.net_ads_kerberos.*.klist.*--use-krb5-ccache.*
diff --git a/source3/utils/net.c b/source3/utils/net.c
index ecabd980d0c..271c96cf804 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -1396,7 +1396,7 @@ static struct functable net_func[] = {
cli_credentials_get_principal_obtained(c->creds);
enum credentials_obtained password_obtained =
cli_credentials_get_password_obtained(c->creds);
- char *krb5ccname = NULL;
+ const char *krb5ccname = NULL;
if (principal_obtained == CRED_SPECIFIED) {
c->explicit_credentials = true;
@@ -1415,15 +1415,20 @@ static struct functable net_func[] = {
}
/* cli_credentials_get_ccache_name_obtained() would not work
- * here, we also cannot get the content of --use-krb5-ccache= so
- * for now at least honour the KRB5CCNAME environment variable
- * to get 'net ads kerberos' functions to work at all - gd */
-
- krb5ccname = getenv("KRB5CCNAME");
- if (krb5ccname == NULL) {
+ * here but we can now access the content of the
+ * --use-krb5-ccache option via cli credentials. Fallback to
+ * KRB5CCNAME environment variable to get 'net ads kerberos'
+ * functions to work at all - gd */
+
+ krb5ccname = cli_credentials_get_out_ccache_name(c->creds);
+ if (krb5ccname == NULL || krb5ccname[0] == '\0') {
+ krb5ccname = getenv("KRB5CCNAME");
+ }
+ if (krb5ccname == NULL || krb5ccname[0] == '\0') {
krb5ccname = talloc_strdup(c, "MEMORY:net");
}
if (krb5ccname == NULL) {
+ DBG_ERR("Not able to setup krb5 ccache");
exit(1);
}
c->opt_krb5_ccache = krb5ccname;
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 753b957e43f..2dc7de37e43 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -3283,7 +3283,11 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **
if (ret) {
d_printf(_("failed to kinit password: %s\n"),
nt_errstr(status));
+ return ret;
}
+
+ d_printf("Stored Kerberos TGT in: %s\n", c->opt_krb5_ccache);
+
return ret;
}
--
2.53.0
From 4800989ab9721c075ad0f23001f45f20677c7389 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Sat, 13 Dec 2025 13:49:37 +0100
Subject: [PATCH 30/38] doc-xml: Document "net ads kerberos" commands
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15840
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Günther Deschner <gd@samba.org>
Autobuild-Date(master): Mon Jan 5 15:49:04 UTC 2026 on atb-devel-224
---
docs-xml/manpages/net.8.xml | 139 ++++++++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index 05191236ecc..3f276236e1e 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -1801,7 +1801,146 @@ the following entry types;
</refsect2>
+<refsect2>
+ <title>ADS KERBEROS</title>
+
+<para>
+ Issue Kerberos operations against an Active Directory KDC.
+</para>
+
+</refsect2>
+
+<refsect2>
+ <title>ADS KERBEROS KINIT</title>
+
+<para>
+ Issue a kinit request for a given user. When no other options are
+ defined the ticket granting ticket (TGT) will be stored in a memory cache.
+</para>
+
+<para>
+ To store the TGT in a different location either use the
+ <option>--krb5-ccache</option> option or set the
+ <replaceable>KRB5CCNAME</replaceable> environment variable.
+</para>
+
+<para>Example: <userinput>net ads kerberos kinit -P --krb5-ccache=/tmp/krb5cache</userinput></para>
+
+</refsect2>
+
+<refsect2>
+ <title>ADS KERBEROS RENEW</title>
+
+<para>
+ Renew an already acquired ticket granting ticket (TGT).
+</para>
+
+<para>Example: <userinput>net ads kerberos renew</userinput></para>
+
+</refsect2>
+
+<refsect2>
+ <title>ADS KERBEROS PAC</title>
+
+<para>
+ Request a Kerberos PAC while authenticating to an Active Directory KDC.
+</para>
+
+<para>
+ The following commands are provided:
+</para>
+
+<simplelist>
+<member>net ads kerberos pac dump - Dump a PAC to stdout.</member>
+<member>net ads kerneros pac save - Save a PAC to a file.</member>
+</simplelist>
+
+<para>
+ All commands allow to define an impersonation principal to do a Kerberos
+ Service for User (S4U2SELF) operation via
+ the <replaceable>impersonate=STRING</replaceable> option.
+ The impersonation principal can have multiple different formats:
+</para>
+
+<itemizedlist>
+ <listitem>
+ <para><replaceable>user@MY.REALM</replaceable></para>
+ <para>This is the default format.</para>
+ </listitem>
+ <listitem>
+ <para><replaceable>user@MY.REALM@MY.REALM</replaceable></para>
+ <para>The Kerberos Service for User (S4U2SELF) also supports
+ Enterprise Principals.</para>
+ </listitem>
+ <listitem>
+ <para><replaceable>user@UPN.SUFFIX@MY.REALM</replaceable></para>
+ <para>Enterprise Principal using a defined upn suffix.</para>
+ </listitem>
+ <listitem>
+ <para><replaceable>user@WORKGROUP@MY.REALM</replaceable></para>
+ <para>Enterprise Principal with netbios domain name.
+ This format is currently not supported by Samba AD.</para>
+ </listitem>
+</itemizedlist>
+<para>
+ By default net will request a service ticket for the local service
+ of the joined machine. A different service can be defined via
+ <replaceable>local_service=STRING</replaceable>.
+</para>
+
+</refsect2>
+<refsect2>
+ <title>ADS KERBEROS PAC DUMP [impersonate=string] [local_service=string] [pac_buffer_type=int]</title>
+
+<para>
+ Request a Kerberos PAC while authenticating to an Active Directory KDC.
+ The PAC will be printed on stdout.
+</para>
+
+<para>
+ When no specific pac_buffer is selected, all buffers will be printed.
+ It is possible to select a specific one via
+ <replaceable>pac_buffer_type=INT</replaceable> from this list:
+</para>
+
+<simplelist>
+<member>1 PAC_TYPE_LOGON_INFO</member>
+<member>2 PAC_TYPE_CREDENTIAL_INFO</member>
+<member>6 PAC_TYPE_SRV_CHECKSUM</member>
+<member>7 PAC_TYPE_KDC_CHECKSUM</member>
+<member>10 PAC_TYPE_LOGON_NAME</member>
+<member>11 PAC_TYPE_CONSTRAINED_DELEGATION</member>
+<member>12 PAC_TYPE_UPN_DNS_INFO</member>
+<member>13 PAC_TYPE_CLIENT_CLAIMS_INFO</member>
+<member>14 PAC_TYPE_DEVICE_INFO</member>
+<member>15 PAC_TYPE_DEVICE_CLAIMS_INFO</member>
+<member>16 PAC_TYPE_TICKET_CHECKSUM</member>
+<member>17 PAC_TYPE_ATTRIBUTES_INFO</member>
+<member>18 PAC_TYPE_REQUESTER_SID</member>
+<member>19 PAC_TYPE_FULL_CHECKSUM</member>
+</simplelist>
+
+<para>Example: <userinput>net ads kerberos pac dump -P impersonate=anyuser@MY.REALM.COM</userinput></para>
+
+</refsect2>
+
+<refsect2>
+ <title>ADS KERBEROS PAC SAVE [impersonate=string] [local_service=string] [filename=string]</title>
+
+<para>
+ Request a Kerberos PAC while authenticating to an Active Directory KDC.
+ The PAC will be saved in a file.
+</para>
+
+<para>
+ The filename to store the PAC can be set via the
+ <replaceable>filename=STRING</replaceable> option.
+</para>
+
+<para>Example: <userinput>net ads kerberos pac save -U user%password filename=/tmp/pacstore</userinput></para>
+
+</refsect2>
<refsect2>
<title>SAM CREATEBUILTINGROUP &lt;NAME&gt;</title>
--
2.53.0
From 5b3b05af328824dbbab431da7aafc53f4ff2c474 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Tue, 3 Feb 2026 12:53:10 +0100
Subject: [PATCH 31/38] s3:utils: 'net ads kerberos kinit' should use also
default ccache name from krb5.conf
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is re-introducing the behavior from samba-4.20 where both these
commands operated on the same ccache (default_ccache_name in
[libdefaults] section of krb5.conf)
'net ads kerberos kinit -P'
'klist'
With samba-4.21 it no longer works, 'net ads kerberos kinit -P'
fallbacks to 'MEMORY:net' (which is of a very limited use, ticket
cannot be used by other process) and klist finds no ticket.
The order is changed from:
--use-krb5-ccache
env "KRB5CCNAME"
"MEMORY:net"
to ("MEMORY:net" is removed):
--use-krb5-ccache
env "KRB5CCNAME"
default_ccache_name
'--use-krb5-ccache=MEMORY:net' can be used to validate the credentials.
Use smb_force_krb5_cc_default_name() instead of krb5_cc_default_name()
because of commit:
1ca6fb5 make sure krb5_cc_default[_name]() is no longer used directly
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15993
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 4cc6a13590434f6a3aa1add663728188970d727e)
---
source3/utils/net.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 271c96cf804..0ce03f8213d 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -54,6 +54,7 @@
#include "source3/utils/passwd_proto.h"
#include "auth/gensec/gensec.h"
#include "lib/param/param.h"
+#include "lib/krb5_wrap/krb5_samba.h"
#ifdef WITH_FAKE_KASERVER
#include "utils/net_afs.h"
@@ -1414,18 +1415,33 @@ static struct functable net_func[] = {
CRED_SPECIFIED);
}
- /* cli_credentials_get_ccache_name_obtained() would not work
- * here but we can now access the content of the
- * --use-krb5-ccache option via cli credentials. Fallback to
- * KRB5CCNAME environment variable to get 'net ads kerberos'
- * functions to work at all - gd */
-
+ /*
+ * Priority order for krb5 credential cache name
+ *
+ * via cli_credentials_get_out_ccache_name() :
+ *
+ * 1. '--use-krb5-ccache' option
+ *
+ * via krb5_cc_default_name() :
+ *
+ * 2. KRB5CCNAME environment variable
+ * 3. default_ccache_name in [libdefaults] section of krb5.conf
+ * 4. ...more - krb5_cc_default_name() always returns something
+ * - see documentation
+ */
krb5ccname = cli_credentials_get_out_ccache_name(c->creds);
if (krb5ccname == NULL || krb5ccname[0] == '\0') {
- krb5ccname = getenv("KRB5CCNAME");
- }
- if (krb5ccname == NULL || krb5ccname[0] == '\0') {
- krb5ccname = talloc_strdup(c, "MEMORY:net");
+ krb5_context ct = NULL;
+ krb5_error_code ret = smb_krb5_init_context_common(&ct);
+
+ if (ret == 0) {
+ krb5ccname = smb_force_krb5_cc_default_name(ct);
+ if (krb5ccname != NULL) {
+ krb5ccname = talloc_strdup(c,
+ krb5ccname);
+ }
+ krb5_free_context(ct);
+ }
}
if (krb5ccname == NULL) {
DBG_ERR("Not able to setup krb5 ccache");
--
2.53.0
From c230940ede67f1078a6671be163968dea4d76061 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
Date: Thu, 5 Feb 2026 16:04:25 +0100
Subject: [PATCH 32/38] manpages: Update NET ADS KERBEROS KINIT manpage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15993
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Pavel Filipensky <pfilipensky@samba.org>
Autobuild-Date(master): Thu Feb 5 21:11:13 UTC 2026 on atb-devel-224
(cherry picked from commit 9d083a28fe45afd8f82441c6e24255e4c64c113b)
---
docs-xml/manpages/net.8.xml | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index 3f276236e1e..4e149394df3 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -1814,17 +1814,37 @@ the following entry types;
<title>ADS KERBEROS KINIT</title>
<para>
- Issue a kinit request for a given user. When no other options are
- defined the ticket granting ticket (TGT) will be stored in a memory cache.
+ Issue a kinit request for a given user. The following methods can be used
+ to specify where to store the ticket granting ticket (TGT) (in order of
+ precedence):
</para>
-<para>
- To store the TGT in a different location either use the
- <option>--krb5-ccache</option> option or set the
- <replaceable>KRB5CCNAME</replaceable> environment variable.
-</para>
+<itemizedlist>
+ <listitem>
+ <para>option <option>--use-krb5-ccache</option></para>
+ </listitem>
+ <listitem>
+ <para><replaceable>KRB5CCNAME</replaceable> environment variable</para>
+ </listitem>
+ <listitem>
+ <para><parameter>default_ccache_name</parameter> setting in <filename>krb5.conf</filename></para>
+ </listitem>
+</itemizedlist>
-<para>Example: <userinput>net ads kerberos kinit -P --krb5-ccache=/tmp/krb5cache</userinput></para>
+<variablelist><title>Examples:</title>
+<varlistentry>
+<term>Use file based cache (FILE:/tmp/krb5cache)</term>
+<listitem><literallayout>
+net ads kerberos kinit -P --use-krb5-ccache=/tmp/krb5cache
+</literallayout></listitem>
+</varlistentry>
+<varlistentry>
+<term>Use memory cache (MEMORY:net) to verify the authentication</term>
+<listitem><literallayout>
+net ads kerberos kinit -P --use-krb5-ccache=MEMORY:net
+</literallayout></listitem>
+</varlistentry>
+</variablelist>
</refsect2>
--
2.53.0
From 51b0f44caddd8e4cc5975dd8f982fad9f35f99fe Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Thu, 23 Oct 2025 11:00:38 +0200
Subject: [PATCH 33/38] docs-xml: Improve the samba-bgqd manpage
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15809
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Anoop C S <anoopcs@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Fri Nov 14 15:05:11 UTC 2025 on atb-devel-224
(cherry picked from commit 9322231f716237abba8627acda62c279c6a90f4f)
---
docs-xml/manpages/samba-bgqd.8.xml | 37 +++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/docs-xml/manpages/samba-bgqd.8.xml b/docs-xml/manpages/samba-bgqd.8.xml
index ef50a542a9e..9a16a2aaad0 100644
--- a/docs-xml/manpages/samba-bgqd.8.xml
+++ b/docs-xml/manpages/samba-bgqd.8.xml
@@ -14,28 +14,53 @@
<refnamediv>
<refname>samba-bgqd</refname>
<refpurpose>This is an internal helper program performing
- asynchronous printing-related jobs.</refpurpose>
+ asynchronous printing-related tasks</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>samba-bgqd</command>
+ <arg choice="opt">-D|--daemon</arg>
+ <arg choice="opt">-i|--interactive</arg>
+ <arg choice="opt">-F|--foreground</arg>
+ <arg choice="opt">--no-process-group</arg>
+ <arg choice="opt">-d &lt;debug level&gt;</arg>
+ <arg choice="opt">--debug-stdout</arg>
+ <arg choice="opt">--configfile=&lt;configuration file&gt;</arg>
+ <arg choice="opt">--option=&lt;name&gt;=&lt;value&gt;</arg>
+ <arg choice="opt">-l|--log-basename &lt;log directory&gt;</arg>
+ <arg choice="opt">--ready-signal-fd &lt;fd&gt;</arg>
+ <arg choice="opt">--parent-watch-fd &lt;fd&gt;</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
- <para>This tool is part of the
+ <para>This program is part of the
<citerefentry><refentrytitle>samba</refentrytitle>
<manvolnum>7</manvolnum></citerefentry> suite.</para>
- <para>samba-bgqd is an helper program to be spawned by smbd or
- spoolssd to perform jobs like updating the printer list or
- other management tasks asynchronously on demand. It is not
- intended to be called by users or administrators.</para>
+ <para><command>samba-bgqd</command> is not intended to be invoked
+ directly by users.</para>
+
+ <para>Likewise, while <command>samba-bgqd</command> is also not
+ intended to be run manually by system administrators, on systems with a
+ large number of printers configured via CUPS, it is recommended to run
+ <command>samba-bgqd</command> as a systemd service to improve
+ performance and responsiveness of printing operations.</para>
</refsect1>
+<refsect1>
+ <title>SEE ALSO</title>
+
+ <para>
+ <citerefentry><refentrytitle>smbd</refentrytitle>
+ <manvolnum>8</manvolnum></citerefentry>, and
+ <citerefentry><refentrytitle>smb.conf</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry>.
+ </para>
+</refsect1>
<refsect1>
<title>AUTHOR</title>
--
2.53.0
From 058dd1db3914b7e9ca7dff5b8d1e3727fe236ef0 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Thu, 23 Oct 2025 10:49:31 +0200
Subject: [PATCH 34/38] s3:printing: Load the shares for [printers] in
samba-bgqd
One of the main functions of bgqd is:
delete_and_reload_printers_full()
It isn't able to do its work, if we don't load the shares. Normally bgqd was
forked from smbd and this loaded the shares. But with the introduction of
samba-dcerpcd it is a standalone service now. As a standalone service it is
responsible to load the shares if it needs to work on them.
The following message is printed if delete_and_reload_printers_full() tries to
do its job:
[2025/10/23 09:57:27, 7, pid=41935, effective(0, 0), real(0, 0)] ../../source3/param/loadparm.c:4419(lp_servicenumber)
lp_servicenumber: couldn't find printers
[2025/10/23 09:57:27, 7, pid=41935, effective(0, 0), real(0, 0)] ../../source3/param/loadparm.c:4419(lp_servicenumber)
lp_servicenumber: couldn't find printers
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15936
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Anoop C S <anoopcs@samba.org>
(cherry picked from commit 327e60adf2e1e0c040bd32c748fbabc9e4a3593b)
---
source3/printing/queue_process.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/source3/printing/queue_process.c b/source3/printing/queue_process.c
index 0f95bd736f2..51eafa31572 100644
--- a/source3/printing/queue_process.c
+++ b/source3/printing/queue_process.c
@@ -265,6 +265,7 @@ static void bq_smb_conf_updated(struct messaging_context *msg_ctx,
DEBUG(10,("smb_conf_updated: Got message saying smb.conf was "
"updated. Reloading.\n"));
change_to_root_user();
+ lp_load_with_shares(get_dyn_CONFIGFILE());
pcap_cache_reload(state->ev, msg_ctx, reload_pcap_change_notify);
printing_subsystem_queue_tasks(state);
}
@@ -322,6 +323,8 @@ struct bq_state *register_printing_bq_handlers(
goto fail_free_handlers;
}
+ /* Load shares, needed for [printers] */
+ lp_load_with_shares(get_dyn_CONFIGFILE());
/* Initialize the printcap cache as soon as the daemon starts. */
pcap_cache_reload(state->ev, state->msg, reload_pcap_change_notify);
--
2.53.0
From 6f78c96595c9f19dbaecd671ce5dc6582158e64d Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power@suse.com>
Date: Fri, 13 Feb 2026 11:54:46 +0000
Subject: [PATCH 35/38] selftest: Update tests to use
--use-kereros=desired|required no creds
Add tests to call smbclient without passing credentials to
demonstrate failure with --use-kereros=desired
Also add knownfail
Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit a22af9420965083b99b956477d1833000b7f2414)
---
selftest/knownfail | 2 ++
source3/script/tests/test_smbclient_kerberos.sh | 12 ++++++++++++
2 files changed, 14 insertions(+)
diff --git a/selftest/knownfail b/selftest/knownfail
index ab2d79d7114..f0a5f7bb935 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -315,6 +315,8 @@
# ad_member don't support ntlmv1 (not even over SMB1)
^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.member.creds.*as.user.*ad_member
^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.*mNT1.member.creds.*as.user.*ad_member
+# regression smbclient using --use-kerberos=desired https://bugzilla.samba.org/show_bug.cgi?id=15789
+samba3.blackbox.smbclient.kerberos.smbclient.smb3.kerberos.desired \(no user/pass\).*
#nt-vfs server blocks read with execute access
^samba4.smb2.read.access
#ntvfs server blocks copychunk with execute access on read handle
diff --git a/source3/script/tests/test_smbclient_kerberos.sh b/source3/script/tests/test_smbclient_kerberos.sh
index 31678d17e28..1139efd70d7 100755
--- a/source3/script/tests/test_smbclient_kerberos.sh
+++ b/source3/script/tests/test_smbclient_kerberos.sh
@@ -73,6 +73,18 @@ test_smbclient "smbclient.smb3.kerberos.desired[//${SERVER}/tmp]" \
--use-kerberos=desired -U${USERNAME}%${PASSWORD} -mSMB3 ||
failed=$(expr $failed + 1)
+test_smbclient "smbclient.smb3.kerberos.desired (no user/pass) [//${SERVER}/tmp]" \
+ "ls; quit" //${SERVER}/tmp \
+ --use-kerberos=desired -mSMB3 ||
+ failed=$(expr $failed + 1)
+
+test_smbclient "smbclient.smb3.kerberos.required (no user/pass) [//${SERVER}/tmp]" \
+ "ls; quit" //${SERVER}/tmp \
+ --use-kerberos=required -mSMB3 ||
+ failed=$(expr $failed + 1)
+
+
+
$samba_kdestroy
rm -rf $KRB5CCNAME_PATH
--
2.53.0
From 27542cd8ed5c0efbfd3f4fe4b399668c931fdcc4 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power@suse.com>
Date: Mon, 19 Jan 2026 15:46:59 +0000
Subject: [PATCH 36/38] auth/credentials: Fix regression with
--use-kerberos=desired for smbclient
As part of the gse_krb5 processing the following call chain
gensec_gse_client_start()
---> gensec_kerberos_possible()
---> cli_credentials_authentication_requested()
gensec_kerberos_possible() will always fail when
cli_credentials_get_kerberos_state() returns CRED_USE_KERBEROS_DESIRED
It seems since use kerberos == desired is the default that it isn't
necessary to see if credentials were modified to indicated authentication
was requested. gensec_kerberos_possible() should afaics return true
if kerberos is desired OR required (regardless of whether credentials
were requested)
This commit removes the knownfail associated with this bug.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=15789
Signed-off-by: <noel.power@suse.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 88f42eb222f299189d5f5f8204ae353e63a50970)
---
auth/gensec/gensec_util.c | 5 -----
selftest/knownfail | 2 --
2 files changed, 7 deletions(-)
diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
index 0c7688d33d2..af6d198d48f 100644
--- a/auth/gensec/gensec_util.c
+++ b/auth/gensec/gensec_util.c
@@ -362,7 +362,6 @@ char *gensec_get_unparsed_target_principal(struct gensec_security *gensec_securi
NTSTATUS gensec_kerberos_possible(struct gensec_security *gensec_security)
{
struct cli_credentials *creds = gensec_get_credentials(gensec_security);
- bool auth_requested = cli_credentials_authentication_requested(creds);
enum credentials_use_kerberos krb5_state =
cli_credentials_get_kerberos_state(creds);
char *user_principal = NULL;
@@ -370,10 +369,6 @@ NTSTATUS gensec_kerberos_possible(struct gensec_security *gensec_security)
const char *target_principal = gensec_get_target_principal(gensec_security);
const char *hostname = gensec_get_target_hostname(gensec_security);
- if (!auth_requested) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
if (krb5_state == CRED_USE_KERBEROS_DISABLED) {
return NT_STATUS_INVALID_PARAMETER;
}
diff --git a/selftest/knownfail b/selftest/knownfail
index f0a5f7bb935..ab2d79d7114 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -315,8 +315,6 @@
# ad_member don't support ntlmv1 (not even over SMB1)
^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.member.creds.*as.user.*ad_member
^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.*mNT1.member.creds.*as.user.*ad_member
-# regression smbclient using --use-kerberos=desired https://bugzilla.samba.org/show_bug.cgi?id=15789
-samba3.blackbox.smbclient.kerberos.smbclient.smb3.kerberos.desired \(no user/pass\).*
#nt-vfs server blocks read with execute access
^samba4.smb2.read.access
#ntvfs server blocks copychunk with execute access on read handle
--
2.53.0
From 5d396529406d8bd48ab396d7640303ac762c3ed8 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power@suse.com>
Date: Mon, 19 Jan 2026 16:10:10 +0000
Subject: [PATCH 37/38] s3/libsmb: cli_session_creds_init fails when kerberos
is desired
There is a regression with code using cli_session_creds_init when
cli_credentials_get_kerberos_state() returns CRED_USE_KERBEROS_DESIRED
Authentication succeeds when boolean fallback_after_kerberos is false
and fails when true.
There doesn't seem to be a good reason why the value of
fallback_after_kerberos should initialise the krb5 ccache or not.
It would seems that krb5 cache should be setup for creds
for *any* kerberos auth (whether fallback is enabled or not)
Partial patch from <will69@gmx.de> (see bug referenced below)
Bug: https://bugzilla.samba.org/show_bug.cgi?id=15789
Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 1c48599105736499d18aa1f647bce9e1f8dbdcca)
---
source3/libsmb/cliconnect.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index bd75393ac07..da751f54f00 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -215,7 +215,7 @@ struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
goto fail;
}
}
- } else if (use_kerberos && !fallback_after_kerberos) {
+ } else if (use_kerberos) {
const char *error_string = NULL;
int rc;
--
2.53.0
From c9f258277da8089deb16b251aa42e7877039a3c3 Mon Sep 17 00:00:00 2001
From: Noel Power <noel.power@suse.com>
Date: Mon, 19 Jan 2026 16:18:02 +0000
Subject: [PATCH 38/38] s3/libsmb: block anon authentication fallback is
use-kerberos = desired
When cli_credentials_get_kerberos_state returns CRED_USE_KERBEROS_REQUIRED
libsmbclient method SMBC_server_internal will still try to fallback to
anon NTLM. This patch prevents that.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=15789
Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Noel Power <npower@samba.org>
Autobuild-Date(master): Tue Feb 17 16:06:18 UTC 2026 on atb-devel-224
(cherry picked from commit bc868800276fe09cbcb206ebe4cb4da32af7599f)
---
source3/libsmb/libsmb_server.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index 8808781d410..a0d9c47e431 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -607,6 +607,8 @@ SMBC_server_internal(TALLOC_CTX *ctx,
password_used = "";
if (smbc_getOptionNoAutoAnonymousLogin(context) ||
+ cli_credentials_get_kerberos_state(creds) ==
+ CRED_USE_KERBEROS_REQUIRED ||
!NT_STATUS_IS_OK(cli_session_setup_anon(c))) {
cli_shutdown(c);
--
2.53.0