LCOV - code coverage report
Current view: top level - src - bfile.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 50 87 57.5 %
Date: 2022-08-30 22:36:43 Functions: 9 11 81.8 %

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

Generated by: LCOV version 1.13