smbd: add an option to inherit only the UNIX owner
authorUri Simchoni <uri@samba.org>
Tue, 2 Aug 2016 06:37:00 +0000 (09:37 +0300)
committerUri Simchoni <uri@samba.org>
Wed, 10 Aug 2016 06:18:17 +0000 (08:18 +0200)
This can be used to emulate folder quotas, as explained in the
modified manpage.

Signed-off-by: Uri Simchoni <uri@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
docs-xml/smbdotconf/security/inheritowner.xml
lib/param/loadparm.h
lib/param/param_table.c
source3/smbd/open.c
source3/smbd/posix_acls.c

index ab7da57ed59a4baba8f6fa168e63f57658b71d8e..2a7a4b8b61de076b31fa35774dbaefcec1086e85 100644 (file)
@@ -1,6 +1,7 @@
 <samba:parameter name="inherit owner"
                  context="S"
-                 type="boolean"
+                 type="enum"
+                enumlist="enum_inherit_owner_vals"
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
        <para>The ownership of new files and directories 
@@ -8,11 +9,47 @@
        This option allows the Samba administrator to specify that
        the ownership for new files and directories should be controlled
        by the ownership of the parent directory.</para>
-       
+
+       <para>Valid options are:</para>
+       <itemizedlist>
+       <listitem><para><constant>no</constant> -
+       Both the Windows (SID) owner and the UNIX (uid) owner of the file are
+       governed by the identity of the user that created the file.
+       </para></listitem>
+
+       <listitem><para><constant>windows and unix</constant> -
+       The Windows (SID) owner and the UNIX (uid) owner of new files and
+       directories are set to the respective owner of the parent directory.
+       </para></listitem>
+
+       <listitem><para><constant>yes</constant> - a synonym for
+       <constant>windows and unix</constant>.
+       </para></listitem>
+
+       <listitem><para><constant>unix only</constant> -
+       Only the UNIX owner is set to the UNIX owner of the parent directory.
+       </para></listitem>
+       </itemizedlist>
+
        <para>Common scenarios where this behavior is useful is in 
        implementing drop-boxes, where users can create and edit files but
        not delete them and ensuring that newly created files in a user's
        roaming profile directory are actually owned by the user.</para>
+
+       <para>The <constant>unix only</constant> option effectively
+       breaks the tie between the Windows owner of a file and the
+       UNIX owner. As a logical consequence, in this mode,
+       setting the the Windows owner of a file does not modify the UNIX
+       owner. Using this mode should typically be combined with a
+       backing store that can emulate the full NT ACL model without
+       affecting the POSIX permissions, such as the acl_xattr
+       VFS module, coupled with
+       <smbconfoption name="acl_xattr:ignore system acls">yes</smbconfoption>.
+       This can be used to emulate folder quotas, when files are
+       exposed only via SMB (without UNIX extensions).
+       The UNIX owner of a directory is locally set
+       and inherited by all subdirectories and files, and they all
+       consume the same quota.</para>
 </description>
 
 <related>inherit permissions</related>
index d8f69753ad4f4d4879b3b578747845b52bcfb61b..f9fb7d8d804f9d08f8e1ee3b2b6e67e660bfaf32 100644 (file)
@@ -229,6 +229,13 @@ enum mapreadonly_options {MAP_READONLY_NO, MAP_READONLY_YES, MAP_READONLY_PERMIS
 /* case handling */
 enum case_handling {CASE_LOWER,CASE_UPPER};
 
+/* inherit owner options */
+enum inheritowner_options {
+       INHERIT_OWNER_NO,
+       INHERIT_OWNER_WINDOWS_AND_UNIX,
+       INHERIT_OWNER_UNIX_ONLY
+};
+
 /*
  * Default passwd chat script.
  */
index c8520d29c5575638edbd6e9b9850e739fe68e58c..4b5234a7c9e484cbb2a2e30b698e013a100cb55b 100644 (file)
@@ -308,6 +308,12 @@ static const struct enum_list enum_case[] = {
        {-1, NULL}
 };
 
+static const struct enum_list enum_inherit_owner_vals[] = {
+    {INHERIT_OWNER_NO, "no"},
+    {INHERIT_OWNER_WINDOWS_AND_UNIX, "windows and unix"},
+    {INHERIT_OWNER_WINDOWS_AND_UNIX, "yes"},
+    {INHERIT_OWNER_UNIX_ONLY, "unix only"},
+    {-1, NULL}};
 
 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
  *
index 2ae6f835bbcde2fd52efd2754616f9cdf389aaf2..d5360767efd3e26b0af5cde05906ce8394fc028c 100644 (file)
@@ -930,7 +930,7 @@ static NTSTATUS open_file(files_struct *fsp,
                        }
 
                        /* Change the owner if required. */
-                       if (lp_inherit_owner(SNUM(conn))) {
+                       if (lp_inherit_owner(SNUM(conn)) != INHERIT_OWNER_NO) {
                                change_file_owner_to_parent(conn, parent_dir,
                                                            fsp);
                                need_re_stat = true;
@@ -3375,7 +3375,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
        }
 
        /* Change the owner if required. */
-       if (lp_inherit_owner(SNUM(conn))) {
+       if (lp_inherit_owner(SNUM(conn)) != INHERIT_OWNER_NO) {
                change_dir_owner_to_parent(conn, parent_dir,
                                           smb_dname->base_name,
                                           &smb_dname->st);
@@ -4017,7 +4017,8 @@ static NTSTATUS inherit_new_acl(files_struct *fsp)
        const struct dom_sid *group_sid = NULL;
        uint32_t security_info_sent = (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL);
        struct security_token *token = fsp->conn->session_info->security_token;
-       bool inherit_owner = lp_inherit_owner(SNUM(fsp->conn));
+       bool inherit_owner =
+           (lp_inherit_owner(SNUM(fsp->conn)) == INHERIT_OWNER_WINDOWS_AND_UNIX);
        bool inheritable_components = false;
        bool try_builtin_administrators = false;
        const struct dom_sid *BA_U_sid = NULL;
index c57556836587c3554dce5044c4d209412d2cfee3..e8e819c7eeb8f7565a0fd8463bdfa603f9d1ad62 100644 (file)
@@ -3754,6 +3754,14 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32_t security_info_sent, const struct
                security_info_sent &= ~SECINFO_GROUP;
        }
 
+       /* If UNIX owner is inherited and Windows isn't, then
+        * setting the UNIX owner based on Windows owner conflicts
+        * with the inheritance rule
+        */
+       if (lp_inherit_owner(SNUM(conn)) == INHERIT_OWNER_UNIX_ONLY) {
+               security_info_sent &= ~SECINFO_OWNER;
+       }
+
        status = unpack_nt_owners( conn, &user, &grp, security_info_sent, psd);
        if (!NT_STATUS_IS_OK(status)) {
                return status;