LCOV - code coverage report
Current view: top level - src/client - acl.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 77 84 91.7 %
Date: 2022-12-03 01:09:05 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../cmd.h"
       4             : #include "../log.h"
       5             : #include "../prepend.h"
       6             : #include "../sbuf.h"
       7             : #include "acl.h"
       8             : #include "extrameta.h"
       9             : 
      10             : #ifdef HAVE_ACL
      11             : #if defined(HAVE_LINUX_OS) || \
      12             :     defined(HAVE_FREEBSD_OS) || \
      13             :     defined(HAVE_NETBSD_OS)
      14             : #include "sys/acl.h"
      15             : 
      16             : /* Linux can do shorter ACLs */
      17             : #if defined(HAVE_LINUX_OS)
      18             : #include <acl/libacl.h>
      19             : #define acl_to_text(acl,len)        (acl_to_any_text((acl), NULL, ',', TEXT_ABBREVIATE|TEXT_NUMERIC_IDS))
      20             : #endif
      21             : 
      22             : // section of acl_is_trivial copied from bacula 
      23          21 : static int acl_is_trivial(acl_t acl)
      24             : {
      25             : #if defined(HAVE_LINUX_OS) \
      26             :  || defined(HAVE_FREEBSD_OS) \
      27             :  || defined(HAVE_NETBSD_OS)
      28             :         /*
      29             :          * acl is trivial if it has only the following entries:
      30             :          * "user::",
      31             :          * "group::",
      32             :          * "other::"
      33             :          */
      34             :         acl_entry_t ace;
      35             :         acl_tag_t tag;
      36             :         int entry_available;
      37             : 
      38          21 :         entry_available = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace);
      39          89 :         while(entry_available==1)
      40             :         {
      41             :                 /*
      42             :                  * Get the tag type of this acl entry.
      43             :                  * If we fail to get the tagtype we call the acl non-trivial.
      44             :                  */
      45          55 :                 if (acl_get_tag_type(ace, &tag) < 0)
      46             :                         return 0;
      47             :                 /*
      48             :                  * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ
      49             :                  * or ACL_OTHER breaks the spell.
      50             :                  */
      51          55 :                 if(tag!=ACL_USER_OBJ
      52          55 :                   && tag!=ACL_GROUP_OBJ
      53          21 :                   && tag!=ACL_OTHER)
      54             :                         return 0;
      55          47 :                 entry_available=acl_get_entry(acl, ACL_NEXT_ENTRY, &ace);
      56             :         }
      57             : #endif
      58             :         return 1;
      59             : }
      60             : 
      61             : static int default_acl_contains_something(acl_t acl)
      62             : {
      63             :         acl_entry_t ace;
      64           9 :         return acl_get_entry(acl, ACL_FIRST_ENTRY, &ace)==1;
      65             : }
      66             : 
      67          30 : static acl_t acl_contains_something(const char *path, int acl_type)
      68             : {
      69          30 :         acl_t acl=NULL;
      70          30 :         if(!(acl=acl_get_file(path, acl_type)))
      71             :                 return NULL;
      72          30 :         switch(acl_type)
      73             :         {
      74             :                 case ACL_TYPE_ACCESS:
      75          21 :                         if(acl_is_trivial(acl))
      76             :                                 goto nothing;
      77             :                         break;
      78             :                 case ACL_TYPE_DEFAULT:
      79           9 :                         if(!default_acl_contains_something(acl))
      80             :                                 goto nothing;
      81             :                         break;
      82             :         }
      83             :         return acl;
      84             : nothing:
      85          18 :         acl_free(acl);
      86          18 :         return NULL;
      87             : }
      88             : 
      89          13 : int has_acl(const char *path, enum cmd cmd)
      90             : {
      91          13 :         acl_t acl=NULL;
      92          13 :         if((acl=acl_contains_something(path, ACL_TYPE_ACCESS)))
      93             :         {
      94           3 :                 acl_free(acl);
      95           3 :                 return 1;
      96             :         }
      97          10 :         if(cmd==CMD_DIRECTORY
      98           5 :             && (acl=acl_contains_something(path, ACL_TYPE_DEFAULT)))
      99             :         {
     100           1 :                 acl_free(acl);
     101           1 :                 return 1;
     102             :         }
     103             :         return 0;
     104             : }
     105             : 
     106           8 : static int get_acl_string(struct asfd *asfd, acl_t acl, char **acltext,
     107             :         size_t *alen, const char *path, char type, struct cntr *cntr)
     108             : {
     109           8 :         int ret=0;
     110           8 :         char pre[10]="";
     111           8 :         char *tmp=NULL;
     112           8 :         uint32_t tlen=0;
     113           8 :         char *ourtext=NULL;
     114           8 :         char *oldtext=*acltext;
     115           8 :         uint32_t maxlen=0xFFFFFFFF/2;
     116             : 
     117           8 :         if(!(tmp=acl_to_text(acl, NULL)))
     118             :         {
     119           0 :                 logw(asfd, cntr, "could not get ACL text of '%s'\n", path);
     120           0 :                 goto end; // carry on
     121             :         }
     122             : 
     123           8 :         tlen=(uint32_t)strlen(tmp);
     124             : 
     125           8 :         if(tlen>maxlen)
     126             :         {
     127           0 :                 logw(asfd, cntr, "ACL of '%s' too long: %d\n", path, tlen);
     128           0 :                 goto end; // carry on
     129             :         }
     130             : 
     131           8 :         snprintf(pre, sizeof(pre), "%c%08X", type, tlen);
     132           8 :         if(!(ourtext=prepend(pre, tmp))
     133           8 :           || !(*acltext=prepend_len(oldtext,
     134           8 :                 *alen, ourtext, tlen+9, "", 0, alen)))
     135             :                         ret=-1;
     136           8 :         free_w(&oldtext);
     137             : end:
     138           8 :         if(tmp) acl_free(tmp);
     139           8 :         free_w(&ourtext);
     140           8 :         return ret;
     141             : }
     142             : 
     143           8 : int get_acl(struct asfd *asfd, const char *path, int isdir,
     144             :         char **acltext, size_t *alen, struct cntr *cntr)
     145             : {
     146           8 :         int ret=-1;
     147           8 :         acl_t acl=NULL;
     148             : 
     149           8 :         if((acl=acl_contains_something(path, ACL_TYPE_ACCESS)))
     150             :         {
     151           5 :                 if(get_acl_string(asfd, acl,
     152             :                         acltext, alen, path, META_ACCESS_ACL, cntr))
     153             :                                 goto end;
     154             :         }
     155             : 
     156           8 :         if(isdir)
     157             :         {
     158           4 :                 if(acl) acl_free(acl);
     159           4 :                 if((acl=acl_contains_something(path, ACL_TYPE_DEFAULT)))
     160             :                 {
     161           3 :                         if(get_acl_string(asfd, acl,
     162             :                                 acltext, alen, path, META_DEFAULT_ACL, cntr))
     163             :                                         goto end;
     164             :                 }
     165             :         }
     166             :         ret=0;
     167             : end:
     168           8 :         if(acl) acl_free(acl);
     169           8 :         return ret;
     170             : }
     171             : 
     172          10 : static int do_set_acl(struct asfd *asfd, const char *path,
     173             :         const char *acltext, int acltype, struct cntr *cntr)
     174             : {
     175             :         acl_t acl;
     176          10 :         int ret=-1;
     177          10 :         if(!(acl=acl_from_text(acltext)))
     178             :         {
     179           1 :                 logp("acl_from_text error on %s (%s): %s\n",
     180           1 :                         path, acltext, strerror(errno));
     181           1 :                 logw(asfd, cntr, "acl_from_text error on %s (%s): %s\n",
     182             :                         path, acltext, strerror(errno));
     183           1 :                 goto end;
     184             :         }
     185           9 :         if(acl_valid(acl))
     186             :         {
     187           0 :                 logp("acl_valid error on %s: %s", path, strerror(errno));
     188           0 :                 logw(asfd, cntr, "acl_valid error on %s: %s\n",
     189             :                         path, strerror(errno));
     190           0 :                 goto end;
     191             :         }
     192           9 :         if(acl_set_file(path, acltype, acl))
     193             :         {
     194           1 :                 logp("acl set error on %s: %s", path, strerror(errno));
     195           1 :                 logw(asfd, cntr, "acl set error on %s: %s\n",
     196             :                         path, strerror(errno));
     197           1 :                 goto end;
     198             :         }
     199             :         ret=0;
     200             : end:
     201          10 :         if(acl) acl_free(acl);
     202          10 :         return ret;
     203             : }
     204             : 
     205          11 : int set_acl(struct asfd *asfd, const char *path,
     206             :         const char *acltext, char metacmd, struct cntr *cntr)
     207             : {
     208          11 :         switch(metacmd)
     209             :         {
     210             :                 case META_ACCESS_ACL:
     211           5 :                         return do_set_acl(asfd, path,
     212             :                                 acltext, ACL_TYPE_ACCESS, cntr);
     213             :                 case META_DEFAULT_ACL:
     214           5 :                         return do_set_acl(asfd, path,
     215             :                                 acltext, ACL_TYPE_DEFAULT, cntr);
     216             :                 default:
     217           1 :                         logp("unknown acl type: %c\n", metacmd);
     218           1 :                         logw(asfd, cntr, "unknown acl type: %c\n", metacmd);
     219           1 :                         return -1;
     220             :         }
     221             : }
     222             : 
     223             : #endif
     224             : #endif

Generated by: LCOV version 1.13