LCOV - code coverage report
Current view: top level - source3/modules - vfs_acl_xattr.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 101 113 89.4 %
Date: 2021-09-23 10:06:22 Functions: 11 11 100.0 %

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

Generated by: LCOV version 1.13