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 100655 : void bfile_setup_funcs(struct BFILE *bfd)
529 : {
530 100722 : bfd->open=bfile_open;
531 100722 : bfd->close=bfile_close;
532 100722 : bfd->read=bfile_read;
533 100722 : bfd->write=bfile_write;
534 100722 : bfd->open_for_send=bfile_open_for_send;
535 : #ifdef HAVE_WIN32
536 : bfd->set_win32_api=bfile_set_win32_api;
537 : #else
538 100722 : bfd->set_vss_strip=bfile_set_vss_strip;
539 : #endif
540 100655 : }
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 : }
|