2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
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
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 General Public License for more details.
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
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula File Daemon restore.c Restorefiles.
31 * Kern Sibbald, November MM
42 const bool have_darwin_os = true;
44 const bool have_darwin_os = false;
47 #if defined(HAVE_CRYPTO)
48 const bool have_crypto = true;
50 const bool have_crypto = false;
54 const bool have_acl = true;
56 const bool have_acl = false;
60 const bool have_sha2 = true;
62 const bool have_sha2 = false;
65 #if defined(HAVE_XATTR)
66 const bool have_xattr = true;
68 const bool have_xattr = false;
72 * Data received from Storage Daemon
74 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
77 * Forward referenced functions
79 #if defined(HAVE_LIBZ)
80 static const char *zlib_strerror(int stat);
81 const bool have_libz = true;
83 const bool have_libz = false;
86 const bool have_lzo = true;
88 const bool have_lzo = false;
92 static void deallocate_cipher(r_ctx &rctx);
93 static void deallocate_fork_cipher(r_ctx &rctx);
94 static void free_signature(r_ctx &rctx);
95 static void free_session(r_ctx &rctx);
96 static void close_previous_stream(r_ctx &rctx);
98 static bool verify_signature(JCR *jcr, r_ctx &rctx);
99 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
100 uint64_t *addr, int flags, int32_t stream, RESTORE_CIPHER_CTX *cipher_ctx);
101 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags, int32_t stream,
102 RESTORE_CIPHER_CTX *cipher_ctx);
105 * Close a bfd check that we are at the expected file offset.
106 * Makes use of some code from set_attributes().
108 static int bclose_chksize(JCR *jcr, BFILE *bfd, boffset_t osize)
110 char ec1[50], ec2[50];
113 fsize = blseek(bfd, 0, SEEK_CUR);
115 if (fsize > 0 && fsize != osize) {
116 Qmsg3(jcr, M_WARNING, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
117 jcr->last_fname, edit_uint64(osize, ec1),
118 edit_uint64(fsize, ec2));
124 #ifdef HAVE_DARWIN_OS
125 bool restore_finderinfo(JCR *jcr, POOLMEM *buf, int32_t buflen)
127 struct attrlist attrList;
129 memset(&attrList, 0, sizeof(attrList));
130 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
131 attrList.commonattr = ATTR_CMN_FNDRINFO;
133 Dmsg0(130, "Restoring Finder Info\n");
134 jcr->ff->flags |= FO_HFSPLUS;
136 Jmsg(jcr, M_WARNING, 0, _("Invalid length of Finder Info (got %d, not 32)\n"), buflen);
140 if (setattrlist(jcr->last_fname, &attrList, buf, buflen, 0) != 0) {
141 Jmsg(jcr, M_WARNING, 0, _("Could not set Finder Info on %s\n"), jcr->last_fname);
148 bool restore_finderinfo(JCR *jcr, POOLMEM *buf, int32_t buflen)
155 * Restore the requested files.
157 void do_restore(JCR *jcr)
160 uint32_t VolSessionId, VolSessionTime;
162 char ec1[50]; /* Buffer printing huge values */
163 uint32_t buf_size; /* client buffer size */
165 int64_t rsrc_len = 0; /* Original length of resource fork */
168 /* ***FIXME*** make configurable */
169 crypto_digest_t signing_algorithm = have_sha2 ?
170 CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
171 memset(&rctx, 0, sizeof(rctx));
175 * The following variables keep track of "known unknowns"
177 int non_support_data = 0;
178 int non_support_attr = 0;
179 int non_support_rsrc = 0;
180 int non_support_finfo = 0;
181 int non_support_acl = 0;
182 int non_support_progname = 0;
183 int non_support_crypto = 0;
184 int non_support_xattr = 0;
186 sd = jcr->store_bsock;
187 jcr->setJobStatus(JS_Running);
190 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
193 buf_size = client->max_network_buffer_size;
195 buf_size = 0; /* use default */
197 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
198 jcr->setJobStatus(JS_ErrorTerminated);
201 jcr->buf_size = sd->msglen;
204 * St Bernard code goes here if implemented -- see end of file
207 /* use the same buffer size to decompress both gzip and lzo */
208 if (have_libz || have_lzo) {
209 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
210 jcr->compress_buf = get_memory(compress_buf_size);
211 jcr->compress_buf_size = compress_buf_size;
215 if (lzo_init() != LZO_E_OK) {
216 Jmsg(jcr, M_FATAL, 0, _("LZO init failed\n"));
222 rctx.cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
223 if (have_darwin_os) {
224 rctx.fork_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
229 * Get a record from the Storage daemon. We are guaranteed to
230 * receive records in the following order:
231 * 1. Stream record header
232 * 2. Stream data (one or more of the following in the order given)
233 * a. Attributes (Unix or Win32)
234 * b. Possibly stream encryption session data (e.g., symmetric session key)
235 * c. File data for the file
236 * d. Alternate data stream (e.g. Resource Fork)
240 * h. Possibly a cryptographic signature
241 * i. Possibly MD5 or SHA1 record
244 * NOTE: We keep track of two bacula file descriptors:
245 * 1. bfd for file data.
246 * This fd is opened for non empty files when an attribute stream is
247 * encountered and closed when we find the next attribute stream.
248 * 2. fork_bfd for alternate data streams
249 * This fd is opened every time we encounter a new alternate data
250 * stream for the current file. When we find any other stream, we
252 * The expected size of the stream, fork_len, should be set when
254 * 3. Not all the stream data records are required -- e.g. if there
255 * is no fork, there is no alternate data stream, no ACL, ...
258 binit(&rctx.forkbfd);
259 attr = rctx.attr = new_attr(jcr);
261 jcr->acl_data = (acl_data_t *)malloc(sizeof(acl_data_t));
262 memset((caddr_t)jcr->acl_data, 0, sizeof(acl_data_t));
263 jcr->acl_data->content = get_pool_memory(PM_MESSAGE);
266 jcr->xattr_data = (xattr_data_t *)malloc(sizeof(xattr_data_t));
267 memset((caddr_t)jcr->xattr_data, 0, sizeof(xattr_data_t));
268 jcr->xattr_data->content = get_pool_memory(PM_MESSAGE);
271 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
273 * Remember previous stream type
275 rctx.prev_stream = rctx.stream;
278 * First we expect a Stream Record Header
280 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
281 &rctx.full_stream, &rctx.size) != 5) {
282 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
285 /* Strip off new stream high bits */
286 rctx.stream = rctx.full_stream & STREAMMASK_TYPE;
287 Dmsg5(150, "Got hdr: Files=%d FilInx=%d size=%d Stream=%d, %s.\n",
288 jcr->JobFiles, file_index, rctx.size, rctx.stream, stream_to_ascii(rctx.stream));
291 * Now we expect the Stream Data
293 if (bget_msg(sd) < 0) {
294 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
297 if (rctx.size != (uint32_t)sd->msglen) {
298 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"),
299 sd->msglen, rctx.size);
300 Dmsg2(50, "Actual data size %d not same as header %d\n",
301 sd->msglen, rctx.size);
304 Dmsg3(130, "Got stream: %s len=%d extract=%d\n", stream_to_ascii(rctx.stream),
305 sd->msglen, rctx.extract);
308 * If we change streams, close and reset alternate data streams
310 if (rctx.prev_stream != rctx.stream) {
311 if (is_bopen(&rctx.forkbfd)) {
312 deallocate_fork_cipher(rctx);
313 bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
316 * Use an impossible value and set a proper one below
323 * File Attributes stream
325 switch (rctx.stream) {
326 case STREAM_UNIX_ATTRIBUTES:
327 case STREAM_UNIX_ATTRIBUTES_EX:
329 * if any previous stream open, close it
331 close_previous_stream(rctx);
334 * TODO: manage deleted files
336 if (rctx.type == FT_DELETED) { /* deleted file */
340 * Restore objects should be ignored here -- they are
341 * returned at the beginning of the restore.
343 if (rctx.type == FT_RESTORE_FIRST) {
348 * Unpack attributes and do sanity check them
350 if (!unpack_attributes_record(jcr, rctx.stream, sd->msg, sd->msglen, attr)) {
354 Dmsg3(100, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
355 attr->attr, attr->attrEx);
356 Dmsg3(100, "=== msglen=%d attrExlen=%d msg=%s\n", sd->msglen,
357 strlen(attr->attrEx), sd->msg);
359 attr->data_stream = decode_stat(attr->attr, &attr->statp, sizeof(attr->statp), &attr->LinkFI);
361 if (!is_restore_stream_supported(attr->data_stream)) {
362 if (!non_support_data++) {
363 Jmsg(jcr, M_WARNING, 0, _("%s stream not supported on this Client.\n"),
364 stream_to_ascii(attr->data_stream));
369 build_attr_output_fnames(jcr, attr);
372 * Try to actually create the file, which returns a status telling
373 * us if we need to extract or not.
375 jcr->num_files_examined++;
376 rctx.extract = false;
378 stat = plugin_create_file(jcr, attr, &rctx.bfd, jcr->replace);
380 stat = create_file(jcr, attr, &rctx.bfd, jcr->replace);
383 pm_strcpy(jcr->last_fname, attr->ofname);
384 jcr->last_type = attr->type;
386 Dmsg2(130, "Outfile=%s create_file stat=%d\n", attr->ofname, stat);
390 pm_strcpy(jcr->last_fname, attr->ofname);
391 jcr->last_type = attr->type;
395 * File created and we expect file data
403 * File created, but there is no content
406 print_ls_output(jcr, attr);
408 if (have_darwin_os) {
410 * Only restore the resource fork for regular files
412 from_base64(&rsrc_len, attr->attrEx);
413 if (attr->type == FT_REG && rsrc_len > 0) {
418 * Count the resource forks not as regular files being restored.
429 * set attributes now because file will not be extracted
432 plugin_set_attributes(jcr, attr, &rctx.bfd);
434 set_attributes(jcr, attr, &rctx.bfd);
444 case STREAM_ENCRYPTED_SESSION_DATA:
445 crypto_error_t cryptoerr;
448 * Is this an unexpected session data entry?
451 Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic session data stream.\n"));
452 rctx.extract = false;
458 * Do we have any keys at all?
460 if (!jcr->crypto.pki_recipients) {
461 Jmsg(jcr, M_ERROR, 0, _("No private decryption keys have been defined to decrypt encrypted backup data.\n"));
462 rctx.extract = false;
467 if (jcr->crypto.digest) {
468 crypto_digest_free(jcr->crypto.digest);
470 jcr->crypto.digest = crypto_digest_new(jcr, signing_algorithm);
471 if (!jcr->crypto.digest) {
472 Jmsg0(jcr, M_FATAL, 0, _("Could not create digest.\n"));
473 rctx.extract = false;
479 * Decode and save session keys.
481 cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen,
482 jcr->crypto.pki_recipients, &rctx.cs);
484 case CRYPTO_ERROR_NONE:
489 case CRYPTO_ERROR_NORECIPIENT:
490 Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data.\n"));
492 case CRYPTO_ERROR_DECRYPTION:
493 Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.\n"));
499 Jmsg1(jcr, M_ERROR, 0, _("An error occurred while decoding encrypted session data stream: %s\n"), crypto_strerror(cryptoerr));
503 if (cryptoerr != CRYPTO_ERROR_NONE) {
504 rctx.extract = false;
511 case STREAM_FILE_DATA:
512 case STREAM_SPARSE_DATA:
513 case STREAM_WIN32_DATA:
514 case STREAM_GZIP_DATA:
515 case STREAM_SPARSE_GZIP_DATA:
516 case STREAM_WIN32_GZIP_DATA:
517 case STREAM_COMPRESSED_DATA:
518 case STREAM_SPARSE_COMPRESSED_DATA:
519 case STREAM_WIN32_COMPRESSED_DATA:
520 case STREAM_ENCRYPTED_FILE_DATA:
521 case STREAM_ENCRYPTED_WIN32_DATA:
522 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
523 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
524 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
525 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
527 * Force an expected, consistent stream type here
529 if (rctx.extract && (rctx.prev_stream == rctx.stream
530 || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES
531 || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES_EX
532 || rctx.prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
535 if (rctx.stream == STREAM_SPARSE_DATA
536 || rctx.stream == STREAM_SPARSE_COMPRESSED_DATA
537 || rctx.stream == STREAM_SPARSE_GZIP_DATA) {
538 rctx.flags |= FO_SPARSE;
541 if (rctx.stream == STREAM_GZIP_DATA
542 || rctx.stream == STREAM_SPARSE_GZIP_DATA
543 || rctx.stream == STREAM_WIN32_GZIP_DATA
544 || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
545 || rctx.stream == STREAM_COMPRESSED_DATA
546 || rctx.stream == STREAM_SPARSE_COMPRESSED_DATA
547 || rctx.stream == STREAM_WIN32_COMPRESSED_DATA
548 || rctx.stream == STREAM_ENCRYPTED_FILE_COMPRESSED_DATA
549 || rctx.stream == STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA
550 || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
551 rctx.flags |= FO_COMPRESS;
552 rctx.comp_stream = rctx.stream;
555 if (rctx.stream == STREAM_ENCRYPTED_FILE_DATA
556 || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
557 || rctx.stream == STREAM_ENCRYPTED_WIN32_DATA
558 || rctx.stream == STREAM_ENCRYPTED_FILE_COMPRESSED_DATA
559 || rctx.stream == STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA
560 || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
562 * Set up a decryption context
564 if (!rctx.cipher_ctx.cipher) {
566 Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
567 rctx.extract = false;
572 if ((rctx.cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false,
573 &rctx.cipher_ctx.block_size)) == NULL) {
574 Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
576 rctx.extract = false;
581 rctx.flags |= FO_ENCRYPT;
584 if (is_win32_stream(rctx.stream) && !have_win32_api()) {
585 set_portable_backup(&rctx.bfd);
587 * "decompose" BackupWrite data
589 rctx.flags |= FO_WIN32DECOMP;
592 if (extract_data(jcr, &rctx.bfd, sd->msg, sd->msglen, &rctx.fileAddr,
593 rctx.flags, rctx.stream, &rctx.cipher_ctx) < 0) {
594 rctx.extract = false;
602 * Resource fork stream - only recorded after a file to be restored
603 * Silently ignore if we cannot write - we already reported that
605 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
606 case STREAM_MACOS_FORK_DATA:
607 if (have_darwin_os) {
609 jcr->ff->flags |= FO_HFSPLUS;
611 if (rctx.stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) {
612 rctx.fork_flags |= FO_ENCRYPT;
615 * Set up a decryption context
617 if (rctx.extract && !rctx.fork_cipher_ctx.cipher) {
619 Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
620 rctx.extract = false;
625 if ((rctx.fork_cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false, &rctx.fork_cipher_ctx.block_size)) == NULL) {
626 Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
628 rctx.extract = false;
636 if (rctx.prev_stream != rctx.stream) {
637 if (bopen_rsrc(&rctx.forkbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
638 Jmsg(jcr, M_WARNING, 0, _("Cannot open resource fork for %s.\n"), jcr->last_fname);
639 rctx.extract = false;
643 rctx.fork_size = rsrc_len;
644 Dmsg0(130, "Restoring resource fork\n");
647 if (extract_data(jcr, &rctx.forkbfd, sd->msg, sd->msglen, &rctx.fork_addr, rctx.fork_flags,
648 rctx.stream, &rctx.fork_cipher_ctx) < 0) {
649 rctx.extract = false;
650 bclose(&rctx.forkbfd);
659 case STREAM_HFSPLUS_ATTRIBUTES:
660 if (have_darwin_os) {
661 if (!restore_finderinfo(jcr, sd->msg, sd->msglen)) {
669 case STREAM_UNIX_ACCESS_ACL:
670 case STREAM_UNIX_DEFAULT_ACL:
671 case STREAM_ACL_AIX_TEXT:
672 case STREAM_ACL_DARWIN_ACCESS_ACL:
673 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
674 case STREAM_ACL_FREEBSD_ACCESS_ACL:
675 case STREAM_ACL_HPUX_ACL_ENTRY:
676 case STREAM_ACL_IRIX_DEFAULT_ACL:
677 case STREAM_ACL_IRIX_ACCESS_ACL:
678 case STREAM_ACL_LINUX_DEFAULT_ACL:
679 case STREAM_ACL_LINUX_ACCESS_ACL:
680 case STREAM_ACL_TRU64_DEFAULT_ACL:
681 case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
682 case STREAM_ACL_TRU64_ACCESS_ACL:
683 case STREAM_ACL_SOLARIS_ACLENT:
684 case STREAM_ACL_SOLARIS_ACE:
685 case STREAM_ACL_AFS_TEXT:
686 case STREAM_ACL_AIX_AIXC:
687 case STREAM_ACL_AIX_NFS4:
688 case STREAM_ACL_FREEBSD_NFS4_ACL:
690 * Do not restore ACLs when
691 * a) The current file is not extracted
692 * b) and it is not a directory (they are never "extracted")
693 * c) or the file name is empty
695 if ((!rctx.extract && jcr->last_type != FT_DIREND) || (*jcr->last_fname == 0)) {
699 pm_memcpy(jcr->acl_data->content, sd->msg, sd->msglen);
700 jcr->acl_data->content_length = sd->msglen;
701 switch (parse_acl_streams(jcr, rctx.stream)) {
702 case bacl_exit_fatal:
704 case bacl_exit_error:
706 * Non-fatal errors, count them and when the number is under ACL_REPORT_ERR_MAX_PER_JOB
707 * print the error message set by the lower level routine in jcr->errmsg.
709 if (jcr->acl_data->nr_errors < ACL_REPORT_ERR_MAX_PER_JOB) {
710 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
712 jcr->acl_data->nr_errors++;
722 case STREAM_XATTR_IRIX:
723 case STREAM_XATTR_TRU64:
724 case STREAM_XATTR_AIX:
725 case STREAM_XATTR_OPENBSD:
726 case STREAM_XATTR_SOLARIS_SYS:
727 case STREAM_XATTR_SOLARIS:
728 case STREAM_XATTR_DARWIN:
729 case STREAM_XATTR_FREEBSD:
730 case STREAM_XATTR_LINUX:
731 case STREAM_XATTR_NETBSD:
733 * Do not restore Extended Attributes when
734 * a) The current file is not extracted
735 * b) and it is not a directory (they are never "extracted")
736 * c) or the file name is empty
738 if ((!rctx.extract && jcr->last_type != FT_DIREND) || (*jcr->last_fname == 0)) {
742 pm_memcpy(jcr->xattr_data->content, sd->msg, sd->msglen);
743 jcr->xattr_data->content_length = sd->msglen;
744 switch (parse_xattr_streams(jcr, rctx.stream)) {
745 case bxattr_exit_fatal:
747 case bxattr_exit_error:
749 * Non-fatal errors, count them and when the number is under XATTR_REPORT_ERR_MAX_PER_JOB
750 * print the error message set by the lower level routine in jcr->errmsg.
752 if (jcr->xattr_data->nr_errors < XATTR_REPORT_ERR_MAX_PER_JOB) {
753 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
755 jcr->xattr_data->nr_errors++;
765 case STREAM_SIGNED_DIGEST:
767 * Is this an unexpected signature?
770 Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic signature data stream.\n"));
771 free_signature(rctx);
777 if (rctx.extract && (rctx.sig = crypto_sign_decode(jcr, (uint8_t *)sd->msg, (uint32_t)sd->msglen)) == NULL) {
778 Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname);
782 case STREAM_MD5_DIGEST:
783 case STREAM_SHA1_DIGEST:
784 case STREAM_SHA256_DIGEST:
785 case STREAM_SHA512_DIGEST:
788 case STREAM_PROGRAM_NAMES:
789 case STREAM_PROGRAM_DATA:
790 if (!non_support_progname) {
791 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
792 non_support_progname++;
796 case STREAM_PLUGIN_NAME:
797 close_previous_stream(rctx);
798 Dmsg1(50, "restore stream_plugin_name=%s\n", sd->msg);
799 plugin_name_stream(jcr, sd->msg);
802 case STREAM_RESTORE_OBJECT:
803 break; /* these are sent by Director */
806 close_previous_stream(rctx);
807 Jmsg(jcr, M_WARNING, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
809 Dmsg2(0, "Unknown stream=%d data=%s\n", rctx.stream, sd->msg);
811 } /* end switch(stream) */
812 } /* end while get_msg() */
815 * If output file is still open, it was the last one in the
816 * archive since we just hit an end of file, so close the file.
818 if (is_bopen(&rctx.forkbfd)) {
819 bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
822 close_previous_stream(rctx);
823 jcr->setJobStatus(JS_Terminated);
827 jcr->setJobStatus(JS_ErrorTerminated);
831 * First output the statistics.
833 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
834 edit_uint64(jcr->JobBytes, ec1));
835 if (have_acl && jcr->acl_data->nr_errors > 0) {
836 Jmsg(jcr, M_WARNING, 0, _("Encountered %ld acl errors while doing restore\n"),
837 jcr->acl_data->nr_errors);
839 if (have_xattr && jcr->xattr_data->nr_errors > 0) {
840 Jmsg(jcr, M_WARNING, 0, _("Encountered %ld xattr errors while doing restore\n"),
841 jcr->xattr_data->nr_errors);
843 if (non_support_data > 1 || non_support_attr > 1) {
844 Jmsg(jcr, M_WARNING, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
845 non_support_data, non_support_attr);
847 if (non_support_rsrc) {
848 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
850 if (non_support_finfo) {
851 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
853 if (non_support_acl) {
854 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
856 if (non_support_crypto) {
857 Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl);
859 if (non_support_xattr) {
860 Jmsg(jcr, M_INFO, 0, _("%d non-supported xattr streams ignored.\n"), non_support_xattr);
864 * Free Signature & Crypto Data
866 free_signature(rctx);
868 if (jcr->crypto.digest) {
869 crypto_digest_free(jcr->crypto.digest);
870 jcr->crypto.digest = NULL;
874 * Free file cipher restore context
876 if (rctx.cipher_ctx.cipher) {
877 crypto_cipher_free(rctx.cipher_ctx.cipher);
878 rctx.cipher_ctx.cipher = NULL;
881 if (rctx.cipher_ctx.buf) {
882 free_pool_memory(rctx.cipher_ctx.buf);
883 rctx.cipher_ctx.buf = NULL;
887 * Free alternate stream cipher restore context
889 if (rctx.fork_cipher_ctx.cipher) {
890 crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
891 rctx.fork_cipher_ctx.cipher = NULL;
893 if (rctx.fork_cipher_ctx.buf) {
894 free_pool_memory(rctx.fork_cipher_ctx.buf);
895 rctx.fork_cipher_ctx.buf = NULL;
898 if (jcr->compress_buf) {
899 free_pool_memory(jcr->compress_buf);
900 jcr->compress_buf = NULL;
901 jcr->compress_buf_size = 0;
904 if (have_acl && jcr->acl_data) {
905 free_pool_memory(jcr->acl_data->content);
907 jcr->acl_data = NULL;
910 if (have_xattr && jcr->xattr_data) {
911 free_pool_memory(jcr->xattr_data->content);
912 free(jcr->xattr_data);
913 jcr->xattr_data = NULL;
916 bclose(&rctx.forkbfd);
918 free_attr(rctx.attr);
923 * Convert ZLIB error code into an ASCII message
925 static const char *zlib_strerror(int stat)
932 return _("Zlib errno");
934 return _("Zlib stream error");
936 return _("Zlib data error");
938 return _("Zlib memory error");
940 return _("Zlib buffer error");
941 case Z_VERSION_ERROR:
942 return _("Zlib version error");
949 static int do_file_digest(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
951 Dmsg1(50, "do_file_digest jcr=%p\n", jcr);
952 return (digest_file(jcr, ff_pkt, jcr->crypto.digest));
956 * Verify the signature for the last restored file
957 * Return value is either true (signature correct)
958 * or false (signature could not be verified).
959 * TODO landonf: Implement without using find_one_file and
960 * without re-reading the file.
962 static bool verify_signature(JCR *jcr, r_ctx &rctx)
964 X509_KEYPAIR *keypair;
965 DIGEST *digest = NULL;
967 uint64_t saved_bytes;
968 crypto_digest_t signing_algorithm = have_sha2 ?
969 CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
970 crypto_digest_t algorithm;
971 SIGNATURE *sig = rctx.sig;
974 if (!jcr->crypto.pki_sign) {
981 if (rctx.type == FT_REGE || rctx.type == FT_REG || rctx.type == FT_RAW) {
982 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"),
990 * Iterate through the trusted signers
992 foreach_alist(keypair, jcr->crypto.pki_signers) {
993 err = crypto_sign_get_digest(sig, jcr->crypto.pki_keypair, algorithm, &digest);
995 case CRYPTO_ERROR_NONE:
996 Dmsg0(50, "== Got digest\n");
998 * We computed jcr->crypto.digest using signing_algorithm while writing
999 * the file. If it is not the same as the algorithm used for
1000 * this file, punt by releasing the computed algorithm and
1001 * computing by re-reading the file.
1003 if (algorithm != signing_algorithm) {
1004 if (jcr->crypto.digest) {
1005 crypto_digest_free(jcr->crypto.digest);
1006 jcr->crypto.digest = NULL;
1009 if (jcr->crypto.digest) {
1011 * Use digest computed while writing the file to verify the signature
1013 if ((err = crypto_sign_verify(sig, keypair, jcr->crypto.digest)) != CRYPTO_ERROR_NONE) {
1014 Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
1015 Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"),
1016 jcr->last_fname, crypto_strerror(err));
1021 * Signature found, digest allocated. Old method,
1022 * re-read the file and compute the digest
1024 jcr->crypto.digest = digest;
1027 * Checksum the entire file
1028 * Make sure we don't modify JobBytes by saving and restoring it
1030 saved_bytes = jcr->JobBytes;
1031 if (find_one_file(jcr, jcr->ff, do_file_digest, jcr->last_fname, (dev_t)-1, 1) != 0) {
1032 Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"),
1034 jcr->JobBytes = saved_bytes;
1037 jcr->JobBytes = saved_bytes;
1040 * Verify the signature
1042 if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
1043 Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
1044 Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"),
1045 jcr->last_fname, crypto_strerror(err));
1048 jcr->crypto.digest = NULL;
1054 Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
1055 crypto_digest_free(digest);
1058 case CRYPTO_ERROR_NOSIGNER:
1060 * Signature not found, try again
1063 crypto_digest_free(digest);
1069 * Something strange happened (that shouldn't happen!)...
1071 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
1079 Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
1083 crypto_digest_free(digest);
1088 bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *length)
1093 unser_begin(*data, OFFSET_FADDR_SIZE);
1094 unser_uint64(faddr);
1095 if (*addr != faddr) {
1097 if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
1099 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
1100 edit_uint64(*addr, ec1), jcr->last_fname,
1101 be.bstrerror(bfd->berrno));
1105 *data += OFFSET_FADDR_SIZE;
1106 *length -= OFFSET_FADDR_SIZE;
1110 bool decompress_data(JCR *jcr, int32_t stream, char **data, uint32_t *length)
1112 char ec1[50]; /* Buffer printing huge values */
1114 Dmsg1(200, "Stream found in decompress_data(): %d\n", stream);
1115 if(stream == STREAM_COMPRESSED_DATA || stream == STREAM_SPARSE_COMPRESSED_DATA || stream == STREAM_WIN32_COMPRESSED_DATA
1116 || stream == STREAM_ENCRYPTED_FILE_COMPRESSED_DATA || stream == STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA)
1118 uint32_t comp_magic, comp_len;
1119 uint16_t comp_level, comp_version;
1121 lzo_uint compress_len;
1122 const unsigned char *cbuf;
1123 int r, real_compress_len;
1126 /* read compress header */
1128 unser_begin(*data, sizeof(comp_stream_header));
1129 unser_uint32(comp_magic);
1130 unser_uint32(comp_len);
1131 unser_uint16(comp_level);
1132 unser_uint16(comp_version);
1133 Dmsg4(200, "Compressed data stream found: magic=0x%x, len=%d, level=%d, ver=0x%x\n", comp_magic, comp_len,
1134 comp_level, comp_version);
1137 if (comp_version != COMP_HEAD_VERSION) {
1138 Qmsg(jcr, M_ERROR, 0, _("Compressed header version error. version=0x%x\n"), comp_version);
1142 if (comp_len + sizeof(comp_stream_header) != *length) {
1143 Qmsg(jcr, M_ERROR, 0, _("Compressed header size error. comp_len=%d, msglen=%d\n"),
1147 switch(comp_magic) {
1149 case COMPRESS_LZO1X:
1150 compress_len = jcr->compress_buf_size;
1151 cbuf = (const unsigned char*)*data + sizeof(comp_stream_header);
1152 real_compress_len = *length - sizeof(comp_stream_header);
1153 Dmsg2(200, "Comp_len=%d msglen=%d\n", compress_len, *length);
1154 while ((r=lzo1x_decompress_safe(cbuf, real_compress_len,
1155 (unsigned char *)jcr->compress_buf, &compress_len, NULL)) == LZO_E_OUTPUT_OVERRUN)
1158 * The buffer size is too small, try with a bigger one
1160 compress_len = jcr->compress_buf_size = jcr->compress_buf_size + (jcr->compress_buf_size >> 1);
1161 Dmsg2(200, "Comp_len=%d msglen=%d\n", compress_len, *length);
1162 jcr->compress_buf = check_pool_memory_size(jcr->compress_buf,
1165 if (r != LZO_E_OK) {
1166 Qmsg(jcr, M_ERROR, 0, _("LZO uncompression error on file %s. ERR=%d\n"),
1167 jcr->last_fname, r);
1170 *data = jcr->compress_buf;
1171 *length = compress_len;
1172 Dmsg2(200, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
1176 Qmsg(jcr, M_ERROR, 0, _("Compression algorithm 0x%x found, but not supported!\n"), comp_magic);
1185 * NOTE! We only use uLong and Byte because they are
1186 * needed by the zlib routines, they should not otherwise
1187 * be used in Bacula.
1189 compress_len = jcr->compress_buf_size;
1190 Dmsg2(200, "Comp_len=%d msglen=%d\n", compress_len, *length);
1191 while ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
1192 (const Byte *)*data, (uLong)*length)) == Z_BUF_ERROR)
1195 * The buffer size is too small, try with a bigger one
1197 compress_len = jcr->compress_buf_size = jcr->compress_buf_size + (jcr->compress_buf_size >> 1);
1198 Dmsg2(200, "Comp_len=%d msglen=%d\n", compress_len, *length);
1199 jcr->compress_buf = check_pool_memory_size(jcr->compress_buf,
1203 Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
1204 jcr->last_fname, zlib_strerror(stat));
1207 *data = jcr->compress_buf;
1208 *length = compress_len;
1209 Dmsg2(200, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
1212 Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
1218 static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
1221 if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
1222 unser_begin(&ctx->buf[0], CRYPTO_LEN_SIZE);
1223 unser_uint32(ctx->packet_len);
1224 ctx->packet_len += CRYPTO_LEN_SIZE;
1228 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
1230 if (jcr->crypto.digest) {
1231 crypto_digest_update(jcr->crypto.digest, (uint8_t *)data, length);
1234 if (!processWin32BackupAPIBlock(bfd, data, length)) {
1236 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
1237 jcr->last_fname, be.bstrerror(bfd->berrno));
1240 } else if (bwrite(bfd, data, length) != (ssize_t)length) {
1242 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
1243 jcr->last_fname, be.bstrerror(bfd->berrno));
1251 * In the context of jcr, write data to bfd.
1252 * We write buflen bytes in buf at addr. addr is updated in place.
1253 * The flags specify whether to use sparse files or compression.
1254 * Return value is the number of bytes written, or -1 on errors.
1256 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
1257 uint64_t *addr, int flags, int32_t stream, RESTORE_CIPHER_CTX *cipher_ctx)
1259 char *wbuf; /* write buffer */
1260 uint32_t wsize; /* write size */
1261 uint32_t rsize; /* read size */
1262 uint32_t decrypted_len = 0; /* Decryption output length */
1263 char ec1[50]; /* Buffer printing huge values */
1266 jcr->ReadBytes += rsize;
1270 if (flags & FO_ENCRYPT) {
1271 ASSERT(cipher_ctx->cipher);
1274 * NOTE: We must implement block preserving semantics for the
1275 * non-streaming compression and sparse code.
1277 * Grow the crypto buffer, if necessary.
1278 * crypto_cipher_update() will process only whole blocks,
1279 * buffering the remaining input.
1281 cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf,
1282 cipher_ctx->buf_len + wsize + cipher_ctx->block_size);
1285 * Decrypt the input block
1287 if (!crypto_cipher_update(cipher_ctx->cipher,
1288 (const u_int8_t *)wbuf,
1290 (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1293 * Decryption failed. Shouldn't happen.
1295 Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
1299 if (decrypted_len == 0) {
1301 * No full block of encrypted data available, write more data
1306 Dmsg2(200, "decrypted len=%d encrypted len=%d\n", decrypted_len, wsize);
1308 cipher_ctx->buf_len += decrypted_len;
1309 wbuf = cipher_ctx->buf;
1312 * If one full preserved block is available, write it to disk,
1313 * and then buffer any remaining data. This should be effecient
1314 * as long as Bacula's block size is not significantly smaller than the
1315 * encryption block size (extremely unlikely!)
1317 unser_crypto_packet_len(cipher_ctx);
1318 Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1320 if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
1322 * No full preserved block is available.
1328 * We have one full block, set up the filter input buffers
1330 wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1331 wbuf = &wbuf[CRYPTO_LEN_SIZE]; /* Skip the block length header */
1332 cipher_ctx->buf_len -= cipher_ctx->packet_len;
1333 Dmsg2(130, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1336 if ((flags & FO_SPARSE) || (flags & FO_OFFSETS)) {
1337 if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1342 if (flags & FO_COMPRESS) {
1343 if (!decompress_data(jcr, stream, &wbuf, &wsize)) {
1348 if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1351 jcr->JobBytes += wsize;
1353 Dmsg2(130, "Write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1356 * Clean up crypto buffers
1358 if (flags & FO_ENCRYPT) {
1359 /* Move any remaining data to start of buffer */
1360 if (cipher_ctx->buf_len > 0) {
1361 Dmsg1(130, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1362 memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
1363 cipher_ctx->buf_len);
1366 * The packet was successfully written, reset the length so that the next
1367 * packet length may be re-read by unser_crypto_packet_len()
1369 cipher_ctx->packet_len = 0;
1379 * If extracting, close any previous stream
1381 static void close_previous_stream(r_ctx &rctx)
1384 * If extracting, it was from previous stream, so
1385 * close the output file and validate the signature.
1388 if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
1389 Jmsg0(rctx.jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
1390 Dmsg2(000, "=== logic error size=%d bopen=%d\n", rctx.size,
1391 is_bopen(&rctx.bfd));
1394 if (rctx.prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
1395 deallocate_cipher(rctx);
1396 deallocate_fork_cipher(rctx);
1399 if (rctx.jcr->plugin) {
1400 plugin_set_attributes(rctx.jcr, rctx.attr, &rctx.bfd);
1402 set_attributes(rctx.jcr, rctx.attr, &rctx.bfd);
1404 rctx.extract = false;
1407 * Verify the cryptographic signature, if any
1409 rctx.type = rctx.attr->type;
1410 verify_signature(rctx.jcr, rctx);
1415 free_signature(rctx);
1417 rctx.jcr->ff->flags = 0;
1418 Dmsg0(130, "Stop extracting.\n");
1419 } else if (is_bopen(&rctx.bfd)) {
1420 Jmsg0(rctx.jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
1421 Dmsg0(000, "=== logic error !open\n");
1428 * In the context of jcr, flush any remaining data from the cipher context,
1429 * writing it to bfd.
1430 * Return value is true on success, false on failure.
1432 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags, int32_t stream,
1433 RESTORE_CIPHER_CTX *cipher_ctx)
1435 uint32_t decrypted_len = 0;
1436 char *wbuf; /* write buffer */
1437 uint32_t wsize; /* write size */
1438 char ec1[50]; /* Buffer printing huge values */
1439 bool second_pass = false;
1443 * Write out the remaining block and free the cipher context
1445 cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len +
1446 cipher_ctx->block_size);
1448 if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1451 * Writing out the final, buffered block failed. Shouldn't happen.
1453 Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"),
1454 cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
1457 Dmsg2(130, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
1459 * If nothing new was decrypted, and our output buffer is empty, return
1461 if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
1465 cipher_ctx->buf_len += decrypted_len;
1467 unser_crypto_packet_len(cipher_ctx);
1468 Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1469 wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1471 * Decrypted, possibly decompressed output here.
1473 wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE];
1474 cipher_ctx->buf_len -= cipher_ctx->packet_len;
1475 Dmsg2(130, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1477 if ((flags & FO_SPARSE) || (flags & FO_OFFSETS)) {
1478 if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1483 if (flags & FO_COMPRESS) {
1484 if (!decompress_data(jcr, stream, &wbuf, &wsize)) {
1489 Dmsg0(130, "Call store_data\n");
1490 if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1493 jcr->JobBytes += wsize;
1494 Dmsg2(130, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1497 * Move any remaining data to start of buffer
1499 if (cipher_ctx->buf_len > 0) {
1500 Dmsg1(130, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1501 memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
1502 cipher_ctx->buf_len);
1505 * The packet was successfully written, reset the length so that the next
1506 * packet length may be re-read by unser_crypto_packet_len()
1508 cipher_ctx->packet_len = 0;
1510 if (cipher_ctx->buf_len >0 && !second_pass) {
1518 cipher_ctx->buf_len = 0;
1519 cipher_ctx->packet_len = 0;
1524 static void deallocate_cipher(r_ctx &rctx)
1527 * Flush and deallocate previous stream's cipher context
1529 if (rctx.cipher_ctx.cipher) {
1530 flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, rctx.comp_stream, &rctx.cipher_ctx);
1531 crypto_cipher_free(rctx.cipher_ctx.cipher);
1532 rctx.cipher_ctx.cipher = NULL;
1536 static void deallocate_fork_cipher(r_ctx &rctx)
1540 * Flush and deallocate previous stream's fork cipher context
1542 if (rctx.fork_cipher_ctx.cipher) {
1543 flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, rctx.comp_stream, &rctx.fork_cipher_ctx);
1544 crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
1545 rctx.fork_cipher_ctx.cipher = NULL;
1549 static void free_signature(r_ctx &rctx)
1552 crypto_sign_free(rctx.sig);
1557 static void free_session(r_ctx &rctx)
1560 crypto_session_free(rctx.cs);
1567 * This code if implemented goes above
1569 #ifdef stbernard_implemented
1570 / #if defined(HAVE_WIN32)
1571 bool bResumeOfmOnExit = FALSE;
1572 if (isOpenFileManagerRunning()) {
1573 if ( pauseOpenFileManager() ) {
1574 Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
1575 bResumeOfmOnExit = TRUE;
1578 Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
1582 char username[UNLEN+1];
1583 DWORD usize = sizeof(username);
1584 int privs = enable_backup_privileges(NULL, 1);
1585 if (GetUserName(username, &usize)) {
1586 Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
1588 Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));