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

Generated by: LCOV version 1.14