[SCM] Samba Shared Repository - branch v4-20-stable updated
Jule Anger
janger at samba.org
Wed Mar 27 17:13:06 UTC 2024
The branch, v4-20-stable has been updated
via 8fdd82c8b9c VERSION: Disable GIT_SNAPSHOT for the 4.20.0 release.
via 797464b7624 WHATSNEW: Add release notes for Samba 4.20.0.
via 5cedf3b5eb0 Revert "token_util.c: prefer capabilities over become_root"
via f7491b29941 Revert "dosmode.c: prefer use of capabilities at two places over become_root"
via 6ca9461a1db Revert "nfs4_acls.c: prefer capabilities over become_root"
via 52b1d9d7cb8 Revert "vfs_acl_common.c: prefer capabilities over become_root"
via 6e0986b2c30 Revert "vfs_default.c: prefer capabilities over become_root"
via f6d549de47c Revert "vfs_posix_eadb.c: prefer capabilities over become_root"
via d0c295e5344 Revert "vfs_recycle.c: prefer capabilities over become_root"
via 4f38859f5d8 Revert "open.c: prefer capabilities over become_root"
via dc161626303 Revert "posix_acls.c: prefer capabilities over become_root"
via bb68b730290 Revert "dosmode: prefer capabilities over become_root"
via aee05f11670 s3/smbd: If we fail to close file_handle ensure we should reset the fd
via 72f70868257 smbd: simplify handling of failing fstat() after unlinking file
via 3be368ff2bc ndr: always attempt ACE coda pull if ACE type suggests a coda
via 1273cb7e10b tests/krb5: Add tests for AllowedToAuthenticateTo with an AS-REQ
via 28fc1850e5c libcli/security: check again for NULL values
via ce78896e262 libcli/security: claims_conversions: check for NULL in claims array
via 99b6feac932 WHATSNEW: announce Service Witness Protocol [MS-SWN] and related options
via 69b69bb2085 libgpo: Do not segfault if we don't have a valid security descriptor
via 72bd247c97d libgpo: Fix trailing spaces in pygpo.c
via 4d1536f86b9 VERSION: Bump version up to Samba 4.20.0rc5...
from 964c0e97e7a VERSION: Disable GIT_SNAPSHOT for the 4.20.0rc4 release.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-20-stable
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
VERSION | 2 +-
WHATSNEW.txt | 112 +++++++-
libcli/security/claims-conversions.c | 13 +
libgpo/pygpo.c | 7 +-
librpc/ndr/ndr_sec_helper.c | 5 +-
python/samba/tests/krb5/authn_policy_tests.py | 372 ++++++++++++++++++++++++++
selftest/knownfail_mit_kdc | 8 +
source3/auth/token_util.c | 4 +-
source3/modules/nfs4_acls.c | 4 +-
source3/modules/vfs_acl_common.c | 8 +-
source3/modules/vfs_default.c | 4 +-
source3/modules/vfs_posix_eadb.c | 4 +-
source3/modules/vfs_recycle.c | 4 +-
source3/smbd/close.c | 1 +
source3/smbd/dosmode.c | 16 +-
source3/smbd/open.c | 39 +--
source3/smbd/posix_acls.c | 40 +--
17 files changed, 559 insertions(+), 84 deletions(-)
Changeset truncated at 500 lines:
diff --git a/VERSION b/VERSION
index fcee8581107..482360b7d68 100644
--- a/VERSION
+++ b/VERSION
@@ -89,7 +89,7 @@ SAMBA_VERSION_PRE_RELEASE=
# e.g. SAMBA_VERSION_RC_RELEASE=1 #
# -> "3.0.0rc1" #
########################################################
-SAMBA_VERSION_RC_RELEASE=4
+SAMBA_VERSION_RC_RELEASE=
########################################################
# To mark SVN snapshots this should be set to 'yes' #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index dd80f116a10..5c97836d36f 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,16 +1,11 @@
-Release Announcements
-=====================
+ ==============================
+ Release Notes for Samba 4.20.0
+ March 27, 2024
+ ==============================
-This is the fourth release candidate of Samba 4.20. This is *not*
-intended for production environments and is designed for testing
-purposes only. Please report any defects via the Samba bug reporting
-system at https://bugzilla.samba.org/.
-Samba 4.20 will be the next version of the Samba suite.
-
-
-UPGRADING
-=========
+This is the first stable release of the Samba 4.20 release series.
+Please read the release notes carefully before upgrading.
NEW FEATURES/CHANGES
@@ -191,6 +186,68 @@ The Security Descriptor Definition Language has extensions for
conditional ACEs and resource attribute ACEs; these are now supported
by Samba.
+Service Witness Protocol [MS-SWN]
+---------------------------------
+
+In a ctdb cluster it is now possible to provide
+the SMB witness service that allows clients to
+monitor their current smb connection to cluster
+node A by asking cluster node B to notify the
+client if the ip address from node A or the
+whole node A becomes unavailable.
+
+For disk shares in a ctdb cluster
+SMB2_SHARE_CAP_SCALEOUT is now always returned
+for SMB3 tree connect responses.
+
+If the witness service is active
+SMB2_SHARE_CAP_CLUSTER is now also returned.
+
+In order to activate the witness service
+"rpc start on demand helpers = no" needs to
+be configured in the global section.
+At the same time the 'samba-dcerpcd' service
+needs to be started explicitly, typically
+with the '--libexec-rpcds' option in order
+to make all available services usable.
+One important aspect is that tcp ports
+135 (for the endpoint mapper) and various
+ports in the 'rpc server dynamic port range'
+will be used to provide the witness service
+(rpcd_witness).
+
+ctdb provides a '47.samba-dcerpcd.script' in order
+to manage the samba-dcerpcd.service.
+Typically as systemd service, but that's up
+to the packager and/or admin.
+
+Please note that current windows client
+requires SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY
+in addition to SMB2_SHARE_CAP_CLUSTER in order
+to make use of the witness service.
+But SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY implies
+the windows clients always ask for persistent handle
+(which are not implemented in samba yet), so
+that every open generates a warning in the
+windows smb client event log.
+That's why SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY
+is not returned by default.
+An explicit 'smb3 share cap:CONTINUOUS AVAILABILITY = yes'
+is needed.
+
+There are also new 'net witness' commands in order
+to let the admin list active client registrations
+or ask specific clients to move their smb connection
+to another cluster node. These are available:
+
+ net witness list
+ net witness client-move
+ net witness share-move
+ net witness force-unregister
+ net witness force-response
+
+Consult 'man net' or 'net witness help' for further details.
+
REMOVED FEATURES
================
@@ -210,8 +267,39 @@ smb.conf changes
Parameter Name Description Default
-------------- ----------- -------
- smb3 unix extensions Per share -
acl claims evaluation new AD DC only
+ smb3 unix extensions Per share -
+ smb3 share cap:ASYMMETRIC new no
+ smb3 share cap:CLUSTER new see 'man smb.conf'
+ smb3 share cap:CONTINUOUS AVAILABILITY new no
+ smb3 share cap:SCALE OUT new see 'man smb.conf'
+
+
+Changes since 4.20.0rc4
+=======================
+
+o Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
+ * BUG 15606: Avoid null-dereference with bad claims.
+ * BUG 15613: ndr_pull_security_ace can leave resource attribute ACE coda
+ claim struct undefined.
+
+o Ralph Boehme <slow at samba.org>
+ * BUG 15527: fd_handle_destructor() panics within an smbd_smb2_close() if
+ vfs_stat_fsp() fails in fd_close().
+
+o Björn Jacke <bjacke at samba.org>
+ * BUG 15583: set_nt_acl sometimes fails with NT_STATUS_INVALID_PARAMETER -
+ openat() EACCES.
+
+o Noel Power <noel.power at suse.com>
+ * BUG 15527: fd_handle_destructor() panics within an smbd_smb2_close() if
+ vfs_stat_fsp() fails in fd_close().
+
+o Andreas Schneider <asn at samba.org>
+ * BUG 15599: libgpo: Segfault in python bindings.
+
+o Jo Sutton <josutton at catalyst.net.nz>
+ * BUG 15607: Samba AD is missing some authentication policy tests.
CHANGES SINCE 4.20.0rc3
diff --git a/libcli/security/claims-conversions.c b/libcli/security/claims-conversions.c
index bbba5973852..ccf1375fc8f 100644
--- a/libcli/security/claims-conversions.c
+++ b/libcli/security/claims-conversions.c
@@ -262,6 +262,9 @@ static bool claim_v1_offset_to_ace_token(
uint8_t f = claim->flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
result->flags = f | CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR;
+ if (claim->values[offset].int_value == NULL) {
+ return false;
+ }
switch (claim->value_type) {
case CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
return claim_v1_int_to_ace_int(claim, offset, result);
@@ -935,6 +938,16 @@ NTSTATUS claim_v1_check_and_sort(TALLOC_CTX *mem_ctx,
.case_sensitive = case_sensitive
};
+ /*
+ * It could be that the values array contains a NULL pointer, in which
+ * case we don't need to worry about what type it is.
+ */
+ for (i = 0; i < claim->value_count; i++) {
+ if (claim->values[i].int_value == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
if (claim->value_type == CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN) {
NTSTATUS status = claim_v1_check_and_sort_boolean(mem_ctx, claim);
if (NT_STATUS_IS_OK(status)) {
diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c
index adbd5b4688d..0f7116313f2 100644
--- a/libgpo/pygpo.c
+++ b/libgpo/pygpo.c
@@ -116,6 +116,11 @@ static PyObject *GPO_marshall_get_sec_desc_buf(PyObject *self, PyObject *args,
uint8_t *data = NULL;
size_t len = 0;
+ if (gpo_ptr->security_descriptor == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Uninitialized");
+ return NULL;
+ }
+
status = marshall_sec_desc(gpo_ptr, gpo_ptr->security_descriptor,
&data, &len);
if (!NT_STATUS_IS_OK(status)) {
@@ -371,7 +376,7 @@ static int py_ads_init(ADS *self, PyObject *args, PyObject *kwds)
workgroup,
ldap_server,
ADS_SASL_PLAIN);
-
+
return 0;
}
diff --git a/librpc/ndr/ndr_sec_helper.c b/librpc/ndr/ndr_sec_helper.c
index f870a17aafc..1a156b01d40 100644
--- a/librpc/ndr/ndr_sec_helper.c
+++ b/librpc/ndr/ndr_sec_helper.c
@@ -104,7 +104,6 @@ _PUBLIC_ enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, ndr_flags
{
NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
if (ndr_flags & NDR_SCALARS) {
- ssize_t sub_size;
NDR_CHECK(ndr_pull_align(ndr, 5));
NDR_CHECK(ndr_pull_security_ace_type(ndr, NDR_SCALARS, &r->type));
NDR_CHECK(ndr_pull_security_ace_flags(ndr, NDR_SCALARS, &r->flags));
@@ -112,12 +111,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, ndr_flags
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->access_mask));
NDR_CHECK(ndr_maybe_pull_security_ace_object_ctr(ndr, NDR_SCALARS, r));
NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->trustee));
- sub_size = ndr_subcontext_size_of_ace_coda(r, r->size, ndr->flags);
- if (!sec_ace_has_extra_blob(r->type) || sub_size == 0) {
+ if (!sec_ace_has_extra_blob(r->type)) {
r->coda.ignored.data = NULL;
r->coda.ignored.length = 0;
} else {
struct ndr_pull *_ndr_coda;
+ ssize_t sub_size = ndr_subcontext_size_of_ace_coda(r, r->size, ndr->flags);
NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_coda, 0, sub_size));
NDR_CHECK(ndr_pull_set_switch_value(_ndr_coda, &r->coda, r->type));
NDR_CHECK(ndr_pull_security_ace_coda(_ndr_coda, NDR_SCALARS|NDR_BUFFERS, &r->coda));
diff --git a/python/samba/tests/krb5/authn_policy_tests.py b/python/samba/tests/krb5/authn_policy_tests.py
index 2f15f8b2417..43db839cee7 100755
--- a/python/samba/tests/krb5/authn_policy_tests.py
+++ b/python/samba/tests/krb5/authn_policy_tests.py
@@ -295,6 +295,115 @@ class AuthnPolicyBaseTests(AuthLogTestBase, KdcTgsBaseTests):
opts=opts,
use_cache=cached)
+ def _fast_as_req(self,
+ client_creds,
+ target_creds,
+ armor_tgt,
+ expected_error=0,
+ expect_status=None,
+ expected_status=None,
+ expected_groups=None,
+ expect_device_info=None,
+ expected_device_groups=None,
+ expect_device_claims=None,
+ expected_device_claims=None):
+ client_username = client_creds.get_username()
+ client_realm = client_creds.get_realm()
+ client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
+ names=[client_username])
+
+ target_name = target_creds.get_username()
+ target_sname = self.PrincipalName_create(
+ name_type=NT_PRINCIPAL, names=[target_name])
+ target_realm = target_creds.get_realm()
+ target_decryption_key = self.TicketDecryptionKey_from_creds(
+ target_creds)
+ target_etypes = target_creds.tgs_supported_enctypes
+
+ authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
+ armor_key = self.generate_armor_key(authenticator_subkey,
+ armor_tgt.session_key)
+
+ preauth_key = self.PasswordKey_from_creds(client_creds,
+ kcrypto.Enctype.AES256)
+
+ client_challenge_key = (
+ self.generate_client_challenge_key(armor_key, preauth_key))
+ fast_padata = [self.get_challenge_pa_data(client_challenge_key)]
+
+ def _generate_fast_padata(kdc_exchange_dict,
+ _callback_dict,
+ req_body):
+ return list(fast_padata), req_body
+
+ etypes = kcrypto.Enctype.AES256, kcrypto.Enctype.RC4
+
+ if expected_error:
+ check_error_fn = self.generic_check_kdc_error
+ check_rep_fn = None
+ else:
+ check_error_fn = None
+ check_rep_fn = self.generic_check_kdc_rep
+
+ pac_options = '1' # claims support
+
+ samdb = self.get_samdb()
+ domain_sid_str = samdb.get_domain_sid()
+
+ if expected_groups is not None:
+ expected_groups = self.map_sids(expected_groups, None, domain_sid_str)
+
+ if expected_device_groups is not None:
+ expected_device_groups = self.map_sids(expected_device_groups, None, domain_sid_str)
+
+ kdc_exchange_dict = self.as_exchange_dict(
+ creds=client_creds,
+ expected_crealm=client_realm,
+ expected_cname=client_cname,
+ expected_srealm=target_realm,
+ expected_sname=target_sname,
+ expected_supported_etypes=target_etypes,
+ ticket_decryption_key=target_decryption_key,
+ generate_fast_fn=self.generate_simple_fast,
+ generate_fast_armor_fn=self.generate_ap_req,
+ generate_fast_padata_fn=_generate_fast_padata,
+ fast_armor_type=FX_FAST_ARMOR_AP_REQUEST,
+ check_error_fn=check_error_fn,
+ check_rep_fn=check_rep_fn,
+ check_kdc_private_fn=self.generic_check_kdc_private,
+ expected_error_mode=expected_error,
+ expected_salt=client_creds.get_salt(),
+ expect_status=expect_status,
+ expected_status=expected_status,
+ expected_groups=expected_groups,
+ expect_device_info=expect_device_info,
+ expected_device_domain_sid=domain_sid_str,
+ expected_device_groups=expected_device_groups,
+ expect_device_claims=expect_device_claims,
+ expected_device_claims=expected_device_claims,
+ authenticator_subkey=authenticator_subkey,
+ preauth_key=preauth_key,
+ armor_key=armor_key,
+ armor_tgt=armor_tgt,
+ armor_subkey=authenticator_subkey,
+ kdc_options='0',
+ pac_options=pac_options,
+ # PA-DATA types are not important for these tests.
+ check_patypes=False)
+
+ rep = self._generic_kdc_exchange(
+ kdc_exchange_dict,
+ cname=client_cname,
+ realm=client_realm,
+ sname=target_sname,
+ etypes=etypes)
+ if expected_error:
+ self.check_error_rep(rep, expected_error)
+ return None
+ else:
+ self.check_as_reply(rep)
+ return kdc_exchange_dict['rep_ticket_creds']
+
@staticmethod
def audit_type(msg):
return AuditType(msg['type'])
@@ -6532,6 +6641,269 @@ class AuthnPolicyTests(AuthnPolicyBaseTests):
self.check_tgs_log(client_creds, target_creds, policy=policy)
+ def test_authn_policy_allowed_to_computer_allow_as_req(self):
+ # Create a machine account with which to perform FAST.
+ mach_creds = self.get_cached_creds(
+ account_type=self.AccountType.COMPUTER)
+ mach_tgt = self.get_tgt(mach_creds)
+
+ # Create a user account.
+ client_creds = self.get_cached_creds(
+ account_type=self.AccountType.USER)
+
+ # Create an authentication policy that applies to a computer and
+ # explicitly allows the user account to obtain a service ticket.
+ allowed = f'O:SYD:(A;;CR;;;{client_creds.get_sid()})'
+ denied = 'O:SYD:(D;;CR;;;WD)'
+ policy = self.create_authn_policy(enforced=True,
+ user_allowed_to=denied,
+ computer_allowed_to=allowed,
+ service_allowed_to=denied)
+
+ # Create a computer account with the assigned policy.
+ target_creds = self._get_creds(account_type=self.AccountType.COMPUTER,
+ assigned_policy=policy)
+
+ # Show that obtaining a service ticket with an AS-REQ is allowed.
+ self._fast_as_req(client_creds, target_creds, mach_tgt)
+
+ self.check_as_log(client_creds,
+ server_policy=policy)
+
+ def test_authn_policy_allowed_to_computer_deny_as_req(self):
+ # Create a machine account with which to perform FAST.
+ mach_creds = self.get_cached_creds(
+ account_type=self.AccountType.COMPUTER)
+ mach_tgt = self.get_tgt(mach_creds)
+
+ # Create a user account.
+ client_creds = self.get_cached_creds(
+ account_type=self.AccountType.USER)
+
+ # Create an authentication policy that applies to a computer and
+ # explicitly denies the user account to obtain a service ticket.
+ denied = f'O:SYD:(D;;CR;;;{client_creds.get_sid()})'
+ allowed = 'O:SYD:(A;;CR;;;WD)'
+ policy = self.create_authn_policy(enforced=True,
+ user_allowed_to=allowed,
+ computer_allowed_to=denied,
+ service_allowed_to=allowed)
+
+ # Create a computer account with the assigned policy.
+ target_creds = self._get_creds(account_type=self.AccountType.COMPUTER,
+ assigned_policy=policy)
+
+ # Show that obtaining a service ticket with an AS-REQ is denied.
+ self._fast_as_req(
+ client_creds, target_creds, mach_tgt,
+ expected_error=KDC_ERR_POLICY,
+ # We aren’t particular about whether or not we get an NTSTATUS.
+ expect_status=None,
+ expected_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED)
+
+ self.check_as_log(
+ client_creds,
+ server_policy=policy,
+ server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED,
+ event=AuditEvent.KERBEROS_SERVER_RESTRICTION,
+ reason=AuditReason.ACCESS_DENIED,
+ status=ntstatus.NT_STATUS_INVALID_WORKSTATION)
+
+ def test_authn_policy_allowed_to_user_allow_as_req(self):
+ # Create a machine account with which to perform FAST.
+ mach_creds = self.get_cached_creds(
+ account_type=self.AccountType.COMPUTER)
+ mach_tgt = self.get_tgt(mach_creds)
+
+ # Create a user account.
+ client_creds = self.get_cached_creds(
+ account_type=self.AccountType.USER)
+
+ # Create an authentication policy that applies to a user and explicitly
+ # allows the user account to obtain a service ticket.
+ allowed = f'O:SYD:(A;;CR;;;{client_creds.get_sid()})'
+ denied = 'O:SYD:(D;;CR;;;WD)'
+ policy = self.create_authn_policy(enforced=True,
+ user_allowed_to=allowed,
+ computer_allowed_to=denied,
+ service_allowed_to=denied)
+
+ # Create a user account with the assigned policy.
+ target_creds = self._get_creds(account_type=self.AccountType.USER,
+ assigned_policy=policy,
+ spn='host/{account}')
+
+ # Show that obtaining a service ticket with an AS-REQ is allowed.
+ self._fast_as_req(client_creds, target_creds, mach_tgt)
+
+ self.check_as_log(client_creds,
+ server_policy=policy)
+
+ def test_authn_policy_allowed_to_user_deny_as_req(self):
+ # Create a machine account with which to perform FAST.
+ mach_creds = self.get_cached_creds(
+ account_type=self.AccountType.COMPUTER)
+ mach_tgt = self.get_tgt(mach_creds)
+
+ # Create a user account.
+ client_creds = self.get_cached_creds(
+ account_type=self.AccountType.USER)
+
+ # Create an authentication policy that applies to a user and
+ # explicitly denies the user account to obtain a service ticket.
+ denied = f'O:SYD:(D;;CR;;;{client_creds.get_sid()})'
+ allowed = 'O:SYD:(A;;CR;;;WD)'
+ policy = self.create_authn_policy(enforced=True,
+ user_allowed_to=denied,
+ computer_allowed_to=allowed,
+ service_allowed_to=allowed)
+
+ # Create a user account with the assigned policy.
+ target_creds = self._get_creds(account_type=self.AccountType.USER,
+ assigned_policy=policy,
+ spn='host/{account}')
+
+ # Show that obtaining a service ticket with an AS-REQ is denied.
+ self._fast_as_req(
+ client_creds, target_creds, mach_tgt,
+ expected_error=KDC_ERR_POLICY,
+ # We aren’t particular about whether or not we get an NTSTATUS.
+ expect_status=None,
+ expected_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED)
+
+ self.check_as_log(
+ client_creds,
+ server_policy=policy,
+ server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED,
+ event=AuditEvent.KERBEROS_SERVER_RESTRICTION,
+ reason=AuditReason.ACCESS_DENIED,
+ status=ntstatus.NT_STATUS_INVALID_WORKSTATION)
+
+ def test_authn_policy_allowed_to_service_allow_as_req(self):
+ # Create a machine account with which to perform FAST.
+ mach_creds = self.get_cached_creds(
+ account_type=self.AccountType.COMPUTER)
+ mach_tgt = self.get_tgt(mach_creds)
--
Samba Shared Repository
More information about the samba-cvs
mailing list