LCOV - code coverage report
Current view: top level - src/client - xattr.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 90 140 64.3 %
Date: 2015-11-30 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../cntr.h"
       6             : #include "../log.h"
       7             : #include "../prepend.h"
       8             : #include "extrameta.h"
       9             : #include "xattr.h"
      10             : 
      11             : #ifdef HAVE_XATTR
      12             : #if defined(HAVE_LINUX_OS) \
      13             :  || defined(HAVE_FREEBSD_OS) \
      14             :  || defined(HAVE_NETBSD_OS) \
      15             :  || defined(HAVE_OPENBSD_OS) \
      16             :  || defined(HAVE_DARWIN_OS)
      17             : 
      18          24 : static char *get_next_str(struct asfd *asfd, char **data, size_t *l,
      19             :         struct cntr *cntr, ssize_t *s, const char *path)
      20             : {
      21          24 :         char *ret=NULL;
      22             : 
      23          24 :         if((sscanf(*data, "%08X", (unsigned int *)s))!=1)
      24             :         {
      25             :                 logw(asfd, cntr, "sscanf of xattr '%s' %d failed for %s\n",
      26           0 :                         *data, *l, path);
      27           0 :                 return NULL;
      28             :         }
      29          24 :         *data+=8;
      30          24 :         *l-=8;
      31          24 :         if(!(ret=(char *)malloc_w((*s)+1, __func__)))
      32           0 :                 return NULL;
      33          24 :         memcpy(ret, *data, *s);
      34          24 :         ret[*s]='\0';
      35             : 
      36          24 :         *data+=*s;
      37          24 :         *l-=*s;
      38             : 
      39          24 :         return ret;
      40             : }
      41             : #endif
      42             : #endif
      43             : 
      44             : #ifdef HAVE_XATTR
      45             : #if defined(HAVE_LINUX_OS) \
      46             :  || defined(HAVE_DARWIN_OS)
      47             : #include <sys/xattr.h>
      48             : 
      49             : 
      50             : #if defined(HAVE_DARWIN_OS)
      51             : 
      52             : static const char *xattr_acl_skiplist[2] = {
      53             :     "com.apple.system.Security",
      54             :     NULL
      55             : };
      56             : 
      57             : #else
      58             : 
      59             : static const char *xattr_acl_skiplist[3] = { "system.posix_acl_access", "system.posix_acl_default", NULL };
      60             : //static const char *xattr_skiplist[1] = { NULL };
      61             : #endif
      62             : 
      63             : 
      64             : /*
      65             :  * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
      66             :  * listxattr, getxattr and setxattr with an extra options argument
      67             :  * which mimics the l variants of the functions when we specify
      68             :  * XATTR_NOFOLLOW as the options value.
      69             :  */
      70             : #if defined(HAVE_DARWIN_OS)
      71             : #define llistxattr(path, list, size) \
      72             : listxattr((path), (list), (size), XATTR_NOFOLLOW)
      73             : #define lgetxattr(path, name, value, size) \
      74             : getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
      75             : #define lsetxattr(path, name, value, size, flags) \
      76             : setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
      77             : 
      78             : #endif
      79             : 
      80             : 
      81           8 : int has_xattr(const char *path)
      82             : {
      83           8 :         if(llistxattr(path, NULL, 0)>0) return 1;
      84           8 :         return 0;
      85             : }
      86             : 
      87           8 : int get_xattr(struct asfd *asfd, const char *path,
      88             :         char **xattrtext, size_t *xlen, struct cntr *cntr)
      89             : {
      90           8 :         char *z=NULL;
      91           8 :         size_t len=0;
      92           8 :         int have_acl=0;
      93           8 :         char *toappend=NULL;
      94           8 :         char *xattrlist=NULL;
      95           8 :         size_t totallen=0;
      96           8 :         size_t maxlen=0xFFFFFFFF/2;
      97             : 
      98           8 :         if((len=llistxattr(path, NULL, 0))<0)
      99             :         {
     100             :                 logw(asfd, cntr, "could not llistxattr '%s': %d %s\n",
     101           0 :                         path, len, strerror(errno));
     102           0 :                 return 0; // carry on
     103             :         }
     104           8 :         if(!(xattrlist=(char *)calloc_w(1, len+1, __func__)))
     105           0 :                 return -1;
     106           8 :         if((len=llistxattr(path, xattrlist, len))<0)
     107             :         {
     108             :                 logw(asfd, cntr, "could not llistxattr '%s': %d %s\n",
     109           0 :                         path, len, strerror(errno));
     110           0 :                 free_w(&xattrlist);
     111           0 :                 return 0; // carry on
     112             :         }
     113           8 :         xattrlist[len]='\0';
     114             : 
     115           8 :         if(xattrtext && *xattrtext)
     116             :         {
     117             :                 // Already have some meta text, which means that some
     118             :                 // ACLs were set.
     119           0 :                 have_acl++;
     120             :         }
     121             : 
     122           8 :         z=xattrlist;
     123          20 :         for(z=xattrlist; len > (size_t)(z-xattrlist)+1; z=strchr(z, '\0')+1)
     124             :         {
     125             :                 char tmp1[9];
     126             :                 char tmp2[9];
     127          12 :                 char *val=NULL;
     128          12 :                 size_t vlen=0;
     129          12 :                 size_t zlen=0;
     130          12 :                 size_t newlen=0;
     131             : 
     132          12 :                 if((zlen=strlen(z))>maxlen)
     133             :                 {
     134             :                         logw(asfd, cntr, "xattr element of '%s' too long: %d\n",
     135           0 :                                 path, zlen);
     136           0 :                         free_w(&toappend);
     137           0 :                         break;
     138             :                 }
     139             : 
     140          12 :                 if(have_acl)
     141             :                 {
     142           0 :                         int c=0;
     143           0 :                         int skip=0;
     144             :                         // skip xattr entries that were already saved as ACLs.
     145           0 :                         for(c=0; xattr_acl_skiplist[c]; c++)
     146             :                         {
     147           0 :                                 if(!strcmp(z, xattr_acl_skiplist[c]))
     148             :                                 {
     149           0 :                                         skip++;
     150           0 :                                         break;
     151             :                                 }
     152             :                         }
     153           0 :                         if(skip) continue;
     154             :                 }
     155             : 
     156          12 :                 if((vlen=lgetxattr(path, z, NULL, 0))<0)
     157             :                 {
     158             :                         logw(asfd, cntr,
     159             :                                 "could not lgetxattr on %s for %s: %d %s\n",
     160           0 :                                 path, z, vlen, strerror(errno));
     161           0 :                         continue;
     162             :                 }
     163          12 :                 if(vlen)
     164             :                 {
     165           8 :                         if(!(val=(char *)malloc_w(vlen+1, __func__)))
     166             :                         {
     167           0 :                                 free_w(&xattrlist);
     168           0 :                                 free_w(&toappend);
     169           0 :                                 return -1;
     170             :                         }
     171           8 :                         if((vlen=lgetxattr(path, z, val, vlen))<0)
     172             :                         {
     173             :                                 logw(asfd, cntr,
     174             :                                   "could not lgetxattr %s for %s: %d %s\n",
     175           0 :                                         path, z, vlen, strerror(errno));
     176           0 :                                 free_w(&val);
     177           0 :                                 continue;
     178             :                         }
     179           8 :                         val[vlen]='\0';
     180             : 
     181           8 :                         if(vlen>maxlen)
     182             :                         {
     183             :                                 logw(asfd, cntr,
     184             :                                         "xattr value of '%s' too long: %d\n",
     185           0 :                                         path, vlen);
     186           0 :                                 free_w(&toappend);
     187           0 :                                 free_w(&val);
     188           0 :                                 break;
     189             :                         }
     190             :                 }
     191             : 
     192          12 :                 snprintf(tmp1, sizeof(tmp1), "%08X", (unsigned int)zlen);
     193          12 :                 snprintf(tmp2, sizeof(tmp2), "%08X", (unsigned int)vlen);
     194          12 :                 newlen=totallen+8+zlen+8+vlen;
     195          12 :                 if(!(toappend=(char *)realloc_w(toappend, newlen, __func__)))
     196             :                 {
     197           0 :                         free_w(&val);
     198           0 :                         free_w(&xattrlist);
     199           0 :                         return -1;
     200             :                 }
     201          12 :                 memcpy(toappend+totallen, tmp1, 8);
     202          12 :                 totallen+=8;
     203          12 :                 memcpy(toappend+totallen, z, zlen);
     204          12 :                 totallen+=zlen;
     205          12 :                 memcpy(toappend+totallen, tmp2, 8);
     206          12 :                 totallen+=8;
     207          12 :                 memcpy(toappend+totallen, val, vlen);
     208          12 :                 totallen+=vlen;
     209          12 :                 free_w(&val);
     210             : 
     211          12 :                 if(totallen>maxlen)
     212             :                 {
     213             :                         logw(asfd, cntr,
     214             :                                 "xattr length of '%s' grew too long: %d\n",
     215           0 :                                 path, totallen);
     216           0 :                         free_w(&val);
     217           0 :                         free_w(&toappend);
     218           0 :                         free_w(&xattrlist);
     219           0 :                         return 0; // carry on
     220             :                 }
     221             :         }
     222             : 
     223           8 :         if(toappend)
     224             :         {
     225             :                 char tmp3[10];
     226           8 :                 size_t newlen=0;
     227             :                 snprintf(tmp3, sizeof(tmp3), "%c%08X",
     228           8 :                         META_XATTR, (unsigned int)totallen);
     229           8 :                 newlen=(*xlen)+9+totallen;
     230          16 :                 if(!(*xattrtext=(char *)
     231          16 :                         realloc_w(*xattrtext, newlen, __func__)))
     232             :                 {
     233           0 :                         free_w(&toappend);
     234           0 :                         free_w(&xattrlist);
     235           0 :                         return -1;
     236             :                 }
     237           8 :                 memcpy(*xattrtext, tmp3, 9);
     238           8 :                 (*xlen)+=9;
     239           8 :                 memcpy((*xattrtext)+(*xlen), toappend, totallen);
     240           8 :                 (*xlen)+=totallen;
     241           8 :                 free_w(&toappend);
     242             :         }
     243           8 :         free_w(&xattrlist);
     244           8 :         return 0;
     245             : }
     246             : 
     247           8 : static int do_set_xattr(struct asfd *asfd,
     248             :         const char *path,
     249             :         const char *xattrtext, size_t xlen, struct cntr *cntr)
     250             : {
     251           8 :         size_t l=0;
     252           8 :         int ret=-1;
     253           8 :         char *data=NULL;
     254           8 :         char *name=NULL;
     255           8 :         char *value=NULL;
     256             : 
     257           8 :         data=(char *)xattrtext;
     258           8 :         l=xlen;
     259          28 :         while(l>0)
     260             :         {
     261          12 :                 ssize_t s=0;
     262          12 :                 free_w(&name);
     263          12 :                 free_w(&value);
     264             : 
     265          36 :                 if(!(name=get_next_str(asfd, &data, &l, cntr, &s, path))
     266          24 :                   || !(value=get_next_str(asfd, &data, &l, cntr, &s, path)))
     267           0 :                         goto end;
     268          12 :                 if(lsetxattr(path, name, value, s, 0))
     269             :                 {
     270             :                         logw(asfd, cntr, "lsetxattr error on %s: %s\n",
     271           0 :                                 path, strerror(errno));
     272           0 :                         goto end;
     273             :                 }
     274             :         }
     275             : 
     276           8 :         ret=0;
     277             : end:
     278           8 :         free_w(&name);
     279           8 :         free_w(&value);
     280           8 :         return ret;
     281             : }
     282             : 
     283           8 : int set_xattr(struct asfd *asfd, const char *path,
     284             :         const char *xattrtext, size_t xlen, char metacmd, struct cntr *cntr)
     285             : {
     286           8 :         switch(metacmd)
     287             :         {
     288             :                 case META_XATTR:
     289             :                         return do_set_xattr(asfd,
     290           8 :                                 path, xattrtext, xlen, cntr);
     291             :                 default:
     292           0 :                         logp("unknown xattr type: %c\n", metacmd);
     293           0 :                         logw(asfd, cntr, "unknown xattr type: %c\n", metacmd);
     294           0 :                         break;
     295             :         }
     296           0 :         return -1;
     297             : }
     298             : 
     299             : #endif // HAVE_LINUX_OS
     300             : 
     301             : #if defined(HAVE_FREEBSD_OS) \
     302             :  || defined(HAVE_NETBSD_OS) \
     303             :  || defined(HAVE_OPENBSD_OS)
     304             : 
     305             : 
     306             : #include <sys/extattr.h>
     307             : #include <libutil.h>
     308             : 
     309             : static int namespaces[2] = { EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM };
     310             : 
     311             : #if defined(HAVE_FREEBSD_OS)
     312             : static const char *acl_skiplist[2] = { "system.posix1e.acl_access", NULL };
     313             : #endif
     314             : 
     315             : int has_xattr(const char *path)
     316             : {
     317             :         int i=0;
     318             :         for(i=0; i<(int)(sizeof(namespaces)/sizeof(int)); i++)
     319             :         {
     320             :                 if(extattr_list_link(path, namespaces[i], NULL, 0)>0)
     321             :                         return 1;
     322             :         }
     323             :         return 0;
     324             : }
     325             : 
     326             : #define BSD_BUF_SIZE    1024
     327             : int get_xattr(struct asfd *asfd, const char *path,
     328             :         char **xattrtext, size_t *xlen, struct cntr *cntr)
     329             : {
     330             :         int i=0;
     331             :         size_t maxlen=0xFFFFFFFF/2;
     332             : 
     333             :         for(i=0; i<(int)(sizeof(namespaces)/sizeof(int)); i++)
     334             :         {
     335             :                 int j=0;
     336             :                 ssize_t len=0;
     337             :                 int have_acl=0;
     338             :                 char *xattrlist=NULL;
     339             :                 char *cnamespace=NULL;
     340             :                 size_t totallen=0;
     341             :                 char *toappend=NULL;
     342             :                 char z[BSD_BUF_SIZE]="";
     343             :                 char cattrname[BSD_BUF_SIZE]="";
     344             :                 if((len=extattr_list_link(path, namespaces[i], NULL, 0))<0)
     345             :                 {
     346             :                         logw(asfd, cntr, "could not extattr_list_link of '%s': %d\n",
     347             :                                 path, len);
     348             :                         return 0; // carry on
     349             :                 }
     350             :                 if(!len) continue;
     351             :                 if(xattrtext && *xattrtext)
     352             :                 {
     353             :                         // Already have some meta text, which means that some
     354             :                         // ACLs were set.
     355             :                         have_acl++;
     356             :                 }
     357             :                 if(!(xattrlist=(char *)calloc_w(1, len+1, __func__)))
     358             :                         return -1;
     359             :                 if((len=extattr_list_link(path, namespaces[i], xattrlist, len))<=0)
     360             :                 {
     361             :                         logw(asfd, cntr, "could not extattr_list_link '%s': %d\n",
     362             :                                 path, len);
     363             :                         free_w(&xattrlist);
     364             :                         return 0; // carry on
     365             :                 }
     366             :                 xattrlist[len]='\0';
     367             : 
     368             :                 // Convert namespace number to string. It has to be freed
     369             :                 // later on.
     370             :                 if(extattr_namespace_to_string(namespaces[i], &cnamespace))
     371             :                 {
     372             :                         logp("Failed to convert %d into namespace on '%s'\n",
     373             :                                  namespaces[i], path);
     374             :                         free_w(&xattrlist);
     375             :                         return 0; // carry on
     376             :                 }
     377             : 
     378             : 
     379             :                 for(j=0; j<(int)len; j+=xattrlist[j]+1)
     380             :                 {
     381             :                         int cnt=0;
     382             :                         char tmp1[9];
     383             :                         char tmp2[9];
     384             :                         size_t newlen=0;
     385             :                         size_t zlen=0;
     386             :                         ssize_t vlen=0;
     387             :                         char *val=NULL;
     388             :                         cnt=xattrlist[j];
     389             :                         if(cnt>((int)sizeof(cattrname)-1))
     390             :                                 cnt=((int)sizeof(cattrname)-1);
     391             :                         strncpy(cattrname, xattrlist+(j+1), cnt);
     392             :                         cattrname[cnt]='\0';
     393             :                         snprintf(z, sizeof(z), "%s.%s",
     394             :                                 cnamespace, cattrname);
     395             : 
     396             :                         if(have_acl)
     397             :                         {
     398             :                                 int c=0;
     399             :                                 int skip=0;
     400             :                                 // skip xattr entries that were already saved
     401             :                                 // as ACLs.
     402             :                                 for(c=0; acl_skiplist[c]; c++)
     403             :                                 {
     404             :                                         if(!strcmp(z, acl_skiplist[c]))
     405             :                                         {
     406             :                                                 skip++;
     407             :                                                 break;
     408             :                                         }
     409             :                                 }
     410             :                                 if(skip) continue;
     411             :                         }
     412             :                         zlen=strlen(z);
     413             :                         //printf("\ngot: %s (%s)\n", z, path);
     414             : 
     415             :                         if((vlen=extattr_list_link(path, namespaces[i],
     416             :                                 xattrlist, len))<0)
     417             :                         {
     418             :                                 logw(asfd, cntr, "could not extattr_list_link on %s for %s: %d\n", path, namespaces[i], vlen);
     419             :                                 continue;
     420             :                         }
     421             :                         if(vlen)
     422             :                         {
     423             :                                 if(!(val=(char *)malloc_w(vlen+1, __func__)))
     424             :                                 {
     425             :                                         free_w(&xattrlist);
     426             :                                         free_w(&toappend);
     427             :                                         return -1;
     428             :                                 }
     429             :                                 if((vlen=extattr_get_link(path, namespaces[i],
     430             :                                         cattrname, val, vlen))<0)
     431             :                                 {
     432             :                                         logw(asfd, cntr, "could not extattr_list_link %s for %s: %d\n", path, namespaces[i], vlen);
     433             :                                         free_w(&val);
     434             :                                         continue;
     435             :                                 }
     436             :                                 val[vlen]='\0';
     437             : 
     438             :                                 if(vlen>maxlen)
     439             :                                 {
     440             :                                         logw(asfd, cntr, "xattr value of '%s' too long: %d\n",
     441             :                                                 path, vlen);
     442             :                                         free_w(&toappend);
     443             :                                         free_w(&val);
     444             :                                         break;
     445             :                                 }
     446             :                         }
     447             : 
     448             :                         snprintf(tmp1, sizeof(tmp1), "%08X", (unsigned int)zlen);
     449             :                         snprintf(tmp2, sizeof(tmp2), "%08X", (unsigned int)vlen);
     450             :                         newlen=totallen+8+zlen+8+vlen;
     451             :                         if(!(toappend=(char *)realloc_w(toappend, newlen, __func__)))
     452             :                         {
     453             :                                 free_w(&val);
     454             :                                 free_w(&xattrlist);
     455             :                                 return -1;
     456             :                         }
     457             :                         memcpy(toappend+totallen, tmp1, 8);
     458             :                         totallen+=8;
     459             :                         memcpy(toappend+totallen, z, zlen);
     460             :                         totallen+=zlen;
     461             :                         memcpy(toappend+totallen, tmp2, 8);
     462             :                         totallen+=8;
     463             :                         memcpy(toappend+totallen, val, vlen);
     464             :                         totallen+=vlen;
     465             :                         free_w(&val);
     466             : 
     467             :                         if(totallen>maxlen)
     468             :                         {
     469             :                                 logw(asfd, cntr,
     470             :                                         "xattr length of '%s' grew too long: %d\n",
     471             :                                         path, totallen);
     472             :                                 free_w(&val);
     473             :                                 free_w(&toappend);
     474             :                                 free_w(&xattrlist);
     475             :                                 return 0; // carry on
     476             :                         }
     477             :                 }
     478             : 
     479             :                 free_w(&cnamespace);
     480             : 
     481             :                 if(toappend)
     482             :                 {
     483             :                         char tmp3[10];
     484             :                         size_t newlen=0;
     485             :                         snprintf(tmp3, sizeof(tmp3), "%c%08X",
     486             :                                 META_XATTR_BSD, (unsigned int)totallen);
     487             :                         newlen=(*xlen)+9+totallen;
     488             :                         if(!(*xattrtext=(char *)
     489             :                                 realloc_w(*xattrtext, newlen, __func__)))
     490             :                         {
     491             :                                 free_w(&toappend);
     492             :                                 free_w(&xattrlist);
     493             :                                 return -1;
     494             :                         }
     495             :                         memcpy(*xattrtext, tmp3, 9);
     496             :                         (*xlen)+=9;
     497             :                         memcpy((*xattrtext)+(*xlen), toappend, totallen);
     498             :                         (*xlen)+=totallen;
     499             :                         free_w(&toappend);
     500             :                 }
     501             :                 free_w(&xattrlist);
     502             :         }
     503             : 
     504             :         return 0;
     505             : }
     506             : 
     507             : static int do_set_xattr_bsd(struct asfd *asfd,
     508             :         const char *path,
     509             :         const char *xattrtext, size_t xlen, struct cntr *cntr)
     510             : {
     511             :         int ret=-1;
     512             :         size_t l=0;
     513             :         char *data=NULL;
     514             :         char *value=NULL;
     515             :         char *nspace=NULL;
     516             : 
     517             :         data=(char *)xattrtext;
     518             :         l=xlen;
     519             :         while(l>0)
     520             :         {
     521             :                 int cnt;
     522             :                 ssize_t vlen=0;
     523             :                 int cnspace=0;
     524             :                 char *name=NULL;
     525             : 
     526             :                 if(!(nspace=get_next_str(asfd, &data, &l, cntr, &vlen, path))
     527             :                   || !(value=get_next_str(asfd, &data, &l, cntr, &vlen, path)))
     528             :                         goto end;
     529             : 
     530             :                 // Need to split the name into two parts.
     531             :                 if(!(name=strchr(nspace, '.')))
     532             :                 {
     533             :                         logw(asfd, cntr,
     534             :                           "could not split %s into namespace and name on %s\n",
     535             :                                 nspace, path);
     536             :                         goto end;
     537             :                 }
     538             :                 *name='\0';
     539             :                 name++;
     540             : 
     541             :                 if(extattr_string_to_namespace(nspace, &cnspace))
     542             :                 {
     543             :                         logw(asfd, cntr,
     544             :                                 "could not convert %s into namespace on %s\n",
     545             :                                 nspace, path);
     546             :                         goto end;
     547             :                 }
     548             : 
     549             :                 //printf("set_link: %d %s %s %s\n", cnspace, nspace, name, value);
     550             :                 if((cnt=extattr_set_link(path,
     551             :                         cnspace, name, value, vlen))!=vlen)
     552             :                 {
     553             :                         logw(asfd, cntr,
     554             :                                 "extattr_set_link error on %s %d!=vlen: %s\n",
     555             :                                 path, strerror(errno));
     556             :                         goto end;
     557             :                 }
     558             : 
     559             :                 free_w(&nspace);
     560             :                 free_w(&value);
     561             :         }
     562             :         ret=0;
     563             : end:
     564             :         free_w(&nspace);
     565             :         free_w(&value);
     566             :         return ret;
     567             : }
     568             : 
     569             : int set_xattr(struct asfd *asfd, const char *path,
     570             :         const char *xattrtext,
     571             :         size_t xlen, char metacmd, struct cntr *cntr)
     572             : {
     573             :         switch(metacmd)
     574             :         {
     575             :                 case META_XATTR_BSD:
     576             :                         return do_set_xattr_bsd(asfd, path,
     577             :                                 xattrtext, xlen, cntr);
     578             :                 default:
     579             :                         logp("unknown xattr type: %c\n", metacmd);
     580             :                         logw(asfd, cntr, "unknown xattr type: %c\n", metacmd);
     581             :                         break;
     582             :         }
     583             :         return -1;
     584             : }
     585             : 
     586             : #endif // HAVE_FREE/NET/OPENBSD_OS
     587             : 
     588             : #endif // HAVE_XATTR

Generated by: LCOV version 1.10