1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, November MM
25 */
26 /**
27 * @file
28 * Bareos File Daemon restore.c Restorefiles.
29 */
30
31 #include "include/bareos.h"
32 #include "filed/filed.h"
33 #include "filed/filed_globals.h"
34 #include "filed/jcr_private.h"
35 #include "filed/compression.h"
36 #include "filed/crypto.h"
37 #include "filed/restore.h"
38 #include "filed/verify.h"
39 #include "include/ch.h"
40 #include "findlib/create_file.h"
41 #include "findlib/attribs.h"
42 #include "findlib/find.h"
43 #include "lib/berrno.h"
44 #include "lib/bget_msg.h"
45 #include "lib/bnet.h"
46 #include "lib/bsock.h"
47 #include "lib/edit.h"
48 #include "lib/parse_conf.h"
49 #include "include/make_unique.h"
50
51 #ifdef HAVE_WIN32
52 #include "win32/findlib/win32.h"
53 #endif
54
55 #if defined(HAVE_DARWIN_OS)
56 #include <sys/attr.h>
57 #endif
58
59 namespace filedaemon {
60
61 #if defined(HAVE_DARWIN_OS)
62 const bool have_darwin_os = true;
63 #else
64 const bool have_darwin_os = false;
65 #endif
66
67 #if defined(HAVE_CRYPTO)
68 const bool have_crypto = true;
69 #else
70 const bool have_crypto = false;
71 #endif
72
73 #if defined(HAVE_ACL)
74 const bool have_acl = true;
75 #else
76 const bool have_acl = false;
77 #endif
78
79 #if defined(HAVE_SHA2)
80 const bool have_sha2 = true;
81 #else
82 const bool have_sha2 = false;
83 #endif
84
85 #if defined(HAVE_XATTR)
86 const bool have_xattr = true;
87 #else
88 const bool have_xattr = false;
89 #endif
90
91 /**
92 * Data received from Storage Daemon
93 */
94 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
95
96 /**
97 * Forward referenced functions
98 */
99 #if defined(HAVE_LIBZ)
100 const bool have_libz = true;
101 #else
102 const bool have_libz = false;
103 #endif
104 #if defined(HAVE_LZO)
105 const bool have_lzo = true;
106 #else
107 const bool have_lzo = false;
108 #endif
109 const bool have_fastlz = true;
110
111 static void FreeSignature(r_ctx& rctx);
112 static bool ClosePreviousStream(JobControlRecord* jcr, r_ctx& rctx);
113
114 int32_t ExtractData(JobControlRecord* jcr,
115 BareosWinFilePacket* bfd,
116 POOLMEM* buf,
117 int32_t buflen,
118 uint64_t* addr,
119 char* flags,
120 int32_t stream,
121 RestoreCipherContext* cipher_ctx);
122
123 /**
124 * Close a bfd check that we are at the expected file offset.
125 * Makes use of some code from SetAttributes().
126 */
BcloseChksize(JobControlRecord * jcr,BareosWinFilePacket * bfd,boffset_t osize)127 static int BcloseChksize(JobControlRecord* jcr,
128 BareosWinFilePacket* bfd,
129 boffset_t osize)
130 {
131 char ec1[50], ec2[50];
132 boffset_t fsize;
133
134 fsize = blseek(bfd, 0, SEEK_CUR);
135 bclose(bfd);
136 if (fsize > 0 && fsize != osize) {
137 Qmsg3(jcr, M_WARNING, 0,
138 _("Size of data or stream of %s not correct. Original %s, restored "
139 "%s.\n"),
140 jcr->impl->last_fname, edit_uint64(osize, ec1),
141 edit_uint64(fsize, ec2));
142 return -1;
143 }
144 return 0;
145 }
146
RestoreFinderinfo(JobControlRecord * jcr,POOLMEM * buf,int32_t buflen)147 static inline bool RestoreFinderinfo(JobControlRecord* jcr,
148 POOLMEM* buf,
149 int32_t buflen)
150 {
151 #ifdef HAVE_DARWIN_OS
152 struct attrlist attrList;
153
154 memset(&attrList, 0, sizeof(attrList));
155 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
156 attrList.commonattr = ATTR_CMN_FNDRINFO;
157
158 Dmsg0(130, "Restoring Finder Info\n");
159 SetBit(FO_HFSPLUS, jcr->impl->ff->flags);
160 if (buflen != 32) {
161 Jmsg(jcr, M_WARNING, 0,
162 _("Invalid length of Finder Info (got %d, not 32)\n"), buflen);
163 return false;
164 }
165
166 if (setattrlist(jcr->impl->last_fname, &attrList, buf, buflen, 0) != 0) {
167 Jmsg(jcr, M_WARNING, 0, _("Could not set Finder Info on %s\n"),
168 jcr->impl->last_fname);
169 return false;
170 }
171
172 return true;
173 #else
174 return true;
175 #endif
176 }
177
178 /**
179 * Cleanup of delayed restore stack with streams for later processing.
180 */
DropDelayedDataStreams(r_ctx & rctx,bool reuse)181 static inline void DropDelayedDataStreams(r_ctx& rctx, bool reuse)
182 {
183 DelayedDataStream* dds = nullptr;
184
185 if (!rctx.delayed_streams || rctx.delayed_streams->empty()) { return; }
186
187 foreach_alist (dds, rctx.delayed_streams) {
188 free(dds->content);
189 }
190
191 rctx.delayed_streams->destroy();
192 if (reuse) { rctx.delayed_streams->init(10, owned_by_alist); }
193 }
194
195 /**
196 * Push a data stream onto the delayed restore stack for later processing.
197 */
PushDelayedDataStream(r_ctx & rctx,BareosSocket * sd)198 static inline void PushDelayedDataStream(r_ctx& rctx, BareosSocket* sd)
199 {
200 DelayedDataStream* dds;
201
202 if (!rctx.delayed_streams) {
203 rctx.delayed_streams = new alist(10, owned_by_alist);
204 }
205
206 dds = (DelayedDataStream*)malloc(sizeof(DelayedDataStream));
207 dds->stream = rctx.stream;
208 dds->content = (char*)malloc(sd->message_length);
209 memcpy(dds->content, sd->msg, sd->message_length);
210 dds->content_length = sd->message_length;
211
212 rctx.delayed_streams->append(dds);
213 }
214
215 /**
216 * Perform a restore of an ACL using the stream received.
217 * This can either be a delayed restore or direct restore.
218 */
do_reStoreAcl(JobControlRecord * jcr,int stream,char * content,uint32_t content_length)219 static inline bool do_reStoreAcl(JobControlRecord* jcr,
220 int stream,
221 char* content,
222 uint32_t content_length)
223
224 {
225 bacl_exit_code retval;
226
227 jcr->impl->acl_data->last_fname = jcr->impl->last_fname;
228 switch (stream) {
229 case STREAM_ACL_PLUGIN:
230 retval = plugin_parse_acl_streams(jcr, jcr->impl->acl_data.get(), stream,
231 content, content_length);
232 break;
233 default:
234 retval = parse_acl_streams(jcr, jcr->impl->acl_data.get(), stream,
235 content, content_length);
236 break;
237 }
238
239 switch (retval) {
240 case bacl_exit_fatal:
241 return false;
242 case bacl_exit_error:
243 /*
244 * Non-fatal errors, count them and when the number is under
245 * ACL_REPORT_ERR_MAX_PER_JOB print the error message set by the lower
246 * level routine in jcr->errmsg.
247 */
248 if (jcr->impl->acl_data->u.parse->nr_errors <
249 ACL_REPORT_ERR_MAX_PER_JOB) {
250 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
251 }
252 jcr->impl->acl_data->u.parse->nr_errors++;
253 break;
254 case bacl_exit_ok:
255 break;
256 }
257
258 return true;
259 }
260
261 /**
262 * Perform a restore of an XATTR using the stream received.
263 * This can either be a delayed restore or direct restore.
264 */
do_restore_xattr(JobControlRecord * jcr,int stream,char * content,uint32_t content_length)265 static inline bool do_restore_xattr(JobControlRecord* jcr,
266 int stream,
267 char* content,
268 uint32_t content_length)
269 {
270 BxattrExitCode retval;
271
272 jcr->impl->xattr_data->last_fname = jcr->impl->last_fname;
273 switch (stream) {
274 case STREAM_XATTR_PLUGIN:
275 retval = PluginParseXattrStreams(jcr, jcr->impl->xattr_data.get(), stream,
276 content, content_length);
277 break;
278 default:
279 retval = ParseXattrStreams(jcr, jcr->impl->xattr_data.get(), stream,
280 content, content_length);
281 break;
282 }
283
284 switch (retval) {
285 case BxattrExitCode::kErrorFatal:
286 return false;
287 case BxattrExitCode::kWarning:
288 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
289 break;
290 case BxattrExitCode::kError:
291 Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
292 jcr->impl->xattr_data->u.parse->nr_errors++;
293 break;
294 case BxattrExitCode::kSuccess:
295 break;
296 }
297
298 return true;
299 }
300
301 /**
302 * Restore any data streams that are restored after the file
303 * is fully restored and has its attributes restored. Things
304 * like acls and xattr are restored after we set the file
305 * attributes otherwise we might clear some security flags
306 * by setting the attributes.
307 */
PopDelayedDataStreams(JobControlRecord * jcr,r_ctx & rctx)308 static inline bool PopDelayedDataStreams(JobControlRecord* jcr, r_ctx& rctx)
309 {
310 DelayedDataStream* dds = nullptr;
311
312 /*
313 * See if there is anything todo.
314 */
315 if (!rctx.delayed_streams || rctx.delayed_streams->empty()) { return true; }
316
317 /*
318 * Only process known delayed data streams here.
319 * If you start using more delayed data streams
320 * be sure to add them in this loop and add the
321 * proper calls here.
322 *
323 * Currently we support delayed data stream
324 * processing for the following type of streams:
325 * - *_ACL_*
326 * - *_XATTR_*
327 */
328 foreach_alist (dds, rctx.delayed_streams) {
329 switch (dds->stream) {
330 case STREAM_UNIX_ACCESS_ACL:
331 case STREAM_UNIX_DEFAULT_ACL:
332 case STREAM_ACL_AIX_TEXT:
333 case STREAM_ACL_DARWIN_ACCESS_ACL:
334 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
335 case STREAM_ACL_FREEBSD_ACCESS_ACL:
336 case STREAM_ACL_HPUX_ACL_ENTRY:
337 case STREAM_ACL_IRIX_DEFAULT_ACL:
338 case STREAM_ACL_IRIX_ACCESS_ACL:
339 case STREAM_ACL_LINUX_DEFAULT_ACL:
340 case STREAM_ACL_LINUX_ACCESS_ACL:
341 case STREAM_ACL_TRU64_DEFAULT_ACL:
342 case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
343 case STREAM_ACL_TRU64_ACCESS_ACL:
344 case STREAM_ACL_SOLARIS_ACLENT:
345 case STREAM_ACL_SOLARIS_ACE:
346 case STREAM_ACL_AFS_TEXT:
347 case STREAM_ACL_AIX_AIXC:
348 case STREAM_ACL_AIX_NFS4:
349 case STREAM_ACL_FREEBSD_NFS4_ACL:
350 case STREAM_ACL_HURD_DEFAULT_ACL:
351 case STREAM_ACL_HURD_ACCESS_ACL:
352 if (!do_reStoreAcl(jcr, dds->stream, dds->content,
353 dds->content_length)) {
354 goto bail_out;
355 }
356 free(dds->content);
357 break;
358 case STREAM_XATTR_PLUGIN:
359 case STREAM_XATTR_HURD:
360 case STREAM_XATTR_IRIX:
361 case STREAM_XATTR_TRU64:
362 case STREAM_XATTR_AIX:
363 case STREAM_XATTR_OPENBSD:
364 case STREAM_XATTR_SOLARIS_SYS:
365 case STREAM_XATTR_DARWIN:
366 case STREAM_XATTR_FREEBSD:
367 case STREAM_XATTR_LINUX:
368 case STREAM_XATTR_NETBSD:
369 if (!do_restore_xattr(jcr, dds->stream, dds->content,
370 dds->content_length)) {
371 goto bail_out;
372 }
373 free(dds->content);
374 break;
375 default:
376 Jmsg(jcr, M_WARNING, 0,
377 _("Unknown stream=%d ignored. This shouldn't happen!\n"),
378 dds->stream);
379 break;
380 }
381 }
382
383 /*
384 * We processed the stack so we can destroy it.
385 */
386 rctx.delayed_streams->destroy();
387
388 /*
389 * (Re)Initialize the stack for a new use.
390 */
391 rctx.delayed_streams->init(10, owned_by_alist);
392
393 return true;
394
395 bail_out:
396
397 /*
398 * Destroy the content of the stack and (re)initialize it for a new use.
399 */
400 DropDelayedDataStreams(rctx, true);
401
402 return false;
403 }
404
405 /**
406 * Restore the requested files.
407 */
DoRestore(JobControlRecord * jcr)408 void DoRestore(JobControlRecord* jcr)
409 {
410 BareosSocket* sd;
411 uint32_t VolSessionId, VolSessionTime;
412 int32_t file_index;
413 char ec1[50]; /* Buffer printing huge values */
414 uint32_t buf_size; /* client buffer size */
415 int status;
416 int64_t rsrc_len = 0; /* Original length of resource fork */
417 r_ctx rctx;
418 Attributes* attr;
419 /* ***FIXME*** make configurable */
420 crypto_digest_t signing_algorithm =
421 have_sha2 ? CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
422 /*
423 * The following variables keep track of "known unknowns"
424 */
425 int non_support_data = 0;
426 int non_support_attr = 0;
427 int non_support_rsrc = 0;
428 int non_support_finfo = 0;
429 int non_support_acl = 0;
430 int non_support_progname = 0;
431 int non_support_crypto = 0;
432 int non_support_xattr = 0;
433
434 rctx.jcr = jcr;
435
436 sd = jcr->store_bsock;
437 jcr->setJobStatus(JS_Running);
438
439 LockRes(my_config);
440 ClientResource* client =
441 (ClientResource*)my_config->GetNextRes(R_CLIENT, NULL);
442 UnlockRes(my_config);
443 if (client) {
444 buf_size = client->max_network_buffer_size;
445 } else {
446 buf_size = 0; /* use default */
447 }
448 if (!BnetSetBufferSize(sd, buf_size, BNET_SETBUF_WRITE)) {
449 jcr->setJobStatus(JS_ErrorTerminated);
450 return;
451 }
452 jcr->buf_size = sd->message_length;
453
454 if (have_libz || have_lzo || have_fastlz) {
455 if (!AdjustDecompressionBuffers(jcr)) { goto bail_out; }
456 }
457
458 if (have_crypto) {
459 rctx.cipher_ctx.buf = GetMemory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
460 if (have_darwin_os) {
461 rctx.fork_cipher_ctx.buf = GetMemory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
462 }
463 }
464
465 /*
466 * Get a record from the Storage daemon. We are guaranteed to
467 * receive records in the following order:
468 * 1. Stream record header
469 * 2. Stream data (one or more of the following in the order given)
470 * a. Attributes (Unix or Win32)
471 * b. Possibly stream encryption session data (e.g., symmetric session
472 * key) c. File data for the file d. Alternate data stream (e.g. Resource
473 * Fork) e. Finder info f. ACLs g. XATTRs h. Possibly a cryptographic
474 * signature i. Possibly MD5 or SHA1 record
475 * 3. Repeat step 1
476 *
477 * NOTE: We keep track of two bareos file descriptors:
478 * 1. bfd for file data.
479 * This fd is opened for non empty files when an attribute stream is
480 * encountered and closed when we find the next attribute stream.
481 * 2. fork_bfd for alternate data streams
482 * This fd is opened every time we encounter a new alternate data
483 * stream for the current file. When we find any other stream, we
484 * close it again.
485 * The expected size of the stream, fork_len, should be set when
486 * opening the fd.
487 * 3. Not all the stream data records are required -- e.g. if there
488 * is no fork, there is no alternate data stream, no ACL, ...
489 */
490 binit(&rctx.bfd);
491 binit(&rctx.forkbfd);
492 attr = rctx.attr = new_attr(jcr);
493 if (have_acl) {
494 jcr->impl->acl_data = std::make_unique<AclData>();
495 jcr->impl->acl_data->u.parse =
496 (acl_parse_data_t*)malloc(sizeof(acl_parse_data_t));
497 memset(jcr->impl->acl_data->u.parse, 0, sizeof(acl_parse_data_t));
498 }
499 if (have_xattr) {
500 jcr->impl->xattr_data = std::make_unique<XattrData>();
501 jcr->impl->xattr_data->u.parse =
502 (xattr_parse_data_t*)malloc(sizeof(xattr_parse_data_t));
503 memset(jcr->impl->xattr_data->u.parse, 0, sizeof(xattr_parse_data_t));
504 }
505
506 while (BgetMsg(sd) >= 0 && !JobCanceled(jcr)) {
507 /*
508 * Remember previous stream type
509 */
510 rctx.prev_stream = rctx.stream;
511
512 /*
513 * First we expect a Stream Record Header
514 */
515 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
516 &rctx.full_stream, &rctx.size) != 5) {
517 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
518 goto bail_out;
519 }
520 /* Strip off new stream high bits */
521 rctx.stream = rctx.full_stream & STREAMMASK_TYPE;
522 Dmsg5(150, "Got hdr: Files=%d FilInx=%d size=%d Stream=%d, %s.\n",
523 jcr->JobFiles, file_index, rctx.size, rctx.stream,
524 stream_to_ascii(rctx.stream));
525
526 /*
527 * Now we expect the Stream Data
528 */
529 if (BgetMsg(sd) < 0) {
530 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
531 goto bail_out;
532 }
533 if (rctx.size != (uint32_t)sd->message_length) {
534 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"),
535 sd->message_length, rctx.size);
536 Dmsg2(50, "Actual data size %d not same as header %d\n",
537 sd->message_length, rctx.size);
538 goto bail_out;
539 }
540 Dmsg3(130, "Got stream: %s len=%d extract=%d\n",
541 stream_to_ascii(rctx.stream), sd->message_length, rctx.extract);
542
543 /*
544 * If we change streams, close and reset alternate data streams
545 */
546 if (rctx.prev_stream != rctx.stream) {
547 if (IsBopen(&rctx.forkbfd)) {
548 DeallocateForkCipher(rctx);
549 BcloseChksize(jcr, &rctx.forkbfd, rctx.fork_size);
550 }
551 /*
552 * Use an impossible value and set a proper one below
553 */
554 rctx.fork_size = -1;
555 rctx.fork_addr = 0;
556 }
557
558 /*
559 * File Attributes stream
560 */
561 switch (rctx.stream) {
562 case STREAM_UNIX_ATTRIBUTES:
563 case STREAM_UNIX_ATTRIBUTES_EX:
564 /*
565 * if any previous stream open, close it
566 */
567 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
568
569 /*
570 * TODO: manage deleted files
571 */
572 if (rctx.type == FT_DELETED) { /* deleted file */
573 continue;
574 }
575 /*
576 * Restore objects should be ignored here -- they are
577 * returned at the beginning of the restore.
578 */
579 if (IS_FT_OBJECT(rctx.type)) { continue; }
580
581 /*
582 * Unpack attributes and do sanity check them
583 */
584 if (!UnpackAttributesRecord(jcr, rctx.stream, sd->msg,
585 sd->message_length, attr)) {
586 goto bail_out;
587 }
588
589 Dmsg3(100, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
590 attr->attr, attr->attrEx);
591 Dmsg3(100, "=== message_length=%d attrExlen=%d msg=%s\n",
592 sd->message_length, strlen(attr->attrEx), sd->msg);
593
594 attr->data_stream = DecodeStat(attr->attr, &attr->statp,
595 sizeof(attr->statp), &attr->LinkFI);
596
597 if (!IsRestoreStreamSupported(attr->data_stream)) {
598 if (!non_support_data++) {
599 Jmsg(jcr, M_WARNING, 0,
600 _("%s stream not supported on this Client.\n"),
601 stream_to_ascii(attr->data_stream));
602 }
603 continue;
604 }
605
606 BuildAttrOutputFnames(jcr, attr);
607
608 /*
609 * Try to actually create the file, which returns a status telling
610 * us if we need to extract or not.
611 */
612 jcr->impl->num_files_examined++;
613 rctx.extract = false;
614 status = CF_CORE; /* By default, let Bareos's core handle it */
615
616 if (jcr->IsPlugin()) {
617 status = PluginCreateFile(jcr, attr, &rctx.bfd, jcr->impl->replace);
618 }
619
620 if (status == CF_CORE) {
621 status = CreateFile(jcr, attr, &rctx.bfd, jcr->impl->replace);
622 }
623 jcr->lock();
624 PmStrcpy(jcr->impl->last_fname, attr->ofname);
625 jcr->impl->last_type = attr->type;
626 jcr->unlock();
627 Dmsg2(130, "Outfile=%s CreateFile status=%d\n", attr->ofname, status);
628 switch (status) {
629 case CF_ERROR:
630 break;
631 case CF_SKIP:
632 jcr->JobFiles++;
633 break;
634 case CF_EXTRACT:
635 /*
636 * File created and we expect file data
637 */
638 rctx.extract = true;
639 /*
640 * FALLTHROUGH
641 */
642 case CF_CREATED:
643 /*
644 * File created, but there is no content
645 */
646 rctx.fileAddr = 0;
647 PrintLsOutput(jcr, attr);
648
649 if (have_darwin_os) {
650 /*
651 * Only restore the resource fork for regular files
652 */
653 FromBase64(&rsrc_len, attr->attrEx);
654 if (attr->type == FT_REG && rsrc_len > 0) { rctx.extract = true; }
655
656 /*
657 * Do not count the resource forks as regular files being
658 * restored.
659 */
660 if (rsrc_len == 0) { jcr->JobFiles++; }
661 } else {
662 jcr->JobFiles++;
663 }
664
665 if (!rctx.extract) {
666 /*
667 * Set attributes now because file will not be extracted
668 */
669 if (jcr->IsPlugin()) {
670 PluginSetAttributes(jcr, attr, &rctx.bfd);
671 } else {
672 SetAttributes(jcr, attr, &rctx.bfd);
673 }
674 }
675 break;
676 }
677 break;
678
679 /*
680 * Data stream
681 */
682 case STREAM_ENCRYPTED_SESSION_DATA:
683 if (rctx.extract) {
684 crypto_error_t cryptoerr;
685
686 /*
687 * Is this an unexpected session data entry?
688 */
689 if (rctx.cs) {
690 Jmsg0(jcr, M_ERROR, 0,
691 _("Unexpected cryptographic session data stream.\n"));
692 rctx.extract = false;
693 bclose(&rctx.bfd);
694 continue;
695 }
696
697 /*
698 * Do we have any keys at all?
699 */
700 if (!jcr->impl->crypto.pki_recipients) {
701 Jmsg(jcr, M_ERROR, 0,
702 _("No private decryption keys have been defined to decrypt "
703 "encrypted backup data.\n"));
704 rctx.extract = false;
705 bclose(&rctx.bfd);
706 break;
707 }
708
709 if (jcr->impl->crypto.digest) {
710 CryptoDigestFree(jcr->impl->crypto.digest);
711 }
712 jcr->impl->crypto.digest = crypto_digest_new(jcr, signing_algorithm);
713 if (!jcr->impl->crypto.digest) {
714 Jmsg0(jcr, M_FATAL, 0, _("Could not create digest.\n"));
715 rctx.extract = false;
716 bclose(&rctx.bfd);
717 break;
718 }
719
720 /*
721 * Decode and save session keys.
722 */
723 cryptoerr = CryptoSessionDecode(
724 (uint8_t*)sd->msg, (uint32_t)sd->message_length,
725 jcr->impl->crypto.pki_recipients, &rctx.cs);
726 switch (cryptoerr) {
727 case CRYPTO_ERROR_NONE:
728 /*
729 * Success
730 */
731 break;
732 case CRYPTO_ERROR_NORECIPIENT:
733 Jmsg(jcr, M_ERROR, 0,
734 _("Missing private key required to decrypt encrypted backup "
735 "data.\n"));
736 break;
737 case CRYPTO_ERROR_DECRYPTION:
738 Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.\n"));
739 break;
740 default:
741 /*
742 * Shouldn't happen
743 */
744 Jmsg1(jcr, M_ERROR, 0,
745 _("An error occurred while decoding encrypted session data "
746 "stream: %s\n"),
747 crypto_strerror(cryptoerr));
748 break;
749 }
750
751 if (cryptoerr != CRYPTO_ERROR_NONE) {
752 rctx.extract = false;
753 bclose(&rctx.bfd);
754 continue;
755 }
756 }
757 break;
758
759 case STREAM_FILE_DATA:
760 case STREAM_SPARSE_DATA:
761 case STREAM_WIN32_DATA:
762 case STREAM_GZIP_DATA:
763 case STREAM_SPARSE_GZIP_DATA:
764 case STREAM_WIN32_GZIP_DATA:
765 case STREAM_COMPRESSED_DATA:
766 case STREAM_SPARSE_COMPRESSED_DATA:
767 case STREAM_WIN32_COMPRESSED_DATA:
768 case STREAM_ENCRYPTED_FILE_DATA:
769 case STREAM_ENCRYPTED_WIN32_DATA:
770 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
771 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
772 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
773 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
774 if (rctx.extract) {
775 bool process_data = false;
776
777 /*
778 * Force an expected, consistent stream type here
779 * First see if we need to process the data and
780 * set the flags.
781 */
782 if (rctx.prev_stream == rctx.stream) {
783 process_data = true;
784 } else {
785 switch (rctx.prev_stream) {
786 case STREAM_UNIX_ATTRIBUTES:
787 case STREAM_UNIX_ATTRIBUTES_EX:
788 case STREAM_ENCRYPTED_SESSION_DATA:
789 process_data = true;
790 break;
791 default:
792 break;
793 }
794 }
795
796 /*
797 * If process_data is set in the test above continue here with the
798 * processing of the data based on the stream type available.
799 */
800 if (process_data) {
801 ClearAllBits(FO_MAX, rctx.flags);
802 switch (rctx.stream) {
803 case STREAM_SPARSE_DATA:
804 SetBit(FO_SPARSE, rctx.flags);
805 break;
806 case STREAM_SPARSE_GZIP_DATA:
807 case STREAM_SPARSE_COMPRESSED_DATA:
808 SetBit(FO_SPARSE, rctx.flags);
809 SetBit(FO_COMPRESS, rctx.flags);
810 rctx.comp_stream = rctx.stream;
811 break;
812 case STREAM_GZIP_DATA:
813 case STREAM_COMPRESSED_DATA:
814 case STREAM_WIN32_GZIP_DATA:
815 case STREAM_WIN32_COMPRESSED_DATA:
816 SetBit(FO_COMPRESS, rctx.flags);
817 rctx.comp_stream = rctx.stream;
818 break;
819 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
820 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
821 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
822 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
823 if (!rctx.cipher_ctx.cipher) {
824 if (!SetupDecryptionContext(rctx, rctx.cipher_ctx)) {
825 rctx.extract = false;
826 bclose(&rctx.bfd);
827 continue;
828 }
829 }
830 SetBit(FO_COMPRESS, rctx.flags);
831 SetBit(FO_ENCRYPT, rctx.flags);
832 rctx.comp_stream = rctx.stream;
833 break;
834 case STREAM_ENCRYPTED_FILE_DATA:
835 case STREAM_ENCRYPTED_WIN32_DATA:
836 if (!rctx.cipher_ctx.cipher) {
837 if (!SetupDecryptionContext(rctx, rctx.cipher_ctx)) {
838 rctx.extract = false;
839 bclose(&rctx.bfd);
840 continue;
841 }
842 }
843 SetBit(FO_ENCRYPT, rctx.flags);
844 break;
845 default:
846 break;
847 }
848
849 /*
850 * Check for a win32 stream type on a system without the win32 API.
851 * On those we decompose the BackupWrite data.
852 */
853 if (is_win32_stream(rctx.stream) && !have_win32_api()) {
854 SetPortableBackup(&rctx.bfd);
855 /*
856 * "decompose" BackupWrite data
857 */
858 SetBit(FO_WIN32DECOMP, rctx.flags);
859 }
860
861 if (ExtractData(jcr, &rctx.bfd, sd->msg, sd->message_length,
862 &rctx.fileAddr, rctx.flags, rctx.stream,
863 &rctx.cipher_ctx) < 0) {
864 rctx.extract = false;
865 bclose(&rctx.bfd);
866 continue;
867 }
868 }
869 }
870 break;
871
872 /*
873 * Resource fork stream - only recorded after a file to be restored
874 * Silently ignore if we cannot write - we already reported that
875 */
876 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
877 case STREAM_MACOS_FORK_DATA:
878 if (have_darwin_os) {
879 ClearAllBits(FO_MAX, rctx.fork_flags);
880 SetBit(FO_HFSPLUS, jcr->impl->ff->flags);
881
882 if (rctx.stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) {
883 SetBit(FO_ENCRYPT, rctx.fork_flags);
884 if (rctx.extract && !rctx.fork_cipher_ctx.cipher) {
885 if (!SetupDecryptionContext(rctx, rctx.fork_cipher_ctx)) {
886 rctx.extract = false;
887 bclose(&rctx.bfd);
888 continue;
889 }
890 }
891 }
892
893 if (rctx.extract) {
894 if (rctx.prev_stream != rctx.stream) {
895 if (BopenRsrc(&rctx.forkbfd, jcr->impl->last_fname,
896 O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
897 Jmsg(jcr, M_WARNING, 0,
898 _("Cannot open resource fork for %s.\n"),
899 jcr->impl->last_fname);
900 rctx.extract = false;
901 continue;
902 }
903
904 rctx.fork_size = rsrc_len;
905 Dmsg0(130, "Restoring resource fork\n");
906 }
907
908 if (ExtractData(jcr, &rctx.forkbfd, sd->msg, sd->message_length,
909 &rctx.fork_addr, rctx.fork_flags, rctx.stream,
910 &rctx.fork_cipher_ctx) < 0) {
911 rctx.extract = false;
912 bclose(&rctx.forkbfd);
913 continue;
914 }
915 }
916 } else {
917 non_support_rsrc++;
918 }
919 break;
920
921 case STREAM_HFSPLUS_ATTRIBUTES:
922 if (have_darwin_os) {
923 if (!RestoreFinderinfo(jcr, sd->msg, sd->message_length)) {
924 continue;
925 }
926 } else {
927 non_support_finfo++;
928 }
929 break;
930
931 case STREAM_UNIX_ACCESS_ACL:
932 case STREAM_UNIX_DEFAULT_ACL:
933 case STREAM_ACL_AIX_TEXT:
934 case STREAM_ACL_DARWIN_ACCESS_ACL:
935 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
936 case STREAM_ACL_FREEBSD_ACCESS_ACL:
937 case STREAM_ACL_HPUX_ACL_ENTRY:
938 case STREAM_ACL_IRIX_DEFAULT_ACL:
939 case STREAM_ACL_IRIX_ACCESS_ACL:
940 case STREAM_ACL_LINUX_DEFAULT_ACL:
941 case STREAM_ACL_LINUX_ACCESS_ACL:
942 case STREAM_ACL_TRU64_DEFAULT_ACL:
943 case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
944 case STREAM_ACL_TRU64_ACCESS_ACL:
945 case STREAM_ACL_SOLARIS_ACLENT:
946 case STREAM_ACL_SOLARIS_ACE:
947 case STREAM_ACL_AFS_TEXT:
948 case STREAM_ACL_AIX_AIXC:
949 case STREAM_ACL_AIX_NFS4:
950 case STREAM_ACL_FREEBSD_NFS4_ACL:
951 case STREAM_ACL_HURD_DEFAULT_ACL:
952 case STREAM_ACL_HURD_ACCESS_ACL:
953 /*
954 * Do not restore ACLs when
955 * a) The current file is not extracted
956 * b) and it is not a directory (they are never "extracted")
957 * c) or the file name is empty
958 */
959 if ((!rctx.extract && jcr->impl->last_type != FT_DIREND) ||
960 (*jcr->impl->last_fname == 0)) {
961 break;
962 }
963 if (have_acl) {
964 /*
965 * For anything that is not a directory we delay
966 * the restore of acls till a later stage.
967 */
968 if (jcr->impl->last_type != FT_DIREND) {
969 PushDelayedDataStream(rctx, sd);
970 } else {
971 if (!do_reStoreAcl(jcr, rctx.stream, sd->msg, sd->message_length)) {
972 goto bail_out;
973 }
974 }
975 } else {
976 non_support_acl++;
977 }
978 break;
979
980 case STREAM_XATTR_PLUGIN:
981 case STREAM_XATTR_HURD:
982 case STREAM_XATTR_IRIX:
983 case STREAM_XATTR_TRU64:
984 case STREAM_XATTR_AIX:
985 case STREAM_XATTR_OPENBSD:
986 case STREAM_XATTR_SOLARIS_SYS:
987 case STREAM_XATTR_DARWIN:
988 case STREAM_XATTR_FREEBSD:
989 case STREAM_XATTR_LINUX:
990 case STREAM_XATTR_NETBSD:
991 /*
992 * Do not restore Extended Attributes when
993 * a) The current file is not extracted
994 * b) and it is not a directory (they are never "extracted")
995 * c) or the file name is empty
996 */
997 if ((!rctx.extract && jcr->impl->last_type != FT_DIREND) ||
998 (*jcr->impl->last_fname == 0)) {
999 break;
1000 }
1001 if (have_xattr) {
1002 /*
1003 * For anything that is not a directory we delay
1004 * the restore of xattr till a later stage.
1005 */
1006 if (jcr->impl->last_type != FT_DIREND) {
1007 PushDelayedDataStream(rctx, sd);
1008 } else {
1009 if (!do_restore_xattr(jcr, rctx.stream, sd->msg,
1010 sd->message_length)) {
1011 goto bail_out;
1012 }
1013 }
1014 } else {
1015 non_support_xattr++;
1016 }
1017 break;
1018
1019 case STREAM_XATTR_SOLARIS:
1020 /*
1021 * Do not restore Extended Attributes when
1022 * a) The current file is not extracted
1023 * b) and it is not a directory (they are never "extracted")
1024 * c) or the file name is empty
1025 */
1026 if ((!rctx.extract && jcr->impl->last_type != FT_DIREND) ||
1027 (*jcr->impl->last_fname == 0)) {
1028 break;
1029 }
1030 if (have_xattr) {
1031 if (!do_restore_xattr(jcr, rctx.stream, sd->msg,
1032 sd->message_length)) {
1033 goto bail_out;
1034 }
1035 } else {
1036 non_support_xattr++;
1037 }
1038 break;
1039
1040 case STREAM_SIGNED_DIGEST:
1041 /*
1042 * Is this an unexpected signature?
1043 */
1044 if (rctx.sig) {
1045 Jmsg0(jcr, M_ERROR, 0,
1046 _("Unexpected cryptographic signature data stream.\n"));
1047 FreeSignature(rctx);
1048 continue;
1049 }
1050 /*
1051 * Save signature.
1052 */
1053 if (rctx.extract && (rctx.sig = crypto_sign_decode(
1054 jcr, (uint8_t*)sd->msg,
1055 (uint32_t)sd->message_length)) == NULL) {
1056 Jmsg1(jcr, M_ERROR, 0,
1057 _("Failed to decode message signature for %s\n"),
1058 jcr->impl->last_fname);
1059 }
1060 break;
1061
1062 case STREAM_MD5_DIGEST:
1063 case STREAM_SHA1_DIGEST:
1064 case STREAM_SHA256_DIGEST:
1065 case STREAM_SHA512_DIGEST:
1066 break;
1067
1068 case STREAM_PROGRAM_NAMES:
1069 case STREAM_PROGRAM_DATA:
1070 if (!non_support_progname) {
1071 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
1072 non_support_progname++;
1073 }
1074 break;
1075
1076 case STREAM_PLUGIN_NAME:
1077 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
1078 Dmsg1(50, "restore stream_plugin_name=%s\n", sd->msg);
1079 if (!PluginNameStream(jcr, sd->msg)) { goto bail_out; }
1080 break;
1081
1082 case STREAM_RESTORE_OBJECT:
1083 break; /* these are sent by Director */
1084
1085 default:
1086 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
1087 Jmsg(jcr, M_WARNING, 0,
1088 _("Unknown stream=%d ignored. This shouldn't happen!\n"),
1089 rctx.stream);
1090 Dmsg2(0, "Unknown stream=%d data=%s\n", rctx.stream, sd->msg);
1091 break;
1092 } /* end switch(stream) */
1093 } /* end while get_msg() */
1094
1095 /*
1096 * If output file is still open, it was the last one in the
1097 * archive since we just hit an end of file, so close the file.
1098 */
1099 if (IsBopen(&rctx.forkbfd)) {
1100 BcloseChksize(jcr, &rctx.forkbfd, rctx.fork_size);
1101 }
1102
1103 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
1104 jcr->setJobStatus(JS_Terminated);
1105 goto ok_out;
1106
1107 bail_out:
1108 jcr->setJobStatus(JS_ErrorTerminated);
1109
1110 ok_out:
1111 #ifdef HAVE_WIN32
1112 /*
1113 * Cleanup the copy thread if we restored any EFS data.
1114 */
1115 if (jcr->cp_thread) { win32_cleanup_copy_thread(jcr); }
1116 #endif
1117
1118 /*
1119 * First output the statistics.
1120 */
1121 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
1122 edit_uint64(jcr->JobBytes, ec1));
1123 if (have_acl && jcr->impl->acl_data->u.parse->nr_errors > 0) {
1124 Jmsg(jcr, M_WARNING, 0,
1125 _("Encountered %ld acl errors while doing restore\n"),
1126 jcr->impl->acl_data->u.parse->nr_errors);
1127 }
1128 if (have_xattr && jcr->impl->xattr_data->u.parse->nr_errors > 0) {
1129 Jmsg(jcr, M_WARNING, 0,
1130 _("Encountered %ld xattr errors while doing restore\n"),
1131 jcr->impl->xattr_data->u.parse->nr_errors);
1132 }
1133 if (non_support_data > 1 || non_support_attr > 1) {
1134 Jmsg(jcr, M_WARNING, 0,
1135 _("%d non-supported data streams and %d non-supported attrib streams "
1136 "ignored.\n"),
1137 non_support_data, non_support_attr);
1138 }
1139 if (non_support_rsrc) {
1140 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"),
1141 non_support_rsrc);
1142 }
1143 if (non_support_finfo) {
1144 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"),
1145 non_support_finfo);
1146 }
1147 if (non_support_acl) {
1148 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"),
1149 non_support_acl);
1150 }
1151 if (non_support_crypto) {
1152 Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"),
1153 non_support_crypto);
1154 }
1155 if (non_support_xattr) {
1156 Jmsg(jcr, M_INFO, 0, _("%d non-supported xattr streams ignored.\n"),
1157 non_support_xattr);
1158 }
1159
1160 /*
1161 * Free Signature & Crypto Data
1162 */
1163 FreeSignature(rctx);
1164 FreeSession(rctx);
1165 if (jcr->impl->crypto.digest) {
1166 CryptoDigestFree(jcr->impl->crypto.digest);
1167 jcr->impl->crypto.digest = NULL;
1168 }
1169
1170 /*
1171 * Free file cipher restore context
1172 */
1173 if (rctx.cipher_ctx.cipher) {
1174 CryptoCipherFree(rctx.cipher_ctx.cipher);
1175 rctx.cipher_ctx.cipher = NULL;
1176 }
1177
1178 if (rctx.cipher_ctx.buf) {
1179 FreePoolMemory(rctx.cipher_ctx.buf);
1180 rctx.cipher_ctx.buf = NULL;
1181 }
1182
1183 /*
1184 * Free alternate stream cipher restore context
1185 */
1186 if (rctx.fork_cipher_ctx.cipher) {
1187 CryptoCipherFree(rctx.fork_cipher_ctx.cipher);
1188 rctx.fork_cipher_ctx.cipher = NULL;
1189 }
1190 if (rctx.fork_cipher_ctx.buf) {
1191 FreePoolMemory(rctx.fork_cipher_ctx.buf);
1192 rctx.fork_cipher_ctx.buf = NULL;
1193 }
1194
1195 if (have_acl && jcr->impl->acl_data) { free(jcr->impl->acl_data->u.parse); }
1196
1197 if (have_xattr && jcr->impl->xattr_data) {
1198 free(jcr->impl->xattr_data->u.parse);
1199 }
1200
1201 /*
1202 * Free the delayed stream stack list.
1203 */
1204 if (rctx.delayed_streams) {
1205 DropDelayedDataStreams(rctx, false);
1206 delete rctx.delayed_streams;
1207 }
1208
1209 CleanupCompression(jcr);
1210
1211 bclose(&rctx.forkbfd);
1212 bclose(&rctx.bfd);
1213 FreeAttr(rctx.attr);
1214 }
1215
DoFileDigest(JobControlRecord * jcr,FindFilesPacket * ff_pkt,bool top_level)1216 int DoFileDigest(JobControlRecord* jcr, FindFilesPacket* ff_pkt, bool top_level)
1217 {
1218 Dmsg1(50, "DoFileDigest jcr=%p\n", jcr);
1219 return (DigestFile(jcr, ff_pkt, jcr->impl->crypto.digest));
1220 }
1221
SparseData(JobControlRecord * jcr,BareosWinFilePacket * bfd,uint64_t * addr,char ** data,uint32_t * length)1222 bool SparseData(JobControlRecord* jcr,
1223 BareosWinFilePacket* bfd,
1224 uint64_t* addr,
1225 char** data,
1226 uint32_t* length)
1227 {
1228 unser_declare;
1229 uint64_t faddr;
1230 char ec1[50];
1231
1232 UnserBegin(*data, OFFSET_FADDR_SIZE);
1233 unser_uint64(faddr);
1234 if (*addr != faddr) {
1235 *addr = faddr;
1236 if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
1237 BErrNo be;
1238 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
1239 edit_uint64(*addr, ec1), jcr->impl->last_fname,
1240 be.bstrerror(bfd->BErrNo));
1241 return false;
1242 }
1243 }
1244 *data += OFFSET_FADDR_SIZE;
1245 *length -= OFFSET_FADDR_SIZE;
1246 return true;
1247 }
1248
StoreData(JobControlRecord * jcr,BareosWinFilePacket * bfd,char * data,const int32_t length,bool win32_decomp)1249 bool StoreData(JobControlRecord* jcr,
1250 BareosWinFilePacket* bfd,
1251 char* data,
1252 const int32_t length,
1253 bool win32_decomp)
1254 {
1255 if (jcr->impl->crypto.digest) {
1256 CryptoDigestUpdate(jcr->impl->crypto.digest, (uint8_t*)data, length);
1257 }
1258
1259 if (win32_decomp) {
1260 if (!processWin32BackupAPIBlock(bfd, data, length)) {
1261 BErrNo be;
1262 Jmsg2(jcr, M_ERROR, 0,
1263 _("Write error in Win32 Block Decomposition on %s: %s\n"),
1264 jcr->impl->last_fname, be.bstrerror(bfd->BErrNo));
1265 return false;
1266 }
1267 #ifdef HAVE_WIN32
1268 } else {
1269 if (bfd->encrypted) {
1270 if (win32_send_to_copy_thread(jcr, bfd, data, length) !=
1271 (ssize_t)length) {
1272 BErrNo be;
1273 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
1274 jcr->impl->last_fname, be.bstrerror(bfd->BErrNo));
1275 return false;
1276 }
1277 } else {
1278 if (bwrite(bfd, data, length) != (ssize_t)length) {
1279 BErrNo be;
1280 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
1281 jcr->impl->last_fname, be.bstrerror(bfd->BErrNo));
1282 }
1283 }
1284 }
1285 #else
1286 } else if (bwrite(bfd, data, length) != (ssize_t)length) {
1287 BErrNo be;
1288 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), jcr->impl->last_fname,
1289 be.bstrerror(bfd->BErrNo));
1290 return false;
1291 }
1292 #endif
1293
1294 return true;
1295 }
1296
1297 /**
1298 * In the context of jcr, write data to bfd.
1299 * We write buflen bytes in buf at addr. addr is updated in place.
1300 * The flags specify whether to use sparse files or compression.
1301 * Return value is the number of bytes written, or -1 on errors.
1302 */
ExtractData(JobControlRecord * jcr,BareosWinFilePacket * bfd,POOLMEM * buf,int32_t buflen,uint64_t * addr,char * flags,int32_t stream,RestoreCipherContext * cipher_ctx)1303 int32_t ExtractData(JobControlRecord* jcr,
1304 BareosWinFilePacket* bfd,
1305 POOLMEM* buf,
1306 int32_t buflen,
1307 uint64_t* addr,
1308 char* flags,
1309 int32_t stream,
1310 RestoreCipherContext* cipher_ctx)
1311 {
1312 char* wbuf; /* write buffer */
1313 uint32_t wsize; /* write size */
1314 uint32_t rsize; /* read size */
1315 char ec1[50]; /* Buffer printing huge values */
1316
1317 rsize = buflen;
1318 jcr->ReadBytes += rsize;
1319 wsize = rsize;
1320 wbuf = buf;
1321
1322 if (BitIsSet(FO_ENCRYPT, flags)) {
1323 if (!DecryptData(jcr, &wbuf, &wsize, cipher_ctx)) { goto bail_out; }
1324 if (wsize == 0) { return 0; }
1325 }
1326
1327 if (BitIsSet(FO_SPARSE, flags) || BitIsSet(FO_OFFSETS, flags)) {
1328 if (!SparseData(jcr, bfd, addr, &wbuf, &wsize)) { goto bail_out; }
1329 }
1330
1331 if (BitIsSet(FO_COMPRESS, flags)) {
1332 if (!DecompressData(jcr, jcr->impl->last_fname, stream, &wbuf, &wsize,
1333 false)) {
1334 goto bail_out;
1335 }
1336 }
1337
1338 if (!StoreData(jcr, bfd, wbuf, wsize, BitIsSet(FO_WIN32DECOMP, flags))) {
1339 goto bail_out;
1340 }
1341 jcr->JobBytes += wsize;
1342 *addr += wsize;
1343 Dmsg2(130, "Write %u bytes, JobBytes=%s\n", wsize,
1344 edit_uint64(jcr->JobBytes, ec1));
1345
1346 /*
1347 * Clean up crypto buffers
1348 */
1349 if (BitIsSet(FO_ENCRYPT, flags)) {
1350 /*
1351 * Move any remaining data to start of buffer
1352 */
1353 if (cipher_ctx->buf_len > 0) {
1354 Dmsg1(130, "Moving %u buffered bytes to start of buffer\n",
1355 cipher_ctx->buf_len);
1356 memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
1357 cipher_ctx->buf_len);
1358 }
1359 /*
1360 * The packet was successfully written, reset the length so that the next
1361 * packet length may be re-read by UnserCryptoPacketLen()
1362 */
1363 cipher_ctx->packet_len = 0;
1364 }
1365
1366 return wsize;
1367
1368 bail_out:
1369 return -1;
1370 }
1371
1372 /**
1373 * If extracting, close any previous stream
1374 */
ClosePreviousStream(JobControlRecord * jcr,r_ctx & rctx)1375 static bool ClosePreviousStream(JobControlRecord* jcr, r_ctx& rctx)
1376 {
1377 /*
1378 * If extracting, it was from previous stream, so
1379 * close the output file and validate the signature.
1380 */
1381 if (rctx.extract) {
1382 if (rctx.size > 0 && !IsBopen(&rctx.bfd)) {
1383 Jmsg0(rctx.jcr, M_ERROR, 0,
1384 _("Logic error: output file should be open\n"));
1385 Dmsg2(000, "=== logic error size=%d bopen=%d\n", rctx.size,
1386 IsBopen(&rctx.bfd));
1387 }
1388
1389 if (rctx.prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
1390 DeallocateCipher(rctx);
1391 DeallocateForkCipher(rctx);
1392 }
1393
1394 #ifdef HAVE_WIN32
1395 if (jcr->cp_thread) { win32_flush_copy_thread(jcr); }
1396 #endif
1397
1398 if (jcr->IsPlugin()) {
1399 PluginSetAttributes(rctx.jcr, rctx.attr, &rctx.bfd);
1400 } else {
1401 SetAttributes(rctx.jcr, rctx.attr, &rctx.bfd);
1402 }
1403 rctx.extract = false;
1404
1405 /*
1406 * Now perform the delayed restore of some specific data streams.
1407 */
1408 if (!PopDelayedDataStreams(jcr, rctx)) { return false; }
1409
1410 /*
1411 * Verify the cryptographic signature, if any
1412 */
1413 rctx.type = rctx.attr->type;
1414 VerifySignature(rctx.jcr, rctx);
1415
1416 /*
1417 * Free Signature
1418 */
1419 FreeSignature(rctx);
1420 FreeSession(rctx);
1421 ClearAllBits(FO_MAX, rctx.jcr->impl->ff->flags);
1422 Dmsg0(130, "Stop extracting.\n");
1423 } else if (IsBopen(&rctx.bfd)) {
1424 Jmsg0(rctx.jcr, M_ERROR, 0,
1425 _("Logic error: output file should not be open\n"));
1426 Dmsg0(000, "=== logic error !open\n");
1427 bclose(&rctx.bfd);
1428 }
1429 return true;
1430 }
1431
FreeSignature(r_ctx & rctx)1432 static void FreeSignature(r_ctx& rctx)
1433 {
1434 if (rctx.sig) {
1435 CryptoSignFree(rctx.sig);
1436 rctx.sig = NULL;
1437 }
1438 }
1439
FreeSession(r_ctx & rctx)1440 void FreeSession(r_ctx& rctx)
1441 {
1442 if (rctx.cs) {
1443 CryptoSessionFree(rctx.cs);
1444 rctx.cs = NULL;
1445 }
1446 }
1447
1448 } /* namespace filedaemon */
1449