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 60 : static int bfile_close(struct BFILE *bfd, struct asfd *asfd)
418 : {
419 60 : if(!bfd || bfd->mode==BF_CLOSED) return 0;
420 :
421 49 : if(!close(bfd->fd))
422 : {
423 49 : 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 49 : bfd->mode=BF_CLOSED;
427 49 : bfd->fd=-1;
428 49 : free_w(&bfd->path);
429 49 : return 0;
430 : }
431 0 : free_w(&bfd->path);
432 0 : return -1;
433 : }
434 :
435 49 : static int bfile_open(struct BFILE *bfd,
436 : struct asfd *asfd, const char *fname, int flags, mode_t mode)
437 : {
438 49 : if(!bfd) return 0;
439 49 : if(bfd->mode!=BF_CLOSED && bfd->close(bfd, asfd))
440 : return -1;
441 49 : if((bfd->fd=open(fname, flags, mode))<0)
442 : return -1;
443 49 : if(flags & O_CREAT || flags & O_WRONLY)
444 18 : bfd->mode=BF_WRITE;
445 : else
446 31 : bfd->mode=BF_READ;
447 49 : if(!(bfd->path=strdup_w(fname, __func__)))
448 : return -1;
449 49 : return 0;
450 : }
451 :
452 54 : static ssize_t bfile_read(struct BFILE *bfd, void *buf, size_t count)
453 : {
454 108 : 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 31 : 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 31 : 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 31 : bfile_init(bfd, winattr, cntr);
490 31 : 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 100622 : void bfile_setup_funcs(struct BFILE *bfd)
507 : {
508 100688 : bfd->open=bfile_open;
509 100688 : bfd->close=bfile_close;
510 100688 : bfd->read=bfile_read;
511 100688 : bfd->write=bfile_write;
512 100688 : bfd->open_for_send=bfile_open_for_send;
513 : #ifdef HAVE_WIN32
514 : bfd->set_win32_api=bfile_set_win32_api;
515 : #endif
516 100622 : }
517 :
518 66 : void bfile_init(struct BFILE *bfd, int64_t winattr, struct cntr *cntr)
519 : {
520 : memset(bfd, 0, sizeof(struct BFILE));
521 66 : bfd->mode=BF_CLOSED;
522 66 : bfd->winattr=winattr;
523 66 : bfd->cntr=cntr;
524 66 : if(!bfd->open) bfile_setup_funcs(bfd);
525 : #ifdef HAVE_WIN32
526 : bfile_set_win32_api(bfd, 1);
527 : #else
528 66 : bfd->fd=-1;
529 : #endif
530 66 : }
531 :
532 13 : struct BFILE *bfile_alloc(void)
533 : {
534 13 : return (struct BFILE *)calloc_w(1, sizeof(struct BFILE), __func__);
535 : }
|