Line data Source code
1 : /*
2 : * VFS module to disallow writes for older files
3 : *
4 : * Copyright (C) 2013, Volker Lendecke
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "smbd/smbd.h"
22 : #include "system/filesys.h"
23 : #include "libcli/security/security.h"
24 :
25 : struct worm_config_data {
26 : double grace_period;
27 : };
28 :
29 0 : static int vfs_worm_connect(struct vfs_handle_struct *handle,
30 : const char *service, const char *user)
31 : {
32 0 : struct worm_config_data *config = NULL;
33 : int ret;
34 :
35 0 : ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
36 0 : if (ret < 0) {
37 0 : return ret;
38 : }
39 :
40 0 : if (IS_IPC(handle->conn) || IS_PRINT(handle->conn)) {
41 0 : return 0;
42 : }
43 :
44 0 : config = talloc_zero(handle->conn, struct worm_config_data);
45 0 : if (config == NULL) {
46 0 : DBG_ERR("talloc_zero() failed\n");
47 0 : errno = ENOMEM;
48 0 : return -1;
49 : }
50 0 : config->grace_period = lp_parm_int(SNUM(handle->conn), "worm",
51 : "grace_period", 3600);
52 :
53 0 : SMB_VFS_HANDLE_SET_DATA(handle, config,
54 : NULL, struct worm_config_data,
55 : return -1);
56 0 : return 0;
57 :
58 : }
59 :
60 0 : static NTSTATUS vfs_worm_create_file(vfs_handle_struct *handle,
61 : struct smb_request *req,
62 : struct files_struct *dirfsp,
63 : struct smb_filename *smb_fname,
64 : uint32_t access_mask,
65 : uint32_t share_access,
66 : uint32_t create_disposition,
67 : uint32_t create_options,
68 : uint32_t file_attributes,
69 : uint32_t oplock_request,
70 : const struct smb2_lease *lease,
71 : uint64_t allocation_size,
72 : uint32_t private_flags,
73 : struct security_descriptor *sd,
74 : struct ea_list *ea_list,
75 : files_struct **result,
76 : int *pinfo,
77 : const struct smb2_create_blobs *in_context_blobs,
78 : struct smb2_create_blobs *out_context_blobs)
79 : {
80 0 : bool readonly = false;
81 0 : const uint32_t write_access_flags =
82 : FILE_WRITE_DATA | FILE_APPEND_DATA |
83 : FILE_WRITE_ATTRIBUTES | DELETE_ACCESS |
84 : WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS;
85 : NTSTATUS status;
86 0 : struct worm_config_data *config = NULL;
87 :
88 0 : SMB_VFS_HANDLE_GET_DATA(handle, config,
89 : struct worm_config_data,
90 : return NT_STATUS_INTERNAL_ERROR);
91 :
92 0 : if (VALID_STAT(smb_fname->st)) {
93 : double age;
94 0 : age = timespec_elapsed(&smb_fname->st.st_ex_ctime);
95 0 : if (age > config->grace_period) {
96 0 : readonly = true;
97 : }
98 : }
99 :
100 0 : if (readonly && (access_mask & write_access_flags)) {
101 0 : return NT_STATUS_ACCESS_DENIED;
102 : }
103 :
104 0 : status = SMB_VFS_NEXT_CREATE_FILE(
105 : handle, req, dirfsp, smb_fname, access_mask,
106 : share_access, create_disposition, create_options,
107 : file_attributes, oplock_request, lease, allocation_size,
108 : private_flags, sd, ea_list, result, pinfo,
109 : in_context_blobs, out_context_blobs);
110 0 : if (!NT_STATUS_IS_OK(status)) {
111 0 : return status;
112 : }
113 :
114 : /*
115 : * Access via MAXIMUM_ALLOWED_ACCESS?
116 : */
117 0 : if (readonly && ((*result)->access_mask & write_access_flags)) {
118 0 : close_file_free(req, result, NORMAL_CLOSE);
119 0 : return NT_STATUS_ACCESS_DENIED;
120 : }
121 0 : return NT_STATUS_OK;
122 : }
123 :
124 : static struct vfs_fn_pointers vfs_worm_fns = {
125 : .connect_fn = vfs_worm_connect,
126 : .create_file_fn = vfs_worm_create_file,
127 : };
128 :
129 : static_decl_vfs;
130 27 : NTSTATUS vfs_worm_init(TALLOC_CTX *ctx)
131 : {
132 : NTSTATUS ret;
133 :
134 27 : ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "worm",
135 : &vfs_worm_fns);
136 27 : if (!NT_STATUS_IS_OK(ret)) {
137 0 : return ret;
138 : }
139 :
140 27 : return ret;
141 : }
|