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