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

Generated by: LCOV version 1.10