1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2011 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, March MM
25  */
26 /**
27  * @file
28  * Bareos File Daemon  backup.c  send file attributes and data to the Storage
29  * daemon.
30  */
31 
32 #include "include/bareos.h"
33 #include "filed/filed.h"
34 #include "filed/filed_globals.h"
35 #include "filed/accurate.h"
36 #include "filed/compression.h"
37 #include "filed/crypto.h"
38 #include "filed/heartbeat.h"
39 #include "filed/backup.h"
40 #include "filed/jcr_private.h"
41 #include "include/ch.h"
42 #include "findlib/attribs.h"
43 #include "findlib/hardlink.h"
44 #include "findlib/find_one.h"
45 #include "lib/berrno.h"
46 #include "lib/bsock.h"
47 #include "lib/btimers.h"
48 #include "lib/parse_conf.h"
49 #include "lib/util.h"
50 #include "include/make_unique.h"
51 
52 namespace filedaemon {
53 
54 #ifdef HAVE_DARWIN_OS
55 const bool have_darwin_os = true;
56 #else
57 const bool have_darwin_os = false;
58 #endif
59 
60 #if defined(HAVE_ACL)
61 const bool have_acl = true;
62 #else
63 const bool have_acl = false;
64 #endif
65 
66 #if defined(HAVE_XATTR)
67 const bool have_xattr = true;
68 #else
69 const bool have_xattr = false;
70 #endif
71 
72 #ifndef compressBound
73 #  define compressBound(sourceLen) \
74     (sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13)
75 #endif
76 
77 /* Forward referenced functions */
78 int SaveFile(JobControlRecord* jcr, FindFilesPacket* ff_pkt, bool top_level);
79 static int send_data(JobControlRecord* jcr,
80                      int stream,
81                      FindFilesPacket* ff_pkt,
82                      DIGEST* digest,
83                      DIGEST* signature_digest);
84 bool EncodeAndSendAttributes(JobControlRecord* jcr,
85                              FindFilesPacket* ff_pkt,
86                              int& data_stream);
87 static void CloseVssBackupSession(JobControlRecord* jcr);
88 
89 /**
90  * Find all the requested files and send them
91  * to the Storage daemon.
92  *
93  * Note, we normally carry on a one-way
94  * conversation from this point on with the SD, simply blasting
95  * data to him.  To properly know what is going on, we
96  * also run a "heartbeat" monitor which reads the socket and
97  * reacts accordingly (at the moment it has nothing to do
98  * except echo the heartbeat to the Director).
99  */
BlastDataToStorageDaemon(JobControlRecord * jcr,char * addr,crypto_cipher_t cipher)100 bool BlastDataToStorageDaemon(JobControlRecord* jcr,
101                               char* addr,
102                               crypto_cipher_t cipher)
103 {
104   BareosSocket* sd;
105   bool ok = true;
106 
107   sd = jcr->store_bsock;
108 
109   jcr->setJobStatus(JS_Running);
110 
111   Dmsg1(300, "filed: opened data connection %d to stored\n", sd->fd_);
112 
113   LockRes(my_config);
114   ClientResource* client
115       = (ClientResource*)my_config->GetNextRes(R_CLIENT, NULL);
116   UnlockRes(my_config);
117   uint32_t buf_size;
118   if (client) {
119     buf_size = client->max_network_buffer_size;
120   } else {
121     buf_size = 0; /* use default */
122   }
123   if (!sd->SetBufferSize(buf_size, BNET_SETBUF_WRITE)) {
124     jcr->setJobStatus(JS_ErrorTerminated);
125     Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
126     return false;
127   }
128 
129   jcr->buf_size = sd->message_length;
130 
131   if (!AdjustCompressionBuffers(jcr)) { return false; }
132 
133   if (!CryptoSessionStart(jcr, cipher)) { return false; }
134 
135   SetFindOptions((FindFilesPacket*)jcr->impl->ff, jcr->impl->incremental,
136                  jcr->impl->since_time);
137 
138   /**
139    * In accurate mode, we overload the find_one check function
140    */
141   if (jcr->accurate) {
142     SetFindChangedFunction((FindFilesPacket*)jcr->impl->ff, AccurateCheckFile);
143   }
144 
145   StartHeartbeatMonitor(jcr);
146 
147   if (have_acl) {
148     jcr->impl->acl_data = std::make_unique<AclData>();
149     jcr->impl->acl_data->u.build
150         = (acl_build_data_t*)malloc(sizeof(acl_build_data_t));
151     memset(jcr->impl->acl_data->u.build, 0, sizeof(acl_build_data_t));
152     jcr->impl->acl_data->u.build->content = GetPoolMemory(PM_MESSAGE);
153   }
154 
155   if (have_xattr) {
156     jcr->impl->xattr_data = std::make_unique<XattrData>();
157     jcr->impl->xattr_data->u.build
158         = (xattr_build_data_t*)malloc(sizeof(xattr_build_data_t));
159     memset(jcr->impl->xattr_data->u.build, 0, sizeof(xattr_build_data_t));
160     jcr->impl->xattr_data->u.build->content = GetPoolMemory(PM_MESSAGE);
161   }
162 
163   /**
164    * Subroutine SaveFile() is called for each file
165    */
166   if (!FindFiles(jcr, (FindFilesPacket*)jcr->impl->ff, SaveFile, PluginSave)) {
167     ok = false; /* error */
168     jcr->setJobStatus(JS_ErrorTerminated);
169   }
170 
171   if (have_acl && jcr->impl->acl_data->u.build->nr_errors > 0) {
172     Jmsg(jcr, M_WARNING, 0,
173          _("Encountered %ld acl errors while doing backup\n"),
174          jcr->impl->acl_data->u.build->nr_errors);
175   }
176   if (have_xattr && jcr->impl->xattr_data->u.build->nr_errors > 0) {
177     Jmsg(jcr, M_WARNING, 0,
178          _("Encountered %ld xattr errors while doing backup\n"),
179          jcr->impl->xattr_data->u.build->nr_errors);
180   }
181 
182   CloseVssBackupSession(jcr);
183 
184   AccurateFinish(jcr); /* send deleted or base file list to SD */
185 
186   StopHeartbeatMonitor(jcr);
187 
188   sd->signal(BNET_EOD); /* end of sending data */
189 
190   if (have_acl && jcr->impl->acl_data) {
191     FreePoolMemory(jcr->impl->acl_data->u.build->content);
192     free(jcr->impl->acl_data->u.build);
193   }
194 
195   if (have_xattr && jcr->impl->xattr_data) {
196     FreePoolMemory(jcr->impl->xattr_data->u.build->content);
197     free(jcr->impl->xattr_data->u.build);
198   }
199 
200   if (jcr->impl->big_buf) {
201     free(jcr->impl->big_buf);
202     jcr->impl->big_buf = NULL;
203   }
204 
205   CleanupCompression(jcr);
206   CryptoSessionEnd(jcr);
207 
208   Dmsg1(100, "end blast_data ok=%d\n", ok);
209   return ok;
210 }
211 
212 /**
213  * Save OSX specific resource forks and finder info.
214  */
SaveRsrcAndFinder(b_save_ctx & bsctx)215 static inline bool SaveRsrcAndFinder(b_save_ctx& bsctx)
216 {
217   char flags[FOPTS_BYTES];
218   int rsrc_stream;
219   BareosSocket* sd = bsctx.jcr->store_bsock;
220   bool retval = false;
221 
222   if (bsctx.ff_pkt->hfsinfo.rsrclength > 0) {
223     if (BopenRsrc(&bsctx.ff_pkt->bfd, bsctx.ff_pkt->fname, O_RDONLY | O_BINARY,
224                   0)
225         < 0) {
226       bsctx.ff_pkt->ff_errno = errno;
227       BErrNo be;
228       Jmsg(bsctx.jcr, M_NOTSAVED, -1,
229            _("     Cannot open resource fork for \"%s\": ERR=%s.\n"),
230            bsctx.ff_pkt->fname, be.bstrerror());
231       bsctx.jcr->JobErrors++;
232       if (IsBopen(&bsctx.ff_pkt->bfd)) { bclose(&bsctx.ff_pkt->bfd); }
233     } else {
234       int status;
235 
236       memcpy(flags, bsctx.ff_pkt->flags, sizeof(flags));
237       ClearBit(FO_COMPRESS, bsctx.ff_pkt->flags);
238       ClearBit(FO_SPARSE, bsctx.ff_pkt->flags);
239       ClearBit(FO_OFFSETS, bsctx.ff_pkt->flags);
240       rsrc_stream = BitIsSet(FO_ENCRYPT, flags)
241                         ? STREAM_ENCRYPTED_MACOS_FORK_DATA
242                         : STREAM_MACOS_FORK_DATA;
243 
244       status = send_data(bsctx.jcr, rsrc_stream, bsctx.ff_pkt, bsctx.digest,
245                          bsctx.signing_digest);
246 
247       memcpy(bsctx.ff_pkt->flags, flags, sizeof(flags));
248       bclose(&bsctx.ff_pkt->bfd);
249       if (!status) { goto bail_out; }
250     }
251   }
252 
253   Dmsg1(300, "Saving Finder Info for \"%s\"\n", bsctx.ff_pkt->fname);
254   sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
255   Dmsg1(300, "filed>stored:header %s", sd->msg);
256   PmMemcpy(sd->msg, bsctx.ff_pkt->hfsinfo.fndrinfo, 32);
257   sd->message_length = 32;
258   if (bsctx.digest) {
259     CryptoDigestUpdate(bsctx.digest, (uint8_t*)sd->msg, sd->message_length);
260   }
261   if (bsctx.signing_digest) {
262     CryptoDigestUpdate(bsctx.signing_digest, (uint8_t*)sd->msg,
263                        sd->message_length);
264   }
265   sd->send();
266   sd->signal(BNET_EOD);
267 
268   retval = true;
269 
270 bail_out:
271   return retval;
272 }
273 
274 /**
275  * Setup for digest handling. If this fails, the digest will be set to NULL
276  * and not used. Note, the digest (file hash) can be any one of the four
277  * algorithms below.
278  *
279  * The signing digest is a single algorithm depending on
280  * whether or not we have SHA2.
281  *   ****FIXME****  the signing algorithm should really be
282  *   determined a different way!!!!!!  What happens if
283  *   sha2 was available during backup but not restore?
284  */
SetupEncryptionDigests(b_save_ctx & bsctx)285 static inline bool SetupEncryptionDigests(b_save_ctx& bsctx)
286 {
287   bool retval = false;
288   // TODO landonf: Allow the user to specify the digest algorithm
289 #ifdef HAVE_SHA2
290   crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA256;
291 #else
292   crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA1;
293 #endif
294 
295   if (BitIsSet(FO_MD5, bsctx.ff_pkt->flags)) {
296     bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_MD5);
297     bsctx.digest_stream = STREAM_MD5_DIGEST;
298   } else if (BitIsSet(FO_SHA1, bsctx.ff_pkt->flags)) {
299     bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_SHA1);
300     bsctx.digest_stream = STREAM_SHA1_DIGEST;
301   } else if (BitIsSet(FO_SHA256, bsctx.ff_pkt->flags)) {
302     bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_SHA256);
303     bsctx.digest_stream = STREAM_SHA256_DIGEST;
304   } else if (BitIsSet(FO_SHA512, bsctx.ff_pkt->flags)) {
305     bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_SHA512);
306     bsctx.digest_stream = STREAM_SHA512_DIGEST;
307   }
308 
309   /*
310    * Did digest initialization fail?
311    */
312   if (bsctx.digest_stream != STREAM_NONE && bsctx.digest == NULL) {
313     Jmsg(bsctx.jcr, M_WARNING, 0, _("%s digest initialization failed\n"),
314          stream_to_ascii(bsctx.digest_stream));
315   }
316 
317   /**
318    * Set up signature digest handling. If this fails, the signature digest
319    * will be set to NULL and not used.
320    */
321   /* TODO landonf: We should really only calculate the digest once, for
322    * both verification and signing.
323    */
324   if (bsctx.jcr->impl->crypto.pki_sign) {
325     bsctx.signing_digest = crypto_digest_new(bsctx.jcr, signing_algorithm);
326 
327     /*
328      * Full-stop if a failure occurred initializing the signature digest
329      */
330     if (bsctx.signing_digest == NULL) {
331       Jmsg(bsctx.jcr, M_NOTSAVED, 0,
332            _("%s signature digest initialization failed\n"),
333            stream_to_ascii(signing_algorithm));
334       bsctx.jcr->JobErrors++;
335       goto bail_out;
336     }
337   }
338 
339   /*
340    * Enable encryption
341    */
342   if (bsctx.jcr->impl->crypto.pki_encrypt) {
343     SetBit(FO_ENCRYPT, bsctx.ff_pkt->flags);
344   }
345   retval = true;
346 
347 bail_out:
348   return retval;
349 }
350 
351 /**
352  * Terminate the signing digest and send it to the Storage daemon
353  */
TerminateSigningDigest(b_save_ctx & bsctx)354 static inline bool TerminateSigningDigest(b_save_ctx& bsctx)
355 {
356   uint32_t size = 0;
357   bool retval = false;
358   SIGNATURE* signature = NULL;
359   BareosSocket* sd = bsctx.jcr->store_bsock;
360 
361   if ((signature = crypto_sign_new(bsctx.jcr)) == NULL) {
362     Jmsg(bsctx.jcr, M_FATAL, 0,
363          _("Failed to allocate memory for crypto signature.\n"));
364     goto bail_out;
365   }
366 
367   if (!CryptoSignAddSigner(signature, bsctx.signing_digest,
368                            bsctx.jcr->impl->crypto.pki_keypair)) {
369     Jmsg(bsctx.jcr, M_FATAL, 0,
370          _("An error occurred while signing the stream.\n"));
371     goto bail_out;
372   }
373 
374   /*
375    * Get signature size
376    */
377   if (!CryptoSignEncode(signature, NULL, &size)) {
378     Jmsg(bsctx.jcr, M_FATAL, 0,
379          _("An error occurred while signing the stream.\n"));
380     goto bail_out;
381   }
382 
383   /*
384    * Grow the bsock buffer to fit our message if necessary
385    */
386   if (SizeofPoolMemory(sd->msg) < (int32_t)size) {
387     sd->msg = ReallocPoolMemory(sd->msg, size);
388   }
389 
390   /*
391    * Send our header
392    */
393   sd->fsend("%ld %ld 0", bsctx.jcr->JobFiles, STREAM_SIGNED_DIGEST);
394   Dmsg1(300, "filed>stored:header %s", sd->msg);
395 
396   /*
397    * Encode signature data
398    */
399   if (!CryptoSignEncode(signature, (uint8_t*)sd->msg, &size)) {
400     Jmsg(bsctx.jcr, M_FATAL, 0,
401          _("An error occurred while signing the stream.\n"));
402     goto bail_out;
403   }
404 
405   sd->message_length = size;
406   sd->send();
407   sd->signal(BNET_EOD); /* end of checksum */
408   retval = true;
409 
410 bail_out:
411   if (signature) { CryptoSignFree(signature); }
412   return retval;
413 }
414 
415 /**
416  * Terminate any digest and send it to Storage daemon
417  */
TerminateDigest(b_save_ctx & bsctx)418 static inline bool TerminateDigest(b_save_ctx& bsctx)
419 {
420   uint32_t size;
421   bool retval = false;
422   BareosSocket* sd = bsctx.jcr->store_bsock;
423 
424   sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, bsctx.digest_stream);
425   Dmsg1(300, "filed>stored:header %s", sd->msg);
426 
427   size = CRYPTO_DIGEST_MAX_SIZE;
428 
429   /*
430    * Grow the bsock buffer to fit our message if necessary
431    */
432   if (SizeofPoolMemory(sd->msg) < (int32_t)size) {
433     sd->msg = ReallocPoolMemory(sd->msg, size);
434   }
435 
436   if (!CryptoDigestFinalize(bsctx.digest, (uint8_t*)sd->msg, &size)) {
437     Jmsg(bsctx.jcr, M_FATAL, 0,
438          _("An error occurred finalizing signing the stream.\n"));
439     goto bail_out;
440   }
441 
442   /*
443    * Keep the checksum if this file is a hardlink
444    */
445   if (bsctx.ff_pkt->linked) {
446     FfPktSetLinkDigest(bsctx.ff_pkt, bsctx.digest_stream, sd->msg, size);
447   }
448 
449   sd->message_length = size;
450   sd->send();
451   sd->signal(BNET_EOD); /* end of checksum */
452   retval = true;
453 
454 bail_out:
455   return retval;
456 }
457 
DoBackupAcl(JobControlRecord * jcr,FindFilesPacket * ff_pkt)458 static inline bool DoBackupAcl(JobControlRecord* jcr, FindFilesPacket* ff_pkt)
459 {
460   bacl_exit_code retval;
461 
462   jcr->impl->acl_data->filetype = ff_pkt->type;
463   jcr->impl->acl_data->last_fname = jcr->impl->last_fname;
464 
465   if (jcr->IsPlugin()) {
466     retval = PluginBuildAclStreams(jcr, jcr->impl->acl_data.get(), ff_pkt);
467   } else {
468     retval = BuildAclStreams(jcr, jcr->impl->acl_data.get(), ff_pkt);
469   }
470 
471   switch (retval) {
472     case bacl_exit_fatal:
473       return false;
474     case bacl_exit_error:
475       Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
476       jcr->impl->acl_data->u.build->nr_errors++;
477       break;
478     case bacl_exit_ok:
479       break;
480   }
481 
482   return true;
483 }
484 
DoBackupXattr(JobControlRecord * jcr,FindFilesPacket * ff_pkt)485 static inline bool DoBackupXattr(JobControlRecord* jcr, FindFilesPacket* ff_pkt)
486 {
487   BxattrExitCode retval;
488 
489   jcr->impl->xattr_data->last_fname = jcr->impl->last_fname;
490 
491   if (jcr->IsPlugin()) {
492     retval = PluginBuildXattrStreams(jcr, jcr->impl->xattr_data.get(), ff_pkt);
493   } else {
494     retval = BuildXattrStreams(jcr, jcr->impl->xattr_data.get(), ff_pkt);
495   }
496 
497   switch (retval) {
498     case BxattrExitCode::kErrorFatal:
499       return false;
500     case BxattrExitCode::kWarning:
501       Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
502       break;
503     case BxattrExitCode::kError:
504       Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
505       jcr->impl->xattr_data->u.build->nr_errors++;
506       break;
507     case BxattrExitCode::kSuccess:
508       break;
509   }
510 
511   return true;
512 }
513 
514 /**
515  * Called here by find() for each file included.
516  * This is a callback. The original is FindFiles() above.
517  *
518  * Send the file and its data to the Storage daemon.
519  *
520  * Returns: 1 if OK
521  *          0 if error
522  *         -1 to ignore file/directory (not used here)
523  */
SaveFile(JobControlRecord * jcr,FindFilesPacket * ff_pkt,bool top_level)524 int SaveFile(JobControlRecord* jcr, FindFilesPacket* ff_pkt, bool top_level)
525 {
526   bool do_read = false;
527   bool plugin_started = false;
528   bool do_plugin_set = false;
529   int status, data_stream;
530   int rtnstat = 0;
531   b_save_ctx bsctx;
532   bool has_file_data = false;
533   struct save_pkt sp; /* use by option plugin */
534   BareosSocket* sd = jcr->store_bsock;
535 
536   if (jcr->IsCanceled() || jcr->IsIncomplete()) { return 0; }
537 
538   jcr->impl->num_files_examined++; /* bump total file count */
539 
540   switch (ff_pkt->type) {
541     case FT_LNKSAVED: /* Hard linked, file already saved */
542       Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname,
543             ff_pkt->link);
544       break;
545     case FT_REGE:
546       Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
547       has_file_data = true;
548       break;
549     case FT_REG:
550       Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
551       has_file_data = true;
552       break;
553     case FT_LNK:
554       Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
555       break;
556     case FT_RESTORE_FIRST:
557       Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
558       break;
559     case FT_PLUGIN_CONFIG:
560       Dmsg1(100, "FT_PLUGIN_CONFIG saving: %s\n", ff_pkt->fname);
561       break;
562     case FT_DIRBEGIN:
563       jcr->impl->num_files_examined--; /* correct file count */
564       return 1;                        /* not used */
565     case FT_NORECURSE:
566       Jmsg(jcr, M_INFO, 1,
567            _("     Recursion turned off. Will not descend from %s into %s\n"),
568            ff_pkt->top_fname, ff_pkt->fname);
569       ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
570       break;
571     case FT_NOFSCHG:
572       /* Suppress message for /dev filesystems */
573       if (!IsInFileset(ff_pkt)) {
574         Jmsg(jcr, M_INFO, 1,
575              _("     %s is a different filesystem. Will not descend from %s "
576                "into it.\n"),
577              ff_pkt->fname, ff_pkt->top_fname);
578       }
579       ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
580       break;
581     case FT_INVALIDFS:
582       Jmsg(jcr, M_INFO, 1,
583            _("     Disallowed filesystem. Will not descend from %s into %s\n"),
584            ff_pkt->top_fname, ff_pkt->fname);
585       ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
586       break;
587     case FT_INVALIDDT:
588       Jmsg(jcr, M_INFO, 1,
589            _("     Disallowed drive type. Will not descend into %s\n"),
590            ff_pkt->fname);
591       break;
592     case FT_REPARSE:
593     case FT_JUNCTION:
594     case FT_DIREND:
595       Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
596       break;
597     case FT_SPEC:
598       Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
599       if (S_ISSOCK(ff_pkt->statp.st_mode)) {
600         Jmsg(jcr, M_SKIPPED, 1, _("     Socket file skipped: %s\n"),
601              ff_pkt->fname);
602         return 1;
603       }
604       break;
605     case FT_RAW:
606       Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
607       has_file_data = true;
608       break;
609     case FT_FIFO:
610       Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
611       break;
612     case FT_NOACCESS: {
613       BErrNo be;
614       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not access \"%s\": ERR=%s\n"),
615            ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
616       jcr->JobErrors++;
617       return 1;
618     }
619     case FT_NOFOLLOW: {
620       BErrNo be;
621       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not follow link \"%s\": ERR=%s\n"),
622            ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
623       jcr->JobErrors++;
624       return 1;
625     }
626     case FT_NOSTAT: {
627       BErrNo be;
628       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not stat \"%s\": ERR=%s\n"),
629            ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
630       jcr->JobErrors++;
631       return 1;
632     }
633     case FT_DIRNOCHG:
634     case FT_NOCHG:
635       Jmsg(jcr, M_SKIPPED, 1, _("     Unchanged file skipped: %s\n"),
636            ff_pkt->fname);
637       return 1;
638     case FT_ISARCH:
639       Jmsg(jcr, M_NOTSAVED, 0, _("     Archive file not saved: %s\n"),
640            ff_pkt->fname);
641       return 1;
642     case FT_NOOPEN: {
643       BErrNo be;
644       Jmsg(jcr, M_NOTSAVED, 0,
645            _("     Could not open directory \"%s\": ERR=%s\n"), ff_pkt->fname,
646            be.bstrerror(ff_pkt->ff_errno));
647       jcr->JobErrors++;
648       return 1;
649     }
650     case FT_DELETED:
651       Dmsg1(130, "FT_DELETED: %s\n", ff_pkt->fname);
652       break;
653     default:
654       Jmsg(jcr, M_NOTSAVED, 0, _("     Unknown file type %d; not saved: %s\n"),
655            ff_pkt->type, ff_pkt->fname);
656       jcr->JobErrors++;
657       return 1;
658   }
659 
660   Dmsg1(130, "filed: sending %s to stored\n", ff_pkt->fname);
661 
662   /*
663    * Setup backup signing context.
664    */
665   memset(&bsctx, 0, sizeof(b_save_ctx));
666   bsctx.digest_stream = STREAM_NONE;
667   bsctx.jcr = jcr;
668   bsctx.ff_pkt = ff_pkt;
669 
670   /*
671    * Digests and encryption are only useful if there's file data
672    */
673   if (has_file_data) {
674     if (!SetupEncryptionDigests(bsctx)) { goto good_rtn; }
675   }
676 
677   /*
678    * Initialize the file descriptor we use for data and other streams.
679    */
680   binit(&ff_pkt->bfd);
681   if (BitIsSet(FO_PORTABLE, ff_pkt->flags)) {
682     SetPortableBackup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
683   }
684 
685   /*
686    * Option and cmd plugin are not compatible together
687    */
688   if (ff_pkt->cmd_plugin) {
689     do_plugin_set = true;
690   } else if (ff_pkt->opt_plugin) {
691     /*
692      * Ask the option plugin what to do with this file
693      */
694     switch (PluginOptionHandleFile(jcr, ff_pkt, &sp)) {
695       case bRC_OK:
696         Dmsg2(10, "Option plugin %s will be used to backup %s\n",
697               ff_pkt->plugin, ff_pkt->fname);
698         jcr->opt_plugin = true;
699         jcr->impl->plugin_sp = &sp;
700         PluginUpdateFfPkt(ff_pkt, &sp);
701         do_plugin_set = true;
702         break;
703       case bRC_Skip:
704         Dmsg2(10, "Option plugin %s decided to skip %s\n", ff_pkt->plugin,
705               ff_pkt->fname);
706         goto good_rtn;
707       case bRC_Core:
708         Dmsg2(10, "Option plugin %s decided to let bareos handle %s\n",
709               ff_pkt->plugin, ff_pkt->fname);
710         break;
711       default:
712         goto bail_out;
713     }
714   }
715 
716   if (do_plugin_set) {
717     /*
718      * Tell bfile that it needs to call plugin
719      */
720     if (!SetCmdPlugin(&ff_pkt->bfd, jcr)) { goto bail_out; }
721     SendPluginName(jcr, sd, true); /* signal start of plugin data */
722     plugin_started = true;
723   }
724 
725   /*
726    * Send attributes -- must be done after binit()
727    */
728   if (!EncodeAndSendAttributes(jcr, ff_pkt, data_stream)) { goto bail_out; }
729 
730   /*
731    * Meta data only for restore object
732    */
733   if (IS_FT_OBJECT(ff_pkt->type)) { goto good_rtn; }
734 
735   /*
736    * Meta data only for deleted files
737    */
738   if (ff_pkt->type == FT_DELETED) { goto good_rtn; }
739 
740   /*
741    * Set up the encryption context and send the session data to the SD
742    */
743   if (has_file_data && jcr->impl->crypto.pki_encrypt) {
744     if (!CryptoSessionSend(jcr, sd)) { goto bail_out; }
745   }
746 
747   /*
748    * For a command plugin use the setting from the plugins savepkt no_read field
749    * which is saved in the ff_pkt->no_read variable. do_read is the inverted
750    * value of this variable as no_read == TRUE means do_read == FALSE
751    */
752   if (ff_pkt->cmd_plugin) {
753     do_read = !ff_pkt->no_read;
754   } else {
755     /*
756      * Open any file with data that we intend to save, then save it.
757      *
758      * Note, if is_win32_backup, we must open the Directory so that
759      * the BackupRead will save its permissions and ownership streams.
760      */
761     if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) {
762 #ifdef HAVE_WIN32
763       do_read = !IsPortableBackup(&ff_pkt->bfd) || ff_pkt->statp.st_size > 0;
764 #else
765       do_read = ff_pkt->statp.st_size > 0;
766 #endif
767     } else if (ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO
768                || ff_pkt->type == FT_REPARSE || ff_pkt->type == FT_JUNCTION
769                || (!IsPortableBackup(&ff_pkt->bfd)
770                    && ff_pkt->type == FT_DIREND)) {
771       do_read = true;
772     }
773   }
774 
775   Dmsg2(150, "type=%d do_read=%d\n", ff_pkt->type, do_read);
776   if (do_read) {
777     btimer_t* tid;
778     int noatime;
779 
780     if (ff_pkt->type == FT_FIFO) {
781       tid = start_thread_timer(jcr, pthread_self(), 60);
782     } else {
783       tid = NULL;
784     }
785 
786     noatime = BitIsSet(FO_NOATIME, ff_pkt->flags) ? O_NOATIME : 0;
787     ff_pkt->bfd.reparse_point
788         = (ff_pkt->type == FT_REPARSE || ff_pkt->type == FT_JUNCTION);
789 
790     if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0,
791               ff_pkt->statp.st_rdev)
792         < 0) {
793       ff_pkt->ff_errno = errno;
794       BErrNo be;
795       Jmsg(jcr, M_NOTSAVED, 0, _("     Cannot open \"%s\": ERR=%s.\n"),
796            ff_pkt->fname, be.bstrerror());
797       jcr->JobErrors++;
798       if (tid) {
799         StopThreadTimer(tid);
800         tid = NULL;
801       }
802       goto good_rtn;
803     }
804 
805     if (tid) {
806       StopThreadTimer(tid);
807       tid = NULL;
808     }
809 
810     status = send_data(jcr, data_stream, ff_pkt, bsctx.digest,
811                        bsctx.signing_digest);
812 
813     if (BitIsSet(FO_CHKCHANGES, ff_pkt->flags)) { HasFileChanged(jcr, ff_pkt); }
814 
815     bclose(&ff_pkt->bfd);
816 
817     if (!status) { goto bail_out; }
818   }
819 
820   if (have_darwin_os) {
821     /*
822      * Regular files can have resource forks and Finder Info
823      */
824     if (ff_pkt->type != FT_LNKSAVED
825         && (S_ISREG(ff_pkt->statp.st_mode)
826             && BitIsSet(FO_HFSPLUS, ff_pkt->flags))) {
827       if (!SaveRsrcAndFinder(bsctx)) { goto bail_out; }
828     }
829   }
830 
831   /*
832    * Save ACLs when requested and available for anything not being a symlink.
833    */
834   if (have_acl) {
835     if (BitIsSet(FO_ACL, ff_pkt->flags) && ff_pkt->type != FT_LNK) {
836       if (!DoBackupAcl(jcr, ff_pkt)) { goto bail_out; }
837     }
838   }
839 
840   /*
841    * Save Extended Attributes when requested and available for all files.
842    */
843   if (have_xattr) {
844     if (BitIsSet(FO_XATTR, ff_pkt->flags)) {
845       if (!DoBackupXattr(jcr, ff_pkt)) { goto bail_out; }
846     }
847   }
848 
849   /*
850    * Terminate the signing digest and send it to the Storage daemon
851    */
852   if (bsctx.signing_digest) {
853     if (!TerminateSigningDigest(bsctx)) { goto bail_out; }
854   }
855 
856   /*
857    * Terminate any digest and send it to Storage daemon
858    */
859   if (bsctx.digest) {
860     if (!TerminateDigest(bsctx)) { goto bail_out; }
861   }
862 
863   /*
864    * Check if original file has a digest, and send it
865    */
866   if (ff_pkt->type == FT_LNKSAVED && ff_pkt->digest) {
867     Dmsg2(300, "Link %s digest %d\n", ff_pkt->fname, ff_pkt->digest_len);
868     sd->fsend("%ld %d 0", jcr->JobFiles, ff_pkt->digest_stream);
869 
870     sd->msg = CheckPoolMemorySize(sd->msg, ff_pkt->digest_len);
871     memcpy(sd->msg, ff_pkt->digest, ff_pkt->digest_len);
872     sd->message_length = ff_pkt->digest_len;
873     sd->send();
874 
875     sd->signal(BNET_EOD); /* end of hardlink record */
876   }
877 
878 good_rtn:
879   rtnstat = jcr->IsCanceled() ? 0 : 1; /* good return if not canceled */
880 
881 bail_out:
882   if (jcr->IsIncomplete() || jcr->IsCanceled()) { rtnstat = 0; }
883   if (plugin_started) {
884     SendPluginName(jcr, sd, false); /* signal end of plugin data */
885   }
886   if (ff_pkt->opt_plugin) {
887     jcr->impl->plugin_sp = NULL; /* sp is local to this function */
888     jcr->opt_plugin = false;
889   }
890   if (bsctx.digest) { CryptoDigestFree(bsctx.digest); }
891   if (bsctx.signing_digest) { CryptoDigestFree(bsctx.signing_digest); }
892 
893   return rtnstat;
894 }
895 
896 /**
897  * Handle the data just read and send it to the SD after doing any
898  * postprocessing needed.
899  */
SendDataToSd(b_ctx * bctx)900 static inline bool SendDataToSd(b_ctx* bctx)
901 {
902   BareosSocket* sd = bctx->jcr->store_bsock;
903   bool need_more_data;
904 
905   /*
906    * Check for sparse blocks
907    */
908   if (BitIsSet(FO_SPARSE, bctx->ff_pkt->flags)) {
909     bool allZeros;
910     ser_declare;
911 
912     allZeros = false;
913     if ((sd->message_length == bctx->rsize
914          && (bctx->fileAddr + sd->message_length
915              < (uint64_t)bctx->ff_pkt->statp.st_size))
916         || ((bctx->ff_pkt->type == FT_RAW || bctx->ff_pkt->type == FT_FIFO)
917             && ((uint64_t)bctx->ff_pkt->statp.st_size == 0))) {
918       allZeros = IsBufZero(bctx->rbuf, bctx->rsize);
919     }
920 
921     if (!allZeros) {
922       /*
923        * Put file address as first data in buffer
924        */
925       SerBegin(bctx->wbuf, OFFSET_FADDR_SIZE);
926       ser_uint64(bctx->fileAddr); /* store fileAddr in begin of buffer */
927     }
928 
929     bctx->fileAddr += sd->message_length; /* update file address */
930 
931     /*
932      * Skip block of all zeros
933      */
934     if (allZeros) { return true; }
935   } else if (BitIsSet(FO_OFFSETS, bctx->ff_pkt->flags)) {
936     ser_declare;
937     SerBegin(bctx->wbuf, OFFSET_FADDR_SIZE);
938     ser_uint64(bctx->ff_pkt->bfd.offset); /* store offset in begin of buffer */
939   }
940 
941   bctx->jcr->ReadBytes += sd->message_length; /* count bytes read */
942 
943   /*
944    * Uncompressed cipher input length
945    */
946   bctx->cipher_input_len = sd->message_length;
947 
948   /*
949    * Update checksum if requested
950    */
951   if (bctx->digest) {
952     CryptoDigestUpdate(bctx->digest, (uint8_t*)bctx->rbuf, sd->message_length);
953   }
954 
955   /*
956    * Update signing digest if requested
957    */
958   if (bctx->signing_digest) {
959     CryptoDigestUpdate(bctx->signing_digest, (uint8_t*)bctx->rbuf,
960                        sd->message_length);
961   }
962 
963   /*
964    * Compress the data.
965    */
966   if (BitIsSet(FO_COMPRESS, bctx->ff_pkt->flags)) {
967     if (!CompressData(bctx->jcr, bctx->ff_pkt->Compress_algo, bctx->rbuf,
968                       bctx->jcr->store_bsock->message_length, bctx->cbuf,
969                       bctx->max_compress_len, &bctx->compress_len)) {
970       return false;
971     }
972 
973     /*
974      * See if we need to generate a compression header.
975      */
976     if (bctx->chead) {
977       ser_declare;
978 
979       /*
980        * Complete header
981        */
982       SerBegin(bctx->chead, sizeof(comp_stream_header));
983       ser_uint32(bctx->ch.magic);
984       ser_uint32(bctx->compress_len);
985       ser_uint16(bctx->ch.level);
986       ser_uint16(bctx->ch.version);
987       SerEnd(bctx->chead, sizeof(comp_stream_header));
988 
989       bctx->compress_len += sizeof(comp_stream_header); /* add size of header */
990     }
991 
992     bctx->jcr->store_bsock->message_length
993         = bctx->compress_len; /* set compressed length */
994     bctx->cipher_input_len = bctx->compress_len;
995   }
996 
997   /*
998    * Encrypt the data.
999    */
1000   need_more_data = false;
1001   if (BitIsSet(FO_ENCRYPT, bctx->ff_pkt->flags)
1002       && !EncryptData(bctx, &need_more_data)) {
1003     if (need_more_data) { return true; }
1004     return false;
1005   }
1006 
1007   /*
1008    * Send the buffer to the Storage daemon
1009    */
1010   if (BitIsSet(FO_SPARSE, bctx->ff_pkt->flags)
1011       || BitIsSet(FO_OFFSETS, bctx->ff_pkt->flags)) {
1012     sd->message_length += OFFSET_FADDR_SIZE; /* include fileAddr in size */
1013   }
1014   sd->msg = bctx->wbuf; /* set correct write buffer */
1015 
1016   if (!sd->send()) {
1017     if (!bctx->jcr->IsJobCanceled()) {
1018       Jmsg1(bctx->jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1019             sd->bstrerror());
1020     }
1021     return false;
1022   }
1023 
1024   Dmsg1(130, "Send data to SD len=%d\n", sd->message_length);
1025   bctx->jcr->JobBytes += sd->message_length; /* count bytes saved possibly
1026                                                 compressed/encrypted */
1027   sd->msg = bctx->msgsave;                   /* restore read buffer */
1028 
1029   return true;
1030 }
1031 
1032 #ifdef HAVE_WIN32
1033 /**
1034  * Callback method for ReadEncryptedFileRaw()
1035  */
send_efs_data(PBYTE pbData,PVOID pvCallbackContext,ULONG ulLength)1036 static DWORD WINAPI send_efs_data(PBYTE pbData,
1037                                   PVOID pvCallbackContext,
1038                                   ULONG ulLength)
1039 {
1040   b_ctx* bctx = (b_ctx*)pvCallbackContext;
1041   BareosSocket* sd = bctx->jcr->store_bsock;
1042 
1043   if (ulLength == 0) { return ERROR_SUCCESS; }
1044 
1045   /*
1046    * See if we can fit the data into the current bctx->rbuf which can hold
1047    * bctx->rsize bytes.
1048    */
1049   if (ulLength <= (ULONG)bctx->rsize) {
1050     sd->message_length = ulLength;
1051     memcpy(bctx->rbuf, pbData, ulLength);
1052     if (!SendDataToSd(bctx)) { return ERROR_NET_WRITE_FAULT; }
1053   } else {
1054     /*
1055      * Need to chunk the data into pieces.
1056      */
1057     ULONG offset = 0;
1058 
1059     while (ulLength > 0) {
1060       sd->message_length = MIN((ULONG)bctx->rsize, ulLength);
1061       memcpy(bctx->rbuf, pbData + offset, sd->message_length);
1062       if (!SendDataToSd(bctx)) { return ERROR_NET_WRITE_FAULT; }
1063 
1064       offset += sd->message_length;
1065       ulLength -= sd->message_length;
1066     }
1067   }
1068 
1069   return ERROR_SUCCESS;
1070 }
1071 
1072 /**
1073  * Send the content of an Encrypted file on an EFS filesystem.
1074  */
SendEncryptedData(b_ctx & bctx)1075 static inline bool SendEncryptedData(b_ctx& bctx)
1076 {
1077   bool retval = false;
1078 
1079   if (!p_ReadEncryptedFileRaw) {
1080     Jmsg0(bctx.jcr, M_FATAL, 0,
1081           _("Encrypted file but no EFS support functions\n"));
1082   }
1083 
1084   /*
1085    * The EFS read function, ReadEncryptedFileRaw(), works in a specific way.
1086    * You have to give it a function that it calls repeatedly every time the
1087    * read buffer is filled.
1088    *
1089    * So ReadEncryptedFileRaw() will not return until it has read the whole file.
1090    */
1091   if (p_ReadEncryptedFileRaw((PFE_EXPORT_FUNC)send_efs_data, &bctx,
1092                              bctx.ff_pkt->bfd.pvContext)) {
1093     goto bail_out;
1094   }
1095   retval = true;
1096 
1097 bail_out:
1098   return retval;
1099 }
1100 #endif
1101 
1102 /**
1103  * Send the content of a file on anything but an EFS filesystem.
1104  */
SendPlainData(b_ctx & bctx)1105 static inline bool SendPlainData(b_ctx& bctx)
1106 {
1107   bool retval = false;
1108   BareosSocket* sd = bctx.jcr->store_bsock;
1109 
1110   /*
1111    * Read the file data
1112    */
1113   while ((sd->message_length
1114           = (uint32_t)bread(&bctx.ff_pkt->bfd, bctx.rbuf, bctx.rsize))
1115          > 0) {
1116     if (!SendDataToSd(&bctx)) { goto bail_out; }
1117   }
1118   retval = true;
1119 
1120 bail_out:
1121   return retval;
1122 }
1123 
1124 /**
1125  * Send data read from an already open file descriptor.
1126  *
1127  * We return 1 on sucess and 0 on errors.
1128  *
1129  * ***FIXME***
1130  * We use ff_pkt->statp.st_size when FO_SPARSE to know when to stop reading.
1131  * Currently this is not a problem as the only other stream, resource forks,
1132  * are not handled as sparse files.
1133  */
send_data(JobControlRecord * jcr,int stream,FindFilesPacket * ff_pkt,DIGEST * digest,DIGEST * signing_digest)1134 static int send_data(JobControlRecord* jcr,
1135                      int stream,
1136                      FindFilesPacket* ff_pkt,
1137                      DIGEST* digest,
1138                      DIGEST* signing_digest)
1139 {
1140   b_ctx bctx;
1141   BareosSocket* sd = jcr->store_bsock;
1142 #ifdef FD_NO_SEND_TEST
1143   return 1;
1144 #endif
1145 
1146   /*
1147    * Setup backup context.
1148    */
1149   memset(&bctx, 0, sizeof(b_ctx));
1150   bctx.jcr = jcr;
1151   bctx.ff_pkt = ff_pkt;
1152   bctx.msgsave = sd->msg;                  /* save the original sd buffer */
1153   bctx.rbuf = sd->msg;                     /* read buffer */
1154   bctx.wbuf = sd->msg;                     /* write buffer */
1155   bctx.rsize = jcr->buf_size;              /* read buffer size */
1156   bctx.cipher_input = (uint8_t*)bctx.rbuf; /* encrypt uncompressed data */
1157   bctx.digest = digest;                    /* encryption digest */
1158   bctx.signing_digest = signing_digest;    /* signing digest */
1159 
1160   Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);
1161 
1162   if (!SetupCompressionContext(bctx)) { goto bail_out; }
1163 
1164   if (!SetupEncryptionContext(bctx)) { goto bail_out; }
1165 
1166   /*
1167    * Send Data header to Storage daemon
1168    *    <file-index> <stream> <info>
1169    */
1170   if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
1171     if (!jcr->IsJobCanceled()) {
1172       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1173             sd->bstrerror());
1174     }
1175     goto bail_out;
1176   }
1177   Dmsg1(300, ">stored: datahdr %s", sd->msg);
1178 
1179   /*
1180    * Make space at beginning of buffer for fileAddr because this
1181    *   same buffer will be used for writing if compression is off.
1182    */
1183   if (BitIsSet(FO_SPARSE, ff_pkt->flags)
1184       || BitIsSet(FO_OFFSETS, ff_pkt->flags)) {
1185     bctx.rbuf += OFFSET_FADDR_SIZE;
1186     bctx.rsize -= OFFSET_FADDR_SIZE;
1187 #ifdef HAVE_FREEBSD_OS
1188     /*
1189      * To read FreeBSD partitions, the read size must be a multiple of 512.
1190      */
1191     bctx.rsize = (bctx.rsize / 512) * 512;
1192 #endif
1193   }
1194 
1195   /*
1196    * A RAW device read on win32 only works if the buffer is a multiple of 512
1197    */
1198 #ifdef HAVE_WIN32
1199   if (S_ISBLK(ff_pkt->statp.st_mode)) { bctx.rsize = (bctx.rsize / 512) * 512; }
1200 
1201   if (ff_pkt->statp.st_rdev & FILE_ATTRIBUTE_ENCRYPTED) {
1202     if (!SendEncryptedData(bctx)) { goto bail_out; }
1203   } else {
1204     if (!SendPlainData(bctx)) { goto bail_out; }
1205   }
1206 #else
1207   if (!SendPlainData(bctx)) { goto bail_out; }
1208 #endif
1209 
1210   if (sd->message_length < 0) { /* error */
1211     BErrNo be;
1212     Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"), ff_pkt->fname,
1213          be.bstrerror(ff_pkt->bfd.BErrNo));
1214     if (jcr->JobErrors++ > 1000) { /* insanity check */
1215       Jmsg(jcr, M_FATAL, 0, _("Too many errors. JobErrors=%d.\n"),
1216            jcr->JobErrors);
1217     }
1218   } else if (BitIsSet(FO_ENCRYPT, ff_pkt->flags)) {
1219     /*
1220      * For encryption, we must call finalize to push out any buffered data.
1221      */
1222     if (!CryptoCipherFinalize(bctx.cipher_ctx,
1223                               (uint8_t*)jcr->impl->crypto.crypto_buf,
1224                               &bctx.encrypted_len)) {
1225       /*
1226        * Padding failed. Shouldn't happen.
1227        */
1228       Jmsg(jcr, M_FATAL, 0, _("Encryption padding error\n"));
1229       goto bail_out;
1230     }
1231 
1232     /*
1233      * Note, on SSL pre-0.9.7, there is always some output
1234      */
1235     if (bctx.encrypted_len > 0) {
1236       sd->message_length = bctx.encrypted_len; /* set encrypted length */
1237       sd->msg = jcr->impl->crypto.crypto_buf;  /* set correct write buffer */
1238       if (!sd->send()) {
1239         if (!jcr->IsJobCanceled()) {
1240           Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1241                 sd->bstrerror());
1242         }
1243         goto bail_out;
1244       }
1245       Dmsg1(130, "Send data to SD len=%d\n", sd->message_length);
1246       jcr->JobBytes += sd->message_length; /* count bytes saved possibly
1247                                               compressed/encrypted */
1248       sd->msg = bctx.msgsave;              /* restore bnet buffer */
1249     }
1250   }
1251 
1252   if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
1253     if (!jcr->IsJobCanceled()) {
1254       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1255             sd->bstrerror());
1256     }
1257     goto bail_out;
1258   }
1259 
1260   /*
1261    * Free the cipher context
1262    */
1263   if (bctx.cipher_ctx) { CryptoCipherFree(bctx.cipher_ctx); }
1264 
1265   return 1;
1266 
1267 bail_out:
1268   /*
1269    * Free the cipher context
1270    */
1271   if (bctx.cipher_ctx) { CryptoCipherFree(bctx.cipher_ctx); }
1272 
1273   sd->msg = bctx.msgsave; /* restore bnet buffer */
1274   sd->message_length = 0;
1275 
1276   return 0;
1277 }
1278 
EncodeAndSendAttributes(JobControlRecord * jcr,FindFilesPacket * ff_pkt,int & data_stream)1279 bool EncodeAndSendAttributes(JobControlRecord* jcr,
1280                              FindFilesPacket* ff_pkt,
1281                              int& data_stream)
1282 {
1283   BareosSocket* sd = jcr->store_bsock;
1284   PoolMem attribs(PM_NAME), attribsExBuf(PM_NAME);
1285   char* attribsEx = NULL;
1286   int attr_stream;
1287   int comp_len;
1288   bool status;
1289   int hangup = GetHangup();
1290 #ifdef FD_NO_SEND_TEST
1291   return true;
1292 #endif
1293 
1294   Dmsg1(300, "encode_and_send_attrs fname=%s\n", ff_pkt->fname);
1295   /** Find what data stream we will use, then encode the attributes */
1296   if ((data_stream = SelectDataStream(ff_pkt, me->compatible)) == STREAM_NONE) {
1297     /* This should not happen */
1298     Jmsg0(jcr, M_FATAL, 0,
1299           _("Invalid file flags, no supported data stream type.\n"));
1300     return false;
1301   }
1302   EncodeStat(attribs.c_str(), &ff_pkt->statp, sizeof(ff_pkt->statp),
1303              ff_pkt->LinkFI, data_stream);
1304 
1305   /** Now possibly extend the attributes */
1306   if (IS_FT_OBJECT(ff_pkt->type)) {
1307     attr_stream = STREAM_RESTORE_OBJECT;
1308   } else {
1309     attribsEx = attribsExBuf.c_str();
1310     attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
1311   }
1312 
1313   Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname,
1314         attribs.c_str(), attribsEx);
1315 
1316   jcr->lock();
1317   jcr->JobFiles++;                   /* increment number of files sent */
1318   ff_pkt->FileIndex = jcr->JobFiles; /* return FileIndex */
1319   PmStrcpy(jcr->impl->last_fname, ff_pkt->fname);
1320   jcr->unlock();
1321 
1322   /*
1323    * Debug code: check if we must hangup
1324    */
1325   if (hangup && (jcr->JobFiles > (uint32_t)hangup)) {
1326     jcr->setJobStatus(JS_Incomplete);
1327     Jmsg1(jcr, M_FATAL, 0, "Debug hangup requested after %d files.\n", hangup);
1328     SetHangup(0);
1329     return false;
1330   }
1331 
1332   /**
1333    * Send Attributes header to Storage daemon
1334    *    <file-index> <stream> <info>
1335    */
1336   if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) {
1337     if (!jcr->IsCanceled() && !jcr->IsIncomplete()) {
1338       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1339             sd->bstrerror());
1340     }
1341     return false;
1342   }
1343   Dmsg1(300, ">stored: attrhdr %s", sd->msg);
1344 
1345   /**
1346    * Send file attributes to Storage daemon
1347    *   File_index
1348    *   File type
1349    *   Filename (full path)
1350    *   Encoded attributes
1351    *   Link name (if type==FT_LNK or FT_LNKSAVED)
1352    *   Encoded extended-attributes (for Win32)
1353    *   Delta Sequence Number
1354    *
1355    * or send Restore Object to Storage daemon
1356    *   File_index
1357    *   File_type
1358    *   Object_index
1359    *   Object_len  (possibly compressed)
1360    *   Object_full_len (not compressed)
1361    *   Object_compression
1362    *   Plugin_name
1363    *   Object_name
1364    *   Binary Object data
1365    *
1366    * For a directory, link is the same as fname, but with trailing
1367    * slash. For a linked file, link is the link.
1368    */
1369   if (!IS_FT_OBJECT(ff_pkt->type)
1370       && ff_pkt->type != FT_DELETED) { /* already stripped */
1371     StripPath(ff_pkt);
1372   }
1373   switch (ff_pkt->type) {
1374     case FT_JUNCTION:
1375     case FT_LNK:
1376     case FT_LNKSAVED:
1377       Dmsg3(300, "Link %d %s to %s\n", jcr->JobFiles, ff_pkt->fname,
1378             ff_pkt->link);
1379       status = sd->fsend("%ld %d %s%c%s%c%s%c%s%c%u%c", jcr->JobFiles,
1380                          ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0,
1381                          ff_pkt->link, 0, attribsEx, 0, ff_pkt->delta_seq, 0);
1382       break;
1383     case FT_DIREND:
1384     case FT_REPARSE:
1385       /* Here link is the canonical filename (i.e. with trailing slash) */
1386       status = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
1387                          ff_pkt->type, ff_pkt->link, 0, attribs.c_str(), 0, 0,
1388                          attribsEx, 0, ff_pkt->delta_seq, 0);
1389       break;
1390     case FT_PLUGIN_CONFIG:
1391     case FT_RESTORE_FIRST:
1392       comp_len = ff_pkt->object_len;
1393       ff_pkt->object_compression = 0;
1394 
1395       if (ff_pkt->object_len > 1000) {
1396         /*
1397          * Big object, compress it
1398          */
1399         comp_len = compressBound(ff_pkt->object_len);
1400         POOLMEM* comp_obj = GetMemory(comp_len);
1401         /*
1402          * FIXME: check Zdeflate error
1403          */
1404         Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len);
1405         if (comp_len < ff_pkt->object_len) {
1406           ff_pkt->object = comp_obj;
1407           ff_pkt->object_compression = 1; /* zlib level 9 compression */
1408         } else {
1409           /*
1410            * Uncompressed object smaller, use it
1411            */
1412           comp_len = ff_pkt->object_len;
1413         }
1414         Dmsg2(100, "Object compressed from %d to %d bytes\n",
1415               ff_pkt->object_len, comp_len);
1416       }
1417 
1418       sd->message_length = Mmsg(
1419           sd->msg, "%d %d %d %d %d %d %s%c%s%c", jcr->JobFiles, ff_pkt->type,
1420           ff_pkt->object_index, comp_len, ff_pkt->object_len,
1421           ff_pkt->object_compression, ff_pkt->fname, 0, ff_pkt->object_name, 0);
1422       sd->msg = CheckPoolMemorySize(sd->msg, sd->message_length + comp_len + 2);
1423       memcpy(sd->msg + sd->message_length, ff_pkt->object, comp_len);
1424 
1425       /*
1426        * Note we send one extra byte so Dir can store zero after object
1427        */
1428       sd->message_length += comp_len + 1;
1429       status = sd->send();
1430       if (ff_pkt->object_compression) { FreeAndNullPoolMemory(ff_pkt->object); }
1431       break;
1432     case FT_REG:
1433       status = sd->fsend("%ld %d %s%c%s%c%c%s%c%d%c", jcr->JobFiles,
1434                          ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0, 0,
1435                          attribsEx, 0, ff_pkt->delta_seq, 0);
1436       break;
1437     default:
1438       status = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
1439                          ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0, 0,
1440                          attribsEx, 0, ff_pkt->delta_seq, 0);
1441       break;
1442   }
1443 
1444   if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) {
1445     UnstripPath(ff_pkt);
1446   }
1447 
1448   Dmsg2(300, ">stored: attr len=%d: %s\n", sd->message_length, sd->msg);
1449   if (!status && !jcr->IsJobCanceled()) {
1450     Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1451           sd->bstrerror());
1452   }
1453 
1454   sd->signal(BNET_EOD); /* indicate end of attributes data */
1455 
1456   return status;
1457 }
1458 
1459 /**
1460  * Do in place strip of path
1461  */
do_strip(int count,char * in)1462 static bool do_strip(int count, char* in)
1463 {
1464   char* out = in;
1465   int stripped;
1466   int numsep = 0;
1467 
1468   /**
1469    * Copy to first path separator -- Win32 might have c: ...
1470    */
1471   while (*in && !IsPathSeparator(*in)) {
1472     out++;
1473     in++;
1474   }
1475   if (*in) { /* Not at the end of the string */
1476     out++;
1477     in++;
1478     numsep++; /* one separator seen */
1479   }
1480   for (stripped = 0; stripped < count && *in; stripped++) {
1481     while (*in && !IsPathSeparator(*in)) { in++; /* skip chars */ }
1482     if (*in) {
1483       numsep++; /* count separators seen */
1484       in++;     /* skip separator */
1485     }
1486   }
1487 
1488   /*
1489    * Copy to end
1490    */
1491   while (*in) { /* copy to end */
1492     if (IsPathSeparator(*in)) { numsep++; }
1493     *out++ = *in++;
1494   }
1495   *out = 0;
1496   Dmsg4(500, "stripped=%d count=%d numsep=%d sep>count=%d\n", stripped, count,
1497         numsep, numsep > count);
1498   return stripped == count && numsep > count;
1499 }
1500 
1501 /**
1502  * If requested strip leading components of the path so that we can
1503  * save file as if it came from a subdirectory.  This is most useful
1504  * for dealing with snapshots, by removing the snapshot directory, or
1505  * in handling vendor migrations where files have been restored with
1506  * a vendor product into a subdirectory.
1507  */
StripPath(FindFilesPacket * ff_pkt)1508 void StripPath(FindFilesPacket* ff_pkt)
1509 {
1510   if (!BitIsSet(FO_STRIPPATH, ff_pkt->flags) || ff_pkt->StripPath <= 0) {
1511     Dmsg1(200, "No strip for %s\n", ff_pkt->fname);
1512     return;
1513   }
1514 
1515   if (!ff_pkt->fname_save) {
1516     ff_pkt->fname_save = GetPoolMemory(PM_FNAME);
1517     ff_pkt->link_save = GetPoolMemory(PM_FNAME);
1518   }
1519 
1520   PmStrcpy(ff_pkt->fname_save, ff_pkt->fname);
1521   if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1522     PmStrcpy(ff_pkt->link_save, ff_pkt->link);
1523     Dmsg2(500, "strcpy link_save=%d link=%d\n", strlen(ff_pkt->link_save),
1524           strlen(ff_pkt->link));
1525   }
1526 
1527   /**
1528    * Strip path. If it doesn't succeed put it back. If it does, and there
1529    * is a different link string, attempt to strip the link. If it fails,
1530    * back them both back. Do not strip symlinks. I.e. if either stripping
1531    * fails don't strip anything.
1532    */
1533   if (!do_strip(ff_pkt->StripPath, ff_pkt->fname)) {
1534     UnstripPath(ff_pkt);
1535     goto rtn;
1536   }
1537 
1538   /**
1539    * Strip links but not symlinks
1540    */
1541   if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1542     if (!do_strip(ff_pkt->StripPath, ff_pkt->link)) { UnstripPath(ff_pkt); }
1543   }
1544 
1545 rtn:
1546   Dmsg3(100, "fname=%s stripped=%s link=%s\n", ff_pkt->fname_save,
1547         ff_pkt->fname, ff_pkt->link);
1548 }
1549 
UnstripPath(FindFilesPacket * ff_pkt)1550 void UnstripPath(FindFilesPacket* ff_pkt)
1551 {
1552   if (!BitIsSet(FO_STRIPPATH, ff_pkt->flags) || ff_pkt->StripPath <= 0) {
1553     return;
1554   }
1555 
1556   strcpy(ff_pkt->fname, ff_pkt->fname_save);
1557   if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1558     Dmsg2(500, "strcpy link=%s link_save=%s\n", ff_pkt->link,
1559           ff_pkt->link_save);
1560     strcpy(ff_pkt->link, ff_pkt->link_save);
1561     Dmsg2(500, "strcpy link=%d link_save=%d\n", strlen(ff_pkt->link),
1562           strlen(ff_pkt->link_save));
1563   }
1564 }
1565 
CloseVssBackupSession(JobControlRecord * jcr)1566 static void CloseVssBackupSession(JobControlRecord* jcr)
1567 {
1568 #if defined(WIN32_VSS)
1569   /*
1570    * STOP VSS ON WIN32
1571    * Tell vss to close the backup session
1572    */
1573   if (jcr->impl->pVSSClient) {
1574     /*
1575      * We are about to call the BackupComplete VSS method so let all plugins
1576      * know that by raising the bEventVssBackupComplete event.
1577      */
1578     GeneratePluginEvent(jcr, bEventVssBackupComplete);
1579     if (jcr->impl->pVSSClient->CloseBackup()) {
1580       /*
1581        * Inform user about writer states
1582        */
1583       for (size_t i = 0; i < jcr->impl->pVSSClient->GetWriterCount(); i++) {
1584         int msg_type = M_INFO;
1585         if (jcr->impl->pVSSClient->GetWriterState(i) < 1) {
1586           msg_type = M_WARNING;
1587           jcr->JobErrors++;
1588         }
1589         Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"),
1590              jcr->impl->pVSSClient->GetWriterInfo(i));
1591       }
1592     }
1593 
1594     /*
1595      * Generate Job global writer metadata
1596      */
1597     wchar_t* metadata = jcr->impl->pVSSClient->GetMetadata();
1598     if (metadata) {
1599       FindFilesPacket* ff_pkt = jcr->impl->ff;
1600       ff_pkt->fname = (char*)"*all*"; /* for all plugins */
1601       ff_pkt->type = FT_RESTORE_FIRST;
1602       ff_pkt->LinkFI = 0;
1603       ff_pkt->object_name = (char*)"job_metadata.xml";
1604       ff_pkt->object = BSTR_2_str(metadata);
1605       ff_pkt->object_len = (wcslen(metadata) + 1) * sizeof(wchar_t);
1606       ff_pkt->object_index = (int)time(NULL);
1607       SaveFile(jcr, ff_pkt, true);
1608     }
1609   }
1610 #endif
1611 }
1612 } /* namespace filedaemon */
1613