vfs_zfsacl: fix issue with ACL inheritance in zfsacl
authorawalker <awalker@ixsystems.com>
Fri, 30 Aug 2019 19:30:57 +0000 (15:30 -0400)
committerJeremy Allison <jra@samba.org>
Fri, 20 Dec 2019 23:24:54 +0000 (23:24 +0000)
Add parameter zfsacl:map_dacl_protected to address issue preventing Windows Clients
from disabling inheritance on ACLs. FreeBSD does not currently expose the ACL_PROTECTED
NFS4.1 flag, but it does expose ACE4_INHERITED_ACE. When the parameter is enabled,
map the absence of ACE4_INHERITED_ACE to SEC_DESC_DACL_PROTECTED.

See also the discussion at

https://gitlab.com/samba-team/samba/merge_requests/719

Signed-off-by: Andrew Walker <awalker@ixsystems.com>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Fri Dec 20 23:24:54 UTC 2019 on sn-devel-184

docs-xml/manpages/vfs_zfsacl.8.xml
source3/modules/vfs_zfsacl.c

index 3eb0760dcba5cfd6c27fc3e555aa7fa553913c1d..ae583409fe1f4e51eb4af7ef900f8135f72a3b38 100644 (file)
                </listitem>
                </varlistentry>
 
+               <varlistentry>
+               <term>zfsacl:map_dacl_protected = [yes|no]</term>
+               <listitem>
+               <para>If enabled and the ZFS ACL on the underlying filesystem does not contain
+               any inherited access control entires, then set the SEC_DESC_DACL_PROTECTED flag
+               on the Security Descriptor returned to SMB clients.
+               This ensures correct Windows client behavior when disabling inheritance on
+               directories.</para>
+
+               <para>Following is the behaviour of Samba for different values : </para>
+               <itemizedlist>
+               <listitem><para><command>yes</command> - Enable mapping to
+               SEC_DESC_DACL_PROTECTED</para></listitem>
+               <listitem><para><command>no (default)</command></para></listitem>
+               </itemizedlist>
+               </listitem>
+               </varlistentry>
+
+
        </variablelist>
 </refsect1>
 
index 2fc1714dc86c85baa224ea5e126591853e1ca0a9..524881ab4af0d7d21ab74609ac90d4788050654d 100644 (file)
@@ -38,6 +38,7 @@
 
 struct zfsacl_config_data {
        struct smbacl4_vfs_params nfs4_params;
+       bool zfsacl_map_dacl_protected;
        bool zfsacl_denymissingspecial;
 };
 
@@ -57,6 +58,7 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
        SMB_STRUCT_STAT sbuf;
        const SMB_STRUCT_STAT *psbuf = NULL;
        int ret;
+       bool inherited_is_present = false;
        bool is_dir;
 
        if (VALID_STAT(smb_fname->st)) {
@@ -123,6 +125,11 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
                        aceprop.aceMask |= SMB_ACE4_DELETE_CHILD;
                }
 
+#ifdef ACE_INHERITED_ACE
+               if (aceprop.aceFlags & ACE_INHERITED_ACE) {
+                       inherited_is_present = true;
+               }
+#endif
                if(aceprop.aceFlags & ACE_OWNER) {
                        aceprop.flags = SMB_ACE4_ID_SPECIAL;
                        aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
@@ -139,6 +146,15 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
                        return NT_STATUS_NO_MEMORY;
        }
 
+#ifdef ACE_INHERITED_ACE
+       if (!inherited_is_present && config->zfsacl_map_dacl_protected) {
+               DBG_DEBUG("Setting SEC_DESC_DACL_PROTECTED on [%s]\n",
+                         smb_fname_str_dbg(smb_fname));
+               smbacl4_set_controlflags(pacl,
+                                        SEC_DESC_DACL_PROTECTED |
+                                        SEC_DESC_SELF_RELATIVE);
+       }
+#endif
        *ppacl = pacl;
        return NT_STATUS_OK;
 }
@@ -443,6 +459,9 @@ static int zfsacl_connect(struct vfs_handle_struct *handle,
                return -1;
        }
 
+       config->zfsacl_map_dacl_protected = lp_parm_bool(SNUM(handle->conn),
+                               "zfsacl", "map_dacl_protected", false);
+
        config->zfsacl_denymissingspecial = lp_parm_bool(SNUM(handle->conn),
                                "zfsacl", "denymissingspecial", false);