LCOV - code coverage report
Current view: top level - source3/modules - vfs_fake_acls.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 227 309 73.5 %
Date: 2021-09-23 10:06:22 Functions: 18 19 94.7 %

          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             : }

Generated by: LCOV version 1.13