LCOV - code coverage report
Current view: top level - src - bfile.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 46 52 88.5 %
Date: 2017-03-02 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.10