LCOV - code coverage report
Current view: top level - src - bfile.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 22 58 37.9 %
Date: 2015-10-31 Functions: 5 9 55.6 %

          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           2 : void bfile_free(BFILE **bfd)
      12             : {
      13           2 :         free_v((void **)bfd);
      14           2 : }
      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(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(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             :         if(win32_fname_wchar) free(win32_fname_wchar);
     102             :         if(win32_fname) free(win32_fname);
     103             :         return bfd->mode==BF_CLOSED;
     104             : }
     105             : 
     106             : static int bfile_error(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(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             :         if(win32_fname_wchar) free(win32_fname_wchar);
     276             :         if(win32_fname) free(win32_fname);
     277             :         return bfd->mode==BF_CLOSED;
     278             : }
     279             : 
     280             : static int bfile_close_encrypted(BFILE *bfd, struct asfd *asfd)
     281             : {
     282             :         CloseEncryptedFileRaw(bfd->pvContext);
     283             :         if(bfd->mode==BF_WRITE)
     284             :                 attribs_set(asfd,
     285             :                         bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
     286             :         bfd->pvContext=NULL;
     287             :         bfd->mode=BF_CLOSED;
     288             :         if(bfd->path)
     289             :         {
     290             :                 free(bfd->path);
     291             :                 bfd->path=NULL;
     292             :         }
     293             :         return 0;
     294             : }
     295             : 
     296             : // Return 0 on success, -1 on error.
     297             : static int bfile_close(BFILE *bfd, struct asfd *asfd)
     298             : {
     299             :         int ret=-1;
     300             : 
     301             :         if(!bfd) return 0;
     302             : 
     303             :         if(bfd->mode==BF_CLOSED) return 0;
     304             : 
     305             :         if(bfd->winattr & FILE_ATTRIBUTE_ENCRYPTED)
     306             :                 return bfile_close_encrypted(bfd, asfd);
     307             : 
     308             :         /*
     309             :          * We need to tell the API to release the buffer it
     310             :          * allocated in lpContext.  We do so by calling the
     311             :          * API one more time, but with the Abort bit set.
     312             :          */
     313             :         if(bfd->use_backup_api && bfd->mode==BF_READ)
     314             :         {
     315             :                 BYTE buf[10];
     316             :                 if(bfd->lpContext
     317             :                   && !p_BackupRead(bfd->fh,
     318             :                         buf,              /* buffer */
     319             :                         (DWORD)0,         /* bytes to read */
     320             :                         &bfd->rw_bytes,   /* bytes read */
     321             :                         1,                /* Abort */
     322             :                         1,                /* ProcessSecurity */
     323             :                         &bfd->lpContext)) /* Read context */
     324             :                 {
     325             :                         bfile_error(NULL);
     326             :                         goto end;
     327             :                 }
     328             :         }
     329             :         else if(bfd->use_backup_api && bfd->mode==BF_WRITE)
     330             :         {
     331             :                 BYTE buf[10];
     332             :                 if(bfd->lpContext
     333             :                   && !p_BackupWrite(bfd->fh,
     334             :                         buf,              /* buffer */
     335             :                         (DWORD)0,         /* bytes to read */
     336             :                         &bfd->rw_bytes,   /* bytes written */
     337             :                         1,                /* Abort */
     338             :                         1,                /* ProcessSecurity */
     339             :                         &bfd->lpContext)) /* Write context */
     340             :                 {
     341             :                         bfile_error(NULL);
     342             :                         goto end;
     343             :                 }
     344             :         }
     345             :         if(!CloseHandle(bfd->fh))
     346             :         {
     347             :                 bfile_error(NULL);
     348             :                 goto end;
     349             :         }
     350             : 
     351             :         if(bfd->mode==BF_WRITE)
     352             :                 attribs_set(asfd,
     353             :                         bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
     354             :         bfd->lpContext=NULL;
     355             :         bfd->mode=BF_CLOSED;
     356             : 
     357             :         ret=0;
     358             : end:
     359             :         if(bfd->path)
     360             :         {
     361             :                 free(bfd->path);
     362             :                 bfd->path=NULL;
     363             :         }
     364             :         return ret;
     365             : }
     366             : 
     367             : // Returns: bytes read on success, or 0 on EOF, -1 on error.
     368             : static ssize_t bfile_read(BFILE *bfd, void *buf, size_t count)
     369             : {
     370             :         bfd->rw_bytes=0;
     371             : 
     372             :         if(bfd->use_backup_api)
     373             :         {
     374             :                 if(!p_BackupRead(bfd->fh,
     375             :                         (BYTE *)buf,
     376             :                         count,
     377             :                         &bfd->rw_bytes,
     378             :                         0,                /* no Abort */
     379             :                         1,                /* Process Security */
     380             :                         &bfd->lpContext)) /* Context */
     381             :                                 return bfile_error(bfd);
     382             :         }
     383             :         else
     384             :         {
     385             :                 if(!ReadFile(bfd->fh,
     386             :                         buf,
     387             :                         count,
     388             :                         &bfd->rw_bytes,
     389             :                         NULL))
     390             :                                 return bfile_error(bfd);
     391             :         }
     392             : 
     393             :         return (ssize_t)bfd->rw_bytes;
     394             : }
     395             : 
     396             : static ssize_t bfile_write(BFILE *bfd, void *buf, size_t count)
     397             : {
     398             :         bfd->rw_bytes = 0;
     399             : 
     400             :         if(bfd->use_backup_api)
     401             :         {
     402             :                 if(!p_BackupWrite(bfd->fh,
     403             :                         (BYTE *)buf,
     404             :                         count,
     405             :                         &bfd->rw_bytes,
     406             :                         0,                /* No abort */
     407             :                         1,                /* Process Security */
     408             :                         &bfd->lpContext)) /* Context */
     409             :                                 return bfile_error(bfd);
     410             :         }
     411             :         else
     412             :         {
     413             :                 if(!WriteFile(bfd->fh,
     414             :                         buf,
     415             :                         count,
     416             :                         &bfd->rw_bytes,
     417             :                         NULL))
     418             :                                 return bfile_error(bfd);
     419             :         }
     420             :         return (ssize_t)bfd->rw_bytes;
     421             : }
     422             : 
     423             : #else
     424             : 
     425           2 : static int bfile_close(BFILE *bfd, struct asfd *asfd)
     426             : {
     427           2 :         if(!bfd || bfd->mode==BF_CLOSED) return 0;
     428             : 
     429           0 :         if(!close(bfd->fd))
     430             :         {
     431           0 :                 if(bfd->mode==BF_WRITE)
     432             :                         attribs_set(asfd, bfd->path,
     433           0 :                                 &bfd->statp, bfd->winattr, bfd->cntr);
     434           0 :                 bfd->mode=BF_CLOSED;
     435           0 :                 bfd->fd=-1;
     436           0 :                 free_w(&bfd->path);
     437           0 :                 return 0;
     438             :         }
     439           0 :         free_w(&bfd->path);
     440           0 :         return -1;
     441             : }
     442             : 
     443           0 : static int bfile_open(BFILE *bfd,
     444             :         struct asfd *asfd, const char *fname, int flags, mode_t mode)
     445             : {
     446           0 :         if(!bfd) return 0;
     447           0 :         if(bfd->mode!=BF_CLOSED && bfd->close(bfd, asfd))
     448           0 :                 return -1;
     449           0 :         if((bfd->fd=open(fname, flags, mode))<0)
     450           0 :                 return -1;
     451           0 :         if(flags & O_CREAT || flags & O_WRONLY)
     452           0 :                 bfd->mode=BF_WRITE;
     453             :         else
     454           0 :                 bfd->mode=BF_READ;
     455           0 :         if(!(bfd->path=strdup_w(fname, __func__)))
     456           0 :                 return -1;
     457           0 :         return 0;
     458             : }
     459             : 
     460           0 : static ssize_t bfile_read(BFILE *bfd, void *buf, size_t count)
     461             : {
     462           0 :         return read(bfd->fd, buf, count);
     463             : }
     464             : 
     465           0 : static ssize_t bfile_write(BFILE *bfd, void *buf, size_t count)
     466             : {
     467           0 :         return write(bfd->fd, buf, count);
     468             : }
     469             : 
     470             : #endif
     471             : 
     472           0 : static int bfile_open_for_send(BFILE *bfd, struct asfd *asfd,
     473             :         const char *fname, int64_t winattr, int atime,
     474             :         struct cntr *cntr, enum protocol protocol)
     475             : {
     476           0 :         if(protocol==PROTO_1
     477           0 :           && bfd->mode!=BF_CLOSED)
     478             :         {
     479             : #ifdef HAVE_WIN32
     480             :                 if(bfd->path && !strcmp(bfd->path, fname))
     481             :                 {
     482             :                         // Already open after reading the VSS data.
     483             :                         // Time now for the actual file data.
     484             :                         return 0;
     485             :                 }
     486             :                 else
     487             :                 {
     488             : #endif
     489             :                         // Close the open bfd so that it can be
     490             :                         // used again
     491           0 :                         bfd->close(bfd, asfd);
     492             : #ifdef HAVE_WIN32
     493             :                 }
     494             : #endif
     495             :         }
     496             : 
     497           0 :         bfile_init(bfd, winattr, cntr);
     498           0 :         if(bfile_open(bfd, asfd, fname, O_RDONLY|O_BINARY
     499             : #ifdef O_NOATIME
     500             :                 |atime?0:O_NOATIME
     501             : #endif
     502           0 :                 , 0))
     503             :         {
     504             :                 berrno be;
     505           0 :                 berrno_init(&be);
     506             :                 logw(asfd, cntr,
     507             :                         "Could not open %s: %s\n",
     508           0 :                         fname, berrno_bstrerror(&be, errno));
     509           0 :                 return -1;
     510             :         }
     511           0 :         return 0;
     512             : }
     513             : 
     514       32803 : void bfile_setup_funcs(BFILE *bfd)
     515             : {
     516       32803 :         bfd->open=bfile_open;
     517       32803 :         bfd->close=bfile_close;
     518       32803 :         bfd->read=bfile_read;
     519       32803 :         bfd->write=bfile_write;
     520       32803 :         bfd->open_for_send=bfile_open_for_send;
     521             : #ifdef HAVE_WIN32
     522             :         bfd->set_win32_api=bfile_set_win32_api;
     523             : #endif
     524       32803 : }
     525             : 
     526           2 : void bfile_init(BFILE *bfd, int64_t winattr, struct cntr *cntr)
     527             : {
     528           2 :         memset(bfd, 0, sizeof(BFILE));
     529           2 :         bfd->mode=BF_CLOSED;
     530           2 :         bfd->winattr=winattr;
     531           2 :         bfd->cntr=cntr;
     532           2 :         if(!bfd->open) bfile_setup_funcs(bfd);
     533             : #ifdef HAVE_WIN32
     534             :         bfile_set_win32_api(bfd, 1);
     535             : #else
     536           2 :         bfd->fd=-1;
     537             : #endif
     538           2 : }
     539             : 
     540           2 : BFILE *bfile_alloc(void)
     541             : {
     542           2 :         return (BFILE *)calloc_w(1, sizeof(BFILE), __func__);
     543             : }

Generated by: LCOV version 1.10