2 * Bacula File Daemon restore.c Restorefiles.
4 * Kern Sibbald, November MM
10 Copyright (C) 2000-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
31 /* Data received from Storage Daemon */
32 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
34 /* Forward referenced functions */
36 static const char *zlib_strerror(int stat);
39 int verify_signature(JCR *jcr, SIGNATURE *sig);
40 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
41 uint64_t *addr, int flags);
43 #define RETRY 10 /* retry wait time */
46 * Close a bfd check that we are at the expected file offset.
47 * Makes some code in set_attributes().
49 int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
51 char ec1[50], ec2[50];
54 fsize = blseek(bfd, 0, SEEK_CUR);
55 bclose(bfd); /* first close file */
56 if (fsize > 0 && fsize != osize) {
57 Qmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
58 jcr->last_fname, edit_uint64(osize, ec1),
59 edit_uint64(fsize, ec2));
66 * Restore the requested files.
69 void do_restore(JCR *jcr)
74 uint32_t VolSessionId, VolSessionTime;
77 char ec1[50]; /* Buffer printing huge values */
79 BFILE bfd; /* File content */
80 uint64_t fileAddr = 0; /* file write address */
81 uint32_t size; /* Size of file */
82 BFILE altbfd; /* Alternative data stream */
83 uint64_t alt_addr = 0; /* Write address for alternative stream */
84 intmax_t alt_size = 0; /* Size of alternate stream */
85 SIGNATURE *sig = NULL; /* Cryptographic signature (if any) for file */
86 CRYPTO_SESSION *cs = NULL; /* Cryptographic session data (if any) for file */
87 int flags; /* Options for extract_data() */
91 /* The following variables keep track of "known unknowns" */
92 int non_support_data = 0;
93 int non_support_attr = 0;
94 int non_support_rsrc = 0;
95 int non_support_finfo = 0;
96 int non_support_acl = 0;
97 int non_support_progname = 0;
99 /* Finally, set up for special configurations */
100 #ifdef HAVE_DARWIN_OS
101 intmax_t rsrc_len = 0; /* Original length of resource fork */
102 struct attrlist attrList;
104 memset(&attrList, 0, sizeof(attrList));
105 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
106 attrList.commonattr = ATTR_CMN_FNDRINFO;
109 sd = jcr->store_bsock;
110 set_jcr_job_status(jcr, JS_Running);
113 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
117 buf_size = client->max_network_buffer_size;
119 buf_size = 0; /* use default */
121 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
122 set_jcr_job_status(jcr, JS_ErrorTerminated);
125 jcr->buf_size = sd->msglen;
128 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
129 jcr->compress_buf = (char *)bmalloc(compress_buf_size);
130 jcr->compress_buf_size = compress_buf_size;
134 * Get a record from the Storage daemon. We are guaranteed to
135 * receive records in the following order:
136 * 1. Stream record header
138 * a. Attributes (Unix or Win32)
139 * b. Possibly stream encryption session data (e.g., symmetric session key)
140 * or c. File data for the file
141 * or d. Alternate data stream (e.g. Resource Fork)
144 * or g. Possibly a cryptographic signature
145 * or h. Possibly MD5 or SHA1 record
148 * NOTE: We keep track of two bacula file descriptors:
149 * 1. bfd for file data.
150 * This fd is opened for non empty files when an attribute stream is
151 * encountered and closed when we find the next attribute stream.
152 * 2. alt_bfd for alternate data streams
153 * This fd is opened every time we encounter a new alternate data
154 * stream for the current file. When we find any other stream, we
156 * The expected size of the stream, alt_len, should be set when
162 jcr->acl_text = get_pool_memory(PM_MESSAGE);
164 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
165 /* Remember previous stream type */
166 prev_stream = stream;
168 /* First we expect a Stream Record Header */
169 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
170 &stream, &size) != 5) {
171 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
174 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
176 /* * Now we expect the Stream Data */
177 if (bget_msg(sd) < 0) {
178 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
181 if (size != (uint32_t)sd->msglen) {
182 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
185 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
187 /* If we change streams, close and reset alternate data streams */
188 if (prev_stream != stream) {
189 if (is_bopen(&altbfd)) {
190 bclose_chksize(jcr, &altbfd, alt_size);
192 alt_size = -1; /* Use an impossible value and set a proper one below */
196 /* File Attributes stream */
198 case STREAM_UNIX_ATTRIBUTES:
199 case STREAM_UNIX_ATTRIBUTES_EX:
200 Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
202 * If extracting, it was from previous stream, so
203 * close the output file and validate the signature.
206 if (size > 0 && !is_bopen(&bfd)) {
207 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
209 set_attributes(jcr, attr, &bfd);
212 /* Verify the cryptographic signature, if any */
215 if (!verify_signature(jcr, sig)) {
216 // TODO landonf: Better signature failure handling.
217 // The failure is reported to the director in verify_signature() ...
218 Dmsg1(100, "Bad signature on %s\n", jcr->last_fname);
220 Dmsg1(100, "Signature good on %s\n", jcr->last_fname);
223 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
229 crypto_sign_free(sig);
234 crypto_session_free(cs);
238 Dmsg0(30, "Stop extracting.\n");
239 } else if (is_bopen(&bfd)) {
240 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
245 * Unpack and do sanity check fo attributes.
247 if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
250 if (file_index != attr->file_index) {
251 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
252 file_index, attr->file_index);
253 Dmsg0(100, "File index error\n");
257 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
258 attr->attr, attr->attrEx);
260 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
262 if (!is_restore_stream_supported(attr->data_stream)) {
263 if (!non_support_data++) {
264 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
265 stream_to_ascii(attr->data_stream));
270 build_attr_output_fnames(jcr, attr);
273 * Now determine if we are extracting or not.
275 jcr->num_files_examined++;
276 Dmsg1(30, "Outfile=%s\n", attr->ofname);
278 stat = create_file(jcr, attr, &bfd, jcr->replace);
283 case CF_EXTRACT: /* File created and we expect file data */
286 case CF_CREATED: /* File created, but there is no content */
288 pm_strcpy(jcr->last_fname, attr->ofname);
292 print_ls_output(jcr, attr);
293 #ifdef HAVE_DARWIN_OS
294 /* Only restore the resource fork for regular files */
295 from_base64(&rsrc_len, attr->attrEx);
296 if (attr->type == FT_REG && rsrc_len > 0) {
301 /* set attributes now because file will not be extracted */
302 set_attributes(jcr, attr, &bfd);
309 case STREAM_ENCRYPTED_SESSION_DATA:
310 Dmsg1(30, "Stream=Encrypted Session Data, size: %d\n", sd->msglen);
311 /* Save session keys . */
312 switch(crypto_session_decode(sd->msg, (size_t) sd->msglen, jcr->pki_recipients, &cs)) {
313 case CRYPTO_ERROR_NONE:
316 case CRYPTO_ERROR_NORECIPIENT:
317 Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data."));
319 case CRYPTO_ERROR_DECRYPTION:
320 Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed."));
323 /* Shouldn't happen */
324 Jmsg(jcr, M_ERROR, 0, _("An error occured while decoding encrypted session data stream."));
330 case STREAM_FILE_DATA:
331 case STREAM_SPARSE_DATA:
332 case STREAM_WIN32_DATA:
333 case STREAM_GZIP_DATA:
334 case STREAM_SPARSE_GZIP_DATA:
335 case STREAM_WIN32_GZIP_DATA:
336 /* Force an expected, consistent stream type here */
337 if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
338 || prev_stream == STREAM_UNIX_ATTRIBUTES_EX
339 || prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
341 if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
344 if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
345 || stream == STREAM_WIN32_GZIP_DATA) {
349 if (is_win32_stream(stream) && !have_win32_api()) {
350 set_portable_backup(&bfd);
351 flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
354 if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags) < 0) {
362 /* Resource fork stream - only recorded after a file to be restored */
363 /* Silently ignore if we cannot write - we already reported that */
364 case STREAM_MACOS_FORK_DATA:
365 #ifdef HAVE_DARWIN_OS
367 if (prev_stream != stream) {
368 if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
369 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
374 Dmsg0(30, "Restoring resource fork\n");
377 if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags) < 0) {
388 case STREAM_HFSPLUS_ATTRIBUTES:
389 #ifdef HAVE_DARWIN_OS
390 Dmsg0(30, "Restoring Finder Info\n");
391 if (sd->msglen != 32) {
392 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
395 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
396 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
403 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
405 pm_strcpy(jcr->acl_text, sd->msg);
406 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
407 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
408 Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
415 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
417 pm_strcpy(jcr->acl_text, sd->msg);
418 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
419 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
420 Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
427 case STREAM_SIGNED_DIGEST:
428 /* Save signature. */
429 sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen);
432 case STREAM_MD5_DIGEST:
433 case STREAM_SHA1_DIGEST:
434 case STREAM_SHA256_DIGEST:
435 case STREAM_SHA512_DIGEST:
438 case STREAM_PROGRAM_NAMES:
439 case STREAM_PROGRAM_DATA:
440 if (!non_support_progname) {
441 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
442 non_support_progname++;
447 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
449 Dmsg1(30, "Found wierd stream %d\n", stream);
450 if (size > 0 && !is_bopen(&bfd)) {
451 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
453 set_attributes(jcr, attr, &bfd);
455 } else if (is_bopen(&bfd)) {
456 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
459 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
460 Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
462 } /* end switch(stream) */
464 } /* end while get_msg() */
466 /* If output file is still open, it was the last one in the
467 * archive since we just hit an end of file, so close the file.
469 if (is_bopen(&altbfd)) {
470 bclose_chksize(jcr, &altbfd, alt_size);
473 set_attributes(jcr, attr, &bfd);
475 if (is_bopen(&bfd)) {
478 set_jcr_job_status(jcr, JS_Terminated);
482 set_jcr_job_status(jcr, JS_ErrorTerminated);
484 if (jcr->compress_buf) {
485 free(jcr->compress_buf);
486 jcr->compress_buf = NULL;
487 jcr->compress_buf_size = 0;
492 free_pool_memory(jcr->acl_text);
493 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
494 edit_uint64(jcr->JobBytes, ec1));
495 if (non_support_data > 1 || non_support_attr > 1) {
496 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
497 non_support_data, non_support_attr);
499 if (non_support_rsrc) {
500 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
502 if (non_support_finfo) {
503 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
505 if (non_support_acl) {
506 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
513 * Convert ZLIB error code into an ASCII message
515 static const char *zlib_strerror(int stat)
522 return _("Zlib errno");
524 return _("Zlib stream error");
526 return _("Zlib data error");
528 return _("Zlib memory error");
530 return _("Zlib buffer error");
531 case Z_VERSION_ERROR:
532 return _("Zlib version error");
539 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level) {
540 JCR *jcr = (JCR *) pkt;
541 return (digest_file(jcr, ff_pkt, jcr->digest));
545 * Verify the signature for the last restored file
546 * Return value is either true (signature correct)
547 * or false (signature could not be verified).
549 int verify_signature(JCR *jcr, SIGNATURE *sig)
551 X509_KEYPAIR *keypair;
552 DIGEST *digest = NULL;
556 /* Iterate through the trusted signers */
557 foreach_alist(keypair, jcr->pki_signers) {
558 err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
561 case CRYPTO_ERROR_NONE:
562 /* Signature found, digest allocated */
563 jcr->digest = digest;
565 /* Checksum the entire file */
566 if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
567 Qmsg(jcr, M_ERROR, 0, _("Signature validation failed for %s: \n"), jcr->last_fname);
571 /* Verify the signature */
572 if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
573 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
574 crypto_digest_free(digest);
578 /* Valid signature */
579 crypto_digest_free(digest);
582 case CRYPTO_ERROR_NOSIGNER:
583 /* Signature not found, try again */
586 /* Something strange happened (that shouldn't happen!)... */
587 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
589 crypto_digest_free(digest);
600 * In the context of jcr, write data to bfd.
601 * We write buflen bytes in buf at addr. addr is updated in place.
602 * The flags specify whether to use sparse files or compression.
603 * Return value is the number of bytes written, or -1 on errors.
605 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
606 uint64_t *addr, int flags)
609 char *wbuf; /* write buffer */
610 uint32_t wsize; /* write size */
611 uint32_t rsize; /* read size */
612 char ec1[50]; /* Buffer printing huge values */
614 if (flags & FO_SPARSE) {
618 wbuf = buf + SPARSE_FADDR_SIZE;
619 rsize = buflen - SPARSE_FADDR_SIZE;
620 ser_begin(buf, SPARSE_FADDR_SIZE);
622 if (*addr != faddr) {
624 if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
626 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
627 edit_uint64(*addr, ec1), jcr->last_fname,
628 be.strerror(bfd->berrno));
638 if (flags & FO_GZIP) {
642 * NOTE! We only use uLong and Byte because they are
643 * needed by the zlib routines, they should not otherwise
646 compress_len = jcr->compress_buf_size;
647 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
648 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
649 (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
650 Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
651 jcr->last_fname, zlib_strerror(stat));
654 wbuf = jcr->compress_buf;
655 wsize = compress_len;
656 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
658 Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
662 Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
665 if (flags & FO_WIN32DECOMP) {
666 if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
668 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
669 jcr->last_fname, be.strerror(bfd->berrno));
672 } else if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
674 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
675 jcr->last_fname, be.strerror(bfd->berrno));
679 jcr->JobBytes += wsize;
680 jcr->ReadBytes += rsize;