LCOV - code coverage report
Current view: top level - source3/modules - vfs_fake_acls.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 248 335 74.0 %
Date: 2024-02-28 12:06:22 Functions: 16 17 94.1 %

          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    10212968 : 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    10212968 :         size = SMB_VFS_NEXT_FGETXATTR(handle, fsp, FAKE_UID, uid_buf, sizeof(uid_buf));
      50    10212968 :         if (size == -1 && errno == ENOATTR) {
      51     3519688 :                 return 0;
      52             :         }
      53     6680152 :         if (size != 4) {
      54           3 :                 return -1;
      55             :         }
      56     6680149 :         *uid = IVAL(uid_buf, 0);
      57     6680149 :         return 0;
      58             : }
      59             : 
      60    10212965 : 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    10212965 :         size = SMB_VFS_NEXT_FGETXATTR(handle, fsp, FAKE_GID, gid_buf, sizeof(gid_buf));
      68    10212965 :         if (size == -1 && errno == ENOATTR) {
      69     3519796 :                 return 0;
      70             :         }
      71     6680041 :         if (size != 4) {
      72           0 :                 return -1;
      73             :         }
      74     6680041 :         *gid = IVAL(gid_buf, 0);
      75     6680041 :         return 0;
      76             : }
      77             : 
      78     4845370 : static int fake_acls_stat(vfs_handle_struct *handle,
      79             :                            struct smb_filename *smb_fname)
      80             : {
      81     4845370 :         int ret = -1;
      82     4845370 :         struct in_pathref_data *prd = NULL;
      83     4845370 :         struct smb_filename *smb_fname_cp = NULL;
      84     4845370 :         struct files_struct *fsp = NULL;
      85             : 
      86     4845370 :         SMB_VFS_HANDLE_GET_DATA(handle,
      87             :                                 prd,
      88             :                                 struct in_pathref_data,
      89        9318 :                                 return -1);
      90             : 
      91     4845370 :         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
      92     4845370 :         if (ret != 0) {
      93        3557 :                 return ret;
      94             :         }
      95             : 
      96     4841592 :         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     4818131 :                 if (prd->calling_pathref_fsp) {
     112     3170339 :                         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     3048189 :                 smb_fname_cp = cp_smb_filename(talloc_tos(),
     123             :                                                smb_fname);
     124     3048189 :                 if (smb_fname_cp == NULL) {
     125           0 :                         errno = ENOMEM;
     126           0 :                         return -1;
     127             :                 }
     128             : 
     129             :                 /* Recursion guard. */
     130     3048189 :                 prd->calling_pathref_fsp = true;
     131     3048189 :                 status = openat_pathref_fsp(handle->conn->cwd_fsp,
     132             :                                             smb_fname_cp);
     133             :                 /* End recursion guard. */
     134     3048189 :                 prd->calling_pathref_fsp = false;
     135             : 
     136     3048189 :                 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     1400397 :                         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     1400397 :                         TALLOC_FREE(smb_fname_cp);
     156     1400397 :                         return 0;
     157             :                 }
     158     1647792 :                 fsp = smb_fname_cp->fsp;
     159             :         }
     160             : 
     161     1671253 :         ret = fake_acls_fuid(handle,
     162             :                              fsp,
     163             :                              &smb_fname->st.st_ex_uid);
     164     1671253 :         if (ret != 0) {
     165           3 :                 TALLOC_FREE(smb_fname_cp);
     166           3 :                 return ret;
     167             :         }
     168     1674957 :         ret = fake_acls_fgid(handle,
     169             :                              fsp,
     170     1671250 :                              &smb_fname->st.st_ex_gid);
     171     1671250 :         if (ret != 0) {
     172           0 :                 TALLOC_FREE(smb_fname_cp);
     173           0 :                 return ret;
     174             :         }
     175     1671250 :         TALLOC_FREE(smb_fname_cp);
     176     1667543 :         return ret;
     177             : }
     178             : 
     179       10640 : static int fake_acls_lstat(vfs_handle_struct *handle,
     180             :                            struct smb_filename *smb_fname)
     181             : {
     182       10640 :         int ret = -1;
     183       10640 :         struct in_pathref_data *prd = NULL;
     184             : 
     185       10640 :         SMB_VFS_HANDLE_GET_DATA(handle,
     186             :                                 prd,
     187             :                                 struct in_pathref_data,
     188          70 :                                 return -1);
     189             : 
     190       10640 :         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
     191       10640 :         if (ret == 0) {
     192       10630 :                 struct smb_filename *smb_fname_base = NULL;
     193       10630 :                 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       10630 :                 if (prd->calling_pathref_fsp) {
     207           0 :                         return 0;
     208             :                 }
     209             : 
     210             :                 /* Recursion guard. */
     211       10630 :                 prd->calling_pathref_fsp = true;
     212       10630 :                 status = synthetic_pathref(talloc_tos(),
     213       10630 :                                            handle->conn->cwd_fsp,
     214       10630 :                                            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       10630 :                 prd->calling_pathref_fsp = false;
     222       10630 :                 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       10587 :                         fake_acls_fuid(handle,
     233       10587 :                                        smb_fname_base->fsp,
     234             :                                        &smb_fname->st.st_ex_uid);
     235       10587 :                         fake_acls_fgid(handle,
     236       10587 :                                        smb_fname_base->fsp,
     237       10587 :                                        &smb_fname->st.st_ex_gid);
     238             :                 }
     239       10630 :                 TALLOC_FREE(smb_fname_base);
     240             :         }
     241             : 
     242       10570 :         return ret;
     243             : }
     244             : 
     245     8531128 : static int fake_acls_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
     246             : {
     247     8531128 :         int ret = -1;
     248             : 
     249     8531128 :         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
     250     8531128 :         if (ret == 0) {
     251     8531128 :                 ret = fake_acls_fuid(handle, fsp, &sbuf->st_ex_uid);
     252     8531128 :                 if (ret != 0) {
     253           0 :                         return ret;
     254             :                 }
     255     8531128 :                 ret = fake_acls_fgid(handle, fsp, &sbuf->st_ex_gid);
     256     8531128 :                 if (ret != 0) {
     257           0 :                         return ret;
     258             :                 }
     259             :         }
     260     8496928 :         return ret;
     261             : }
     262             : 
     263     1637057 : static SMB_ACL_T fake_acls_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
     264             : {
     265        2965 :         enum ndr_err_code ndr_err;
     266     1637057 :         struct smb_acl_t *acl = talloc(mem_ctx, struct smb_acl_t);
     267     1637057 :         if (!acl) {
     268           0 :                 errno = ENOMEM;
     269           0 :                 return NULL;
     270             :         }
     271             : 
     272     1637057 :         ndr_err = ndr_pull_struct_blob(blob, acl, acl, 
     273             :                 (ndr_pull_flags_fn_t)ndr_pull_smb_acl_t);
     274             : 
     275     1637057 :         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     1634068 :         return acl;
     282             : }
     283             : 
     284      175144 : 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      175144 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl, 
     289             :                 (ndr_push_flags_fn_t)ndr_push_smb_acl_t);
     290             : 
     291      175144 :         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      175144 :         return blob;
     297             : }
     298             : 
     299     2063594 : 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     2063594 :         DATA_BLOB blob = data_blob_null;
     305        5473 :         ssize_t length;
     306     2063594 :         const char *name = NULL;
     307     2063594 :         struct smb_acl_t *acl = NULL;
     308     2063594 :         TALLOC_CTX *frame = talloc_stackframe();
     309             :                 
     310     2063594 :         switch (type) {
     311     1497920 :         case SMB_ACL_TYPE_ACCESS:
     312     1497920 :                 name = FAKE_ACL_ACCESS_XATTR;
     313     1497920 :                 break;
     314      562032 :         case SMB_ACL_TYPE_DEFAULT:
     315      562032 :                 name = FAKE_ACL_DEFAULT_XATTR;
     316      562032 :                 break;
     317           0 :         default:
     318           0 :                 DBG_ERR("Illegal ACL type %d\n", (int)type);
     319           0 :                 break;
     320             :         }
     321             : 
     322     2063594 :         if (name == NULL) {
     323           0 :                 TALLOC_FREE(frame);
     324           0 :                 return NULL;
     325             :         }
     326             : 
     327        5473 :         do {
     328     2063594 :                 blob.length += 1000;
     329     2063594 :                 blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
     330     2063594 :                 if (!blob.data) {
     331           0 :                         errno = ENOMEM;
     332           0 :                         TALLOC_FREE(frame);
     333           0 :                         return NULL;
     334             :                 }
     335     2063594 :                 length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, blob.data, blob.length);
     336     2063594 :                 blob.length = length;
     337     2063594 :         } while (length == -1 && errno == ERANGE);
     338     2063594 :         if (length == -1 && errno == ENOATTR) {
     339      426537 :                 TALLOC_FREE(frame);
     340      426537 :                 return NULL;
     341             :         }
     342     1637057 :         if (length != -1) {
     343     1637057 :                 acl = fake_acls_blob2acl(&blob, mem_ctx);
     344             :         }
     345     1637057 :         TALLOC_FREE(frame);
     346     1634092 :         return acl;
     347             : }
     348             : 
     349      175144 : 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      175144 :         const char *name = NULL;
     356      175144 :         TALLOC_CTX *frame = talloc_stackframe();
     357      175144 :         DATA_BLOB blob = fake_acls_acl2blob(frame, theacl);
     358      175144 :         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      175144 :         switch (type) {
     366      163296 :         case SMB_ACL_TYPE_ACCESS:
     367      163296 :                 name = FAKE_ACL_ACCESS_XATTR;
     368      163296 :                 break;
     369       11431 :         case SMB_ACL_TYPE_DEFAULT:
     370       11431 :                 name = FAKE_ACL_DEFAULT_XATTR;
     371       11431 :                 break;
     372           0 :         default:
     373           0 :                 errno = EINVAL;
     374           0 :                 return -1;
     375             :         }
     376             : 
     377      175144 :         ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, blob.data, blob.length, 0);
     378      175144 :         TALLOC_FREE(frame);
     379      174604 :         return ret;
     380             : }
     381             : 
     382         324 : static int fake_acls_sys_acl_delete_def_fd(vfs_handle_struct *handle,
     383             :                         struct files_struct *fsp)
     384             : {
     385           0 :         int ret;
     386         324 :         const char *name = FAKE_ACL_DEFAULT_XATTR;
     387             : 
     388         324 :         if (!fsp->fsp_flags.is_directory) {
     389           0 :                 errno = EINVAL;
     390           0 :                 return -1;
     391             :         }
     392             : 
     393         324 :         ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
     394         324 :         if (ret == -1 && errno == ENOATTR) {
     395         207 :                 ret = 0;
     396         207 :                 errno = 0;
     397             :         }
     398             : 
     399         324 :         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      218155 : 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      218155 :         if (uid != -1) {
     455      218137 :                 uid_t current_uid = get_current_uid(handle->conn);
     456             : 
     457      218137 :                 if (current_uid != 0 && current_uid != uid) {
     458       58230 :                         return EACCES;
     459             :                 }
     460             : 
     461      159562 :                 SIVAL(id_buf, 0, uid);
     462      159562 :                 ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, FAKE_UID, id_buf, sizeof(id_buf), 0);
     463      159562 :                 if (ret != 0) {
     464           0 :                         return ret;
     465             :                 }
     466             :         }
     467      159580 :         if (gid != -1) {
     468      158455 :                 SIVAL(id_buf, 0, gid);
     469      158455 :                 ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, FAKE_GID, id_buf, sizeof(id_buf), 0);
     470      158455 :                 if (ret != 0) {
     471           0 :                         return ret;
     472             :                 }
     473             :         }
     474      159130 :         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       62687 : static int fake_acls_connect(struct vfs_handle_struct *handle,
     653             :                              const char *service,
     654             :                              const char *user)
     655             : {
     656       62687 :         struct in_pathref_data *prd = NULL;
     657         874 :         int ret;
     658             : 
     659       62687 :         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
     660       62687 :         if (ret < 0) {
     661          18 :                 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       62669 :         prd = talloc_zero(handle->conn, struct in_pathref_data);
     673       62669 :         if (prd == NULL) {
     674           0 :                 return -1;
     675             :         }
     676       62669 :         SMB_VFS_HANDLE_SET_DATA(handle,
     677             :                                 prd,
     678             :                                 NULL,
     679             :                                 struct in_pathref_data,
     680         874 :                                 return -1);
     681       62669 :         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       32001 : NTSTATUS vfs_fake_acls_init(TALLOC_CTX *ctx)
     701             : {
     702       32001 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_acls",
     703             :                                 &vfs_fake_acls_fns);
     704             : }

Generated by: LCOV version 1.14