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