LCOV - code coverage report
Current view: top level - src - bfile.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 52 87 59.8 %
Date: 2019-07-31 11:35:18 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             :         if(!(win32_fname_wchar=make_win32_path_UTF8_2_wchar_w(fname)))
     124             :                 logp("could not get widename!");
     125             :         if(!(win32_fname=unix_name_to_win32((char *)fname)))
     126             :                 return -1;
     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             :         free_w(&win32_fname_wchar);
     152             :         free_w(&win32_fname);
     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=NULL;
     175             :         char *win32_fname_wchar=NULL;
     176             : 
     177             :         if(bfd->winattr & FILE_ATTRIBUTE_ENCRYPTED)
     178             :                 return bfile_open_encrypted(bfd, fname, flags, mode);
     179             : 
     180             :         if(!p_CreateFileW) return -1;
     181             : 
     182             :         if(!(win32_fname=unix_name_to_win32((char *)fname))) return -1;
     183             : 
     184             :         if(p_CreateFileW && p_MultiByteToWideChar
     185             :           && !(win32_fname_wchar=make_win32_path_UTF8_2_wchar_w(fname)))
     186             :                 logp("could not get widename!");
     187             : 
     188             :         if(flags & O_CREAT)
     189             :         {
     190             :                 /* Create */
     191             : 
     192             :                 if(bfd->winattr & FILE_ATTRIBUTE_DIRECTORY)
     193             :                         mkdir(fname, 0777);
     194             : 
     195             :                 if(bfd->use_backup_api)
     196             :                 {
     197             :                         dwaccess=GENERIC_WRITE
     198             :                                 | FILE_ALL_ACCESS
     199             :                                 | WRITE_OWNER
     200             :                                 | WRITE_DAC
     201             :                                 | ACCESS_SYSTEM_SECURITY;
     202             :                         dwflags=FILE_FLAG_BACKUP_SEMANTICS;
     203             :                 }
     204             :                 else
     205             :                 {
     206             :                         dwaccess=GENERIC_WRITE;
     207             :                         dwflags=0;
     208             :                 }
     209             : 
     210             :                 if(p_CreateFileW && p_MultiByteToWideChar)
     211             :                         // unicode open for create write
     212             :                         bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
     213             :                                 dwaccess,      /* Requested access */
     214             :                                 0,             /* Shared mode */
     215             :                                 NULL,          /* SecurityAttributes */
     216             :                                 CREATE_ALWAYS, /* CreationDisposition */
     217             :                                 dwflags,       /* Flags and attributes */
     218             :                                 NULL);         /* TemplateFile */
     219             : 
     220             :                 bfd->mode=BF_WRITE;
     221             :         }
     222             :         else if(flags & O_WRONLY)
     223             :         {
     224             :                 /* Open existing for write */
     225             :                 if(bfd->use_backup_api)
     226             :                 {
     227             :                         dwaccess=GENERIC_WRITE
     228             :                                 | WRITE_OWNER
     229             :                                 | WRITE_DAC;
     230             :                         dwflags=FILE_FLAG_BACKUP_SEMANTICS
     231             :                                 | FILE_FLAG_OPEN_REPARSE_POINT;
     232             :                 }
     233             :                 else
     234             :                 {
     235             :                         dwaccess=GENERIC_WRITE;
     236             :                         dwflags=0;
     237             :                 }
     238             : 
     239             :                 if(p_CreateFileW && p_MultiByteToWideChar)
     240             :                         // unicode open for open existing write
     241             :                         bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
     242             :                                 dwaccess,      /* Requested access */
     243             :                                 0,             /* Shared mode */
     244             :                                 NULL,          /* SecurityAttributes */
     245             :                                 OPEN_EXISTING, /* CreationDisposition */
     246             :                                 dwflags,       /* Flags and attributes */
     247             :                                 NULL);         /* TemplateFile */
     248             : 
     249             :                 bfd->mode=BF_WRITE;
     250             : 
     251             :         }
     252             :         else
     253             :         {
     254             :                 /* Read */
     255             :                 if(bfd->use_backup_api)
     256             :                 {
     257             :                         dwaccess=GENERIC_READ|READ_CONTROL
     258             :                                 | ACCESS_SYSTEM_SECURITY;
     259             :                         dwflags=FILE_FLAG_BACKUP_SEMANTICS
     260             :                                 | FILE_FLAG_SEQUENTIAL_SCAN
     261             :                                 | FILE_FLAG_OPEN_REPARSE_POINT;
     262             :                         dwshare=FILE_SHARE_READ
     263             :                                 | FILE_SHARE_WRITE
     264             :                                 | FILE_SHARE_DELETE;
     265             :                 }
     266             :                 else
     267             :                 {
     268             :                         dwaccess=GENERIC_READ;
     269             :                         dwflags=0;
     270             :                         dwshare=FILE_SHARE_READ
     271             :                                 | FILE_SHARE_WRITE;
     272             :                 }
     273             : 
     274             :                 if(p_CreateFileW && p_MultiByteToWideChar)
     275             :                         // unicode open for open existing read
     276             :                         bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
     277             :                                 dwaccess,      /* Requested access */
     278             :                                 dwshare,       /* Share modes */
     279             :                                 NULL,          /* SecurityAttributes */
     280             :                                 OPEN_EXISTING, /* CreationDisposition */
     281             :                                 dwflags,       /* Flags and attributes */
     282             :                                 NULL);         /* TemplateFile */
     283             : 
     284             :                 bfd->mode=BF_READ;
     285             :         }
     286             : 
     287             :         if(bfd->fh==INVALID_HANDLE_VALUE)
     288             :         {
     289             :                 bfile_error(bfd);
     290             :                 bfd->mode=BF_CLOSED;
     291             :         }
     292             :         else
     293             :         {
     294             :                 if(!(bfd->path=strdup_w(fname, __func__)))
     295             :                         return -1;
     296             :         }
     297             :         bfd->lpContext=NULL;
     298             :         free_w(&win32_fname_wchar);
     299             :         free_w(&win32_fname);
     300             : 
     301             :         if(bfd->vss_strip)
     302             :                 setup_vss_strip(bfd);
     303             : 
     304             :         return bfd->mode==BF_CLOSED;
     305             : }
     306             : 
     307             : static int bfile_close_encrypted(struct BFILE *bfd, struct asfd *asfd)
     308             : {
     309             :         CloseEncryptedFileRaw(bfd->pvContext);
     310             :         if(bfd->mode==BF_WRITE && bfd->set_attribs_on_close)
     311             :                 attribs_set(asfd,
     312             :                         bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
     313             :         bfd->pvContext=NULL;
     314             :         bfd->mode=BF_CLOSED;
     315             :         free_w(&bfd->path);
     316             :         return 0;
     317             : }
     318             : 
     319             : // Return 0 on success, -1 on error.
     320             : static int bfile_close(struct BFILE *bfd, struct asfd *asfd)
     321             : {
     322             :         int ret=-1;
     323             : 
     324             :         if(!bfd) return 0;
     325             : 
     326             :         if(bfd->mode==BF_CLOSED) return 0;
     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)
     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          61 : static int bfile_close(struct BFILE *bfd, struct asfd *asfd)
     452             : {
     453          61 :         if(!bfd || bfd->mode==BF_CLOSED) return 0;
     454             : 
     455          50 :         if(!close(bfd->fd))
     456             :         {
     457          50 :                 if(bfd->mode==BF_WRITE && bfd->set_attribs_on_close)
     458          18 :                         attribs_set(asfd, bfd->path,
     459             :                                 &bfd->statp, bfd->winattr, bfd->cntr);
     460          50 :                 bfd->mode=BF_CLOSED;
     461          50 :                 bfd->fd=-1;
     462          50 :                 free_w(&bfd->path);
     463          50 :                 return 0;
     464             :         }
     465           0 :         free_w(&bfd->path);
     466           0 :         return -1;
     467             : }
     468             : 
     469          50 : static int bfile_open(struct BFILE *bfd,
     470             :         struct asfd *asfd, const char *fname, int flags, mode_t mode)
     471             : {
     472          50 :         if(!bfd) return 0;
     473          50 :         if(bfd->mode!=BF_CLOSED && bfd->close(bfd, asfd))
     474             :                 return -1;
     475          50 :         if((bfd->fd=open(fname, flags, mode))<0)
     476             :                 return -1;
     477          50 :         if(flags & O_CREAT || flags & O_WRONLY)
     478          18 :                 bfd->mode=BF_WRITE;
     479             :         else
     480          32 :                 bfd->mode=BF_READ;
     481          50 :         if(!(bfd->path=strdup_w(fname, __func__)))
     482             :                 return -1;
     483          50 :         if(bfd->vss_strip)
     484             :                 setup_vss_strip(bfd);
     485             :         return 0;
     486             : }
     487             : 
     488          55 : static ssize_t bfile_read(struct BFILE *bfd, void *buf, size_t count)
     489             : {
     490          55 :         return read(bfd->fd, buf, count);
     491             : }
     492             : 
     493          18 : static ssize_t bfile_write(struct BFILE *bfd, void *buf, size_t count)
     494             : {
     495          18 :         if(bfd->vss_strip)
     496           0 :                 return bfile_write_vss_strip(bfd, buf, count);
     497             : 
     498          18 :         return write(bfd->fd, buf, count);
     499             : }
     500             : 
     501             : #endif
     502             : 
     503          32 : static int bfile_open_for_send(struct BFILE *bfd, struct asfd *asfd,
     504             :         const char *fname, int64_t winattr, int atime,
     505             :         struct cntr *cntr, enum protocol protocol)
     506             : {
     507          32 :         if(protocol==PROTO_1
     508          12 :           && 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          32 :         bfile_init(bfd, winattr, cntr);
     529          32 :         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          18 : static void bfile_set_vss_strip(struct BFILE *bfd, int on)
     549             : {
     550          18 :         bfd->vss_strip=on;
     551          18 : }
     552             : 
     553      100656 : void bfile_setup_funcs(struct BFILE *bfd)
     554             : {
     555      100723 :         bfd->open=bfile_open;
     556      100723 :         bfd->close=bfile_close;
     557      100723 :         bfd->read=bfile_read;
     558      100723 :         bfd->write=bfile_write;
     559      100723 :         bfd->open_for_send=bfile_open_for_send;
     560             : #ifdef HAVE_WIN32
     561             :         bfd->set_win32_api=bfile_set_win32_api;
     562             : #endif
     563      100723 :         bfd->set_vss_strip=bfile_set_vss_strip;
     564      100656 : }
     565             : 
     566          67 : void bfile_init(struct BFILE *bfd, int64_t winattr, struct cntr *cntr)
     567             : {
     568          67 :         memset(bfd, 0, sizeof(struct BFILE));
     569          67 :         bfd->mode=BF_CLOSED;
     570          67 :         bfd->winattr=winattr;
     571          67 :         bfd->cntr=cntr;
     572          67 :         if(!bfd->open) bfile_setup_funcs(bfd);
     573             : #ifdef HAVE_WIN32
     574             :         bfile_set_win32_api(bfd, 1);
     575             : #else
     576          67 :         bfd->fd=-1;
     577             : #endif
     578          67 : }
     579             : 
     580          13 : struct BFILE *bfile_alloc(void)
     581             : {
     582          13 :         return (struct BFILE *)calloc_w(1, sizeof(struct BFILE), __func__);
     583             : }

Generated by: LCOV version 1.13