s3: VFS: Change SMB_VFS_SYS_ACL_BLOB_GET_FILE to use const struct smb_filename *...
[kai/samba-autobuild/.git] / source3 / modules / vfs_acl_common.c
index d7caa24a301b65707f0ac341fced5035cac608cd..bd1d755c91fc582a635bb13425bb12719a0f41c0 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (C) Volker Lendecke, 2008
  * Copyright (C) Jeremy Allison, 2009
+ * Copyright (C) Ralph Böhme, 2016
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -46,8 +47,16 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
                                SECINFO_DACL | \
                                SECINFO_SACL)
 
+enum default_acl_style {DEFAULT_ACL_POSIX, DEFAULT_ACL_WINDOWS};
+
+static const struct enum_list default_acl_style[] = {
+       {DEFAULT_ACL_POSIX,     "posix"},
+       {DEFAULT_ACL_WINDOWS,   "windows"}
+};
+
 struct acl_common_config {
        bool ignore_system_acls;
+       enum default_acl_style default_acl_style;
 };
 
 static bool init_acl_common_config(vfs_handle_struct *handle)
@@ -65,6 +74,11 @@ static bool init_acl_common_config(vfs_handle_struct *handle)
                                                  ACL_MODULE_NAME,
                                                  "ignore system acls",
                                                  false);
+       config->default_acl_style = lp_parm_enum(SNUM(handle->conn),
+                                                ACL_MODULE_NAME,
+                                                "default acl style",
+                                                default_acl_style,
+                                                DEFAULT_ACL_POSIX);
 
        SMB_VFS_HANDLE_SET_DATA(handle, config, NULL,
                                struct acl_common_config,
@@ -131,8 +145,8 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
                        (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
-                       ndr_errstr(ndr_err)));
+               DBG_INFO("ndr_pull_xattr_NTACL failed: %s\n",
+                        ndr_errstr(ndr_err));
                TALLOC_FREE(frame);
                return ndr_map_error2ntstatus(ndr_err);
        }
@@ -228,8 +242,8 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
                        (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
-                       ndr_errstr(ndr_err)));
+               DBG_INFO("ndr_push_xattr_NTACL failed: %s\n",
+                        ndr_errstr(ndr_err));
                return ndr_map_error2ntstatus(ndr_err);
        }
 
@@ -274,8 +288,8 @@ static NTSTATUS create_sys_acl_blob(const struct security_descriptor *psd,
                        (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
-                       ndr_errstr(ndr_err)));
+               DBG_INFO("ndr_push_xattr_NTACL failed: %s\n",
+                        ndr_errstr(ndr_err));
                return ndr_map_error2ntstatus(ndr_err);
        }
 
@@ -332,10 +346,7 @@ static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
 
        mode = dir_mode | file_mode;
 
-       DEBUG(10, ("add_directory_inheritable_components: directory %s, "
-               "mode = 0%o\n",
-               name,
-               (unsigned int)mode ));
+       DBG_DEBUG("directory %s, mode = 0%o\n", name, (unsigned int)mode);
 
        if (num_aces) {
                memcpy(new_ace_list, psd->dacl->aces,
@@ -387,10 +398,10 @@ static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
-                                           const char *name,
-                                           SMB_STRUCT_STAT *psbuf,
-                                           struct security_descriptor **ppdesc)
+static NTSTATUS make_default_acl_posix(TALLOC_CTX *ctx,
+                                      const char *name,
+                                      SMB_STRUCT_STAT *psbuf,
+                                      struct security_descriptor **ppdesc)
 {
        struct dom_sid owner_sid, group_sid;
        size_t size = 0;
@@ -400,8 +411,7 @@ static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
        struct security_acl *new_dacl = NULL;
        int idx = 0;
 
-       DEBUG(10,("make_default_filesystem_acl: file %s mode = 0%o\n",
-               name, (int)mode ));
+       DBG_DEBUG("file %s mode = 0%o\n",name, (int)mode);
 
        uid_to_sid(&owner_sid, psbuf->st_ex_uid);
        gid_to_sid(&group_sid, psbuf->st_ex_gid);
@@ -495,6 +505,105 @@ static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx,
+                                        const char *name,
+                                        SMB_STRUCT_STAT *psbuf,
+                                        struct security_descriptor **ppdesc)
+{
+       struct dom_sid owner_sid, group_sid;
+       size_t size = 0;
+       struct security_ace aces[4];
+       uint32_t access_mask = 0;
+       mode_t mode = psbuf->st_ex_mode;
+       struct security_acl *new_dacl = NULL;
+       int idx = 0;
+
+       DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode);
+
+       uid_to_sid(&owner_sid, psbuf->st_ex_uid);
+       gid_to_sid(&group_sid, psbuf->st_ex_gid);
+
+       /*
+        * We provide 2 ACEs:
+        * - Owner
+        * - NT System
+        */
+
+       if (mode & S_IRUSR) {
+               if (mode & S_IWUSR) {
+                       access_mask |= SEC_RIGHTS_FILE_ALL;
+               } else {
+                       access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+               }
+       }
+       if (mode & S_IWUSR) {
+               access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
+       }
+
+       init_sec_ace(&aces[idx],
+                    &owner_sid,
+                    SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    access_mask,
+                    0);
+       idx++;
+
+       init_sec_ace(&aces[idx],
+                    &global_sid_System,
+                    SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    SEC_RIGHTS_FILE_ALL,
+                    0);
+       idx++;
+
+       new_dacl = make_sec_acl(ctx,
+                               NT4_ACL_REVISION,
+                               idx,
+                               aces);
+
+       if (!new_dacl) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *ppdesc = make_sec_desc(ctx,
+                               SECURITY_DESCRIPTOR_REVISION_1,
+                               SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
+                               &owner_sid,
+                               &group_sid,
+                               NULL,
+                               new_dacl,
+                               &size);
+       if (!*ppdesc) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
+                                           struct acl_common_config *config,
+                                           const char *name,
+                                           SMB_STRUCT_STAT *psbuf,
+                                           struct security_descriptor **ppdesc)
+{
+       NTSTATUS status;
+
+       switch (config->default_acl_style) {
+
+       case DEFAULT_ACL_POSIX:
+               status =  make_default_acl_posix(ctx, name, psbuf, ppdesc);
+               break;
+
+       case DEFAULT_ACL_WINDOWS:
+               status =  make_default_acl_windows(ctx, name, psbuf, ppdesc);
+               break;
+
+       default:
+               DBG_ERR("unknown acl style %d", config->default_acl_style);
+               status = NT_STATUS_INTERNAL_ERROR;
+               break;
+       }
+
+       return status;
+}
+
 /**
  * Validate an ACL blob
  *
@@ -602,7 +711,7 @@ static NTSTATUS validate_nt_acl_blob(TALLOC_CTX *mem_ctx,
                } else {
                        /* Get the full underlying sd, then hash. */
                        ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle,
-                                                smb_fname->base_name,
+                                                smb_fname,
                                                 mem_ctx,
                                                 &sys_acl_blob_description,
                                                 &sys_acl_blob);
@@ -769,7 +878,7 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
                smb_fname = smb_fname_in;
        }
 
-       DEBUG(10, ("get_nt_acl_internal: name=%s\n", smb_fname->base_name));
+       DBG_DEBUG("name=%s\n", smb_fname->base_name);
 
        status = get_acl_blob(mem_ctx, handle, fsp, smb_fname, &blob);
        if (NT_STATUS_IS_OK(status)) {
@@ -805,6 +914,7 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
 
                        status = make_default_filesystem_acl(
                                mem_ctx,
+                               config,
                                smb_fname->base_name,
                                psbuf,
                                &psd);
@@ -892,8 +1002,8 @@ static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
        }
 
        if (DEBUGLEVEL >= 10) {
-               DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
-                       smb_fname->base_name ));
+               DBG_DEBUG("returning acl for %s is:\n",
+                         smb_fname->base_name);
                NDR_PRINT_DEBUG(security_descriptor, psd);
        }
 
@@ -960,9 +1070,8 @@ static NTSTATUS set_underlying_acl(vfs_handle_struct *handle, files_struct *fsp,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       DEBUG(10, ("fset_nt_acl_common: overriding chown on file %s "
-                  "for sid %s\n",
-                  fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid)));
+       DBG_DEBUG("overriding chown on file %s for sid %s\n",
+                  fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid));
 
        /* Ok, we failed to chown and we have
           SEC_STD_WRITE_OWNER access - override. */
@@ -985,27 +1094,25 @@ static NTSTATUS store_v3_blob(vfs_handle_struct *handle, files_struct *fsp,
        DATA_BLOB blob;
 
        if (DEBUGLEVEL >= 10) {
-               DEBUG(10, ("fset_nt_acl_xattr: storing xattr sd for file %s\n",
-                          fsp_str_dbg(fsp)));
+               DBG_DEBUG("storing xattr sd for file %s\n",
+                         fsp_str_dbg(fsp));
                NDR_PRINT_DEBUG(
                    security_descriptor,
                    discard_const_p(struct security_descriptor, psd));
 
                if (pdesc_next != NULL) {
-                       DEBUG(10, ("fset_nt_acl_xattr: storing has in xattr sd "
-                                  "based on \n"));
+                       DBG_DEBUG("storing xattr sd based on \n");
                        NDR_PRINT_DEBUG(
                            security_descriptor,
                            discard_const_p(struct security_descriptor,
                                            pdesc_next));
                } else {
-                       DEBUG(10,
-                             ("fset_nt_acl_xattr: ignoring underlying sd\n"));
+                       DBG_DEBUG("ignoring underlying sd\n");
                }
        }
        status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("fset_nt_acl_xattr: create_acl_blob failed\n"));
+               DBG_DEBUG("create_acl_blob failed\n");
                return status;
        }
 
@@ -1034,8 +1141,7 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
            SNUM(handle->conn), ACL_MODULE_NAME, "ignore system acls", false);
 
        if (DEBUGLEVEL >= 10) {
-               DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
-                         fsp_str_dbg(fsp)));
+               DBG_DEBUG("incoming sd for file %s\n", fsp_str_dbg(fsp));
                NDR_PRINT_DEBUG(security_descriptor,
                        discard_const_p(struct security_descriptor, orig_psd));
        }
@@ -1153,12 +1259,12 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
        }
 
        if (DEBUGLEVEL >= 10) {
-               DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s based on system ACL\n",
-                         fsp_str_dbg(fsp)));
+               DBG_DEBUG("storing xattr sd for file %s based on system ACL\n",
+                         fsp_str_dbg(fsp));
                NDR_PRINT_DEBUG(security_descriptor,
                                discard_const_p(struct security_descriptor, psd));
 
-               DEBUG(10,("fset_nt_acl_xattr: storing hash in xattr sd based on system ACL and:\n"));
+               DBG_DEBUG("storing hash in xattr sd based on system ACL and:\n");
                NDR_PRINT_DEBUG(security_descriptor,
                                discard_const_p(struct security_descriptor, pdesc_next));
        }
@@ -1170,7 +1276,7 @@ static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
        status = create_sys_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash, 
                                     sys_acl_description, sys_acl_hash);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("fset_nt_acl_xattr: create_sys_acl_blob failed\n"));
+               DBG_DEBUG("create_sys_acl_blob failed\n");
                TALLOC_FREE(frame);
                return status;
        }
@@ -1207,9 +1313,8 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
                goto out;
        }
 
-       DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
-               is_directory ? "directory" : "file",
-               parent_dir, final_component ));
+       DBG_DEBUG("removing %s %s/%s\n", is_directory ? "directory" : "file",
+                 parent_dir, final_component);
 
        /* cd into the parent dir to pin it. */
        ret = vfs_ChDir(conn, parent_dir);
@@ -1242,10 +1347,9 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
        }
 
        if (!fsp) {
-               DEBUG(10,("acl_common_remove_object: %s %s/%s "
-                       "not an open file\n",
-                       is_directory ? "directory" : "file",
-                       parent_dir, final_component ));
+               DBG_DEBUG("%s %s/%s not an open file\n",
+                         is_directory ? "directory" : "file",
+                         parent_dir, final_component);
                saved_errno = EACCES;
                goto out;
        }
@@ -1293,9 +1397,9 @@ static int rmdir_acl_common(struct vfs_handle_struct *handle,
                                                true);
        }
 
-       DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
-               smb_fname->base_name,
-               strerror(errno) ));
+       DBG_DEBUG("unlink of %s failed %s\n",
+                 smb_fname->base_name,
+                 strerror(errno));
        return -1;
 }
 
@@ -1322,9 +1426,9 @@ static int unlink_acl_common(struct vfs_handle_struct *handle,
                                        false);
        }
 
-       DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
-               smb_fname->base_name,
-               strerror(errno) ));
+       DBG_DEBUG("unlink of %s failed %s\n",
+                 smb_fname->base_name,
+                 strerror(errno));
        return -1;
 }