LCOV - code coverage report
Current view: top level - src - bfile.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 53 88 60.2 %
Date: 2020-07-31 05:59:47 Functions: 10 11 90.9 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "alloc.h"
       3             : #include "attribs.h"
       4             : #include "berrno.h"
       5             : #include "bfile.h"
       6             : #include "log.h"
       7             : 
       8             : #ifdef HAVE_DARWIN_OS
       9             : #include <sys/paths.h>
      10             : #endif
      11             : 
      12          14 : void bfile_free(struct BFILE **bfd)
      13             : {
      14          14 :         free_v((void **)bfd);
      15          14 : }
      16             : 
      17             : #ifdef HAVE_WIN32
      18             : static ssize_t bfile_write_windows(struct BFILE *bfd, void *buf, size_t count);
      19             : #endif
      20             : 
      21             : #define min(a,b) \
      22             :    ({ __typeof__ (a) _a = (a); \
      23             :        __typeof__ (b) _b = (b); \
      24             :      _a < _b ? _a : _b; })
      25             : 
      26             : static void setup_vss_strip(struct BFILE *bfd)
      27             : {
      28           0 :         memset(&bfd->mysid, 0, sizeof(struct mysid));
      29           0 :         bfd->mysid.needed_s=bsidsize;
      30             : }
      31             : 
      32           0 : static ssize_t bfile_write_vss_strip(struct BFILE *bfd, void *buf, size_t count)
      33             : {
      34             :         size_t mycount;
      35             :         struct mysid *mysid;
      36             :         struct bsid *sid;
      37             : 
      38           0 :         mysid=&bfd->mysid;
      39           0 :         sid=&mysid->sid;
      40           0 :         char *cp=(char *)buf;
      41           0 :         mycount=count;
      42             : 
      43           0 :         while(mycount)
      44             :         {
      45           0 :                 if(mysid->needed_s)
      46             :                 {
      47           0 :                         size_t sidlen=bsidsize-mysid->needed_s;
      48           0 :                         int got=min(mysid->needed_s, mycount);
      49             : 
      50           0 :                         memcpy(sid+sidlen, cp, got);
      51             : 
      52           0 :                         cp+=got;
      53           0 :                         mycount-=got;
      54           0 :                         mysid->needed_s-=got;
      55             : 
      56           0 :                         if(!mysid->needed_s)
      57           0 :                                 mysid->needed_d=sid->Size+sid->dwStreamNameSize;
      58             :                 }
      59           0 :                 if(mysid->needed_d)
      60             :                 {
      61             :                         size_t wrote;
      62           0 :                         int got=min(mysid->needed_d, mycount);
      63             : 
      64           0 :                         if(sid->dwStreamId==1)
      65             :                         {
      66             : #ifdef HAVE_WIN32
      67             :                                 if((wrote=bfile_write_windows(bfd,
      68             :                                         cp, got))<=0)
      69             :                                                 return -1;
      70             : #else
      71           0 :                                 if((wrote=write(bfd->fd,
      72             :                                         cp, got))<=0)
      73             :                                                 return -1;
      74             : #endif
      75             :                         }
      76             :                         else
      77           0 :                                 wrote=got;
      78             : 
      79           0 :                         cp+=wrote;
      80           0 :                         mycount-=wrote;
      81           0 :                         mysid->needed_d-=wrote;
      82           0 :                         if(!mysid->needed_d)
      83           0 :                                 mysid->needed_s=bsidsize;
      84             :                 }
      85             :         }
      86             : 
      87           0 :         return count;
      88             : }
      89             : 
      90             : #ifdef HAVE_WIN32
      91             : 
      92             : char *unix_name_to_win32(char *name);
      93             : extern "C" HANDLE get_osfhandle(int fd);
      94             : 
      95             : static void bfile_set_win32_api(struct BFILE *bfd, int on)
      96             : {
      97             :         if(have_win32_api() && on)
      98             :                 bfd->use_backup_api=1;
      99             :         else
     100             :                 bfd->use_backup_api=0;
     101             : }
     102             : 
     103             : int have_win32_api(void)
     104             : {
     105             :         return p_BackupRead && p_BackupWrite;
     106             : }
     107             : 
     108             : // Windows flags for the OpenEncryptedFileRaw functions
     109             : #define CREATE_FOR_EXPORT       0
     110             : // These are already defined
     111             : //#define CREATE_FOR_IMPORT     1
     112             : //#define CREATE_FOR_DIR        2
     113             : //#define OVERWRITE_HIDDEN      4
     114             : 
     115             : // Return 0 for success, non zero for error.
     116             : static int bfile_open_encrypted(struct BFILE *bfd,
     117             :         const char *fname, int flags, mode_t mode)
     118             : {
     119             :         ULONG ulFlags=0;
     120             :         char *win32_fname=NULL;
     121             :         char *win32_fname_wchar=NULL;
     122             : 
     123             :         bfd->mode=BF_CLOSED;
     124             :         if(!(win32_fname_wchar=make_win32_path_UTF8_2_wchar_w(fname)))
     125             :         {
     126             :                 logp("could not get widename!");
     127             :                 goto end;
     128             :         }
     129             :         if(!(win32_fname=unix_name_to_win32((char *)fname)))
     130             :         {
     131             :                 logp("could not get win32_fname of %s!", fname);
     132             :                 goto end;
     133             :         }
     134             : 
     135             :         if((flags & O_CREAT) /* Create */
     136             :           || (flags & O_WRONLY)) /* Open existing for write */
     137             :         {
     138             :                 ulFlags |= CREATE_FOR_IMPORT;
     139             :                 ulFlags |= OVERWRITE_HIDDEN;
     140             :                 if(bfd->winattr & FILE_ATTRIBUTE_DIRECTORY)
     141             :                 {
     142             :                         mkdir(fname, 0777);
     143             :                         ulFlags |= CREATE_FOR_DIR;
     144             :                 }
     145             :         }
     146             :         else
     147             :         {
     148             :                 /* Open existing for read */
     149             :                 ulFlags=CREATE_FOR_EXPORT;
     150             :         }
     151             : 
     152             :         if(p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
     153             :                 ulFlags, &(bfd->pvContext)))
     154             :                         bfd->mode=BF_CLOSED;
     155             :         else
     156             :                 bfd->mode=BF_READ;
     157             : 
     158             : end:
     159             :         free_w(&win32_fname_wchar);
     160             :         free_w(&win32_fname);
     161             :         return bfd->mode==BF_CLOSED;
     162             : }
     163             : 
     164             : static int bfile_error(struct BFILE *bfd)
     165             : {
     166             :         if(bfd)
     167             :         {
     168             :                 bfd->lerror=GetLastError();
     169             :                 bfd->berrno=b_errno_win32;
     170             :         }
     171             :         errno=b_errno_win32;
     172             :         return -1;
     173             : }
     174             : 
     175             : // Return 0 for success, non zero for error.
     176             : static int bfile_open(struct BFILE *bfd, struct asfd *asfd,
     177             :         const char *fname, int flags, mode_t mode)
     178             : {
     179             :         DWORD dwaccess;
     180             :         DWORD dwflags;
     181             :         DWORD dwshare;
     182             :         char *win32_fname=NULL;
     183             :         char *win32_fname_wchar=NULL;
     184             : 
     185             :         bfd->mode=BF_CLOSED;
     186             : 
     187             :         if(bfd->winattr & FILE_ATTRIBUTE_ENCRYPTED)
     188             :                 return bfile_open_encrypted(bfd, fname, flags, mode);
     189             : 
     190             :         if(!(win32_fname=unix_name_to_win32((char *)fname)))
     191             :         {
     192             :                 logp("could not get win32_fname of %s!\n", fname);
     193             :                 goto end;
     194             :         }
     195             :         if(!(win32_fname_wchar=make_win32_path_UTF8_2_wchar_w(fname)))
     196             :         {
     197             :                 logp("could not get widename!");
     198             :                 goto end;
     199             :         }
     200             : 
     201             :         if(flags & O_CREAT)
     202             :         {
     203             :                 /* Create */
     204             : 
     205             :                 if(bfd->winattr & FILE_ATTRIBUTE_DIRECTORY)
     206             :                         mkdir(fname, 0777);
     207             : 
     208             :                 if(bfd->use_backup_api)
     209             :                 {
     210             :                         dwaccess=GENERIC_WRITE
     211             :                                 | FILE_ALL_ACCESS
     212             :                                 | WRITE_OWNER
     213             :                                 | WRITE_DAC
     214             :                                 | ACCESS_SYSTEM_SECURITY;
     215             :                         dwflags=FILE_FLAG_BACKUP_SEMANTICS;
     216             :                 }
     217             :                 else
     218             :                 {
     219             :                         dwaccess=GENERIC_WRITE;
     220             :                         dwflags=0;
     221             :                 }
     222             : 
     223             :                 // unicode open for create write
     224             :                 bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
     225             :                         dwaccess,      /* Requested access */
     226             :                         0,             /* Shared mode */
     227             :                         NULL,          /* SecurityAttributes */
     228             :                         CREATE_ALWAYS, /* CreationDisposition */
     229             :                         dwflags,       /* Flags and attributes */
     230             :                         NULL);         /* TemplateFile */
     231             : 
     232             :                 bfd->mode=BF_WRITE;
     233             :         }
     234             :         else if(flags & O_WRONLY)
     235             :         {
     236             :                 /* Open existing for write */
     237             :                 if(bfd->use_backup_api)
     238             :                 {
     239             :                         dwaccess=GENERIC_WRITE
     240             :                                 | WRITE_OWNER
     241             :                                 | WRITE_DAC;
     242             :                         dwflags=FILE_FLAG_BACKUP_SEMANTICS
     243             :                                 | FILE_FLAG_OPEN_REPARSE_POINT;
     244             :                 }
     245             :                 else
     246             :                 {
     247             :                         dwaccess=GENERIC_WRITE;
     248             :                         dwflags=0;
     249             :                 }
     250             : 
     251             :                 // unicode open for open existing write
     252             :                 bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
     253             :                         dwaccess,      /* Requested access */
     254             :                         0,             /* Shared mode */
     255             :                         NULL,          /* SecurityAttributes */
     256             :                         OPEN_EXISTING, /* CreationDisposition */
     257             :                         dwflags,       /* Flags and attributes */
     258             :                         NULL);         /* TemplateFile */
     259             : 
     260             :                 bfd->mode=BF_WRITE;
     261             :         }
     262             :         else
     263             :         {
     264             :                 /* Read */
     265             :                 if(bfd->use_backup_api)
     266             :                 {
     267             :                         dwaccess=GENERIC_READ|READ_CONTROL
     268             :                                 | ACCESS_SYSTEM_SECURITY;
     269             :                         dwflags=FILE_FLAG_BACKUP_SEMANTICS
     270             :                                 | FILE_FLAG_SEQUENTIAL_SCAN
     271             :                                 | FILE_FLAG_OPEN_REPARSE_POINT;
     272             :                         dwshare=FILE_SHARE_READ
     273             :                                 | FILE_SHARE_WRITE
     274             :                                 | FILE_SHARE_DELETE;
     275             :                 }
     276             :                 else
     277             :                 {
     278             :                         dwaccess=GENERIC_READ;
     279             :                         dwflags=0;
     280             :                         dwshare=FILE_SHARE_READ
     281             :                                 | FILE_SHARE_WRITE;
     282             :                 }
     283             : 
     284             :                 // unicode open for open existing read
     285             :                 bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
     286             :                         dwaccess,      /* Requested access */
     287             :                         dwshare,       /* Share modes */
     288             :                         NULL,          /* SecurityAttributes */
     289             :                         OPEN_EXISTING, /* CreationDisposition */
     290             :                         dwflags,       /* Flags and attributes */
     291             :                         NULL);         /* TemplateFile */
     292             : 
     293             :                 bfd->mode=BF_READ;
     294             :         }
     295             : 
     296             :         if(bfd->fh==INVALID_HANDLE_VALUE)
     297             :         {
     298             :                 bfile_error(bfd);
     299             :                 bfd->mode=BF_CLOSED;
     300             :         }
     301             :         else
     302             :         {
     303             :                 free_w(&bfd->path);
     304             :                 if(!(bfd->path=strdup_w(fname, __func__)))
     305             :                         goto end;
     306             :         }
     307             : end:
     308             :         bfd->lpContext=NULL;
     309             :         free_w(&win32_fname_wchar);
     310             :         free_w(&win32_fname);
     311             : 
     312             :         if(bfd->vss_strip)
     313             :                 setup_vss_strip(bfd);
     314             : 
     315             :         return bfd->mode==BF_CLOSED;
     316             : }
     317             : 
     318             : static int bfile_close_encrypted(struct BFILE *bfd, struct asfd *asfd)
     319             : {
     320             :         CloseEncryptedFileRaw(bfd->pvContext);
     321             :         if(bfd->mode==BF_WRITE && bfd->set_attribs_on_close)
     322             :                 attribs_set(asfd,
     323             :                         bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
     324             :         bfd->pvContext=NULL;
     325             :         bfd->mode=BF_CLOSED;
     326             :         free_w(&bfd->path);
     327             :         return 0;
     328             : }
     329             : 
     330             : // Return 0 on success, -1 on error.
     331             : static int bfile_close(struct BFILE *bfd, struct asfd *asfd)
     332             : {
     333             :         int ret=-1;
     334             : 
     335             :         if(!bfd) return 0;
     336             : 
     337             :         if(bfd->mode==BF_CLOSED)
     338             :         {
     339             :                 ret=0;
     340             :                 goto end;
     341             :         }
     342             : 
     343             :         if(bfd->winattr & FILE_ATTRIBUTE_ENCRYPTED)
     344             :                 return bfile_close_encrypted(bfd, asfd);
     345             : 
     346             :         /*
     347             :          * We need to tell the API to release the buffer it
     348             :          * allocated in lpContext.  We do so by calling the
     349             :          * API one more time, but with the Abort bit set.
     350             :          */
     351             :         if(bfd->use_backup_api && bfd->mode==BF_READ)
     352             :         {
     353             :                 BYTE buf[10];
     354             :                 if(bfd->lpContext
     355             :                   && !p_BackupRead(bfd->fh,
     356             :                         buf,              /* buffer */
     357             :                         (DWORD)0,         /* bytes to read */
     358             :                         &bfd->rw_bytes,   /* bytes read */
     359             :                         1,                /* Abort */
     360             :                         1,                /* ProcessSecurity */
     361             :                         &bfd->lpContext)) /* Read context */
     362             :                 {
     363             :                         bfile_error(NULL);
     364             :                         goto end;
     365             :                 }
     366             :         }
     367             :         else if(bfd->use_backup_api && bfd->mode==BF_WRITE)
     368             :         {
     369             :                 BYTE buf[10];
     370             :                 if(bfd->lpContext
     371             :                   && !p_BackupWrite(bfd->fh,
     372             :                         buf,              /* buffer */
     373             :                         (DWORD)0,         /* bytes to read */
     374             :                         &bfd->rw_bytes,   /* bytes written */
     375             :                         1,                /* Abort */
     376             :                         1,                /* ProcessSecurity */
     377             :                         &bfd->lpContext)) /* Write context */
     378             :                 {
     379             :                         bfile_error(NULL);
     380             :                         goto end;
     381             :                 }
     382             :         }
     383             :         if(!CloseHandle(bfd->fh))
     384             :         {
     385             :                 bfile_error(NULL);
     386             :                 goto end;
     387             :         }
     388             : 
     389             :         if(bfd->mode==BF_WRITE && bfd->set_attribs_on_close)
     390             :                 attribs_set(asfd,
     391             :                         bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
     392             :         bfd->lpContext=NULL;
     393             :         bfd->mode=BF_CLOSED;
     394             : 
     395             :         ret=0;
     396             : end:
     397             :         free_w(&bfd->path);
     398             :         return ret;
     399             : }
     400             : 
     401             : // Returns: bytes read on success, or 0 on EOF, -1 on error.
     402             : static ssize_t bfile_read(struct BFILE *bfd, void *buf, size_t count)
     403             : {
     404             :         bfd->rw_bytes=0;
     405             : 
     406             :         if(bfd->use_backup_api)
     407             :         {
     408             :                 if(!p_BackupRead(bfd->fh,
     409             :                         (BYTE *)buf,
     410             :                         count,
     411             :                         &bfd->rw_bytes,
     412             :                         0,                /* no Abort */
     413             :                         1,                /* Process Security */
     414             :                         &bfd->lpContext)) /* Context */
     415             :                                 return bfile_error(bfd);
     416             :         }
     417             :         else
     418             :         {
     419             :                 if(!ReadFile(bfd->fh,
     420             :                         buf,
     421             :                         count,
     422             :                         &bfd->rw_bytes,
     423             :                         NULL))
     424             :                                 return bfile_error(bfd);
     425             :         }
     426             : 
     427             :         return (ssize_t)bfd->rw_bytes;
     428             : }
     429             : 
     430             : static ssize_t bfile_write_windows(struct BFILE *bfd, void *buf, size_t count)
     431             : {
     432             :         bfd->rw_bytes = 0;
     433             : 
     434             :         if(bfd->use_backup_api)
     435             :         {
     436             :                 if(!p_BackupWrite(bfd->fh,
     437             :                         (BYTE *)buf,
     438             :                         count,
     439             :                         &bfd->rw_bytes,
     440             :                         0,                /* No abort */
     441             :                         1,                /* Process Security */
     442             :                         &bfd->lpContext)) /* Context */
     443             :                                 return bfile_error(bfd);
     444             :         }
     445             :         else
     446             :         {
     447             :                 if(!WriteFile(bfd->fh,
     448             :                         buf,
     449             :                         count,
     450             :                         &bfd->rw_bytes,
     451             :                         NULL))
     452             :                                 return bfile_error(bfd);
     453             :         }
     454             :         return (ssize_t)bfd->rw_bytes;
     455             : }
     456             : 
     457             : static ssize_t bfile_write(struct BFILE *bfd, void *buf, size_t count)
     458             : {
     459             :         if(bfd->vss_strip)
     460             :                 return bfile_write_vss_strip(bfd, buf, count);
     461             :         return bfile_write_windows(bfd, buf, count);
     462             : }
     463             : 
     464             : #else
     465             : 
     466          61 : static int bfile_close(struct BFILE *bfd, struct asfd *asfd)
     467             : {
     468          61 :         if(!bfd || bfd->mode==BF_CLOSED) return 0;
     469             : 
     470          50 :         if(!close(bfd->fd))
     471             :         {
     472          50 :                 if(bfd->mode==BF_WRITE && bfd->set_attribs_on_close)
     473          18 :                         attribs_set(asfd, bfd->path,
     474             :                                 &bfd->statp, bfd->winattr, bfd->cntr);
     475          50 :                 bfd->mode=BF_CLOSED;
     476          50 :                 bfd->fd=-1;
     477          50 :                 free_w(&bfd->path);
     478          50 :                 return 0;
     479             :         }
     480           0 :         free_w(&bfd->path);
     481           0 :         return -1;
     482             : }
     483             : 
     484          50 : static int bfile_open(struct BFILE *bfd,
     485             :         struct asfd *asfd, const char *fname, int flags, mode_t mode)
     486             : {
     487          50 :         if(!bfd) return 0;
     488          50 :         if(bfd->mode!=BF_CLOSED && bfd->close(bfd, asfd))
     489             :                 return -1;
     490          50 :         if((bfd->fd=open(fname, flags, mode))<0)
     491             :                 return -1;
     492          50 :         if(flags & O_CREAT || flags & O_WRONLY)
     493          18 :                 bfd->mode=BF_WRITE;
     494             :         else
     495          32 :                 bfd->mode=BF_READ;
     496          50 :         free_w(&bfd->path);
     497          50 :         if(!(bfd->path=strdup_w(fname, __func__)))
     498             :                 return -1;
     499          50 :         if(bfd->vss_strip)
     500             :                 setup_vss_strip(bfd);
     501             :         return 0;
     502             : }
     503             : 
     504          55 : static ssize_t bfile_read(struct BFILE *bfd, void *buf, size_t count)
     505             : {
     506          55 :         return read(bfd->fd, buf, count);
     507             : }
     508             : 
     509          18 : static ssize_t bfile_write(struct BFILE *bfd, void *buf, size_t count)
     510             : {
     511          18 :         if(bfd->vss_strip)
     512           0 :                 return bfile_write_vss_strip(bfd, buf, count);
     513             : 
     514          18 :         return write(bfd->fd, buf, count);
     515             : }
     516             : 
     517             : #endif
     518             : 
     519          32 : static int bfile_open_for_send(struct BFILE *bfd, struct asfd *asfd,
     520             :         const char *fname, int64_t winattr, int atime,
     521             :         struct cntr *cntr, enum protocol protocol)
     522             : {
     523          32 :         if(protocol==PROTO_1
     524          12 :           && bfd->mode!=BF_CLOSED)
     525             :         {
     526             : #ifdef HAVE_WIN32
     527             :                 if(bfd->path && !strcmp(bfd->path, fname))
     528             :                 {
     529             :                         // Already open after reading the VSS data.
     530             :                         // Time now for the actual file data.
     531             :                         return 0;
     532             :                 }
     533             :                 else
     534             :                 {
     535             : #endif
     536             :                         // Close the open bfd so that it can be
     537             :                         // used again
     538           0 :                         bfd->close(bfd, asfd);
     539             : #ifdef HAVE_WIN32
     540             :                 }
     541             : #endif
     542             :         }
     543             : 
     544          32 :         bfile_init(bfd, winattr, cntr);
     545          32 :         if(bfile_open(bfd, asfd, fname, O_RDONLY|O_BINARY
     546             : #ifdef O_NOFOLLOW
     547             :                 |O_NOFOLLOW
     548             : #endif
     549             : #ifdef O_NOATIME
     550             :                 |(atime?0:O_NOATIME)
     551             : #endif
     552             :                 , 0))
     553             :         {
     554             :                 struct berrno be;
     555           0 :                 berrno_init(&be);
     556           0 :                 logw(asfd, cntr,
     557             :                         "Could not open %s: %s\n",
     558           0 :                         fname, berrno_bstrerror(&be, errno));
     559             :                 return -1;
     560             :         }
     561             :         return 0;
     562             : }
     563             : 
     564          18 : static void bfile_set_vss_strip(struct BFILE *bfd, int on)
     565             : {
     566          18 :         bfd->vss_strip=on;
     567          18 : }
     568             : 
     569      100656 : void bfile_setup_funcs(struct BFILE *bfd)
     570             : {
     571      100723 :         bfd->open=bfile_open;
     572      100723 :         bfd->close=bfile_close;
     573      100723 :         bfd->read=bfile_read;
     574      100723 :         bfd->write=bfile_write;
     575      100723 :         bfd->open_for_send=bfile_open_for_send;
     576             : #ifdef HAVE_WIN32
     577             :         bfd->set_win32_api=bfile_set_win32_api;
     578             : #endif
     579      100723 :         bfd->set_vss_strip=bfile_set_vss_strip;
     580      100656 : }
     581             : 
     582          67 : void bfile_init(struct BFILE *bfd, int64_t winattr, struct cntr *cntr)
     583             : {
     584          67 :         memset(bfd, 0, sizeof(struct BFILE));
     585          67 :         bfd->mode=BF_CLOSED;
     586          67 :         bfd->winattr=winattr;
     587          67 :         bfd->cntr=cntr;
     588          67 :         if(!bfd->open) bfile_setup_funcs(bfd);
     589             : #ifdef HAVE_WIN32
     590             :         bfile_set_win32_api(bfd, 1);
     591             : #else
     592          67 :         bfd->fd=-1;
     593             : #endif
     594          67 : }
     595             : 
     596          13 : struct BFILE *bfile_alloc(void)
     597             : {
     598          13 :         return (struct BFILE *)calloc_w(1, sizeof(struct BFILE), __func__);
     599             : }

Generated by: LCOV version 1.13