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