vfs_worm: add some more vfs functions that worm needs to take care of
authorBjörn Jacke <bjacke@samba.org>
Thu, 4 Jan 2024 11:48:59 +0000 (12:48 +0100)
committerVolker Lendecke <vl@samba.org>
Tue, 16 Jan 2024 14:37:31 +0000 (14:37 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=10430

Signed-off-by: Bjoern Jacke <bjacke@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/modules/vfs_worm.c

index 0d17bbbc814cc9f215d98fedf396c2abf7041e9f..4abb25d12e8d319ad322b1d577d7d53e1ec1d4a3 100644 (file)
@@ -82,6 +82,29 @@ static bool is_readonly(vfs_handle_struct *handle,
                return true;
        }
 
+out:
+       return false;
+}
+static bool fsp_is_readonly(vfs_handle_struct *handle, files_struct *fsp)
+{
+       double age;
+       struct worm_config_data *config = NULL;
+
+       SMB_VFS_HANDLE_GET_DATA(handle,
+                               config,
+                               struct worm_config_data,
+                               return true);
+
+       if (!VALID_STAT(fsp->fsp_name->st)) {
+               goto out;
+       }
+
+       age = timespec_elapsed(&fsp->fsp_name->st.st_ex_ctime);
+
+       if (age > config->grace_period) {
+               return true;
+       }
+
 out:
        return false;
 }
@@ -135,9 +158,189 @@ static NTSTATUS vfs_worm_create_file(vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
+static int vfs_worm_openat(vfs_handle_struct *handle,
+                          const struct files_struct *dirfsp,
+                          const struct smb_filename *smb_fname,
+                          files_struct *fsp,
+                          const struct vfs_open_how *how)
+{
+       if (is_readonly(handle, smb_fname) &&
+           (fsp->access_mask & write_access_flags)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, how);
+}
+
+static int vfs_worm_fntimes(vfs_handle_struct *handle,
+                           files_struct *fsp,
+                           struct smb_file_time *ft)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
+}
+
+static int vfs_worm_fchmod(vfs_handle_struct *handle,
+                          files_struct *fsp,
+                          mode_t mode)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
+}
+
+static int vfs_worm_fchown(vfs_handle_struct *handle,
+                          files_struct *fsp,
+                          uid_t uid,
+                          gid_t gid)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
+}
+
+static int vfs_worm_renameat(vfs_handle_struct *handle,
+                            files_struct *srcfsp,
+                            const struct smb_filename *smb_fname_src,
+                            files_struct *dstfsp,
+                            const struct smb_filename *smb_fname_dst)
+{
+       if (is_readonly(handle, smb_fname_src)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_RENAMEAT(
+               handle, srcfsp, smb_fname_src, dstfsp, smb_fname_dst);
+}
+
+static int vfs_worm_fsetxattr(struct vfs_handle_struct *handle,
+                             struct files_struct *fsp,
+                             const char *name,
+                             const void *value,
+                             size_t size,
+                             int flags)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, size, flags);
+}
+
+static int vfs_worm_fremotexattr(struct vfs_handle_struct *handle,
+                                struct files_struct *fsp,
+                                const char *name)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
+}
+
+static int vfs_worm_unlinkat(vfs_handle_struct *handle,
+                            struct files_struct *dirfsp,
+                            const struct smb_filename *smb_fname,
+                            int flags)
+{
+       struct smb_filename *full_fname = NULL;
+       bool readonly;
+
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                 dirfsp,
+                                                 smb_fname);
+       if (full_fname == NULL) {
+               return -1;
+       }
+
+       readonly = is_readonly(handle, full_fname);
+
+       TALLOC_FREE(full_fname);
+
+       if (readonly) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_UNLINKAT(handle, dirfsp, smb_fname, flags);
+}
+
+static NTSTATUS vfs_worm_fset_dos_attributes(struct vfs_handle_struct *handle,
+                                            struct files_struct *fsp,
+                                            uint32_t dosmode)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, dosmode);
+}
+
+static NTSTATUS vfs_worm_fset_nt_acl(vfs_handle_struct *handle,
+                                    files_struct *fsp,
+                                    uint32_t security_info_sent,
+                                    const struct security_descriptor *psd)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
+}
+
+static int vfs_worm_sys_acl_set_fd(vfs_handle_struct *handle,
+                                  struct files_struct *fsp,
+                                  SMB_ACL_TYPE_T type,
+                                  SMB_ACL_T theacl)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, type, theacl);
+}
+
+static int vfs_worm_sys_acl_delete_def_fd(vfs_handle_struct *handle,
+                                         struct files_struct *fsp)
+{
+       if (fsp_is_readonly(handle, fsp)) {
+               errno = EACCES;
+               return -1;
+       }
+
+       return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FD(handle, fsp);
+}
+
 static struct vfs_fn_pointers vfs_worm_fns = {
        .connect_fn = vfs_worm_connect,
        .create_file_fn = vfs_worm_create_file,
+       .openat_fn = vfs_worm_openat,
+       .fntimes_fn = vfs_worm_fntimes,
+       .fchmod_fn = vfs_worm_fchmod,
+       .fchown_fn = vfs_worm_fchown,
+       .renameat_fn = vfs_worm_renameat,
+       .fsetxattr_fn = vfs_worm_fsetxattr,
+       .fremovexattr_fn = vfs_worm_fremotexattr,
+       .unlinkat_fn = vfs_worm_unlinkat,
+       .fset_dos_attributes_fn = vfs_worm_fset_dos_attributes,
+       .fset_nt_acl_fn = vfs_worm_fset_nt_acl,
+       .sys_acl_set_fd_fn = vfs_worm_sys_acl_set_fd,
+       .sys_acl_delete_def_fd_fn = vfs_worm_sys_acl_delete_def_fd,
 };
 
 static_decl_vfs;