Line data Source code
1 : /*
2 : * Store Windows ACLs in xattrs.
3 : *
4 : * Copyright (C) Volker Lendecke, 2008
5 : * Copyright (C) Jeremy Allison, 2008
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "smbd/smbd.h"
23 : #include "system/filesys.h"
24 : #include "librpc/gen_ndr/xattr.h"
25 : #include "auth.h"
26 : #include "vfs_acl_common.h"
27 :
28 : /* Pull in the common functions. */
29 : #define ACL_MODULE_NAME "acl_xattr"
30 :
31 : #undef DBGC_CLASS
32 : #define DBGC_CLASS DBGC_VFS
33 :
34 : /*******************************************************************
35 : Pull a security descriptor into a DATA_BLOB from a xattr.
36 : *******************************************************************/
37 :
38 816208 : static ssize_t getxattr_do(vfs_handle_struct *handle,
39 : files_struct *fsp,
40 : const char *xattr_name,
41 : uint8_t *val,
42 : size_t size)
43 : {
44 : ssize_t sizeret;
45 816208 : int saved_errno = 0;
46 :
47 816208 : become_root();
48 816208 : sizeret = SMB_VFS_FGETXATTR(fsp, xattr_name, val, size);
49 816208 : if (sizeret == -1) {
50 188396 : saved_errno = errno;
51 : }
52 816208 : unbecome_root();
53 :
54 815250 : if (saved_errno != 0) {
55 188396 : errno = saved_errno;
56 : }
57 :
58 816208 : return sizeret;
59 : }
60 :
61 816184 : static NTSTATUS fget_acl_blob(TALLOC_CTX *ctx,
62 : vfs_handle_struct *handle,
63 : files_struct *fsp,
64 : DATA_BLOB *pblob)
65 : {
66 816184 : size_t size = 4096;
67 816184 : uint8_t *val = NULL;
68 : uint8_t *tmp;
69 : ssize_t sizeret;
70 :
71 1480829 : ZERO_STRUCTP(pblob);
72 :
73 814539 : again:
74 :
75 816196 : tmp = talloc_realloc(ctx, val, uint8_t, size);
76 816196 : if (tmp == NULL) {
77 0 : TALLOC_FREE(val);
78 0 : return NT_STATUS_NO_MEMORY;
79 : }
80 816196 : val = tmp;
81 :
82 664657 : sizeret =
83 151539 : getxattr_do(handle, fsp, XATTR_NTACL_NAME, val, size);
84 :
85 816196 : if (sizeret >= 0) {
86 627800 : pblob->data = val;
87 627800 : pblob->length = sizeret;
88 627800 : return NT_STATUS_OK;
89 : }
90 :
91 188396 : if (errno != ERANGE) {
92 187697 : goto err;
93 : }
94 :
95 : /* Too small, try again. */
96 12 : sizeret =
97 0 : getxattr_do(handle, fsp, XATTR_NTACL_NAME, NULL, 0);
98 12 : if (sizeret < 0) {
99 0 : goto err;
100 : }
101 :
102 12 : if (size < sizeret) {
103 12 : size = sizeret;
104 : }
105 :
106 12 : if (size > 65536) {
107 : /* Max ACL size is 65536 bytes. */
108 0 : errno = ERANGE;
109 0 : goto err;
110 : }
111 :
112 12 : goto again;
113 189071 : err:
114 : /* Real error - exit here. */
115 188384 : TALLOC_FREE(val);
116 188384 : return map_nt_error_from_unix(errno);
117 : }
118 :
119 : /*******************************************************************
120 : Store a DATA_BLOB into an xattr given an fsp pointer.
121 : *******************************************************************/
122 :
123 151927 : static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
124 : files_struct *fsp,
125 : DATA_BLOB *pblob)
126 : {
127 : int ret;
128 151927 : int saved_errno = 0;
129 :
130 151927 : DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
131 : (unsigned int)pblob->length, fsp_str_dbg(fsp)));
132 :
133 151927 : become_root();
134 151927 : ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
135 : pblob->data, pblob->length, 0);
136 151927 : if (ret) {
137 20 : saved_errno = errno;
138 : }
139 151927 : unbecome_root();
140 151927 : if (ret) {
141 20 : DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s"
142 : "with error %s\n",
143 : fsp_str_dbg(fsp),
144 : strerror(saved_errno) ));
145 20 : errno = saved_errno;
146 20 : return map_nt_error_from_unix(saved_errno);
147 : }
148 151907 : return NT_STATUS_OK;
149 : }
150 :
151 : /*********************************************************************
152 : Remove a Windows ACL - we're setting the underlying POSIX ACL.
153 : *********************************************************************/
154 :
155 162084 : static int sys_acl_set_fd_xattr(vfs_handle_struct *handle,
156 : files_struct *fsp,
157 : SMB_ACL_TYPE_T type,
158 : SMB_ACL_T theacl)
159 : {
160 130412 : struct acl_common_fsp_ext *ext = (struct acl_common_fsp_ext *)
161 31672 : VFS_FETCH_FSP_EXTENSION(handle, fsp);
162 : int ret;
163 :
164 162084 : ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
165 : fsp,
166 : type,
167 : theacl);
168 162084 : if (ret == -1) {
169 0 : return -1;
170 : }
171 :
172 162084 : if (ext != NULL && ext->setting_nt_acl) {
173 161469 : return 0;
174 : }
175 :
176 181 : become_root();
177 181 : SMB_VFS_FREMOVEXATTR(fsp, XATTR_NTACL_NAME);
178 181 : unbecome_root();
179 :
180 181 : return 0;
181 : }
182 :
183 43165 : static int connect_acl_xattr(struct vfs_handle_struct *handle,
184 : const char *service,
185 : const char *user)
186 : {
187 43165 : int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
188 : bool ok;
189 43165 : struct acl_common_config *config = NULL;
190 :
191 43165 : if (ret < 0) {
192 0 : return ret;
193 : }
194 :
195 43165 : ok = init_acl_common_config(handle, ACL_MODULE_NAME);
196 43165 : if (!ok) {
197 0 : DBG_ERR("init_acl_common_config failed\n");
198 0 : return -1;
199 : }
200 :
201 : /* Ensure we have the parameters correct if we're
202 : * using this module. */
203 43165 : DEBUG(2,("connect_acl_xattr: setting 'inherit acls = true' "
204 : "'dos filemode = true' and "
205 : "'force unknown acl user = true' for service %s\n",
206 : service ));
207 :
208 43165 : lp_do_parameter(SNUM(handle->conn), "inherit acls", "true");
209 43165 : lp_do_parameter(SNUM(handle->conn), "dos filemode", "true");
210 43165 : lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true");
211 :
212 43165 : SMB_VFS_HANDLE_GET_DATA(handle, config,
213 : struct acl_common_config,
214 : return -1);
215 :
216 43165 : if (config->ignore_system_acls) {
217 178 : mode_t create_mask = lp_create_mask(SNUM(handle->conn));
218 178 : char *create_mask_str = NULL;
219 :
220 178 : if ((create_mask & 0666) != 0666) {
221 178 : create_mask |= 0666;
222 178 : create_mask_str = talloc_asprintf(handle, "0%o",
223 : create_mask);
224 178 : if (create_mask_str == NULL) {
225 0 : DBG_ERR("talloc_asprintf failed\n");
226 0 : return -1;
227 : }
228 :
229 178 : DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
230 :
231 178 : lp_do_parameter (SNUM(handle->conn),
232 : "create mask", create_mask_str);
233 :
234 178 : TALLOC_FREE(create_mask_str);
235 : }
236 :
237 178 : DBG_NOTICE("setting 'directory mask = 0777', "
238 : "'store dos attributes = yes' and all "
239 : "'map ...' options to 'no'\n");
240 :
241 178 : lp_do_parameter(SNUM(handle->conn), "directory mask", "0777");
242 178 : lp_do_parameter(SNUM(handle->conn), "map archive", "no");
243 178 : lp_do_parameter(SNUM(handle->conn), "map hidden", "no");
244 178 : lp_do_parameter(SNUM(handle->conn), "map readonly", "no");
245 178 : lp_do_parameter(SNUM(handle->conn), "map system", "no");
246 178 : lp_do_parameter(SNUM(handle->conn), "store dos attributes",
247 : "yes");
248 : }
249 :
250 42546 : return 0;
251 : }
252 :
253 142989 : static int acl_xattr_unlinkat(vfs_handle_struct *handle,
254 : struct files_struct *dirfsp,
255 : const struct smb_filename *smb_fname,
256 : int flags)
257 : {
258 : int ret;
259 :
260 142989 : if (flags & AT_REMOVEDIR) {
261 9637 : ret = rmdir_acl_common(handle,
262 : dirfsp,
263 : smb_fname);
264 : } else {
265 133352 : ret = unlink_acl_common(handle,
266 : dirfsp,
267 : smb_fname,
268 : flags);
269 : }
270 142989 : return ret;
271 : }
272 :
273 664255 : static NTSTATUS acl_xattr_fget_nt_acl(vfs_handle_struct *handle,
274 : files_struct *fsp,
275 : uint32_t security_info,
276 : TALLOC_CTX *mem_ctx,
277 : struct security_descriptor **ppdesc)
278 : {
279 : NTSTATUS status;
280 664255 : status = fget_nt_acl_common(fget_acl_blob, handle, fsp,
281 : security_info, mem_ctx, ppdesc);
282 664255 : return status;
283 : }
284 :
285 151929 : static NTSTATUS acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
286 : files_struct *fsp,
287 : uint32_t security_info_sent,
288 : const struct security_descriptor *psd)
289 : {
290 : NTSTATUS status;
291 151929 : status = fset_nt_acl_common(fget_acl_blob, store_acl_blob_fsp,
292 : ACL_MODULE_NAME,
293 : handle, fsp, security_info_sent, psd);
294 151929 : return status;
295 : }
296 :
297 : static struct vfs_fn_pointers vfs_acl_xattr_fns = {
298 : .connect_fn = connect_acl_xattr,
299 : .unlinkat_fn = acl_xattr_unlinkat,
300 : .fchmod_fn = fchmod_acl_module_common,
301 : .fget_nt_acl_fn = acl_xattr_fget_nt_acl,
302 : .fset_nt_acl_fn = acl_xattr_fset_nt_acl,
303 : .sys_acl_set_fd_fn = sys_acl_set_fd_xattr
304 : };
305 :
306 : static_decl_vfs;
307 24554 : NTSTATUS vfs_acl_xattr_init(TALLOC_CTX *ctx)
308 : {
309 24554 : return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_xattr",
310 : &vfs_acl_xattr_fns);
311 : }
|