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

Generated by: LCOV version 1.10