LCOV - code coverage report
Current view: top level - source3/modules - vfs_posixacl.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 147 215 68.4 %
Date: 2024-04-21 15:09:00 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             :    VFS module to get and set posix acls
       4             :    Copyright (C) Volker Lendecke 2006
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/filesys.h"
      22             : #include "smbd/smbd.h"
      23             : #include "modules/vfs_posixacl.h"
      24             : 
      25             : /* prototypes for static functions first - for clarity */
      26             : 
      27             : static bool smb_ace_to_internal(acl_entry_t posix_ace,
      28             :                                 struct smb_acl_entry *ace);
      29             : static struct smb_acl_t *smb_acl_to_internal(acl_t acl, TALLOC_CTX *mem_ctx);
      30             : static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm);
      31             : static acl_t smb_acl_to_posix(const struct smb_acl_t *acl);
      32             : 
      33             : 
      34             : /* public functions - the api */
      35             : 
      36      148915 : SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
      37             :                                   files_struct *fsp,
      38             :                                   SMB_ACL_TYPE_T type,
      39             :                                   TALLOC_CTX *mem_ctx)
      40             : {
      41           0 :         struct smb_acl_t *result;
      42      148915 :         acl_t acl = NULL;
      43           0 :         acl_type_t acl_type;
      44             : 
      45      148915 :         switch(type) {
      46      112901 :         case SMB_ACL_TYPE_ACCESS:
      47      112901 :                 acl_type = ACL_TYPE_ACCESS;
      48      112901 :                 break;
      49       36014 :         case SMB_ACL_TYPE_DEFAULT:
      50       36014 :                 acl_type = ACL_TYPE_DEFAULT;
      51       36014 :                 break;
      52           0 :         default:
      53           0 :                 errno = EINVAL;
      54           0 :                 return NULL;
      55             :         }
      56      148915 :         if (!fsp->fsp_flags.is_pathref && (acl_type == ACL_TYPE_ACCESS)) {
      57             :                 /* POSIX API only allows ACL_TYPE_ACCESS fetched on fd. */
      58       28665 :                 acl = acl_get_fd(fsp_get_io_fd(fsp));
      59      120250 :         } else if (fsp->fsp_flags.have_proc_fds) {
      60       60236 :                 int fd = fsp_get_pathref_fd(fsp);
      61           0 :                 struct sys_proc_fd_path_buf buf;
      62             : 
      63       60236 :                 acl = acl_get_file(sys_proc_fd_path(fd, &buf), acl_type);
      64             :         } else {
      65             :                 /*
      66             :                  * This is no longer a handle based call.
      67             :                  */
      68       60014 :                 acl = acl_get_file(fsp->fsp_name->base_name, acl_type);
      69             :         }
      70      148915 :         if (acl == NULL) {
      71          18 :                 return NULL;
      72             :         }
      73             : 
      74      148897 :         result = smb_acl_to_internal(acl, mem_ctx);
      75      148897 :         acl_free(acl);
      76      148897 :         return result;
      77             : }
      78             : 
      79        1610 : int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
      80             :                             files_struct *fsp,
      81             :                             SMB_ACL_TYPE_T type,
      82             :                             SMB_ACL_T theacl)
      83             : {
      84           0 :         int res;
      85        1610 :         acl_t acl = smb_acl_to_posix(theacl);
      86           0 :         acl_type_t acl_type;
      87        1610 :         int fd = fsp_get_pathref_fd(fsp);
      88             : 
      89        1610 :         if (acl == NULL) {
      90           0 :                 return -1;
      91             :         }
      92             : 
      93        1610 :         switch(type) {
      94        1178 :         case SMB_ACL_TYPE_ACCESS:
      95        1178 :                 acl_type = ACL_TYPE_ACCESS;
      96        1178 :                 break;
      97         432 :         case SMB_ACL_TYPE_DEFAULT:
      98         432 :                 acl_type = ACL_TYPE_DEFAULT;
      99         432 :                 break;
     100           0 :         default:
     101           0 :                 acl_free(acl);
     102           0 :                 errno = EINVAL;
     103           0 :                 return -1;
     104             :         }
     105             : 
     106        1610 :         if (!fsp->fsp_flags.is_pathref && type == SMB_ACL_TYPE_ACCESS) {
     107         976 :                 res = acl_set_fd(fd, acl);
     108         634 :         } else if (fsp->fsp_flags.have_proc_fds) {
     109           0 :                 struct sys_proc_fd_path_buf buf;
     110             : 
     111         317 :                 res = acl_set_file(sys_proc_fd_path(fd, &buf), acl_type, acl);
     112             :         } else {
     113             :                 /*
     114             :                  * This is no longer a handle based call.
     115             :                  */
     116         317 :                 res = acl_set_file(fsp->fsp_name->base_name,
     117             :                                    acl_type,
     118             :                                    acl);
     119             :         }
     120             : 
     121        1610 :         acl_free(acl);
     122        1610 :         return res;
     123             : }
     124             : 
     125           0 : int posixacl_sys_acl_delete_def_fd(vfs_handle_struct *handle,
     126             :                                 files_struct *fsp)
     127             : {
     128           0 :         if (fsp->fsp_flags.have_proc_fds) {
     129           0 :                 int fd = fsp_get_pathref_fd(fsp);
     130           0 :                 struct sys_proc_fd_path_buf buf;
     131             : 
     132           0 :                 return acl_delete_def_file(sys_proc_fd_path(fd, &buf));
     133             :         }
     134             : 
     135             :         /*
     136             :          * This is no longer a handle based call.
     137             :          */
     138           0 :         return acl_delete_def_file(fsp->fsp_name->base_name);
     139             : }
     140             : 
     141             : /* private functions */
     142             : 
     143      450699 : static bool smb_ace_to_internal(acl_entry_t posix_ace,
     144             :                                 struct smb_acl_entry *ace)
     145             : {
     146           0 :         acl_tag_t tag;
     147           0 :         acl_permset_t permset;
     148             : 
     149      450699 :         if (acl_get_tag_type(posix_ace, &tag) != 0) {
     150           0 :                 DEBUG(0, ("smb_acl_get_tag_type failed\n"));
     151           0 :                 return False;
     152             :         }
     153             : 
     154      450699 :         switch(tag) {
     155       25284 :         case ACL_USER:
     156       25284 :                 ace->a_type = SMB_ACL_USER;
     157       25284 :                 break;
     158      119415 :         case ACL_USER_OBJ:
     159      119415 :                 ace->a_type = SMB_ACL_USER_OBJ;
     160      119415 :                 break;
     161       41886 :         case ACL_GROUP:
     162       41886 :                 ace->a_type = SMB_ACL_GROUP;
     163       41886 :                 break;
     164      119415 :         case ACL_GROUP_OBJ:
     165      119415 :                 ace->a_type = SMB_ACL_GROUP_OBJ;
     166      119415 :                 break;
     167      119415 :         case ACL_OTHER:
     168      119415 :                 ace->a_type = SMB_ACL_OTHER;
     169      119415 :                 break;
     170       25284 :         case ACL_MASK:
     171       25284 :                 ace->a_type = SMB_ACL_MASK;
     172       25284 :                 break;
     173             : #ifdef HAVE_ACL_EVERYONE
     174             :         case ACL_EVERYONE:
     175             :                 DEBUG(1, ("ACL tag type ACL_EVERYONE. FreeBSD with ZFS? Use 'vfs objects = zfsacl'\n"));
     176             :                 return false;
     177             : #endif
     178           0 :         default:
     179           0 :                 DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag));
     180           0 :                 return False;
     181             :         }
     182      450699 :         switch(ace->a_type) {
     183       25284 :         case SMB_ACL_USER: {
     184       25284 :                 uid_t *puid = (uid_t *)acl_get_qualifier(posix_ace);
     185       25284 :                 if (puid == NULL) {
     186           0 :                         DEBUG(0, ("smb_acl_get_qualifier failed\n"));
     187           0 :                         return False;
     188             :                 }
     189       25284 :                 ace->info.user.uid = *puid;
     190       25284 :                 acl_free(puid);
     191       25284 :                 break;
     192             :         }
     193             : 
     194       41886 :         case SMB_ACL_GROUP: {
     195       41886 :                 gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace);
     196       41886 :                 if (pgid == NULL) {
     197           0 :                         DEBUG(0, ("smb_acl_get_qualifier failed\n"));
     198           0 :                         return False;
     199             :                 }
     200       41886 :                 ace->info.group.gid = *pgid;
     201       41886 :                 acl_free(pgid);
     202       41886 :                 break;
     203             :         }
     204      383529 :         default:
     205      383529 :                 break;
     206             :         }
     207      450699 :         if (acl_get_permset(posix_ace, &permset) != 0) {
     208           0 :                 DEBUG(0, ("smb_acl_get_mode failed\n"));
     209           0 :                 return False;
     210             :         }
     211      450699 :         ace->a_perm = 0;
     212             : #ifdef HAVE_ACL_GET_PERM_NP
     213             :         ace->a_perm |= (acl_get_perm_np(permset, ACL_READ) ? SMB_ACL_READ : 0);
     214             :         ace->a_perm |= (acl_get_perm_np(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
     215             :         ace->a_perm |= (acl_get_perm_np(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
     216             : #else
     217      450699 :         ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0);
     218      450699 :         ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
     219      450699 :         ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
     220             : #endif
     221      450699 :         return True;
     222             : }
     223             : 
     224      148897 : static struct smb_acl_t *smb_acl_to_internal(acl_t acl, TALLOC_CTX *mem_ctx)
     225             : {
     226      148897 :         struct smb_acl_t *result = sys_acl_init(mem_ctx);
     227      148897 :         int entry_id = ACL_FIRST_ENTRY;
     228           0 :         acl_entry_t e;
     229      148897 :         if (result == NULL) {
     230           0 :                 return NULL;
     231             :         }
     232      599596 :         while (acl_get_entry(acl, entry_id, &e) == 1) {
     233             : 
     234      450699 :                 entry_id = ACL_NEXT_ENTRY;
     235             : 
     236      450699 :                 result->acl = talloc_realloc(result, result->acl,
     237             :                                              struct smb_acl_entry, result->count+1);
     238      450699 :                 if (result->acl == NULL) {
     239           0 :                         TALLOC_FREE(result);
     240           0 :                         DEBUG(0, ("talloc_realloc failed\n"));
     241           0 :                         errno = ENOMEM;
     242           0 :                         return NULL;
     243             :                 }
     244             : 
     245      450699 :                 if (!smb_ace_to_internal(e, &result->acl[result->count])) {
     246           0 :                         TALLOC_FREE(result);
     247           0 :                         return NULL;
     248             :                 }
     249             : 
     250      450699 :                 result->count += 1;
     251             :         }
     252      148897 :         return result;
     253             : }
     254             : 
     255       10835 : static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
     256             : {
     257           3 :         int ret;
     258           3 :         acl_permset_t permset;
     259             : 
     260       10835 :         if ((ret = acl_get_permset(entry, &permset)) != 0) {
     261           0 :                 return ret;
     262             :         }
     263       10835 :         if ((ret = acl_clear_perms(permset)) != 0) {
     264           0 :                 return ret;
     265             :         }
     266       21667 :         if ((perm & SMB_ACL_READ) &&
     267       10833 :             ((ret = acl_add_perm(permset, ACL_READ)) != 0)) {
     268           0 :                 return ret;
     269             :         }
     270       15675 :         if ((perm & SMB_ACL_WRITE) &&
     271        4841 :             ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) {
     272           0 :                 return ret;
     273             :         }
     274       21661 :         if ((perm & SMB_ACL_EXECUTE) &&
     275       10827 :             ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
     276           0 :                 return ret;
     277             :         }
     278             : 
     279       10832 :         return 0;
     280             : }
     281             : 
     282        1611 : static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
     283             : {
     284           1 :         acl_t result;
     285           1 :         int i;
     286             : 
     287        1611 :         result = acl_init(acl->count);
     288        1611 :         if (result == NULL) {
     289           0 :                 DEBUG(10, ("acl_init failed\n"));
     290           0 :                 return NULL;
     291             :         }
     292             : 
     293       12446 :         for (i=0; i<acl->count; i++) {
     294       10835 :                 const struct smb_acl_entry *entry = &acl->acl[i];
     295           3 :                 acl_entry_t e;
     296           3 :                 acl_tag_t tag;
     297             : 
     298       10835 :                 if (acl_create_entry(&result, &e) != 0) {
     299           0 :                         DEBUG(1, ("acl_create_entry failed: %s\n",
     300             :                                   strerror(errno)));
     301           0 :                         goto fail;
     302             :                 }
     303             : 
     304       10835 :                 switch (entry->a_type) {
     305        1610 :                 case SMB_ACL_USER:
     306        1610 :                         tag = ACL_USER;
     307        1610 :                         break;
     308        1610 :                 case SMB_ACL_USER_OBJ:
     309        1610 :                         tag = ACL_USER_OBJ;
     310        1610 :                         break;
     311        2782 :                 case SMB_ACL_GROUP:
     312        2782 :                         tag = ACL_GROUP;
     313        2782 :                         break;
     314        1610 :                 case SMB_ACL_GROUP_OBJ:
     315        1610 :                         tag = ACL_GROUP_OBJ;
     316        1610 :                         break;
     317        1610 :                 case SMB_ACL_OTHER:
     318        1610 :                         tag = ACL_OTHER;
     319        1610 :                         break;
     320        1610 :                 case SMB_ACL_MASK:
     321        1610 :                         tag = ACL_MASK;
     322        1610 :                         break;
     323           0 :                 default:
     324           0 :                         DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
     325           0 :                         goto fail;
     326             :                 }
     327             : 
     328       10835 :                 if (acl_set_tag_type(e, tag) != 0) {
     329           0 :                         DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
     330             :                                    tag, strerror(errno)));
     331           0 :                         goto fail;
     332             :                 }
     333             : 
     334       10835 :                 switch (entry->a_type) {
     335        1610 :                 case SMB_ACL_USER:
     336        1610 :                         if (acl_set_qualifier(e, &entry->info.user.uid) != 0) {
     337           0 :                                 DEBUG(1, ("acl_set_qualifiier failed: %s\n",
     338             :                                           strerror(errno)));
     339           0 :                                 goto fail;
     340             :                         }
     341        1610 :                         break;
     342        2782 :                 case SMB_ACL_GROUP:
     343        2782 :                         if (acl_set_qualifier(e, &entry->info.group.gid) != 0) {
     344           0 :                                 DEBUG(1, ("acl_set_qualifiier failed: %s\n",
     345             :                                           strerror(errno)));
     346           0 :                                 goto fail;
     347             :                         }
     348        2782 :                         break;
     349        6440 :                 default:        /* Shut up, compiler! :-) */
     350        6440 :                         break;
     351             :                 }
     352             : 
     353       10835 :                 if (smb_acl_set_mode(e, entry->a_perm) != 0) {
     354           0 :                         goto fail;
     355             :                 }
     356             :         }
     357             : 
     358        1611 :         if (acl_valid(result) != 0) {
     359           0 :                 char *acl_string = sys_acl_to_text(acl, NULL);
     360           0 :                 DEBUG(0, ("smb_acl_to_posix: ACL %s is invalid for set (%s)\n",
     361             :                           acl_string, strerror(errno)));
     362           0 :                 SAFE_FREE(acl_string);
     363           0 :                 goto fail;
     364             :         }
     365             : 
     366        1611 :         return result;
     367             : 
     368           0 :  fail:
     369           0 :         if (result != NULL) {
     370           0 :                 acl_free(result);
     371             :         }
     372           0 :         return NULL;
     373             : }
     374             : 
     375             : /* VFS operations structure */
     376             : 
     377             : static struct vfs_fn_pointers posixacl_fns = {
     378             :         .sys_acl_get_fd_fn = posixacl_sys_acl_get_fd,
     379             :         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
     380             :         .sys_acl_set_fd_fn = posixacl_sys_acl_set_fd,
     381             :         .sys_acl_delete_def_fd_fn = posixacl_sys_acl_delete_def_fd,
     382             : };
     383             : 
     384             : static_decl_vfs;
     385       29269 : NTSTATUS vfs_posixacl_init(TALLOC_CTX *ctx)
     386             : {
     387       29269 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl",
     388             :                                 &posixacl_fns);
     389             : }

Generated by: LCOV version 1.14