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