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 : }
|