2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 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 two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
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 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 John Walker.
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;
59 /* Data received from Storage Daemon */
60 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
62 typedef struct restore_cipher_ctx {
63 CIPHER_CONTEXT *cipher;
66 POOLMEM *buf; /* Pointer to descryption buffer */
67 int32_t buf_len; /* Count of bytes currently in buf */
68 int32_t packet_len; /* Total bytes in packet */
75 BFILE bfd; /* File content */
76 uint64_t fileAddr; /* file write address */
77 uint32_t size; /* Size of file */
78 int flags; /* Options for extract_data() */
79 BFILE forkbfd; /* Alternative data stream */
80 uint64_t fork_addr; /* Write address for alternative stream */
81 intmax_t fork_size; /* Size of alternate stream */
82 int fork_flags; /* Options for extract_data() */
84 SIGNATURE *sig; /* Cryptographic signature (if any) for file */
85 CRYPTO_SESSION *cs; /* Cryptographic session data (if any) for file */
86 RESTORE_CIPHER_CTX cipher_ctx; /* Cryptographic restore context (if any) for file */
87 RESTORE_CIPHER_CTX fork_cipher_ctx; /* Cryptographic restore context (if any) for alternative stream */
91 /* Forward referenced functions */
92 #if defined(HAVE_LIBZ)
93 static const char *zlib_strerror(int stat);
94 const bool have_libz = true;
96 const bool have_libz = false;
99 static void deallocate_cipher(r_ctx &rctx);
100 static void deallocate_fork_cipher(r_ctx &rctx);
101 static void free_signature(r_ctx &rctx);
102 static void free_session(r_ctx &rctx);
106 static bool verify_signature(JCR *jcr, SIGNATURE *sig);
107 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
108 uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx);
109 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
110 RESTORE_CIPHER_CTX *cipher_ctx);
114 * Close a bfd check that we are at the expected file offset.
115 * Makes some code in set_attributes().
117 int bclose_chksize(JCR *jcr, BFILE *bfd, boffset_t osize)
119 char ec1[50], ec2[50];
122 fsize = blseek(bfd, 0, SEEK_CUR);
123 bclose(bfd); /* first close file */
124 if (fsize > 0 && fsize != osize) {
125 Qmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
126 jcr->last_fname, edit_uint64(osize, ec1),
127 edit_uint64(fsize, ec2));
135 * Restore the requested files.
138 void do_restore(JCR *jcr)
141 uint32_t VolSessionId, VolSessionTime;
142 bool extract = false;
144 char ec1[50]; /* Buffer printing huge values */
145 uint32_t buf_size; /* client buffer size */
148 intmax_t rsrc_len = 0; /* Original length of resource fork */
151 memset(&rctx, 0, sizeof(rctx));
154 /* The following variables keep track of "known unknowns" */
155 int non_support_data = 0;
156 int non_support_attr = 0;
157 int non_support_rsrc = 0;
158 int non_support_finfo = 0;
159 int non_support_acl = 0;
160 int non_support_progname = 0;
161 int non_support_crypto = 0;
163 #ifdef HAVE_DARWIN_OS
164 struct attrlist attrList;
165 memset(&attrList, 0, sizeof(attrList));
166 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
167 attrList.commonattr = ATTR_CMN_FNDRINFO;
171 sd = jcr->store_bsock;
172 set_jcr_job_status(jcr, JS_Running);
175 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
178 buf_size = client->max_network_buffer_size;
180 buf_size = 0; /* use default */
182 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
183 set_jcr_job_status(jcr, JS_ErrorTerminated);
186 jcr->buf_size = sd->msglen;
188 /* St Bernard code goes here if implemented */
191 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
192 jcr->compress_buf = (char *)bmalloc(compress_buf_size);
193 jcr->compress_buf_size = compress_buf_size;
197 rctx.cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
198 if (have_darwin_os) {
199 rctx.fork_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
204 * Get a record from the Storage daemon. We are guaranteed to
205 * receive records in the following order:
206 * 1. Stream record header
208 * a. Attributes (Unix or Win32)
209 * b. Possibly stream encryption session data (e.g., symmetric session key)
210 * or c. File data for the file
211 * or d. Alternate data stream (e.g. Resource Fork)
214 * or g. Possibly a cryptographic signature
215 * or h. Possibly MD5 or SHA1 record
218 * NOTE: We keep track of two bacula file descriptors:
219 * 1. bfd for file data.
220 * This fd is opened for non empty files when an attribute stream is
221 * encountered and closed when we find the next attribute stream.
222 * 2. fork_bfd for alternate data streams
223 * This fd is opened every time we encounter a new alternate data
224 * stream for the current file. When we find any other stream, we
226 * The expected size of the stream, fork_len, should be set when
230 binit(&rctx.forkbfd);
232 jcr->acl_text = get_pool_memory(PM_MESSAGE);
234 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
235 /* Remember previous stream type */
236 rctx.prev_stream = rctx.stream;
238 /* First we expect a Stream Record Header */
239 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
240 &rctx.stream, &rctx.size) != 5) {
241 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
244 Dmsg4(30, "Got hdr: Files=%d FilInx=%d Stream=%d, %s.\n",
245 jcr->JobFiles, file_index, rctx.stream, stream_to_ascii(rctx.stream));
247 /* * Now we expect the Stream Data */
248 if (bget_msg(sd) < 0) {
249 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
252 if (rctx.size != (uint32_t)sd->msglen) {
253 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"),
254 sd->msglen, rctx.size);
257 Dmsg3(30, "Got stream: %s len=%d extract=%d\n", stream_to_ascii(rctx.stream),
258 sd->msglen, extract);
260 /* If we change streams, close and reset alternate data streams */
261 if (rctx.prev_stream != rctx.stream) {
262 if (is_bopen(&rctx.forkbfd)) {
263 deallocate_fork_cipher(rctx);
264 bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
266 rctx.fork_size = -1; /* Use an impossible value and set a proper one below */
270 /* File Attributes stream */
271 switch (rctx.stream) {
272 case STREAM_UNIX_ATTRIBUTES:
273 case STREAM_UNIX_ATTRIBUTES_EX:
275 * If extracting, it was from previous stream, so
276 * close the output file and validate the signature.
279 if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
280 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
283 if (rctx.prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
284 deallocate_cipher(rctx);
285 deallocate_fork_cipher(rctx);
288 set_attributes(jcr, attr, &rctx.bfd);
291 /* Verify the cryptographic signature, if any */
292 verify_signature(jcr, rctx.sig);
295 free_signature(rctx);
298 Dmsg0(30, "Stop extracting.\n");
299 } else if (is_bopen(&rctx.bfd)) {
300 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
305 * Unpack attributes and do sanity check them
307 if (!unpack_attributes_record(jcr, rctx.stream, sd->msg, attr)) {
310 if (file_index != attr->file_index) {
311 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
312 file_index, attr->file_index);
313 Dmsg0(100, "File index error\n");
317 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
318 attr->attr, attr->attrEx);
320 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
322 if (!is_restore_stream_supported(attr->data_stream)) {
323 if (!non_support_data++) {
324 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
325 stream_to_ascii(attr->data_stream));
330 build_attr_output_fnames(jcr, attr);
333 * Now determine if we are extracting or not.
335 jcr->num_files_examined++;
337 stat = create_file(jcr, attr, &rctx.bfd, jcr->replace);
338 Dmsg2(30, "Outfile=%s create_file stat=%d\n", attr->ofname, stat);
343 case CF_EXTRACT: /* File created and we expect file data */
346 case CF_CREATED: /* File created, but there is no content */
348 pm_strcpy(jcr->last_fname, attr->ofname);
349 jcr->last_type = attr->type;
353 print_ls_output(jcr, attr);
355 if (have_darwin_os) {
356 /* Only restore the resource fork for regular files */
357 from_base64(&rsrc_len, attr->attrEx);
358 if (attr->type == FT_REG && rsrc_len > 0) {
363 /* set attributes now because file will not be extracted */
364 set_attributes(jcr, attr, &rctx.bfd);
371 case STREAM_ENCRYPTED_SESSION_DATA:
372 crypto_error_t cryptoerr;
374 /* Is this an unexpected session data entry? */
376 Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic session data stream.\n"));
382 /* Do we have any keys at all? */
383 if (!jcr->pki_recipients) {
384 Jmsg(jcr, M_ERROR, 0, _("No private decryption keys have been defined to decrypt encrypted backup data.\n"));
390 /* Decode and save session keys. */
391 cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen,
392 jcr->pki_recipients, &rctx.cs);
394 case CRYPTO_ERROR_NONE:
397 case CRYPTO_ERROR_NORECIPIENT:
398 Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data.\n"));
400 case CRYPTO_ERROR_DECRYPTION:
401 Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.\n"));
404 /* Shouldn't happen */
405 Jmsg1(jcr, M_ERROR, 0, _("An error occurred while decoding encrypted session data stream: %s\n"), crypto_strerror(cryptoerr));
409 if (cryptoerr != CRYPTO_ERROR_NONE) {
417 case STREAM_FILE_DATA:
418 case STREAM_SPARSE_DATA:
419 case STREAM_WIN32_DATA:
420 case STREAM_GZIP_DATA:
421 case STREAM_SPARSE_GZIP_DATA:
422 case STREAM_WIN32_GZIP_DATA:
423 case STREAM_ENCRYPTED_FILE_DATA:
424 case STREAM_ENCRYPTED_WIN32_DATA:
425 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
426 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
427 /* Force an expected, consistent stream type here */
428 if (extract && (rctx.prev_stream == rctx.stream
429 || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES
430 || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES_EX
431 || rctx.prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
434 if (rctx.stream == STREAM_SPARSE_DATA ||
435 rctx.stream == STREAM_SPARSE_GZIP_DATA) {
436 rctx.flags |= FO_SPARSE;
439 if (rctx.stream == STREAM_GZIP_DATA
440 || rctx.stream == STREAM_SPARSE_GZIP_DATA
441 || rctx.stream == STREAM_WIN32_GZIP_DATA
442 || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
443 || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
444 rctx.flags |= FO_GZIP;
447 if (rctx.stream == STREAM_ENCRYPTED_FILE_DATA
448 || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
449 || rctx.stream == STREAM_ENCRYPTED_WIN32_DATA
450 || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
451 /* Set up a decryption context */
452 if (!rctx.cipher_ctx.cipher) {
454 Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
460 if ((rctx.cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false,
461 &rctx.cipher_ctx.block_size)) == NULL) {
462 Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
469 rctx.flags |= FO_ENCRYPT;
472 if (is_win32_stream(rctx.stream) && !have_win32_api()) {
473 set_portable_backup(&rctx.bfd);
474 rctx.flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
477 if (extract_data(jcr, &rctx.bfd, sd->msg, sd->msglen, &rctx.fileAddr,
478 rctx.flags, &rctx.cipher_ctx) < 0) {
486 /* Resource fork stream - only recorded after a file to be restored */
487 /* Silently ignore if we cannot write - we already reported that */
488 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
489 case STREAM_MACOS_FORK_DATA:
490 #ifdef HAVE_DARWIN_OS
492 jcr->ff->flags |= FO_HFSPLUS;
494 if (stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) {
495 fork_flags |= FO_ENCRYPT;
497 /* Set up a decryption context */
498 if (extract && !rctx.fork_cipher_ctx.cipher) {
500 Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
506 if ((rctx.fork_cipher_ctx.cipher = crypto_cipher_new(cs, false, &rctx.fork_cipher_ctx.block_size)) == NULL) {
507 Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
517 if (prev_stream != stream) {
518 if (bopen_rsrc(&forkbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
519 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
524 fork_size = rsrc_len;
525 Dmsg0(30, "Restoring resource fork\n");
528 if (extract_data(jcr, &forkbfd, sd->msg, sd->msglen, &rctx.fork_addr, fork_flags,
529 &rctxfork_cipher_ctx) < 0) {
540 case STREAM_HFSPLUS_ATTRIBUTES:
541 #ifdef HAVE_DARWIN_OS
542 Dmsg0(30, "Restoring Finder Info\n");
543 jcr->ff->flags |= FO_HFSPLUS;
544 if (sd->msglen != 32) {
545 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
548 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
549 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
557 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
559 pm_strcpy(jcr->acl_text, sd->msg);
560 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
561 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
562 Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
569 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
571 pm_strcpy(jcr->acl_text, sd->msg);
572 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
573 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
574 Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
581 case STREAM_SIGNED_DIGEST:
582 /* Is this an unexpected signature? */
584 Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic signature data stream.\n"));
585 free_signature(rctx);
588 /* Save signature. */
589 if (extract && (rctx.sig = crypto_sign_decode(jcr, (uint8_t *)sd->msg, (uint32_t)sd->msglen)) == NULL) {
590 Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname);
594 case STREAM_MD5_DIGEST:
595 case STREAM_SHA1_DIGEST:
596 case STREAM_SHA256_DIGEST:
597 case STREAM_SHA512_DIGEST:
600 case STREAM_PROGRAM_NAMES:
601 case STREAM_PROGRAM_DATA:
602 if (!non_support_progname) {
603 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
604 non_support_progname++;
609 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
611 Dmsg1(30, "Found wierd stream %d\n", rctx.stream);
612 if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
613 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
615 /* Flush and deallocate cipher context */
616 deallocate_cipher(rctx);
617 deallocate_fork_cipher(rctx);
619 set_attributes(jcr, attr, &rctx.bfd);
621 /* Verify the cryptographic signature if any */
622 verify_signature(jcr, rctx.sig);
624 } else if (is_bopen(&rctx.bfd)) {
625 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
628 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
630 Dmsg2(0, "None of above!!! stream=%d data=%s\n", rctx.stream,sd->msg);
632 } /* end switch(stream) */
634 } /* end while get_msg() */
636 /* If output file is still open, it was the last one in the
637 * archive since we just hit an end of file, so close the file.
639 if (is_bopen(&rctx.forkbfd)) {
640 bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
643 /* Flush and deallocate cipher context */
644 deallocate_cipher(rctx);
645 deallocate_fork_cipher(rctx);
647 set_attributes(jcr, attr, &rctx.bfd);
649 /* Verify the cryptographic signature on the last file, if any */
650 verify_signature(jcr, rctx.sig);
653 if (is_bopen(&rctx.bfd)) {
657 set_jcr_job_status(jcr, JS_Terminated);
661 set_jcr_job_status(jcr, JS_ErrorTerminated);
664 /* Free Signature & Crypto Data */
665 free_signature(rctx);
668 /* Free file cipher restore context */
669 if (rctx.cipher_ctx.cipher) {
670 crypto_cipher_free(rctx.cipher_ctx.cipher);
671 rctx.cipher_ctx.cipher = NULL;
673 if (rctx.cipher_ctx.buf) {
674 free_pool_memory(rctx.cipher_ctx.buf);
675 rctx.cipher_ctx.buf = NULL;
678 /* Free alternate stream cipher restore context */
679 if (rctx.fork_cipher_ctx.cipher) {
680 crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
681 rctx.fork_cipher_ctx.cipher = NULL;
683 if (rctx.fork_cipher_ctx.buf) {
684 free_pool_memory(rctx.fork_cipher_ctx.buf);
685 rctx.fork_cipher_ctx.buf = NULL;
688 if (jcr->compress_buf) {
689 free(jcr->compress_buf);
690 jcr->compress_buf = NULL;
691 jcr->compress_buf_size = 0;
693 bclose(&rctx.forkbfd);
696 free_pool_memory(jcr->acl_text);
697 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
698 edit_uint64(jcr->JobBytes, ec1));
699 if (non_support_data > 1 || non_support_attr > 1) {
700 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
701 non_support_data, non_support_attr);
703 if (non_support_rsrc) {
704 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
706 if (non_support_finfo) {
707 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
709 if (non_support_acl) {
710 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
712 if (non_support_crypto) {
713 Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl);
720 * Convert ZLIB error code into an ASCII message
722 static const char *zlib_strerror(int stat)
729 return _("Zlib errno");
731 return _("Zlib stream error");
733 return _("Zlib data error");
735 return _("Zlib memory error");
737 return _("Zlib buffer error");
738 case Z_VERSION_ERROR:
739 return _("Zlib version error");
746 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level)
748 JCR *jcr = (JCR *)pkt;
749 Dmsg1(50, "do_file_digest jcr=%p\n", jcr);
750 return (digest_file(jcr, ff_pkt, jcr->digest));
754 * Verify the signature for the last restored file
755 * Return value is either true (signature correct)
756 * or false (signature could not be verified).
757 * TODO landonf: Implement without using find_one_file and
758 * without re-reading the file.
760 static bool verify_signature(JCR *jcr, SIGNATURE *sig)
762 X509_KEYPAIR *keypair;
763 DIGEST *digest = NULL;
765 uint64_t saved_bytes;
767 if (!jcr->pki_sign) {
768 return true; /* no signature OK */
771 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"),
775 /* Iterate through the trusted signers */
776 foreach_alist(keypair, jcr->pki_signers) {
777 err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
779 case CRYPTO_ERROR_NONE:
780 Dmsg0(50, "== Got digest\n");
781 /* Signature found, digest allocated */
782 jcr->digest = digest;
784 /* Checksum the entire file */
785 /* Make sure we don't modify JobBytes by saving and restoring it */
786 saved_bytes = jcr->JobBytes;
787 if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
788 Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"),
790 jcr->JobBytes = saved_bytes;
793 jcr->JobBytes = saved_bytes;
795 /* Verify the signature */
796 if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
797 Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
798 Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"),
799 jcr->last_fname, crypto_strerror(err));
803 /* Valid signature */
804 Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
805 crypto_digest_free(digest);
809 case CRYPTO_ERROR_NOSIGNER:
810 /* Signature not found, try again */
812 crypto_digest_free(digest);
817 /* Something strange happened (that shouldn't happen!)... */
818 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
824 Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
828 crypto_digest_free(digest);
834 bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *length)
839 unser_begin(*data, SPARSE_FADDR_SIZE);
841 if (*addr != faddr) {
843 if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
845 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
846 edit_uint64(*addr, ec1), jcr->last_fname,
847 be.bstrerror(bfd->berrno));
851 *data += SPARSE_FADDR_SIZE;
852 *length -= SPARSE_FADDR_SIZE;
856 bool decompress_data(JCR *jcr, char **data, uint32_t *length)
861 char ec1[50]; /* Buffer printing huge values */
864 * NOTE! We only use uLong and Byte because they are
865 * needed by the zlib routines, they should not otherwise
868 compress_len = jcr->compress_buf_size;
869 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, *length);
870 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
871 (const Byte *)*data, (uLong)*length)) != Z_OK) {
872 Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
873 jcr->last_fname, zlib_strerror(stat));
876 *data = jcr->compress_buf;
877 *length = compress_len;
878 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
881 Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
886 static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
889 if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
890 unser_begin(&ctx->buf[0], CRYPTO_LEN_SIZE);
891 unser_uint32(ctx->packet_len);
892 ctx->packet_len += CRYPTO_LEN_SIZE;
896 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
899 if (!processWin32BackupAPIBlock(bfd, data, length)) {
901 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
902 jcr->last_fname, be.bstrerror(bfd->berrno));
905 } else if (bwrite(bfd, data, length) != (ssize_t)length) {
907 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
908 jcr->last_fname, be.bstrerror(bfd->berrno));
916 * In the context of jcr, write data to bfd.
917 * We write buflen bytes in buf at addr. addr is updated in place.
918 * The flags specify whether to use sparse files or compression.
919 * Return value is the number of bytes written, or -1 on errors.
921 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
922 uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx)
924 char *wbuf; /* write buffer */
925 uint32_t wsize; /* write size */
926 uint32_t rsize; /* read size */
927 uint32_t decrypted_len = 0; /* Decryption output length */
928 char ec1[50]; /* Buffer printing huge values */
931 jcr->ReadBytes += rsize;
935 if (flags & FO_ENCRYPT) {
936 ASSERT(cipher_ctx->cipher);
938 /* NOTE: We must implement block preserving semantics for the
939 * non-streaming compression and sparse code. */
942 * Grow the crypto buffer, if necessary.
943 * crypto_cipher_update() will process only whole blocks,
944 * buffering the remaining input.
946 cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf,
947 cipher_ctx->buf_len + wsize + cipher_ctx->block_size);
949 /* Decrypt the input block */
950 if (!crypto_cipher_update(cipher_ctx->cipher,
951 (const u_int8_t *)wbuf,
953 (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
955 /* Decryption failed. Shouldn't happen. */
956 Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
960 if (decrypted_len == 0) {
961 /* No full block of encrypted data available, write more data */
965 Dmsg2(100, "decrypted len=%d encrypted len=%d\n", decrypted_len, wsize);
967 cipher_ctx->buf_len += decrypted_len;
968 wbuf = cipher_ctx->buf;
970 /* If one full preserved block is available, write it to disk,
971 * and then buffer any remaining data. This should be effecient
972 * as long as Bacula's block size is not significantly smaller than the
973 * encryption block size (extremely unlikely!) */
974 unser_crypto_packet_len(cipher_ctx);
975 Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
977 if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
978 /* No full preserved block is available. */
982 /* We have one full block, set up the filter input buffers */
983 wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
984 wbuf = &wbuf[CRYPTO_LEN_SIZE]; /* Skip the block length header */
985 cipher_ctx->buf_len -= cipher_ctx->packet_len;
986 Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
989 if (flags & FO_SPARSE) {
990 if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
995 if (flags & FO_GZIP) {
996 if (!decompress_data(jcr, &wbuf, &wsize)) {
1001 if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1004 jcr->JobBytes += wsize;
1006 Dmsg2(30, "Write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1008 /* Clean up crypto buffers */
1009 if (flags & FO_ENCRYPT) {
1010 /* Move any remaining data to start of buffer */
1011 if (cipher_ctx->buf_len > 0) {
1012 Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1013 memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
1014 cipher_ctx->buf_len);
1016 /* The packet was successfully written, reset the length so that the next
1017 * packet length may be re-read by unser_crypto_packet_len() */
1018 cipher_ctx->packet_len = 0;
1025 * In the context of jcr, flush any remaining data from the cipher context,
1026 * writing it to bfd.
1027 * Return value is true on success, false on failure.
1029 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
1030 RESTORE_CIPHER_CTX *cipher_ctx)
1032 uint32_t decrypted_len = 0;
1033 char *wbuf; /* write buffer */
1034 uint32_t wsize; /* write size */
1035 char ec1[50]; /* Buffer printing huge values */
1036 bool second_pass = false;
1039 /* Write out the remaining block and free the cipher context */
1040 cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len +
1041 cipher_ctx->block_size);
1043 if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1045 /* Writing out the final, buffered block failed. Shouldn't happen. */
1046 Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"),
1047 cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
1050 Dmsg2(30, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
1051 /* If nothing new was decrypted, and our output buffer is empty, return */
1052 if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
1056 cipher_ctx->buf_len += decrypted_len;
1058 unser_crypto_packet_len(cipher_ctx);
1059 Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1060 wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1061 wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE]; /* Decrypted, possibly decompressed output here. */
1062 cipher_ctx->buf_len -= cipher_ctx->packet_len;
1063 Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1065 if (flags & FO_SPARSE) {
1066 if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1071 if (flags & FO_GZIP) {
1072 if (!decompress_data(jcr, &wbuf, &wsize)) {
1077 Dmsg0(30, "Call store_data\n");
1078 if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1081 jcr->JobBytes += wsize;
1082 Dmsg2(30, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1084 /* Move any remaining data to start of buffer */
1085 if (cipher_ctx->buf_len > 0) {
1086 Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1087 memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
1088 cipher_ctx->buf_len);
1090 /* The packet was successfully written, reset the length so that the next
1091 * packet length may be re-read by unser_crypto_packet_len() */
1092 cipher_ctx->packet_len = 0;
1094 if (cipher_ctx->buf_len >0 && !second_pass) {
1099 /* Stop decryption */
1100 cipher_ctx->buf_len = 0;
1101 cipher_ctx->packet_len = 0;
1106 static void deallocate_cipher(r_ctx &rctx)
1108 /* Flush and deallocate previous stream's cipher context */
1109 if (rctx.cipher_ctx.cipher) {
1110 flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx);
1111 crypto_cipher_free(rctx.cipher_ctx.cipher);
1112 rctx.cipher_ctx.cipher = NULL;
1116 static void deallocate_fork_cipher(r_ctx &rctx)
1119 /* Flush and deallocate previous stream's fork cipher context */
1120 if (rctx.fork_cipher_ctx.cipher) {
1121 flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx);
1122 crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
1123 rctx.fork_cipher_ctx.cipher = NULL;
1127 static void free_signature(r_ctx &rctx)
1130 crypto_sign_free(rctx.sig);
1135 static void free_session(r_ctx &rctx)
1138 crypto_session_free(rctx.cs);
1144 /* This code if implemented goes above */
1145 #ifdef stbernard_implemented
1146 / #if defined(HAVE_WIN32)
1147 bool bResumeOfmOnExit = FALSE;
1148 if (isOpenFileManagerRunning()) {
1149 if ( pauseOpenFileManager() ) {
1150 Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
1151 bResumeOfmOnExit = TRUE;
1154 Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
1158 char username[UNLEN+1];
1159 DWORD usize = sizeof(username);
1160 int privs = enable_backup_privileges(NULL, 1);
1161 if (GetUserName(username, &usize)) {
1162 Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
1164 Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));