LCOV - code coverage report
Current view: top level - src - bfile.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 70 87 80.5 %
Date: 2019-04-28 12:12:12 Functions: 11 11 100.0 %

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

Generated by: LCOV version 1.13