- } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA) {
- if (extract) {
- if (stream == STREAM_SPARSE_DATA) {
- ser_declare;
- uint64_t faddr;
- char ec1[50];
-
- wbuf = sd->msg + SPARSE_FADDR_SIZE;
- wsize = sd->msglen - SPARSE_FADDR_SIZE;
- ser_begin(sd->msg, SPARSE_FADDR_SIZE);
- unser_uint64(faddr);
- if (fileAddr != faddr) {
- fileAddr = faddr;
- if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
- Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), ofile, berror(&bfd));
- goto bail_out;
- }
- }
- } else {
- wbuf = sd->msg;
- wsize = sd->msglen;
- }
- Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total);
- if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
- Dmsg0(0, "===Write error===\n");
- Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), ofile, berror(&bfd));
- goto bail_out;
- }
- total += wsize;
- jcr->JobBytes += wsize;
- fileAddr += wsize;
- }
-
- /* GZIP data stream */
- } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
-#ifdef HAVE_LIBZ
- if (extract) {
- ser_declare;
- uLong compress_len;
- uint64_t faddr;
- char ec1[50];
- int stat;
-
- if (stream == STREAM_SPARSE_GZIP_DATA) {
- wbuf = sd->msg + SPARSE_FADDR_SIZE;
- wsize = sd->msglen - SPARSE_FADDR_SIZE;
- ser_begin(sd->msg, SPARSE_FADDR_SIZE);
- unser_uint64(faddr);
- if (fileAddr != faddr) {
- fileAddr = faddr;
- if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
- Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), ofile, berror(&bfd));
- goto bail_out;
- }
- }
- } else {
- wbuf = sd->msg;
- wsize = sd->msglen;
- }
- compress_len = compress_buf_size;
- Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
- if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
- (const Byte *)wbuf, (uLong)wsize)) != Z_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat);
- goto bail_out;
- }
-
- Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
- if ((uLong)bwrite(&bfd, jcr->compress_buf, compress_len) != compress_len) {
- Dmsg0(0, "===Write error===\n");
- Jmsg2(jcr, M_ERROR, 0, "Write error on %s: %s\n", ofile, berror(&bfd));
- goto bail_out;
- }
- total += compress_len;
- jcr->JobBytes += compress_len;
- fileAddr += compress_len;
- }
+ case STREAM_ENCRYPTED_SESSION_DATA:
+ crypto_error_t cryptoerr;
+
+ Dmsg1(30, "Stream=Encrypted Session Data, size: %d\n", sd->msglen);
+
+ /* Decode and save session keys. */
+ cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen, jcr->pki_recipients, &cs);
+ switch(cryptoerr) {
+ case CRYPTO_ERROR_NONE:
+ /* Success */
+ break;
+ case CRYPTO_ERROR_NORECIPIENT:
+ Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data."));
+ break;
+ case CRYPTO_ERROR_DECRYPTION:
+ Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed."));
+ break;
+ default:
+ /* Shouldn't happen */
+ Jmsg1(jcr, M_ERROR, 0, _("An error occured while decoding encrypted session data stream: %s"), crypto_strerror(cryptoerr));
+ break;
+ }
+
+ if (cryptoerr != CRYPTO_ERROR_NONE) {
+ extract = false;
+ bclose(&bfd);
+ continue;
+ }
+
+ /* Set up a decryption context */
+ if ((cipher_ctx = crypto_cipher_new(cs, false, &cipher_block_size)) == NULL) {
+ Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
+ crypto_session_free(cs);
+ cs = NULL;
+ extract = false;
+ bclose(&bfd);
+ continue;
+ }
+ break;
+
+ case STREAM_FILE_DATA:
+ case STREAM_SPARSE_DATA:
+ case STREAM_WIN32_DATA:
+ case STREAM_GZIP_DATA:
+ case STREAM_SPARSE_GZIP_DATA:
+ case STREAM_WIN32_GZIP_DATA:
+ case STREAM_ENCRYPTED_FILE_DATA:
+ case STREAM_ENCRYPTED_WIN32_DATA:
+ case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+ case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
+ /* Force an expected, consistent stream type here */
+ if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
+ || prev_stream == STREAM_UNIX_ATTRIBUTES_EX
+ || prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
+ flags = 0;
+
+ if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
+ flags |= FO_SPARSE;
+ }
+
+ if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
+ || stream == STREAM_WIN32_GZIP_DATA || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
+ || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
+ flags |= FO_GZIP;
+ }
+
+ if (stream == STREAM_ENCRYPTED_FILE_DATA
+ || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
+ || stream == STREAM_ENCRYPTED_WIN32_DATA
+ || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
+ flags |= FO_ENCRYPT;
+ }
+
+ if (is_win32_stream(stream) && !have_win32_api()) {
+ set_portable_backup(&bfd);
+ flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
+ }
+
+ if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags, cipher_ctx, cipher_block_size) < 0) {
+ extract = false;
+ bclose(&bfd);
+ continue;
+ }
+ }
+ break;
+
+ /* Resource fork stream - only recorded after a file to be restored */
+ /* Silently ignore if we cannot write - we already reported that */
+ case STREAM_ENCRYPTED_MACOS_FORK_DATA:
+ flags |= FO_ENCRYPT;
+ case STREAM_MACOS_FORK_DATA:
+#ifdef HAVE_DARWIN_OS
+ if (extract) {
+ if (prev_stream != stream) {
+ if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
+ Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
+ extract = false;
+ continue;
+ }
+ alt_size = rsrc_len;
+ Dmsg0(30, "Restoring resource fork\n");
+ }
+ flags = 0;
+ if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags, cipher_ctx, cipher_block_size) < 0) {
+ extract = false;
+ bclose(&altbfd);
+ continue;
+ }
+ }
+#else
+ non_support_rsrc++;
+#endif
+ break;
+
+ case STREAM_HFSPLUS_ATTRIBUTES:
+#ifdef HAVE_DARWIN_OS
+ Dmsg0(30, "Restoring Finder Info\n");
+ if (sd->msglen != 32) {
+ Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
+ continue;
+ }
+ if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
+ Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
+ continue;
+ }