LCOV - code coverage report
Current view: top level - source3/lib - sysacls.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 111 162 68.5 %
Date: 2021-09-23 10:06:22 Functions: 16 19 84.2 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba system utilities for ACL support.
       4             :    Copyright (C) Jeremy Allison 2000.
       5             :    Copyright (C) Volker Lendecke 2006
       6             :    Copyright (C) Michael Adam 2006,2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/passwd.h"
      24             : 
      25             : #if defined(HAVE_POSIX_ACLS)
      26             : #include "modules/vfs_posixacl.h"
      27             : #endif
      28             : 
      29             : #if defined(HAVE_SOLARIS_UNIXWARE_ACLS)
      30             : #include "modules/vfs_solarisacl.h"
      31             : #endif
      32             : 
      33             : #if defined(HAVE_HPUX_ACLS)
      34             : #include "modules/vfs_hpuxacl.h"
      35             : #endif
      36             : 
      37             : #undef  DBGC_CLASS
      38             : #define DBGC_CLASS DBGC_ACLS
      39             : 
      40             : /*
      41             :  * Note that while this code implements sufficient functionality
      42             :  * to support the sys_acl_* interfaces it does not provide all
      43             :  * of the semantics of the POSIX ACL interfaces.
      44             :  *
      45             :  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
      46             :  * from a call to sys_acl_get_entry() should not be assumed to be
      47             :  * valid after calling any of the following functions, which may
      48             :  * reorder the entries in the ACL.
      49             :  *
      50             :  *      sys_acl_valid()
      51             :  *      sys_acl_set_fd()
      52             :  */
      53             : 
      54     1755579 : int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
      55             : {
      56     1755579 :         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
      57           0 :                 errno = EINVAL;
      58           0 :                 return -1;
      59             :         }
      60             : 
      61     1755579 :         if (entry_p == NULL) {
      62           0 :                 errno = EINVAL;
      63           0 :                 return -1;
      64             :         }
      65             : 
      66     1755579 :         if (entry_id == SMB_ACL_FIRST_ENTRY) {
      67      367966 :                 acl_d->next = 0;
      68             :         }
      69             : 
      70     1755579 :         if (acl_d->next < 0) {
      71           0 :                 errno = EINVAL;
      72           0 :                 return -1;
      73             :         }
      74             : 
      75     1755579 :         if (acl_d->next >= acl_d->count) {
      76      311198 :                 return 0;
      77             :         }
      78             : 
      79     1443947 :         *entry_p = &acl_d->acl[acl_d->next++];
      80             : 
      81     1443947 :         return 1;
      82             : }
      83             : 
      84     1431403 : int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
      85             : {
      86     1431403 :         *type_p = entry_d->a_type;
      87             : 
      88     1431403 :         return 0;
      89             : }
      90             : 
      91     2406441 : int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
      92             : {
      93     2406441 :         *permset_p = &entry_d->a_perm;
      94             : 
      95     2406441 :         return 0;
      96             : }
      97             : 
      98      385206 : void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
      99             : {
     100      385206 :         if (entry_d->a_type == SMB_ACL_USER) {
     101      132403 :                 return &entry_d->info.user.uid;
     102             :         }
     103             : 
     104      252803 :         if (entry_d->a_type == SMB_ACL_GROUP) {
     105      252803 :                 return &entry_d->info.group.gid;
     106             :         }
     107             : 
     108           0 :         errno = EINVAL;
     109           0 :         return NULL;
     110             : }
     111             : 
     112     1025098 : int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
     113             : {
     114     1025098 :         *permset_d = 0;
     115             : 
     116     1025098 :         return 0;
     117             : }
     118             : 
     119     2507684 : int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
     120             : {
     121     2507684 :         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
     122      991187 :             && perm != SMB_ACL_EXECUTE) {
     123           0 :                 errno = EINVAL;
     124           0 :                 return -1;
     125             :         }
     126             : 
     127     2507684 :         if (permset_d == NULL) {
     128           0 :                 errno = EINVAL;
     129           0 :                 return -1;
     130             :         }
     131             : 
     132     2507684 :         *permset_d |= perm;
     133             : 
     134     2507684 :         return 0;
     135             : }
     136             : 
     137     4143972 : int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
     138             : {
     139     4143972 :         return *permset_d & perm;
     140             : }
     141             : 
     142           6 : char *sys_acl_to_text(const struct smb_acl_t *acl_d, ssize_t *len_p)
     143             : {
     144             :         int     i;
     145             :         int     len, maxlen;
     146             :         char    *text;
     147             : 
     148             :         /*
     149             :          * use an initial estimate of 20 bytes per ACL entry
     150             :          * when allocating memory for the text representation
     151             :          * of the ACL
     152             :          */
     153           6 :         len     = 0;
     154           6 :         maxlen  = 20 * acl_d->count;
     155           6 :         if ((text = (char *)SMB_MALLOC(maxlen)) == NULL) {
     156           0 :                 errno = ENOMEM;
     157           0 :                 return NULL;
     158             :         }
     159             : 
     160          60 :         for (i = 0; i < acl_d->count; i++) {
     161          54 :                 struct smb_acl_entry *ap = &acl_d->acl[i];
     162             :                 struct group    *gr;
     163             :                 char            tagbuf[12];
     164             :                 char            idbuf[12];
     165             :                 const char      *tag;
     166          54 :                 const char      *id     = "";
     167             :                 char            perms[4];
     168             :                 int             nbytes;
     169             : 
     170          54 :                 switch (ap->a_type) {
     171             :                         /*
     172             :                          * for debugging purposes it's probably more
     173             :                          * useful to dump unknown tag types rather
     174             :                          * than just returning an error
     175             :                          */
     176           0 :                         default:
     177           0 :                                 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
     178           0 :                                          ap->a_type);
     179           0 :                                 tag = tagbuf;
     180           0 :                                 break;
     181             : 
     182           6 :                         case SMB_ACL_USER:
     183           6 :                                 id = uidtoname(ap->info.user.uid);
     184             : 
     185             :                                 FALL_THROUGH;
     186          12 :                         case SMB_ACL_USER_OBJ:
     187          12 :                                 tag = "user";
     188          12 :                                 break;
     189             : 
     190          24 :                         case SMB_ACL_GROUP:
     191          24 :                                 if ((gr = getgrgid(ap->info.group.gid)) == NULL) {
     192           0 :                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
     193           0 :                                                 (long)ap->info.group.gid);
     194           0 :                                         id = idbuf;
     195             :                                 } else {
     196          24 :                                         id = gr->gr_name;
     197             :                                 }
     198             : 
     199             :                                 FALL_THROUGH;
     200             :                         case SMB_ACL_GROUP_OBJ:
     201          30 :                                 tag = "group";
     202          30 :                                 break;
     203             : 
     204           6 :                         case SMB_ACL_OTHER:
     205           6 :                                 tag = "other";
     206           6 :                                 break;
     207             : 
     208           6 :                         case SMB_ACL_MASK:
     209           6 :                                 tag = "mask";
     210           6 :                                 break;
     211             : 
     212             :                 }
     213             : 
     214          54 :                 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
     215          54 :                 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
     216          54 :                 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
     217          54 :                 perms[3] = '\0';
     218             : 
     219             :                 /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
     220          54 :                 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
     221             : 
     222             :                 /*
     223             :                  * If this entry would overflow the buffer
     224             :                  * allocate enough additional memory for this
     225             :                  * entry and an estimate of another 20 bytes
     226             :                  * for each entry still to be processed
     227             :                  */
     228          54 :                 if ((len + nbytes) > maxlen) {
     229           6 :                         maxlen += nbytes + 20 * (acl_d->count - i);
     230           6 :                         if ((text = (char *)SMB_REALLOC(text, maxlen)) == NULL) {
     231           0 :                                 errno = ENOMEM;
     232           0 :                                 return NULL;
     233             :                         }
     234             :                 }
     235             : 
     236             : 
     237          54 :                 slprintf(&text[len], nbytes, "%s:%s:%s\n", tag, id, perms);
     238          54 :                 len += (nbytes - 1);
     239             :         }
     240             : 
     241           6 :         if (len_p)
     242           0 :                 *len_p = len;
     243             : 
     244           6 :         return text;
     245             : }
     246             : 
     247      368430 : SMB_ACL_T sys_acl_init(TALLOC_CTX *mem_ctx)
     248             : {
     249             :         SMB_ACL_T       a;
     250             : 
     251      368430 :         if ((a = talloc(mem_ctx, struct smb_acl_t)) == NULL) {
     252           0 :                 errno = ENOMEM;
     253           0 :                 return NULL;
     254             :         }
     255             : 
     256      368430 :         a->count = 0;
     257      368430 :         a->next = -1;
     258             : 
     259      368430 :         a->acl = talloc_array(a, struct smb_acl_entry, 0);
     260      368430 :         if (!a->acl) {
     261           0 :                 TALLOC_FREE(a);
     262           0 :                 errno = ENOMEM;
     263           0 :                 return NULL;
     264             :         }
     265             : 
     266      367952 :         return a;
     267             : }
     268             : 
     269     1025069 : int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
     270             : {
     271             :         SMB_ACL_T       acl_d;
     272             :         SMB_ACL_ENTRY_T entry_d;
     273             :         struct smb_acl_entry *acl;
     274             : 
     275     1025069 :         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
     276           0 :                 errno = EINVAL;
     277           0 :                 return -1;
     278             :         }
     279             : 
     280     1025069 :         acl = talloc_realloc(acl_d, acl_d->acl, struct smb_acl_entry, acl_d->count+1);
     281     1025069 :         if (!acl) {
     282           0 :                 errno = ENOMEM;
     283           0 :                 return -1;
     284             :         }
     285     1025069 :         acl_d->acl = acl;
     286     1025069 :         entry_d         = &acl_d->acl[acl_d->count];
     287     1025069 :         entry_d->a_type      = SMB_ACL_TAG_INVALID;
     288     1025069 :         entry_d->a_perm      = 0;
     289     1025069 :         *entry_p        = entry_d;
     290             : 
     291     1025069 :         acl_d->count++;
     292     1025069 :         return 0;
     293             : }
     294             : 
     295     1025069 : int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
     296             : {
     297     1025069 :         switch (tag_type) {
     298     1025069 :                 case SMB_ACL_USER:
     299             :                 case SMB_ACL_USER_OBJ:
     300             :                 case SMB_ACL_GROUP:
     301             :                 case SMB_ACL_GROUP_OBJ:
     302             :                 case SMB_ACL_OTHER:
     303             :                 case SMB_ACL_MASK:
     304     1025069 :                         entry_d->a_type = tag_type;
     305     1020889 :                         break;
     306           0 :                 default:
     307           0 :                         errno = EINVAL;
     308           0 :                         return -1;
     309             :                 }
     310             : 
     311     1025069 :         return 0;
     312             : }
     313             : 
     314      376558 : int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
     315             : {
     316      376558 :         if (entry_d->a_type == SMB_ACL_USER) {
     317      129655 :                 entry_d->info.user.uid = *((uid_t *)qual_p);
     318      129655 :                 return 0;
     319             :         }
     320      246903 :         if (entry_d->a_type == SMB_ACL_GROUP) {
     321      246903 :                 entry_d->info.group.gid = *((gid_t *)qual_p);
     322      246903 :                 return 0;
     323             :         }
     324             : 
     325           0 :         errno = EINVAL;
     326           0 :         return -1;
     327             : }
     328             : 
     329     1025117 : int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
     330             : {
     331     1025117 :         if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
     332           0 :                 errno = EINVAL;
     333           0 :                 return -1;
     334             :         }
     335             : 
     336     1025117 :         entry_d->a_perm = *permset_d;
     337             : 
     338     1025117 :         return 0;
     339             : }
     340             : 
     341           0 : int sys_acl_free_text(char *text)
     342             : {
     343           0 :         SAFE_FREE(text);
     344           0 :         return 0;
     345             : }
     346             : 
     347           0 : int sys_acl_valid(SMB_ACL_T acl_d)
     348             : {
     349           0 :         errno = EINVAL;
     350           0 :         return -1;
     351             : }
     352             : 
     353             : /*
     354             :  * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and
     355             :  * sys_acl_delete_def_fd are to be redirected to the default
     356             :  * statically-bound acl vfs module, but they are replacable.
     357             :  */
     358             : 
     359             : #if defined(HAVE_POSIX_ACLS)
     360             : 
     361      208104 : SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle,
     362             :                          files_struct *fsp,
     363             :                          SMB_ACL_TYPE_T type,
     364             :                          TALLOC_CTX *mem_ctx)
     365             : {
     366      208104 :         return posixacl_sys_acl_get_fd(handle, fsp, type, mem_ctx);
     367             : }
     368             : 
     369         938 : int sys_acl_set_fd(vfs_handle_struct *handle,
     370             :                    files_struct *fsp,
     371             :                    SMB_ACL_TYPE_T type,
     372             :                    SMB_ACL_T acl_d)
     373             : {
     374         938 :         return posixacl_sys_acl_set_fd(handle, fsp, type, acl_d);
     375             : }
     376             : 
     377           0 : int sys_acl_delete_def_fd(vfs_handle_struct *handle,
     378             :                           files_struct *fsp)
     379             : {
     380           0 :         return posixacl_sys_acl_delete_def_fd(handle, fsp);
     381             : }
     382             : 
     383             : #elif defined(HAVE_AIX_ACLS)
     384             : 
     385             : SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle,
     386             :                          files_struct *fsp,
     387             :                          SMB_ACL_TYPE_T type,
     388             :                          TALLOC_CTX *mem_ctx)
     389             : {
     390             :         return aixacl_sys_acl_get_fd(handle, fsp, mem_ctx);
     391             : }
     392             : 
     393             : int sys_acl_set_fd(vfs_handle_struct *handle,
     394             :                    files_struct *fsp,
     395             :                    SMB_ACL_TYPE_T type,
     396             :                    SMB_ACL_T acl_d)
     397             : {
     398             :         return aixacl_sys_acl_set_fd(handle, fsp, type, acl_d);
     399             : }
     400             : 
     401             : int sys_acl_delete_def_fd(vfs_handle_struct *handle,
     402             :                           files_struct *fsp)
     403             : {
     404             :         return aixacl_sys_acl_delete_def_fd(handle, fsp);
     405             : }
     406             : #elif defined(HAVE_SOLARIS_UNIXWARE_ACLS)
     407             : 
     408             : SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle,
     409             :                          files_struct *fsp,
     410             :                          SMB_ACL_TYPE_T type,
     411             :                          TALLOC_CTX *mem_ctx)
     412             : {
     413             :         return solarisacl_sys_acl_get_fd(handle, fsp,
     414             :                                          mem_ctx);
     415             : }
     416             : 
     417             : int sys_acl_set_fd(vfs_handle_struct *handle,
     418             :                    files_struct *fsp,
     419             :                    SMB_ACL_TYPE_T type,
     420             :                    SMB_ACL_T acl_d)
     421             : {
     422             :         return solarisacl_sys_acl_set_fd(handle,
     423             :                                         fsp,
     424             :                                         type,
     425             :                                         acl_d);
     426             : }
     427             : 
     428             : int sys_acl_delete_def_fd(vfs_handle_struct *handle,
     429             :                           files_struct *fsp)
     430             : {
     431             :         return solarisacl_sys_acl_delete_def_fd(handle, fsp);
     432             : }
     433             : #elif defined(HAVE_HPUX_ACLS)
     434             : 
     435             : SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle,
     436             :                          files_struct *fsp,
     437             :                          SMB_ACL_TYPE_T type,
     438             :                          TALLOC_CTX *mem_ctx)
     439             : {
     440             :         return hpuxacl_sys_acl_get_fd(handle, fsp, mem_ctx);
     441             : }
     442             : 
     443             : int sys_acl_set_fd(vfs_handle_struct *handle,
     444             :                    files_struct *fsp,
     445             :                    SMB_ACL_TYPE_T type,
     446             :                    SMB_ACL_T acl_d)
     447             : {
     448             :         return hpuxacl_sys_acl_set_file(handle, fsp->fsp_name, type, acl_d);
     449             : }
     450             : 
     451             : int sys_acl_delete_def_fd(vfs_handle_struct *handle,
     452             :                           files_struct *fsp)
     453             : {
     454             :         return hpuxacl_sys_acl_delete_def_fd(handle, fsp);
     455             : }
     456             : #else /* No ACLs. */
     457             : 
     458             : SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle,
     459             :                          files_struct *fsp,
     460             :                          SMB_ACL_TYPE_T type,
     461             :                          TALLOC_CTX *mem_ctx)
     462             : {
     463             : #ifdef ENOTSUP
     464             :         errno = ENOTSUP;
     465             : #else
     466             :         errno = ENOSYS;
     467             : #endif
     468             :         return NULL;
     469             : }
     470             : 
     471             : int sys_acl_set_fd(vfs_handle_struct *handle,
     472             :                    files_struct *fsp,
     473             :                    SMB_ACL_TYPE_T type,
     474             :                    SMB_ACL_T acl_d)
     475             : {
     476             : #ifdef ENOTSUP
     477             :         errno = ENOTSUP;
     478             : #else
     479             :         errno = ENOSYS;
     480             : #endif
     481             :         return -1;
     482             : }
     483             : 
     484             : int sys_acl_delete_def_fd(vfs_handle_struct *handle,
     485             :                           files_struct *fsp)
     486             : {
     487             : #ifdef ENOTSUP
     488             :         errno = ENOTSUP;
     489             : #else
     490             :         errno = ENOSYS;
     491             : #endif
     492             :         return -1;
     493             : }
     494             : #endif
     495             : 
     496             : /************************************************************************
     497             :  Deliberately outside the ACL defines. Return 1 if this is a "no acls"
     498             :  errno, 0 if not.
     499             : ************************************************************************/
     500             : 
     501          20 : int no_acl_syscall_error(int err)
     502             : {
     503             : #if defined(ENOSYS)
     504          20 :         if (err == ENOSYS) {
     505           0 :                 return 1;
     506             :         }
     507             : #endif
     508             : #if defined(ENOTSUP)
     509          20 :         if (err == ENOTSUP) {
     510           0 :                 return 1;
     511             :         }
     512             : #endif
     513          20 :         return 0;
     514             : }

Generated by: LCOV version 1.13