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-2020 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)
517 != 5) {
518 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
519 goto bail_out;
520 }
521 /* Strip off new stream high bits */
522 rctx.stream = rctx.full_stream & STREAMMASK_TYPE;
523 Dmsg5(150, "Got hdr: Files=%d FilInx=%d size=%d Stream=%d, %s.\n",
524 jcr->JobFiles, file_index, rctx.size, rctx.stream,
525 stream_to_ascii(rctx.stream));
526
527 /*
528 * Now we expect the Stream Data
529 */
530 if (BgetMsg(sd) < 0) {
531 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
532 goto bail_out;
533 }
534 if (rctx.size != (uint32_t)sd->message_length) {
535 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"),
536 sd->message_length, rctx.size);
537 Dmsg2(50, "Actual data size %d not same as header %d\n",
538 sd->message_length, rctx.size);
539 goto bail_out;
540 }
541 Dmsg3(130, "Got stream: %s len=%d extract=%d\n",
542 stream_to_ascii(rctx.stream), sd->message_length, rctx.extract);
543
544 /*
545 * If we change streams, close and reset alternate data streams
546 */
547 if (rctx.prev_stream != rctx.stream) {
548 if (IsBopen(&rctx.forkbfd)) {
549 DeallocateForkCipher(rctx);
550 BcloseChksize(jcr, &rctx.forkbfd, rctx.fork_size);
551 }
552 /*
553 * Use an impossible value and set a proper one below
554 */
555 rctx.fork_size = -1;
556 rctx.fork_addr = 0;
557 }
558
559 /*
560 * File Attributes stream
561 */
562 switch (rctx.stream) {
563 case STREAM_UNIX_ATTRIBUTES:
564 case STREAM_UNIX_ATTRIBUTES_EX:
565 /*
566 * if any previous stream open, close it
567 */
568 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
569
570 /*
571 * TODO: manage deleted files
572 */
573 if (rctx.type == FT_DELETED) { /* deleted file */
574 continue;
575 }
576 /*
577 * Restore objects should be ignored here -- they are
578 * returned at the beginning of the restore.
579 */
580 if (IS_FT_OBJECT(rctx.type)) { continue; }
581
582 /*
583 * Unpack attributes and do sanity check them
584 */
585 if (!UnpackAttributesRecord(jcr, rctx.stream, sd->msg,
586 sd->message_length, attr)) {
587 goto bail_out;
588 }
589
590 Dmsg3(100, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
591 attr->attr, attr->attrEx);
592 Dmsg3(100, "=== message_length=%d attrExlen=%d msg=%s\n",
593 sd->message_length, strlen(attr->attrEx), sd->msg);
594
595 attr->data_stream = DecodeStat(attr->attr, &attr->statp,
596 sizeof(attr->statp), &attr->LinkFI);
597
598 if (!IsRestoreStreamSupported(attr->data_stream)) {
599 if (!non_support_data++) {
600 Jmsg(jcr, M_WARNING, 0,
601 _("%s stream not supported on this Client.\n"),
602 stream_to_ascii(attr->data_stream));
603 }
604 continue;
605 }
606
607 BuildAttrOutputFnames(jcr, attr);
608
609 /*
610 * Try to actually create the file, which returns a status telling
611 * us if we need to extract or not.
612 */
613 jcr->impl->num_files_examined++;
614 rctx.extract = false;
615 status = CF_CORE; /* By default, let Bareos's core handle it */
616
617 if (jcr->IsPlugin()) {
618 status = PluginCreateFile(jcr, attr, &rctx.bfd, jcr->impl->replace);
619 }
620
621 if (status == CF_CORE) {
622 status = CreateFile(jcr, attr, &rctx.bfd, jcr->impl->replace);
623 }
624 jcr->lock();
625 PmStrcpy(jcr->impl->last_fname, attr->ofname);
626 jcr->impl->last_type = attr->type;
627 jcr->unlock();
628 Dmsg2(130, "Outfile=%s CreateFile status=%d\n", attr->ofname, status);
629 switch (status) {
630 case CF_ERROR:
631 break;
632 case CF_SKIP:
633 jcr->JobFiles++;
634 break;
635 case CF_EXTRACT:
636 /*
637 * File created and we expect file data
638 */
639 rctx.extract = true;
640 /*
641 * FALLTHROUGH
642 */
643 case CF_CREATED:
644 /*
645 * File created, but there is no content
646 */
647 rctx.fileAddr = 0;
648 PrintLsOutput(jcr, attr);
649
650 if (have_darwin_os) {
651 /*
652 * Only restore the resource fork for regular files
653 */
654 FromBase64(&rsrc_len, attr->attrEx);
655 if (attr->type == FT_REG && rsrc_len > 0) { rctx.extract = true; }
656
657 /*
658 * Do not count the resource forks as regular files being
659 * restored.
660 */
661 if (rsrc_len == 0) { jcr->JobFiles++; }
662 } else {
663 jcr->JobFiles++;
664 }
665
666 if (!rctx.extract) {
667 /*
668 * Set attributes now because file will not be extracted
669 */
670 if (jcr->IsPlugin()) {
671 PluginSetAttributes(jcr, attr, &rctx.bfd);
672 } else {
673 SetAttributes(jcr, attr, &rctx.bfd);
674 }
675 }
676 break;
677 }
678 break;
679
680 /*
681 * Data stream
682 */
683 case STREAM_ENCRYPTED_SESSION_DATA:
684 if (rctx.extract) {
685 crypto_error_t cryptoerr;
686
687 /*
688 * Is this an unexpected session data entry?
689 */
690 if (rctx.cs) {
691 Jmsg0(jcr, M_ERROR, 0,
692 _("Unexpected cryptographic session data stream.\n"));
693 rctx.extract = false;
694 bclose(&rctx.bfd);
695 continue;
696 }
697
698 /*
699 * Do we have any keys at all?
700 */
701 if (!jcr->impl->crypto.pki_recipients) {
702 Jmsg(jcr, M_ERROR, 0,
703 _("No private decryption keys have been defined to decrypt "
704 "encrypted backup data.\n"));
705 rctx.extract = false;
706 bclose(&rctx.bfd);
707 break;
708 }
709
710 if (jcr->impl->crypto.digest) {
711 CryptoDigestFree(jcr->impl->crypto.digest);
712 }
713 jcr->impl->crypto.digest = crypto_digest_new(jcr, signing_algorithm);
714 if (!jcr->impl->crypto.digest) {
715 Jmsg0(jcr, M_FATAL, 0, _("Could not create digest.\n"));
716 rctx.extract = false;
717 bclose(&rctx.bfd);
718 break;
719 }
720
721 /*
722 * Decode and save session keys.
723 */
724 cryptoerr = CryptoSessionDecode(
725 (uint8_t*)sd->msg, (uint32_t)sd->message_length,
726 jcr->impl->crypto.pki_recipients, &rctx.cs);
727 switch (cryptoerr) {
728 case CRYPTO_ERROR_NONE:
729 /*
730 * Success
731 */
732 break;
733 case CRYPTO_ERROR_NORECIPIENT:
734 Jmsg(jcr, M_ERROR, 0,
735 _("Missing private key required to decrypt encrypted backup "
736 "data.\n"));
737 break;
738 case CRYPTO_ERROR_DECRYPTION:
739 Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.\n"));
740 break;
741 default:
742 /*
743 * Shouldn't happen
744 */
745 Jmsg1(jcr, M_ERROR, 0,
746 _("An error occurred while decoding encrypted session data "
747 "stream: %s\n"),
748 crypto_strerror(cryptoerr));
749 break;
750 }
751
752 if (cryptoerr != CRYPTO_ERROR_NONE) {
753 rctx.extract = false;
754 bclose(&rctx.bfd);
755 continue;
756 }
757 }
758 break;
759
760 case STREAM_FILE_DATA:
761 case STREAM_SPARSE_DATA:
762 case STREAM_WIN32_DATA:
763 case STREAM_GZIP_DATA:
764 case STREAM_SPARSE_GZIP_DATA:
765 case STREAM_WIN32_GZIP_DATA:
766 case STREAM_COMPRESSED_DATA:
767 case STREAM_SPARSE_COMPRESSED_DATA:
768 case STREAM_WIN32_COMPRESSED_DATA:
769 case STREAM_ENCRYPTED_FILE_DATA:
770 case STREAM_ENCRYPTED_WIN32_DATA:
771 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
772 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
773 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
774 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
775 if (rctx.extract) {
776 bool process_data = false;
777
778 /*
779 * Force an expected, consistent stream type here
780 * First see if we need to process the data and
781 * set the flags.
782 */
783 if (rctx.prev_stream == rctx.stream) {
784 process_data = true;
785 } else {
786 switch (rctx.prev_stream) {
787 case STREAM_UNIX_ATTRIBUTES:
788 case STREAM_UNIX_ATTRIBUTES_EX:
789 case STREAM_ENCRYPTED_SESSION_DATA:
790 process_data = true;
791 break;
792 default:
793 break;
794 }
795 }
796
797 /*
798 * If process_data is set in the test above continue here with the
799 * processing of the data based on the stream type available.
800 */
801 if (process_data) {
802 ClearAllBits(FO_MAX, rctx.flags);
803 switch (rctx.stream) {
804 case STREAM_SPARSE_DATA:
805 SetBit(FO_SPARSE, rctx.flags);
806 break;
807 case STREAM_SPARSE_GZIP_DATA:
808 case STREAM_SPARSE_COMPRESSED_DATA:
809 SetBit(FO_SPARSE, rctx.flags);
810 SetBit(FO_COMPRESS, rctx.flags);
811 rctx.comp_stream = rctx.stream;
812 break;
813 case STREAM_GZIP_DATA:
814 case STREAM_COMPRESSED_DATA:
815 case STREAM_WIN32_GZIP_DATA:
816 case STREAM_WIN32_COMPRESSED_DATA:
817 SetBit(FO_COMPRESS, rctx.flags);
818 rctx.comp_stream = rctx.stream;
819 break;
820 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
821 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
822 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
823 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
824 if (!rctx.cipher_ctx.cipher) {
825 if (!SetupDecryptionContext(rctx, rctx.cipher_ctx)) {
826 rctx.extract = false;
827 bclose(&rctx.bfd);
828 continue;
829 }
830 }
831 SetBit(FO_COMPRESS, rctx.flags);
832 SetBit(FO_ENCRYPT, rctx.flags);
833 rctx.comp_stream = rctx.stream;
834 break;
835 case STREAM_ENCRYPTED_FILE_DATA:
836 case STREAM_ENCRYPTED_WIN32_DATA:
837 if (!rctx.cipher_ctx.cipher) {
838 if (!SetupDecryptionContext(rctx, rctx.cipher_ctx)) {
839 rctx.extract = false;
840 bclose(&rctx.bfd);
841 continue;
842 }
843 }
844 SetBit(FO_ENCRYPT, rctx.flags);
845 break;
846 default:
847 break;
848 }
849
850 /*
851 * Check for a win32 stream type on a system without the win32 API.
852 * On those we decompose the BackupWrite data.
853 */
854 if (is_win32_stream(rctx.stream) && !have_win32_api()) {
855 SetPortableBackup(&rctx.bfd);
856 /*
857 * "decompose" BackupWrite data
858 */
859 SetBit(FO_WIN32DECOMP, rctx.flags);
860 }
861
862 if (ExtractData(jcr, &rctx.bfd, sd->msg, sd->message_length,
863 &rctx.fileAddr, rctx.flags, rctx.stream,
864 &rctx.cipher_ctx)
865 < 0) {
866 rctx.extract = false;
867 bclose(&rctx.bfd);
868 continue;
869 }
870 }
871 }
872 break;
873
874 /*
875 * Resource fork stream - only recorded after a file to be restored
876 * Silently ignore if we cannot write - we already reported that
877 */
878 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
879 case STREAM_MACOS_FORK_DATA:
880 if (have_darwin_os) {
881 ClearAllBits(FO_MAX, rctx.fork_flags);
882 SetBit(FO_HFSPLUS, jcr->impl->ff->flags);
883
884 if (rctx.stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) {
885 SetBit(FO_ENCRYPT, rctx.fork_flags);
886 if (rctx.extract && !rctx.fork_cipher_ctx.cipher) {
887 if (!SetupDecryptionContext(rctx, rctx.fork_cipher_ctx)) {
888 rctx.extract = false;
889 bclose(&rctx.bfd);
890 continue;
891 }
892 }
893 }
894
895 if (rctx.extract) {
896 if (rctx.prev_stream != rctx.stream) {
897 if (BopenRsrc(&rctx.forkbfd, jcr->impl->last_fname,
898 O_WRONLY | O_TRUNC | O_BINARY, 0)
899 < 0) {
900 Jmsg(jcr, M_WARNING, 0,
901 _("Cannot open resource fork for %s.\n"),
902 jcr->impl->last_fname);
903 rctx.extract = false;
904 continue;
905 }
906
907 rctx.fork_size = rsrc_len;
908 Dmsg0(130, "Restoring resource fork\n");
909 }
910
911 if (ExtractData(jcr, &rctx.forkbfd, sd->msg, sd->message_length,
912 &rctx.fork_addr, rctx.fork_flags, rctx.stream,
913 &rctx.fork_cipher_ctx)
914 < 0) {
915 rctx.extract = false;
916 bclose(&rctx.forkbfd);
917 continue;
918 }
919 }
920 } else {
921 non_support_rsrc++;
922 }
923 break;
924
925 case STREAM_HFSPLUS_ATTRIBUTES:
926 if (have_darwin_os) {
927 if (!RestoreFinderinfo(jcr, sd->msg, sd->message_length)) {
928 continue;
929 }
930 } else {
931 non_support_finfo++;
932 }
933 break;
934
935 case STREAM_UNIX_ACCESS_ACL:
936 case STREAM_UNIX_DEFAULT_ACL:
937 case STREAM_ACL_AIX_TEXT:
938 case STREAM_ACL_DARWIN_ACCESS_ACL:
939 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
940 case STREAM_ACL_FREEBSD_ACCESS_ACL:
941 case STREAM_ACL_HPUX_ACL_ENTRY:
942 case STREAM_ACL_IRIX_DEFAULT_ACL:
943 case STREAM_ACL_IRIX_ACCESS_ACL:
944 case STREAM_ACL_LINUX_DEFAULT_ACL:
945 case STREAM_ACL_LINUX_ACCESS_ACL:
946 case STREAM_ACL_TRU64_DEFAULT_ACL:
947 case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
948 case STREAM_ACL_TRU64_ACCESS_ACL:
949 case STREAM_ACL_SOLARIS_ACLENT:
950 case STREAM_ACL_SOLARIS_ACE:
951 case STREAM_ACL_AFS_TEXT:
952 case STREAM_ACL_AIX_AIXC:
953 case STREAM_ACL_AIX_NFS4:
954 case STREAM_ACL_FREEBSD_NFS4_ACL:
955 case STREAM_ACL_HURD_DEFAULT_ACL:
956 case STREAM_ACL_HURD_ACCESS_ACL:
957 /*
958 * Do not restore ACLs when
959 * a) The current file is not extracted
960 * b) and it is not a directory (they are never "extracted")
961 * c) or the file name is empty
962 */
963 if ((!rctx.extract && jcr->impl->last_type != FT_DIREND)
964 || (*jcr->impl->last_fname == 0)) {
965 break;
966 }
967 if (have_acl) {
968 /*
969 * For anything that is not a directory we delay
970 * the restore of acls till a later stage.
971 */
972 if (jcr->impl->last_type != FT_DIREND) {
973 PushDelayedDataStream(rctx, sd);
974 } else {
975 if (!do_reStoreAcl(jcr, rctx.stream, sd->msg, sd->message_length)) {
976 goto bail_out;
977 }
978 }
979 } else {
980 non_support_acl++;
981 }
982 break;
983
984 case STREAM_XATTR_PLUGIN:
985 case STREAM_XATTR_HURD:
986 case STREAM_XATTR_IRIX:
987 case STREAM_XATTR_TRU64:
988 case STREAM_XATTR_AIX:
989 case STREAM_XATTR_OPENBSD:
990 case STREAM_XATTR_SOLARIS_SYS:
991 case STREAM_XATTR_DARWIN:
992 case STREAM_XATTR_FREEBSD:
993 case STREAM_XATTR_LINUX:
994 case STREAM_XATTR_NETBSD:
995 /*
996 * Do not restore Extended Attributes when
997 * a) The current file is not extracted
998 * b) and it is not a directory (they are never "extracted")
999 * c) or the file name is empty
1000 */
1001 if ((!rctx.extract && jcr->impl->last_type != FT_DIREND)
1002 || (*jcr->impl->last_fname == 0)) {
1003 break;
1004 }
1005 if (have_xattr) {
1006 /*
1007 * For anything that is not a directory we delay
1008 * the restore of xattr till a later stage.
1009 */
1010 if (jcr->impl->last_type != FT_DIREND) {
1011 PushDelayedDataStream(rctx, sd);
1012 } else {
1013 if (!do_restore_xattr(jcr, rctx.stream, sd->msg,
1014 sd->message_length)) {
1015 goto bail_out;
1016 }
1017 }
1018 } else {
1019 non_support_xattr++;
1020 }
1021 break;
1022
1023 case STREAM_XATTR_SOLARIS:
1024 /*
1025 * Do not restore Extended Attributes when
1026 * a) The current file is not extracted
1027 * b) and it is not a directory (they are never "extracted")
1028 * c) or the file name is empty
1029 */
1030 if ((!rctx.extract && jcr->impl->last_type != FT_DIREND)
1031 || (*jcr->impl->last_fname == 0)) {
1032 break;
1033 }
1034 if (have_xattr) {
1035 if (!do_restore_xattr(jcr, rctx.stream, sd->msg,
1036 sd->message_length)) {
1037 goto bail_out;
1038 }
1039 } else {
1040 non_support_xattr++;
1041 }
1042 break;
1043
1044 case STREAM_SIGNED_DIGEST:
1045 /*
1046 * Is this an unexpected signature?
1047 */
1048 if (rctx.sig) {
1049 Jmsg0(jcr, M_ERROR, 0,
1050 _("Unexpected cryptographic signature data stream.\n"));
1051 FreeSignature(rctx);
1052 continue;
1053 }
1054 /*
1055 * Save signature.
1056 */
1057 if (rctx.extract
1058 && (rctx.sig = crypto_sign_decode(jcr, (uint8_t*)sd->msg,
1059 (uint32_t)sd->message_length))
1060 == NULL) {
1061 Jmsg1(jcr, M_ERROR, 0,
1062 _("Failed to decode message signature for %s\n"),
1063 jcr->impl->last_fname);
1064 }
1065 break;
1066
1067 case STREAM_MD5_DIGEST:
1068 case STREAM_SHA1_DIGEST:
1069 case STREAM_SHA256_DIGEST:
1070 case STREAM_SHA512_DIGEST:
1071 break;
1072
1073 case STREAM_PROGRAM_NAMES:
1074 case STREAM_PROGRAM_DATA:
1075 if (!non_support_progname) {
1076 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
1077 non_support_progname++;
1078 }
1079 break;
1080
1081 case STREAM_PLUGIN_NAME:
1082 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
1083 Dmsg1(50, "restore stream_plugin_name=%s\n", sd->msg);
1084 if (!PluginNameStream(jcr, sd->msg)) { goto bail_out; }
1085 break;
1086
1087 case STREAM_RESTORE_OBJECT:
1088 break; /* these are sent by Director */
1089
1090 default:
1091 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
1092 Jmsg(jcr, M_WARNING, 0,
1093 _("Unknown stream=%d ignored. This shouldn't happen!\n"),
1094 rctx.stream);
1095 Dmsg2(0, "Unknown stream=%d data=%s\n", rctx.stream, sd->msg);
1096 break;
1097 } /* end switch(stream) */
1098 } /* end while get_msg() */
1099
1100 /*
1101 * If output file is still open, it was the last one in the
1102 * archive since we just hit an end of file, so close the file.
1103 */
1104 if (IsBopen(&rctx.forkbfd)) {
1105 BcloseChksize(jcr, &rctx.forkbfd, rctx.fork_size);
1106 }
1107
1108 if (!ClosePreviousStream(jcr, rctx)) { goto bail_out; }
1109 jcr->setJobStatus(JS_Terminated);
1110 goto ok_out;
1111
1112 bail_out:
1113 jcr->setJobStatus(JS_ErrorTerminated);
1114
1115 ok_out:
1116 #ifdef HAVE_WIN32
1117 /*
1118 * Cleanup the copy thread if we restored any EFS data.
1119 */
1120 if (jcr->cp_thread) { win32_cleanup_copy_thread(jcr); }
1121 #endif
1122
1123 /*
1124 * First output the statistics.
1125 */
1126 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
1127 edit_uint64(jcr->JobBytes, ec1));
1128 if (have_acl && jcr->impl->acl_data->u.parse->nr_errors > 0) {
1129 Jmsg(jcr, M_WARNING, 0,
1130 _("Encountered %ld acl errors while doing restore\n"),
1131 jcr->impl->acl_data->u.parse->nr_errors);
1132 }
1133 if (have_xattr && jcr->impl->xattr_data->u.parse->nr_errors > 0) {
1134 Jmsg(jcr, M_WARNING, 0,
1135 _("Encountered %ld xattr errors while doing restore\n"),
1136 jcr->impl->xattr_data->u.parse->nr_errors);
1137 }
1138 if (non_support_data > 1 || non_support_attr > 1) {
1139 Jmsg(jcr, M_WARNING, 0,
1140 _("%d non-supported data streams and %d non-supported attrib streams "
1141 "ignored.\n"),
1142 non_support_data, non_support_attr);
1143 }
1144 if (non_support_rsrc) {
1145 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"),
1146 non_support_rsrc);
1147 }
1148 if (non_support_finfo) {
1149 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"),
1150 non_support_finfo);
1151 }
1152 if (non_support_acl) {
1153 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"),
1154 non_support_acl);
1155 }
1156 if (non_support_crypto) {
1157 Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"),
1158 non_support_crypto);
1159 }
1160 if (non_support_xattr) {
1161 Jmsg(jcr, M_INFO, 0, _("%d non-supported xattr streams ignored.\n"),
1162 non_support_xattr);
1163 }
1164
1165 /*
1166 * Free Signature & Crypto Data
1167 */
1168 FreeSignature(rctx);
1169 FreeSession(rctx);
1170 if (jcr->impl->crypto.digest) {
1171 CryptoDigestFree(jcr->impl->crypto.digest);
1172 jcr->impl->crypto.digest = NULL;
1173 }
1174
1175 /*
1176 * Free file cipher restore context
1177 */
1178 if (rctx.cipher_ctx.cipher) {
1179 CryptoCipherFree(rctx.cipher_ctx.cipher);
1180 rctx.cipher_ctx.cipher = NULL;
1181 }
1182
1183 if (rctx.cipher_ctx.buf) {
1184 FreePoolMemory(rctx.cipher_ctx.buf);
1185 rctx.cipher_ctx.buf = NULL;
1186 }
1187
1188 /*
1189 * Free alternate stream cipher restore context
1190 */
1191 if (rctx.fork_cipher_ctx.cipher) {
1192 CryptoCipherFree(rctx.fork_cipher_ctx.cipher);
1193 rctx.fork_cipher_ctx.cipher = NULL;
1194 }
1195 if (rctx.fork_cipher_ctx.buf) {
1196 FreePoolMemory(rctx.fork_cipher_ctx.buf);
1197 rctx.fork_cipher_ctx.buf = NULL;
1198 }
1199
1200 if (have_acl && jcr->impl->acl_data) { free(jcr->impl->acl_data->u.parse); }
1201
1202 if (have_xattr && jcr->impl->xattr_data) {
1203 free(jcr->impl->xattr_data->u.parse);
1204 }
1205
1206 /*
1207 * Free the delayed stream stack list.
1208 */
1209 if (rctx.delayed_streams) {
1210 DropDelayedDataStreams(rctx, false);
1211 delete rctx.delayed_streams;
1212 }
1213
1214 CleanupCompression(jcr);
1215
1216 bclose(&rctx.forkbfd);
1217 bclose(&rctx.bfd);
1218 FreeAttr(rctx.attr);
1219 }
1220
DoFileDigest(JobControlRecord * jcr,FindFilesPacket * ff_pkt,bool top_level)1221 int DoFileDigest(JobControlRecord* jcr, FindFilesPacket* ff_pkt, bool top_level)
1222 {
1223 Dmsg1(50, "DoFileDigest jcr=%p\n", jcr);
1224 return (DigestFile(jcr, ff_pkt, jcr->impl->crypto.digest));
1225 }
1226
SparseData(JobControlRecord * jcr,BareosWinFilePacket * bfd,uint64_t * addr,char ** data,uint32_t * length)1227 bool SparseData(JobControlRecord* jcr,
1228 BareosWinFilePacket* bfd,
1229 uint64_t* addr,
1230 char** data,
1231 uint32_t* length)
1232 {
1233 unser_declare;
1234 uint64_t faddr;
1235 char ec1[50];
1236
1237 UnserBegin(*data, OFFSET_FADDR_SIZE);
1238 unser_uint64(faddr);
1239 if (*addr != faddr) {
1240 *addr = faddr;
1241 if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
1242 BErrNo be;
1243 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
1244 edit_uint64(*addr, ec1), jcr->impl->last_fname,
1245 be.bstrerror(bfd->BErrNo));
1246 return false;
1247 }
1248 }
1249 *data += OFFSET_FADDR_SIZE;
1250 *length -= OFFSET_FADDR_SIZE;
1251 return true;
1252 }
1253
StoreData(JobControlRecord * jcr,BareosWinFilePacket * bfd,char * data,const int32_t length,bool win32_decomp)1254 bool StoreData(JobControlRecord* jcr,
1255 BareosWinFilePacket* bfd,
1256 char* data,
1257 const int32_t length,
1258 bool win32_decomp)
1259 {
1260 if (jcr->impl->crypto.digest) {
1261 CryptoDigestUpdate(jcr->impl->crypto.digest, (uint8_t*)data, length);
1262 }
1263
1264 if (win32_decomp) {
1265 if (!processWin32BackupAPIBlock(bfd, data, length)) {
1266 BErrNo be;
1267 Jmsg2(jcr, M_ERROR, 0,
1268 _("Write error in Win32 Block Decomposition on %s: %s\n"),
1269 jcr->impl->last_fname, be.bstrerror(bfd->BErrNo));
1270 return false;
1271 }
1272 #ifdef HAVE_WIN32
1273 } else {
1274 if (bfd->encrypted) {
1275 if (win32_send_to_copy_thread(jcr, bfd, data, length)
1276 != (ssize_t)length) {
1277 BErrNo be;
1278 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
1279 jcr->impl->last_fname, be.bstrerror(bfd->BErrNo));
1280 return false;
1281 }
1282 } else {
1283 if (bwrite(bfd, data, length) != (ssize_t)length) {
1284 BErrNo be;
1285 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
1286 jcr->impl->last_fname, be.bstrerror(bfd->BErrNo));
1287 }
1288 }
1289 }
1290 #else
1291 } else if (bwrite(bfd, data, length) != (ssize_t)length) {
1292 BErrNo be;
1293 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), jcr->impl->last_fname,
1294 be.bstrerror(bfd->BErrNo));
1295 return false;
1296 }
1297 #endif
1298
1299 return true;
1300 }
1301
1302 /**
1303 * In the context of jcr, write data to bfd.
1304 * We write buflen bytes in buf at addr. addr is updated in place.
1305 * The flags specify whether to use sparse files or compression.
1306 * Return value is the number of bytes written, or -1 on errors.
1307 */
ExtractData(JobControlRecord * jcr,BareosWinFilePacket * bfd,POOLMEM * buf,int32_t buflen,uint64_t * addr,char * flags,int32_t stream,RestoreCipherContext * cipher_ctx)1308 int32_t ExtractData(JobControlRecord* jcr,
1309 BareosWinFilePacket* bfd,
1310 POOLMEM* buf,
1311 int32_t buflen,
1312 uint64_t* addr,
1313 char* flags,
1314 int32_t stream,
1315 RestoreCipherContext* cipher_ctx)
1316 {
1317 char* wbuf; /* write buffer */
1318 uint32_t wsize; /* write size */
1319 uint32_t rsize; /* read size */
1320 char ec1[50]; /* Buffer printing huge values */
1321
1322 rsize = buflen;
1323 jcr->ReadBytes += rsize;
1324 wsize = rsize;
1325 wbuf = buf;
1326
1327 if (BitIsSet(FO_ENCRYPT, flags)) {
1328 if (!DecryptData(jcr, &wbuf, &wsize, cipher_ctx)) { goto bail_out; }
1329 if (wsize == 0) { return 0; }
1330 }
1331
1332 if (BitIsSet(FO_SPARSE, flags) || BitIsSet(FO_OFFSETS, flags)) {
1333 if (!SparseData(jcr, bfd, addr, &wbuf, &wsize)) { goto bail_out; }
1334 }
1335
1336 if (BitIsSet(FO_COMPRESS, flags)) {
1337 if (!DecompressData(jcr, jcr->impl->last_fname, stream, &wbuf, &wsize,
1338 false)) {
1339 goto bail_out;
1340 }
1341 }
1342
1343 if (!StoreData(jcr, bfd, wbuf, wsize, BitIsSet(FO_WIN32DECOMP, flags))) {
1344 goto bail_out;
1345 }
1346 jcr->JobBytes += wsize;
1347 *addr += wsize;
1348 Dmsg2(130, "Write %u bytes, JobBytes=%s\n", wsize,
1349 edit_uint64(jcr->JobBytes, ec1));
1350
1351 /*
1352 * Clean up crypto buffers
1353 */
1354 if (BitIsSet(FO_ENCRYPT, flags)) {
1355 /*
1356 * Move any remaining data to start of buffer
1357 */
1358 if (cipher_ctx->buf_len > 0) {
1359 Dmsg1(130, "Moving %u buffered bytes to start of buffer\n",
1360 cipher_ctx->buf_len);
1361 memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
1362 cipher_ctx->buf_len);
1363 }
1364 /*
1365 * The packet was successfully written, reset the length so that the next
1366 * packet length may be re-read by UnserCryptoPacketLen()
1367 */
1368 cipher_ctx->packet_len = 0;
1369 }
1370
1371 return wsize;
1372
1373 bail_out:
1374 return -1;
1375 }
1376
1377 /**
1378 * If extracting, close any previous stream
1379 */
ClosePreviousStream(JobControlRecord * jcr,r_ctx & rctx)1380 static bool ClosePreviousStream(JobControlRecord* jcr, r_ctx& rctx)
1381 {
1382 /*
1383 * If extracting, it was from previous stream, so
1384 * close the output file and validate the signature.
1385 */
1386 if (rctx.extract) {
1387 if (rctx.size > 0 && !IsBopen(&rctx.bfd)) {
1388 Jmsg0(rctx.jcr, M_ERROR, 0,
1389 _("Logic error: output file should be open\n"));
1390 Dmsg2(000, "=== logic error size=%d bopen=%d\n", rctx.size,
1391 IsBopen(&rctx.bfd));
1392 }
1393
1394 if (rctx.prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
1395 DeallocateCipher(rctx);
1396 DeallocateForkCipher(rctx);
1397 }
1398
1399 #ifdef HAVE_WIN32
1400 if (jcr->cp_thread) { win32_flush_copy_thread(jcr); }
1401 #endif
1402
1403 if (jcr->IsPlugin()) {
1404 PluginSetAttributes(rctx.jcr, rctx.attr, &rctx.bfd);
1405 } else {
1406 SetAttributes(rctx.jcr, rctx.attr, &rctx.bfd);
1407 }
1408 rctx.extract = false;
1409
1410 /*
1411 * Now perform the delayed restore of some specific data streams.
1412 */
1413 if (!PopDelayedDataStreams(jcr, rctx)) { return false; }
1414
1415 /*
1416 * Verify the cryptographic signature, if any
1417 */
1418 rctx.type = rctx.attr->type;
1419 VerifySignature(rctx.jcr, rctx);
1420
1421 /*
1422 * Free Signature
1423 */
1424 FreeSignature(rctx);
1425 FreeSession(rctx);
1426 ClearAllBits(FO_MAX, rctx.jcr->impl->ff->flags);
1427 Dmsg0(130, "Stop extracting.\n");
1428 } else if (IsBopen(&rctx.bfd)) {
1429 Jmsg0(rctx.jcr, M_ERROR, 0,
1430 _("Logic error: output file should not be open\n"));
1431 Dmsg0(000, "=== logic error !open\n");
1432 bclose(&rctx.bfd);
1433 }
1434 return true;
1435 }
1436
FreeSignature(r_ctx & rctx)1437 static void FreeSignature(r_ctx& rctx)
1438 {
1439 if (rctx.sig) {
1440 CryptoSignFree(rctx.sig);
1441 rctx.sig = NULL;
1442 }
1443 }
1444
FreeSession(r_ctx & rctx)1445 void FreeSession(r_ctx& rctx)
1446 {
1447 if (rctx.cs) {
1448 CryptoSessionFree(rctx.cs);
1449 rctx.cs = NULL;
1450 }
1451 }
1452
1453 } /* namespace filedaemon */
1454