Line data Source code
1 : /*
2 : * Fake ACLs VFS module. Implements passthrough operation of all VFS
3 : * calls to disk functions, except for file ownership and ACLs, which
4 : * are stored in xattrs.
5 : *
6 : * Copyright (C) Tim Potter, 1999-2000
7 : * Copyright (C) Alexander Bokovoy, 2002
8 : * Copyright (C) Andrew Bartlett, 2002,2012
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "smbd/smbd.h"
26 : #include "system/filesys.h"
27 : #include "auth.h"
28 : #include "librpc/gen_ndr/ndr_smb_acl.h"
29 :
30 : #undef DBGC_CLASS
31 : #define DBGC_CLASS DBGC_VFS
32 :
33 : #define FAKE_UID "system.fake_uid"
34 : #define FAKE_GID "system.fake_gid"
35 : #define FAKE_ACL_ACCESS_XATTR "system.fake_access_acl"
36 : #define FAKE_ACL_DEFAULT_XATTR "system.fake_default_acl"
37 :
38 : struct in_pathref_data {
39 : bool calling_pathref_fsp;
40 : };
41 :
42 22317646 : static int fake_acls_fuid(vfs_handle_struct *handle,
43 : files_struct *fsp,
44 : uid_t *uid)
45 : {
46 : ssize_t size;
47 : uint8_t uid_buf[4];
48 :
49 22317646 : size = SMB_VFS_NEXT_FGETXATTR(handle, fsp, FAKE_UID, uid_buf, sizeof(uid_buf));
50 22317646 : if (size == -1 && errno == ENOATTR) {
51 10412198 : return 0;
52 : }
53 11815867 : if (size != 4) {
54 0 : return -1;
55 : }
56 11815867 : *uid = IVAL(uid_buf, 0);
57 11739782 : return 0;
58 : }
59 :
60 22317646 : static int fake_acls_fgid(vfs_handle_struct *handle,
61 : files_struct *fsp,
62 : uid_t *gid)
63 : {
64 : ssize_t size;
65 : uint8_t gid_buf[4];
66 :
67 22317646 : size = SMB_VFS_NEXT_FGETXATTR(handle, fsp, FAKE_GID, gid_buf, sizeof(gid_buf));
68 22317646 : if (size == -1 && errno == ENOATTR) {
69 10412251 : return 0;
70 : }
71 11815814 : if (size != 4) {
72 0 : return -1;
73 : }
74 11815814 : *gid = IVAL(gid_buf, 0);
75 11739729 : return 0;
76 : }
77 :
78 28280907 : static int fake_acls_stat(vfs_handle_struct *handle,
79 : struct smb_filename *smb_fname)
80 : {
81 28280907 : int ret = -1;
82 28280907 : struct in_pathref_data *prd = NULL;
83 :
84 28280907 : SMB_VFS_HANDLE_GET_DATA(handle,
85 : prd,
86 : struct in_pathref_data,
87 : return -1);
88 :
89 28280907 : ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
90 28280907 : if (ret == 0) {
91 27525400 : struct smb_filename *smb_fname_cp = NULL;
92 27525400 : struct files_struct *fsp = NULL;
93 :
94 27525400 : if (smb_fname->fsp != NULL) {
95 27147 : fsp = smb_fname->fsp;
96 27147 : if (fsp->base_fsp != NULL) {
97 : /*
98 : * This is a stream pathname. Use
99 : * the base_fsp to get the xattr.
100 : */
101 52 : fsp = fsp->base_fsp;
102 : }
103 : } else {
104 : NTSTATUS status;
105 :
106 : /*
107 : * Ensure openat_pathref_fsp()
108 : * can't recurse into fake_acls_stat().
109 : * openat_pathref_fsp() doesn't care
110 : * about the uid/gid values, it only
111 : * wants a valid/invalid stat answer
112 : * and we know smb_fname exists as
113 : * the SMB_VFS_NEXT_STAT() returned
114 : * zero above.
115 : */
116 27498253 : if (prd->calling_pathref_fsp) {
117 34745136 : return 0;
118 : }
119 :
120 : /*
121 : * openat_pathref_fsp() expects a talloc'ed
122 : * smb_filename. stat can be passed a struct
123 : * from the stack. Make a talloc'ed copy
124 : * so openat_pathref_fsp() can add its
125 : * destructor.
126 : */
127 8269542 : smb_fname_cp = cp_smb_filename(talloc_tos(),
128 : smb_fname);
129 8269542 : if (smb_fname_cp == NULL) {
130 0 : errno = ENOMEM;
131 0 : return -1;
132 : }
133 :
134 : /* Recursion guard. */
135 8269542 : prd->calling_pathref_fsp = true;
136 8269542 : status = openat_pathref_fsp(handle->conn->cwd_fsp,
137 : smb_fname_cp);
138 : /* End recursion guard. */
139 8269542 : prd->calling_pathref_fsp = false;
140 :
141 8269542 : if (!NT_STATUS_IS_OK(status)) {
142 : /*
143 : * Ignore errors here. We know
144 : * the path exists (the SMB_VFS_NEXT_STAT()
145 : * above succeeded. So being unable to
146 : * open a pathref fsp can be due to a
147 : * range of errors (startup path beginning
148 : * with '/' for example, path = ".." when
149 : * enumerating a directory. Just treat this
150 : * the same way as the path not having the
151 : * FAKE_UID or FAKE_GID EA's present. For the
152 : * test purposes of this module (fake NT ACLs
153 : * from windows clients) this is close enough.
154 : * Just report for debugging purposes.
155 : */
156 59721 : DBG_DEBUG("Unable to get pathref fsp on %s. "
157 : "Error %s\n",
158 : smb_fname_str_dbg(smb_fname_cp),
159 : nt_errstr(status));
160 59721 : TALLOC_FREE(smb_fname_cp);
161 59721 : return 0;
162 : }
163 8209821 : fsp = smb_fname_cp->fsp;
164 : }
165 :
166 8236968 : ret = fake_acls_fuid(handle,
167 : fsp,
168 : &smb_fname->st.st_ex_uid);
169 8236968 : if (ret != 0) {
170 0 : TALLOC_FREE(smb_fname_cp);
171 0 : return ret;
172 : }
173 8236968 : ret = fake_acls_fgid(handle,
174 : fsp,
175 8236968 : &smb_fname->st.st_ex_gid);
176 8236968 : if (ret != 0) {
177 0 : TALLOC_FREE(smb_fname_cp);
178 0 : return ret;
179 : }
180 8236968 : TALLOC_FREE(smb_fname_cp);
181 : }
182 :
183 8917262 : return ret;
184 : }
185 :
186 21099 : static int fake_acls_lstat(vfs_handle_struct *handle,
187 : struct smb_filename *smb_fname)
188 : {
189 21099 : int ret = -1;
190 21099 : struct in_pathref_data *prd = NULL;
191 :
192 21099 : SMB_VFS_HANDLE_GET_DATA(handle,
193 : prd,
194 : struct in_pathref_data,
195 : return -1);
196 :
197 21099 : ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
198 21099 : if (ret == 0) {
199 20921 : struct smb_filename *smb_fname_base = NULL;
200 20921 : SMB_STRUCT_STAT sbuf = { 0 };
201 : NTSTATUS status;
202 :
203 : /*
204 : * Ensure synthetic_pathref()
205 : * can't recurse into fake_acls_lstat().
206 : * synthetic_pathref() doesn't care
207 : * about the uid/gid values, it only
208 : * wants a valid/invalid stat answer
209 : * and we know smb_fname exists as
210 : * the SMB_VFS_NEXT_LSTAT() returned
211 : * zero above.
212 : */
213 20921 : if (prd->calling_pathref_fsp) {
214 0 : return 0;
215 : }
216 :
217 : /* Recursion guard. */
218 20921 : prd->calling_pathref_fsp = true;
219 37851 : status = synthetic_pathref(talloc_tos(),
220 20921 : handle->conn->cwd_fsp,
221 20921 : smb_fname->base_name,
222 : NULL,
223 : &sbuf,
224 : smb_fname->twrp,
225 : 0, /* we want stat, not lstat. */
226 : &smb_fname_base);
227 : /* End recursion guard. */
228 20921 : prd->calling_pathref_fsp = false;
229 20921 : if (NT_STATUS_IS_OK(status)) {
230 : /*
231 : * This isn't quite right (calling fgetxattr not
232 : * lgetxattr), but for the test purposes of this
233 : * module (fake NT ACLs from windows clients), it is
234 : * close enough. We removed the l*xattr functions
235 : * because linux doesn't support using them, but we
236 : * could fake them in xattr_tdb if we really wanted
237 : * to. We ignore errors because the link might not
238 : * point anywhere */
239 37731 : fake_acls_fuid(handle,
240 20861 : smb_fname_base->fsp,
241 : &smb_fname->st.st_ex_uid);
242 20861 : fake_acls_fgid(handle,
243 20861 : smb_fname_base->fsp,
244 20861 : &smb_fname->st.st_ex_gid);
245 : }
246 20921 : TALLOC_FREE(smb_fname_base);
247 : }
248 :
249 20942 : return ret;
250 : }
251 :
252 14059817 : static int fake_acls_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
253 : {
254 14059817 : int ret = -1;
255 :
256 14059817 : ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
257 14059817 : if (ret == 0) {
258 14059817 : ret = fake_acls_fuid(handle, fsp, &sbuf->st_ex_uid);
259 14059817 : if (ret != 0) {
260 0 : return ret;
261 : }
262 14059817 : ret = fake_acls_fgid(handle, fsp, &sbuf->st_ex_gid);
263 14059817 : if (ret != 0) {
264 0 : return ret;
265 : }
266 : }
267 13967839 : return ret;
268 : }
269 :
270 1380704 : static SMB_ACL_T fake_acls_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
271 : {
272 : enum ndr_err_code ndr_err;
273 1380704 : struct smb_acl_t *acl = talloc(mem_ctx, struct smb_acl_t);
274 1380704 : if (!acl) {
275 0 : errno = ENOMEM;
276 0 : return NULL;
277 : }
278 :
279 1380704 : ndr_err = ndr_pull_struct_blob(blob, acl, acl,
280 : (ndr_pull_flags_fn_t)ndr_pull_smb_acl_t);
281 :
282 1380704 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
283 24 : DEBUG(0, ("ndr_pull_acl_t failed: %s\n",
284 : ndr_errstr(ndr_err)));
285 24 : TALLOC_FREE(acl);
286 24 : return NULL;
287 : }
288 1378172 : return acl;
289 : }
290 :
291 161199 : static DATA_BLOB fake_acls_acl2blob(TALLOC_CTX *mem_ctx, SMB_ACL_T acl)
292 : {
293 : enum ndr_err_code ndr_err;
294 : DATA_BLOB blob;
295 161199 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
296 : (ndr_push_flags_fn_t)ndr_push_smb_acl_t);
297 :
298 161199 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
299 0 : DEBUG(0, ("ndr_push_acl_t failed: %s\n",
300 : ndr_errstr(ndr_err)));
301 0 : return data_blob_null;
302 : }
303 161199 : return blob;
304 : }
305 :
306 1750407 : static SMB_ACL_T fake_acls_sys_acl_get_fd(struct vfs_handle_struct *handle,
307 : files_struct *fsp,
308 : SMB_ACL_TYPE_T type,
309 : TALLOC_CTX *mem_ctx)
310 : {
311 1750407 : DATA_BLOB blob = data_blob_null;
312 : ssize_t length;
313 1750407 : const char *name = NULL;
314 1750407 : struct smb_acl_t *acl = NULL;
315 1750407 : TALLOC_CTX *frame = talloc_stackframe();
316 :
317 1750407 : switch (type) {
318 1240758 : case SMB_ACL_TYPE_ACCESS:
319 1240758 : name = FAKE_ACL_ACCESS_XATTR;
320 1240758 : break;
321 507063 : case SMB_ACL_TYPE_DEFAULT:
322 507063 : name = FAKE_ACL_DEFAULT_XATTR;
323 507063 : break;
324 0 : default:
325 0 : DBG_ERR("Illegal ACL type %d\n", (int)type);
326 0 : break;
327 : }
328 :
329 1746470 : if (name == NULL) {
330 0 : TALLOC_FREE(frame);
331 0 : return NULL;
332 : }
333 :
334 : do {
335 1750407 : blob.length += 1000;
336 1750407 : blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
337 1750407 : if (!blob.data) {
338 0 : errno = ENOMEM;
339 0 : TALLOC_FREE(frame);
340 0 : return NULL;
341 : }
342 1750407 : length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, blob.data, blob.length);
343 1750407 : blob.length = length;
344 1750407 : } while (length == -1 && errno == ERANGE);
345 1750407 : if (length == -1 && errno == ENOATTR) {
346 369703 : TALLOC_FREE(frame);
347 368274 : return NULL;
348 : }
349 1380704 : if (length != -1) {
350 1380704 : acl = fake_acls_blob2acl(&blob, mem_ctx);
351 : }
352 1380704 : TALLOC_FREE(frame);
353 1378196 : return acl;
354 : }
355 :
356 161199 : static int fake_acls_sys_acl_set_fd(vfs_handle_struct *handle,
357 : struct files_struct *fsp,
358 : SMB_ACL_TYPE_T type,
359 : SMB_ACL_T theacl)
360 : {
361 : int ret;
362 161199 : const char *name = NULL;
363 161199 : TALLOC_CTX *frame = talloc_stackframe();
364 161199 : DATA_BLOB blob = fake_acls_acl2blob(frame, theacl);
365 161199 : if (!blob.data) {
366 0 : DEBUG(0, ("Failed to convert ACL to linear blob for xattr storage\n"));
367 0 : TALLOC_FREE(frame);
368 0 : errno = EINVAL;
369 0 : return -1;
370 : }
371 :
372 161199 : switch (type) {
373 148922 : case SMB_ACL_TYPE_ACCESS:
374 148922 : name = FAKE_ACL_ACCESS_XATTR;
375 148922 : break;
376 11950 : case SMB_ACL_TYPE_DEFAULT:
377 11950 : name = FAKE_ACL_DEFAULT_XATTR;
378 11950 : break;
379 0 : default:
380 0 : errno = EINVAL;
381 0 : return -1;
382 : }
383 :
384 161199 : ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, blob.data, blob.length, 0);
385 161199 : TALLOC_FREE(frame);
386 160722 : return ret;
387 : }
388 :
389 321 : static int fake_acls_sys_acl_delete_def_fd(vfs_handle_struct *handle,
390 : struct files_struct *fsp)
391 : {
392 : int ret;
393 321 : const char *name = FAKE_ACL_DEFAULT_XATTR;
394 :
395 321 : if (!fsp->fsp_flags.is_directory) {
396 0 : errno = EINVAL;
397 0 : return -1;
398 : }
399 :
400 321 : ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
401 321 : if (ret == -1 && errno == ENOATTR) {
402 207 : ret = 0;
403 207 : errno = 0;
404 : }
405 :
406 321 : return ret;
407 : }
408 :
409 0 : static int fake_acls_lchown(vfs_handle_struct *handle,
410 : const struct smb_filename *smb_fname,
411 : uid_t uid,
412 : gid_t gid)
413 : {
414 : int ret;
415 : uint8_t id_buf[4];
416 0 : if (uid != -1) {
417 0 : uid_t current_uid = get_current_uid(handle->conn);
418 :
419 0 : if (current_uid != 0 && current_uid != uid) {
420 0 : return EACCES;
421 : }
422 :
423 : /* This isn't quite right (calling setxattr not
424 : * lsetxattr), but for the test purposes of this
425 : * module (fake NT ACLs from windows clients), it is
426 : * close enough. We removed the l*xattr functions
427 : * because linux doesn't support using them, but we
428 : * could fake them in xattr_tdb if we really wanted
429 : * to.
430 : */
431 0 : SIVAL(id_buf, 0, uid);
432 0 : ret = SMB_VFS_NEXT_FSETXATTR(handle,
433 : smb_fname->fsp,
434 : FAKE_UID,
435 : id_buf,
436 : sizeof(id_buf),
437 : 0);
438 0 : if (ret != 0) {
439 0 : return ret;
440 : }
441 : }
442 0 : if (gid != -1) {
443 0 : SIVAL(id_buf, 0, gid);
444 0 : ret = SMB_VFS_NEXT_FSETXATTR(handle,
445 : smb_fname->fsp,
446 : FAKE_GID,
447 : id_buf,
448 : sizeof(id_buf),
449 : 0);
450 0 : if (ret != 0) {
451 0 : return ret;
452 : }
453 : }
454 0 : return 0;
455 : }
456 :
457 200191 : static int fake_acls_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
458 : {
459 : int ret;
460 : uint8_t id_buf[4];
461 200191 : if (uid != -1) {
462 200175 : uid_t current_uid = get_current_uid(handle->conn);
463 :
464 200175 : if (current_uid != 0 && current_uid != uid) {
465 56137 : return EACCES;
466 : }
467 :
468 143821 : SIVAL(id_buf, 0, uid);
469 143821 : ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, FAKE_UID, id_buf, sizeof(id_buf), 0);
470 143821 : if (ret != 0) {
471 0 : return ret;
472 : }
473 : }
474 143837 : if (gid != -1) {
475 142725 : SIVAL(id_buf, 0, gid);
476 142725 : ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, FAKE_GID, id_buf, sizeof(id_buf), 0);
477 142725 : if (ret != 0) {
478 0 : return ret;
479 : }
480 : }
481 143515 : return 0;
482 : }
483 :
484 : /*
485 : * Implement the chmod uid/mask/other mode changes on a fake ACL.
486 : */
487 :
488 8 : static int fake_acl_process_chmod(SMB_ACL_T *pp_the_acl,
489 : uid_t owner,
490 : mode_t mode)
491 : {
492 8 : bool got_mask = false;
493 8 : int entry_id = SMB_ACL_FIRST_ENTRY;
494 8 : mode_t umode = 0;
495 8 : mode_t mmode = 0;
496 8 : mode_t omode = 0;
497 8 : int ret = -1;
498 8 : SMB_ACL_T the_acl = *pp_the_acl;
499 :
500 : /* Split the mode into u/mask/other masks. */
501 8 : umode = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR);
502 8 : mmode = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP);
503 8 : omode = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH);
504 :
505 48 : while (1) {
506 : SMB_ACL_ENTRY_T entry;
507 : SMB_ACL_TAG_T tagtype;
508 : SMB_ACL_PERMSET_T permset;
509 56 : uid_t *puid = NULL;
510 :
511 56 : ret = sys_acl_get_entry(the_acl,
512 : entry_id,
513 : &entry);
514 56 : if (ret == 0) {
515 : /* End of ACL */
516 8 : break;
517 : }
518 48 : if (ret == -1) {
519 0 : return -1;
520 : }
521 :
522 48 : ret = sys_acl_get_tag_type(entry, &tagtype);
523 48 : if (ret == -1) {
524 0 : return -1;
525 : }
526 48 : ret = sys_acl_get_permset(entry, &permset);
527 48 : if (ret == -1) {
528 0 : return -1;
529 : }
530 48 : switch (tagtype) {
531 8 : case SMB_ACL_USER_OBJ:
532 8 : ret = map_acl_perms_to_permset(umode, &permset);
533 8 : if (ret == -1) {
534 0 : return -1;
535 : }
536 8 : break;
537 8 : case SMB_ACL_USER:
538 8 : puid = (uid_t *)sys_acl_get_qualifier(entry);
539 8 : if (puid == NULL) {
540 0 : return -1;
541 : }
542 8 : if (owner != *puid) {
543 0 : break;
544 : }
545 8 : ret = map_acl_perms_to_permset(umode, &permset);
546 8 : if (ret == -1) {
547 0 : return -1;
548 : }
549 8 : break;
550 16 : case SMB_ACL_GROUP_OBJ:
551 : case SMB_ACL_GROUP:
552 : /* Ignore all group entries. */
553 16 : break;
554 8 : case SMB_ACL_MASK:
555 8 : ret = map_acl_perms_to_permset(mmode, &permset);
556 8 : if (ret == -1) {
557 0 : return -1;
558 : }
559 8 : got_mask = true;
560 8 : break;
561 8 : case SMB_ACL_OTHER:
562 8 : ret = map_acl_perms_to_permset(omode, &permset);
563 8 : if (ret == -1) {
564 0 : return -1;
565 : }
566 8 : break;
567 0 : default:
568 0 : errno = EINVAL;
569 0 : return -1;
570 : }
571 48 : ret = sys_acl_set_permset(entry, permset);
572 48 : if (ret == -1) {
573 0 : return -1;
574 : }
575 : /* Move to next entry. */
576 48 : entry_id = SMB_ACL_NEXT_ENTRY;
577 : }
578 :
579 : /*
580 : * If we didn't see a mask entry, add one.
581 : */
582 :
583 8 : if (!got_mask) {
584 : SMB_ACL_ENTRY_T mask_entry;
585 : SMB_ACL_PERMSET_T mask_permset;
586 0 : ret = sys_acl_create_entry(&the_acl, &mask_entry);
587 0 : if (ret == -1) {
588 0 : return -1;
589 : }
590 0 : ret = map_acl_perms_to_permset(mmode, &mask_permset);
591 0 : if (ret == -1) {
592 0 : return -1;
593 : }
594 0 : ret = sys_acl_set_permset(mask_entry, mask_permset);
595 0 : if (ret == -1) {
596 0 : return -1;
597 : }
598 0 : ret = sys_acl_set_tag_type(mask_entry, SMB_ACL_MASK);
599 0 : if (ret == -1) {
600 0 : return -1;
601 : }
602 : /* In case we were realloced and moved. */
603 0 : *pp_the_acl = the_acl;
604 : }
605 :
606 8 : return 0;
607 : }
608 :
609 12 : static int fake_acls_fchmod(vfs_handle_struct *handle,
610 : files_struct *fsp,
611 : mode_t mode)
612 : {
613 12 : TALLOC_CTX *frame = talloc_stackframe();
614 12 : int ret = -1;
615 12 : SMB_ACL_T the_acl = NULL;
616 :
617 : /*
618 : * Passthrough first to preserve the
619 : * S_ISUID | S_ISGID | S_ISVTX
620 : * bits.
621 : */
622 :
623 12 : ret = SMB_VFS_NEXT_FCHMOD(handle,
624 : fsp,
625 : mode);
626 12 : if (ret == -1) {
627 0 : TALLOC_FREE(frame);
628 0 : return -1;
629 : }
630 :
631 12 : the_acl = fake_acls_sys_acl_get_fd(handle,
632 : fsp,
633 : SMB_ACL_TYPE_ACCESS,
634 : talloc_tos());
635 12 : if (the_acl == NULL) {
636 4 : TALLOC_FREE(frame);
637 4 : if (errno == ENOATTR) {
638 : /* No ACL on this file. Just passthrough. */
639 4 : return 0;
640 : }
641 0 : return -1;
642 : }
643 8 : ret = fake_acl_process_chmod(&the_acl,
644 8 : fsp->fsp_name->st.st_ex_uid,
645 : mode);
646 8 : if (ret == -1) {
647 0 : TALLOC_FREE(frame);
648 0 : return -1;
649 : }
650 8 : ret = fake_acls_sys_acl_set_fd(handle,
651 : fsp,
652 : SMB_ACL_TYPE_ACCESS,
653 : the_acl);
654 8 : TALLOC_FREE(frame);
655 8 : return ret;
656 : }
657 :
658 42836 : static int fake_acls_connect(struct vfs_handle_struct *handle,
659 : const char *service,
660 : const char *user)
661 : {
662 42836 : struct in_pathref_data *prd = NULL;
663 : int ret;
664 :
665 42836 : ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
666 42836 : if (ret < 0) {
667 0 : return ret;
668 : }
669 : /*
670 : * Create a struct can tell us if we're recursing
671 : * into open_pathref_fsp() in this module. This will
672 : * go away once we have SMB_VFS_STATX() and we will
673 : * have a way for a caller to as for specific stat
674 : * fields in a granular way. Then we will know exactly
675 : * what fields the caller wants, so we won't have to
676 : * fill in everything.
677 : */
678 42836 : prd = talloc_zero(handle->conn, struct in_pathref_data);
679 42836 : if (prd == NULL) {
680 0 : return -1;
681 : }
682 42836 : SMB_VFS_HANDLE_SET_DATA(handle,
683 : prd,
684 : NULL,
685 : struct in_pathref_data,
686 : return -1);
687 42836 : return 0;
688 : }
689 :
690 : static struct vfs_fn_pointers vfs_fake_acls_fns = {
691 : .connect_fn = fake_acls_connect,
692 : .stat_fn = fake_acls_stat,
693 : .lstat_fn = fake_acls_lstat,
694 : .fstat_fn = fake_acls_fstat,
695 : .fchmod_fn = fake_acls_fchmod,
696 : .sys_acl_get_fd_fn = fake_acls_sys_acl_get_fd,
697 : .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
698 : .sys_acl_set_fd_fn = fake_acls_sys_acl_set_fd,
699 : .sys_acl_delete_def_fd_fn = fake_acls_sys_acl_delete_def_fd,
700 : .lchown_fn = fake_acls_lchown,
701 : .fchown_fn = fake_acls_fchown,
702 :
703 : };
704 :
705 : static_decl_vfs;
706 24265 : NTSTATUS vfs_fake_acls_init(TALLOC_CTX *ctx)
707 : {
708 24265 : return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_acls",
709 : &vfs_fake_acls_fns);
710 : }
|