]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/restore.c
Plugin updates
[bacula/bacula] / bacula / src / filed / restore.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
5
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 and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *  Bacula File Daemon  restore.c Restorefiles.
30  *
31  *    Kern Sibbald, November MM
32  *
33  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "filed.h"
39
40 #ifdef HAVE_DARWIN_OS
41 #include <sys/attr.h>
42 const bool have_darwin_os = true;
43 #else
44 const bool have_darwin_os = false;
45 #endif
46
47 #if defined(HAVE_CRYPTO)
48 const bool have_crypto = true;
49 #else
50 const bool have_crypto = false;
51 #endif
52
53 #if defined(HAVE_ACL)
54 const bool have_acl = true;
55 #else
56 const bool have_acl = false;
57 #endif
58
59 #ifdef HAVE_SHA2
60    const bool have_sha2 = true;
61 #else
62    const bool have_sha2 = false;
63 #endif
64
65
66 /* Data received from Storage Daemon */
67 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
68
69 typedef struct restore_cipher_ctx {
70    CIPHER_CONTEXT *cipher;
71    uint32_t block_size;
72
73    POOLMEM *buf;       /* Pointer to descryption buffer */
74    int32_t buf_len;    /* Count of bytes currently in buf */ 
75    int32_t packet_len; /* Total bytes in packet */
76 } RESTORE_CIPHER_CTX;
77
78 struct r_ctx {
79    JCR *jcr;
80    int32_t stream;
81    int32_t prev_stream;
82    BFILE bfd;                          /* File content */
83    uint64_t fileAddr;                  /* file write address */
84    uint32_t size;                      /* Size of file */
85    int flags;                          /* Options for extract_data() */
86    BFILE forkbfd;                      /* Alternative data stream */
87    uint64_t fork_addr;                 /* Write address for alternative stream */
88    intmax_t fork_size;                 /* Size of alternate stream */
89    int fork_flags;                     /* Options for extract_data() */
90    int32_t type;                       /* file type FT_ */
91
92    SIGNATURE *sig;                     /* Cryptographic signature (if any) for file */
93    CRYPTO_SESSION *cs;                 /* Cryptographic session data (if any) for file */
94    RESTORE_CIPHER_CTX cipher_ctx;      /* Cryptographic restore context (if any) for file */
95    RESTORE_CIPHER_CTX fork_cipher_ctx; /* Cryptographic restore context (if any) for alternative stream */
96 };
97
98
99 /* Forward referenced functions */
100 #if   defined(HAVE_LIBZ)
101 static const char *zlib_strerror(int stat);
102 const bool have_libz = true;
103 #else
104 const bool have_libz = false;
105 #endif
106
107 static void deallocate_cipher(r_ctx &rctx);
108 static void deallocate_fork_cipher(r_ctx &rctx);
109 static void free_signature(r_ctx &rctx);
110 static void free_session(r_ctx &rctx);
111
112
113
114 static bool verify_signature(JCR *jcr, r_ctx &rctx);
115 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
116                      uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx);
117 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags, 
118                   RESTORE_CIPHER_CTX *cipher_ctx);
119
120
121 /*
122  * Close a bfd check that we are at the expected file offset.
123  * Makes use of some code from set_attributes().
124  */
125 static int bclose_chksize(JCR *jcr, BFILE *bfd, boffset_t osize)
126 {
127    char ec1[50], ec2[50];
128    boffset_t fsize;
129
130    fsize = blseek(bfd, 0, SEEK_CUR);
131    bclose(bfd);                              /* first close file */
132    if (fsize > 0 && fsize != osize) {
133       Qmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
134             jcr->last_fname, edit_uint64(osize, ec1),
135             edit_uint64(fsize, ec2));
136       return -1;
137    }
138    return 0;
139 }
140
141
142 /*
143  * Restore the requested files.
144  *
145  */
146 void do_restore(JCR *jcr)
147 {
148    BSOCK *sd;
149    uint32_t VolSessionId, VolSessionTime;
150    bool extract = false;
151    int32_t file_index;
152    char ec1[50];                       /* Buffer printing huge values */
153    uint32_t buf_size;                  /* client buffer size */
154    int stat;
155    ATTR *attr;
156    intmax_t rsrc_len = 0;             /* Original length of resource fork */
157    r_ctx rctx;
158    /* ***FIXME*** make configurable */
159    crypto_digest_t signing_algorithm = have_sha2 ? 
160                                        CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
161    memset(&rctx, 0, sizeof(rctx));
162    rctx.jcr = jcr;
163
164    /* The following variables keep track of "known unknowns" */
165    int non_support_data = 0;
166    int non_support_attr = 0;
167    int non_support_rsrc = 0;
168    int non_support_finfo = 0;
169    int non_support_acl = 0;
170    int non_support_progname = 0;
171    int non_support_crypto = 0;
172
173 #ifdef HAVE_DARWIN_OS
174    struct attrlist attrList;
175    memset(&attrList, 0, sizeof(attrList));
176    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
177    attrList.commonattr = ATTR_CMN_FNDRINFO;
178 #endif
179
180
181    sd = jcr->store_bsock;
182    set_jcr_job_status(jcr, JS_Running);
183
184    LockRes();
185    CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
186    UnlockRes();
187    if (client) {
188       buf_size = client->max_network_buffer_size;
189    } else {
190       buf_size = 0;                   /* use default */
191    }
192    if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
193       set_jcr_job_status(jcr, JS_ErrorTerminated);
194       return;
195    }
196    jcr->buf_size = sd->msglen;
197
198    /* St Bernard code goes here if implemented -- see end of file */
199
200    if (have_libz) {
201       uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
202       jcr->compress_buf = (char *)bmalloc(compress_buf_size);
203       jcr->compress_buf_size = compress_buf_size;
204    }
205
206    if (have_crypto) {
207       rctx.cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
208       if (have_darwin_os) {
209          rctx.fork_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
210       }
211    }
212    
213    /*
214     * Get a record from the Storage daemon. We are guaranteed to
215     *   receive records in the following order:
216     *   1. Stream record header
217     *   2. Stream data (one or more of the following in the order given)
218     *        a. Attributes (Unix or Win32)
219     *        b. Possibly stream encryption session data (e.g., symmetric session key)
220     *        c. File data for the file
221     *        d. Alternate data stream (e.g. Resource Fork)
222     *        e. Finder info
223     *        f. ACLs
224     *        g. Possibly a cryptographic signature
225     *        h. Possibly MD5 or SHA1 record
226     *   3. Repeat step 1
227     *
228     * NOTE: We keep track of two bacula file descriptors:
229     *   1. bfd for file data.
230     *      This fd is opened for non empty files when an attribute stream is
231     *      encountered and closed when we find the next attribute stream.
232     *   2. fork_bfd for alternate data streams
233     *      This fd is opened every time we encounter a new alternate data
234     *      stream for the current file. When we find any other stream, we
235     *      close it again.
236     *      The expected size of the stream, fork_len, should be set when
237     *      opening the fd.
238     *   3. Not all the stream data records are required -- e.g. if there
239     *      is no fork, there is no alternate data stream, no ACL, ...
240     */
241    binit(&rctx.bfd);
242    binit(&rctx.forkbfd);
243    attr = new_attr(jcr);
244    jcr->acl_text = get_pool_memory(PM_MESSAGE);
245
246    
247
248    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
249       /* Remember previous stream type */
250       rctx.prev_stream = rctx.stream;
251
252       /* First we expect a Stream Record Header */
253       if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
254           &rctx.stream, &rctx.size) != 5) {
255          Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
256          goto bail_out;
257       }
258       Dmsg4(30, "Got hdr: Files=%d FilInx=%d Stream=%d, %s.\n", 
259             jcr->JobFiles, file_index, rctx.stream, stream_to_ascii(rctx.stream));
260
261       /* * Now we expect the Stream Data */
262       if (bget_msg(sd) < 0) {
263          Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
264          goto bail_out;
265       }
266       if (rctx.size != (uint32_t)sd->msglen) {
267          Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), 
268                sd->msglen, rctx.size);
269          goto bail_out;
270       }
271       Dmsg3(30, "Got stream: %s len=%d extract=%d\n", stream_to_ascii(rctx.stream), 
272             sd->msglen, extract);
273
274       /* If we change streams, close and reset alternate data streams */
275       if (rctx.prev_stream != rctx.stream) {
276          if (is_bopen(&rctx.forkbfd)) {
277             deallocate_fork_cipher(rctx);
278             bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
279          }
280          rctx.fork_size = -1; /* Use an impossible value and set a proper one below */
281          rctx.fork_addr = 0;
282       }
283
284       /* File Attributes stream */
285       switch (rctx.stream) {
286       case STREAM_UNIX_ATTRIBUTES:
287       case STREAM_UNIX_ATTRIBUTES_EX:
288          /*
289           * If extracting, it was from previous stream, so
290           * close the output file and validate the signature.
291           */
292          if (extract) {
293             if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
294                Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
295             }
296
297             if (rctx.prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
298                deallocate_cipher(rctx);
299                deallocate_fork_cipher(rctx);
300             }
301
302             if (jcr->plugin) {
303                plugin_set_attributes(jcr, attr, &rctx.bfd);
304             } else {
305                set_attributes(jcr, attr, &rctx.bfd);
306             }
307             extract = false;
308
309             /* Verify the cryptographic signature, if any */
310             rctx.type = attr->type;
311             verify_signature(jcr, rctx);
312
313             /* Free Signature */
314             free_signature(rctx);
315             free_session(rctx);
316             jcr->ff->flags = 0;
317             Dmsg0(30, "Stop extracting.\n");
318          } else if (is_bopen(&rctx.bfd)) {
319             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
320             bclose(&rctx.bfd);
321          }
322
323          /*
324           * Unpack attributes and do sanity check them
325           */
326          if (!unpack_attributes_record(jcr, rctx.stream, sd->msg, attr)) {
327             goto bail_out;
328          }
329          if (file_index != attr->file_index) {
330             Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
331                  file_index, attr->file_index);
332             Dmsg0(100, "File index error\n");
333             goto bail_out;
334          }
335
336          Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
337                attr->attr, attr->attrEx);
338
339          attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
340
341          if (!is_restore_stream_supported(attr->data_stream)) {
342             if (!non_support_data++) {
343                Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
344                   stream_to_ascii(attr->data_stream));
345             }
346             continue;
347          }
348
349          build_attr_output_fnames(jcr, attr);
350
351          /*
352           * Try to actually create the file, which returns a status telling
353           *  us if we need to extract or not.
354           */
355          jcr->num_files_examined++;
356          extract = false;
357          if (jcr->plugin) {
358             stat = plugin_create_file(jcr, attr, &rctx.bfd, jcr->replace);
359          } else {
360             stat = create_file(jcr, attr, &rctx.bfd, jcr->replace);
361          }
362          Dmsg2(30, "Outfile=%s create_file stat=%d\n", attr->ofname, stat);
363          switch (stat) {
364          case CF_ERROR:
365          case CF_SKIP:
366             break;
367          case CF_EXTRACT:        /* File created and we expect file data */
368             extract = true;
369             /* FALLTHROUGH */
370          case CF_CREATED:        /* File created, but there is no content */
371             jcr->lock();  
372             pm_strcpy(jcr->last_fname, attr->ofname);
373             jcr->last_type = attr->type;
374             jcr->JobFiles++;
375             jcr->unlock();
376             rctx.fileAddr = 0;
377             print_ls_output(jcr, attr);
378
379             if (have_darwin_os) {
380                /* Only restore the resource fork for regular files */
381                from_base64(&rsrc_len, attr->attrEx);
382                if (attr->type == FT_REG && rsrc_len > 0) {
383                   extract = true;
384                }
385             }
386             if (!extract) {
387                /* set attributes now because file will not be extracted */
388                if (jcr->plugin) {
389                   plugin_set_attributes(jcr, attr, &rctx.bfd);
390                } else {
391                   set_attributes(jcr, attr, &rctx.bfd);
392                }
393             }
394             break;
395          }
396          break;
397
398       /* Data stream */
399       case STREAM_ENCRYPTED_SESSION_DATA:
400          crypto_error_t cryptoerr;
401
402          /* Is this an unexpected session data entry? */
403          if (rctx.cs) {
404             Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic session data stream.\n"));
405             extract = false;
406             bclose(&rctx.bfd);
407             continue;
408          }
409
410          /* Do we have any keys at all? */
411          if (!jcr->crypto.pki_recipients) {
412             Jmsg(jcr, M_ERROR, 0, _("No private decryption keys have been defined to decrypt encrypted backup data.\n"));
413             extract = false;
414             bclose(&rctx.bfd);
415             break;
416          }
417
418          if (jcr->crypto.digest) {
419             crypto_digest_free(jcr->crypto.digest);
420          }  
421          jcr->crypto.digest = crypto_digest_new(jcr, signing_algorithm);
422          if (!jcr->crypto.digest) {
423             Jmsg0(jcr, M_FATAL, 0, _("Could not create digest.\n"));
424             extract = false;
425             bclose(&rctx.bfd);
426             break;
427          }
428
429          /* Decode and save session keys. */
430          cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen, 
431                         jcr->crypto.pki_recipients, &rctx.cs);
432          switch(cryptoerr) {
433          case CRYPTO_ERROR_NONE:
434             /* Success */
435             break;
436          case CRYPTO_ERROR_NORECIPIENT:
437             Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data.\n"));
438             break;
439          case CRYPTO_ERROR_DECRYPTION:
440             Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.\n"));
441             break;
442          default:
443             /* Shouldn't happen */
444             Jmsg1(jcr, M_ERROR, 0, _("An error occurred while decoding encrypted session data stream: %s\n"), crypto_strerror(cryptoerr));
445             break;
446          }
447
448          if (cryptoerr != CRYPTO_ERROR_NONE) {
449             extract = false;
450             bclose(&rctx.bfd);
451             continue;
452          }
453
454          break;
455
456       case STREAM_FILE_DATA:
457       case STREAM_SPARSE_DATA:
458       case STREAM_WIN32_DATA:
459       case STREAM_GZIP_DATA:
460       case STREAM_SPARSE_GZIP_DATA:
461       case STREAM_WIN32_GZIP_DATA:
462       case STREAM_ENCRYPTED_FILE_DATA:
463       case STREAM_ENCRYPTED_WIN32_DATA:
464       case STREAM_ENCRYPTED_FILE_GZIP_DATA:
465       case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
466          /* Force an expected, consistent stream type here */
467          if (extract && (rctx.prev_stream == rctx.stream 
468                          || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES
469                          || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES_EX
470                          || rctx.prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
471             rctx.flags = 0;
472
473             if (rctx.stream == STREAM_SPARSE_DATA || 
474                 rctx.stream == STREAM_SPARSE_GZIP_DATA) {
475                rctx.flags |= FO_SPARSE;
476             }
477
478             if (rctx.stream == STREAM_GZIP_DATA 
479                   || rctx.stream == STREAM_SPARSE_GZIP_DATA
480                   || rctx.stream == STREAM_WIN32_GZIP_DATA
481                   || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
482                   || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
483                rctx.flags |= FO_GZIP;
484             }
485
486             if (rctx.stream == STREAM_ENCRYPTED_FILE_DATA
487                   || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
488                   || rctx.stream == STREAM_ENCRYPTED_WIN32_DATA
489                   || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {               
490                /* Set up a decryption context */
491                if (!rctx.cipher_ctx.cipher) {
492                   if (!rctx.cs) {
493                      Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
494                      extract = false;
495                      bclose(&rctx.bfd);
496                      continue;
497                   }
498
499                   if ((rctx.cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false, 
500                            &rctx.cipher_ctx.block_size)) == NULL) {
501                      Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
502                      free_session(rctx);
503                      extract = false;
504                      bclose(&rctx.bfd);
505                      continue;
506                   }
507                }
508                rctx.flags |= FO_ENCRYPT;
509             }
510
511             if (is_win32_stream(rctx.stream) && !have_win32_api()) {
512                set_portable_backup(&rctx.bfd);
513                rctx.flags |= FO_WIN32DECOMP;    /* "decompose" BackupWrite data */
514             }
515
516             if (extract_data(jcr, &rctx.bfd, sd->msg, sd->msglen, &rctx.fileAddr, 
517                              rctx.flags, &rctx.cipher_ctx) < 0) {
518                extract = false;
519                bclose(&rctx.bfd);
520                continue;
521             }
522          }
523          break;
524
525       /* Resource fork stream - only recorded after a file to be restored */
526       /* Silently ignore if we cannot write - we already reported that */
527       case STREAM_ENCRYPTED_MACOS_FORK_DATA:
528       case STREAM_MACOS_FORK_DATA:
529 #ifdef HAVE_DARWIN_OS
530          rctx.fork_flags = 0;
531          jcr->ff->flags |= FO_HFSPLUS;
532
533          if (rctx.stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) {
534             rctx.fork_flags |= FO_ENCRYPT;
535
536             /* Set up a decryption context */
537             if (extract && !rctx.fork_cipher_ctx.cipher) {
538                if (!rctx.cs) {
539                   Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
540                   extract = false;
541                   bclose(&rctx.bfd);
542                   continue;
543                }
544
545                if ((rctx.fork_cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false, &rctx.fork_cipher_ctx.block_size)) == NULL) {
546                   Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
547                   free_session(rctx);
548                   extract = false;
549                   bclose(&rctx.bfd);
550                   continue;
551                }
552             }
553          }
554
555          if (extract) {
556             if (rctx.prev_stream != rctx.stream) {
557                if (bopen_rsrc(&rctx.forkbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
558                   Jmsg(jcr, M_ERROR, 0, _("     Cannot open resource fork for %s.\n"), jcr->last_fname);
559                   extract = false;
560                   continue;
561                }
562
563                rctx.fork_size = rsrc_len;
564                Dmsg0(30, "Restoring resource fork\n");
565             }
566
567             if (extract_data(jcr, &rctx.forkbfd, sd->msg, sd->msglen, &rctx.fork_addr, rctx.fork_flags, 
568                              &rctx.fork_cipher_ctx) < 0) {
569                extract = false;
570                bclose(&rctx.forkbfd);
571                continue;
572             }
573          }
574 #else
575          non_support_rsrc++;
576 #endif
577          break;
578
579       case STREAM_HFSPLUS_ATTRIBUTES:
580 #ifdef HAVE_DARWIN_OS
581          Dmsg0(30, "Restoring Finder Info\n");
582          jcr->ff->flags |= FO_HFSPLUS;
583          if (sd->msglen != 32) {
584             Jmsg(jcr, M_ERROR, 0, _("     Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
585             continue;
586          }
587          if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
588             Jmsg(jcr, M_ERROR, 0, _("     Could not set Finder Info on %s\n"), jcr->last_fname);
589             continue;
590          }
591 #else
592          non_support_finfo++;
593 #endif
594          break;
595
596       case STREAM_UNIX_ACCESS_ACL:
597          if (have_acl) {
598             pm_strcpy(jcr->acl_text, sd->msg);
599             Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
600             if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
601                Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
602             }
603          } else {
604             non_support_acl++;
605          }
606          break;
607
608       case STREAM_UNIX_DEFAULT_ACL:
609          if (have_acl) {
610             pm_strcpy(jcr->acl_text, sd->msg);
611             Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
612             if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
613                Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
614             }
615          } else {
616             non_support_acl++;
617          }
618          break;
619
620       case STREAM_SIGNED_DIGEST:
621          /* Is this an unexpected signature? */
622          if (rctx.sig) {
623             Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic signature data stream.\n"));
624             free_signature(rctx);
625             continue;
626          }
627          /* Save signature. */
628          if (extract && (rctx.sig = crypto_sign_decode(jcr, (uint8_t *)sd->msg, (uint32_t)sd->msglen)) == NULL) {
629             Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname);
630          }
631          break;
632
633       case STREAM_MD5_DIGEST:
634       case STREAM_SHA1_DIGEST:
635       case STREAM_SHA256_DIGEST:
636       case STREAM_SHA512_DIGEST:
637          break;
638
639       case STREAM_PROGRAM_NAMES:
640       case STREAM_PROGRAM_DATA:
641          if (!non_support_progname) {
642             Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
643             non_support_progname++;
644          }
645          break;
646
647       case STREAM_PLUGIN_NAME:
648          Dmsg1(000, "stream_plugin_name=%s\n", sd->msg);
649          plugin_name_stream(jcr, sd->msg);
650          break;
651
652       default:
653          /* If extracting, wierd stream (not 1 or 2), close output file anyway */
654          if (extract) {
655             Dmsg1(30, "Found wierd stream %d\n", rctx.stream);
656             if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
657                Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
658             }
659             /* Flush and deallocate cipher context */
660             deallocate_cipher(rctx);
661             deallocate_fork_cipher(rctx);
662
663             if (jcr->plugin) {
664                plugin_set_attributes(jcr, attr, &rctx.bfd);
665             } else {
666                set_attributes(jcr, attr, &rctx.bfd);
667             }
668
669             /* Verify the cryptographic signature if any */
670             rctx.type = attr->type;
671             verify_signature(jcr, rctx);
672             extract = false;
673          } else if (is_bopen(&rctx.bfd)) {
674             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
675             bclose(&rctx.bfd);
676          }
677          Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
678               rctx.stream);
679          Dmsg2(0, "Unknown stream=%d data=%s\n", rctx.stream, sd->msg);
680          break;
681       } /* end switch(stream) */
682
683    } /* end while get_msg() */
684
685    /* If output file is still open, it was the last one in the
686     * archive since we just hit an end of file, so close the file.
687     */
688    if (is_bopen(&rctx.forkbfd)) {
689       bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
690    }
691    if (extract) {
692       /* Flush and deallocate cipher context */
693       deallocate_cipher(rctx);
694       deallocate_fork_cipher(rctx);
695
696       if (jcr->plugin) {
697          plugin_set_attributes(jcr, attr, &rctx.bfd);
698       } else {
699          set_attributes(jcr, attr, &rctx.bfd);
700       }
701
702       /* Verify the cryptographic signature on the last file, if any */
703       rctx.type = attr->type;
704       verify_signature(jcr, rctx);
705    }
706
707    if (is_bopen(&rctx.bfd)) {
708       bclose(&rctx.bfd);
709    }
710
711    set_jcr_job_status(jcr, JS_Terminated);
712    goto ok_out;
713
714 bail_out:
715    set_jcr_job_status(jcr, JS_ErrorTerminated);
716
717 ok_out:
718    /* Free Signature & Crypto Data */
719    free_signature(rctx);
720    free_session(rctx);
721    if (jcr->crypto.digest) {
722       crypto_digest_free(jcr->crypto.digest);
723       jcr->crypto.digest = NULL;
724    }
725
726    /* Free file cipher restore context */
727    if (rctx.cipher_ctx.cipher) {
728       crypto_cipher_free(rctx.cipher_ctx.cipher);
729       rctx.cipher_ctx.cipher = NULL;
730    }
731    if (rctx.cipher_ctx.buf) {
732       free_pool_memory(rctx.cipher_ctx.buf);
733       rctx.cipher_ctx.buf = NULL;
734    }
735
736    /* Free alternate stream cipher restore context */
737    if (rctx.fork_cipher_ctx.cipher) {
738       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
739       rctx.fork_cipher_ctx.cipher = NULL;
740    }
741    if (rctx.fork_cipher_ctx.buf) {
742       free_pool_memory(rctx.fork_cipher_ctx.buf);
743       rctx.fork_cipher_ctx.buf = NULL;
744    }
745
746    if (jcr->compress_buf) {
747       free(jcr->compress_buf);
748       jcr->compress_buf = NULL;
749       jcr->compress_buf_size = 0;
750    }
751    bclose(&rctx.forkbfd);
752    bclose(&rctx.bfd);
753    free_attr(attr);
754    free_pool_memory(jcr->acl_text);
755    Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
756       edit_uint64(jcr->JobBytes, ec1));
757    if (non_support_data > 1 || non_support_attr > 1) {
758       Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
759          non_support_data, non_support_attr);
760    }
761    if (non_support_rsrc) {
762       Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
763    }
764    if (non_support_finfo) {
765       Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
766    }
767    if (non_support_acl) {
768       Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
769    }
770    if (non_support_crypto) {
771       Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl);
772    }
773
774 }
775
776 #ifdef HAVE_LIBZ
777 /*
778  * Convert ZLIB error code into an ASCII message
779  */
780 static const char *zlib_strerror(int stat)
781 {
782    if (stat >= 0) {
783       return _("None");
784    }
785    switch (stat) {
786    case Z_ERRNO:
787       return _("Zlib errno");
788    case Z_STREAM_ERROR:
789       return _("Zlib stream error");
790    case Z_DATA_ERROR:
791       return _("Zlib data error");
792    case Z_MEM_ERROR:
793       return _("Zlib memory error");
794    case Z_BUF_ERROR:
795       return _("Zlib buffer error");
796    case Z_VERSION_ERROR:
797       return _("Zlib version error");
798    default:
799       return _("*none*");
800    }
801 }
802 #endif
803
804 static int do_file_digest(JCR *jcr, FF_PKT *ff_pkt, bool top_level) 
805 {
806    Dmsg1(50, "do_file_digest jcr=%p\n", jcr);
807    return (digest_file(jcr, ff_pkt, jcr->crypto.digest));
808 }
809
810 /*
811  * Verify the signature for the last restored file
812  * Return value is either true (signature correct)
813  * or false (signature could not be verified).
814  * TODO landonf: Implement without using find_one_file and
815  * without re-reading the file.
816  */
817 static bool verify_signature(JCR *jcr, r_ctx &rctx)
818 {
819    X509_KEYPAIR *keypair;
820    DIGEST *digest = NULL;
821    crypto_error_t err;
822    uint64_t saved_bytes;
823    crypto_digest_t signing_algorithm = have_sha2 ? 
824                                        CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
825    crypto_digest_t algorithm;
826    SIGNATURE *sig = rctx.sig;
827
828
829    if (!jcr->crypto.pki_sign) {
830       return true;                    /* no signature OK */
831    }
832    if (!sig) {
833       if (rctx.type == FT_REGE || rctx.type == FT_REG || rctx.type == FT_RAW) { 
834          Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), 
835                jcr->last_fname);
836          goto bail_out;
837       }
838       return true;
839    }
840
841    /* Iterate through the trusted signers */
842    foreach_alist(keypair, jcr->crypto.pki_signers) {
843       err = crypto_sign_get_digest(sig, jcr->crypto.pki_keypair, algorithm, &digest);
844       switch (err) {
845       case CRYPTO_ERROR_NONE:
846          Dmsg0(50, "== Got digest\n");
847          /*
848           * We computed jcr->crypto.digest using signing_algorithm while writing
849           * the file. If it is not the same as the algorithm used for 
850           * this file, punt by releasing the computed algorithm and 
851           * computing by re-reading the file.
852           */
853          if (algorithm != signing_algorithm) {
854             if (jcr->crypto.digest) {
855                crypto_digest_free(jcr->crypto.digest);
856                jcr->crypto.digest = NULL;
857             }  
858          }
859          if (jcr->crypto.digest) {
860              /* Use digest computed while writing the file to verify the signature */
861             if ((err = crypto_sign_verify(sig, keypair, jcr->crypto.digest)) != CRYPTO_ERROR_NONE) {
862                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
863                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
864                      jcr->last_fname, crypto_strerror(err));
865                goto bail_out;
866             }
867          } else {   
868             /* Signature found, digest allocated.  Old method, 
869              * re-read the file and compute the digest
870              */
871             jcr->crypto.digest = digest;
872
873             /* Checksum the entire file */
874             /* Make sure we don't modify JobBytes by saving and restoring it */
875             saved_bytes = jcr->JobBytes;                     
876             if (find_one_file(jcr, jcr->ff, do_file_digest, jcr->last_fname, (dev_t)-1, 1) != 0) {
877                Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"), 
878                     jcr->last_fname);
879                jcr->JobBytes = saved_bytes;
880                goto bail_out;
881             }
882             jcr->JobBytes = saved_bytes;
883
884             /* Verify the signature */
885             if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
886                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
887                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
888                      jcr->last_fname, crypto_strerror(err));
889                goto bail_out;
890             }
891             jcr->crypto.digest = NULL;
892          }
893
894          /* Valid signature */
895          Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
896          crypto_digest_free(digest);
897          return true;
898
899       case CRYPTO_ERROR_NOSIGNER:
900          /* Signature not found, try again */
901          if (digest) {
902             crypto_digest_free(digest);
903             digest = NULL;
904          }
905          continue;
906       default:
907          /* Something strange happened (that shouldn't happen!)... */
908          Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
909          goto bail_out;
910       }
911    }
912
913    /* No signer */
914    Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
915
916 bail_out:
917    if (digest) {
918       crypto_digest_free(digest);
919    }
920    return false;
921 }
922
923 bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *length)
924 {
925       unser_declare;
926       uint64_t faddr;
927       char ec1[50];
928       unser_begin(*data, SPARSE_FADDR_SIZE);
929       unser_uint64(faddr);
930       if (*addr != faddr) {
931          *addr = faddr;
932          if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
933             berrno be;
934             Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
935                   edit_uint64(*addr, ec1), jcr->last_fname, 
936                   be.bstrerror(bfd->berrno));
937             return false;
938          }
939       }
940       *data += SPARSE_FADDR_SIZE;
941       *length -= SPARSE_FADDR_SIZE;
942       return true;
943 }
944
945 bool decompress_data(JCR *jcr, char **data, uint32_t *length)
946 {
947 #ifdef HAVE_LIBZ
948    uLong compress_len;
949    int stat;
950    char ec1[50];                      /* Buffer printing huge values */
951
952    /* 
953     * NOTE! We only use uLong and Byte because they are
954     *  needed by the zlib routines, they should not otherwise
955     *  be used in Bacula.
956     */
957    compress_len = jcr->compress_buf_size;
958    Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, *length);
959    if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
960                (const Byte *)*data, (uLong)*length)) != Z_OK) {
961       Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
962             jcr->last_fname, zlib_strerror(stat));
963       return false;
964    }
965    *data = jcr->compress_buf;
966    *length = compress_len;
967    Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
968    return true;
969 #else
970    Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
971    return false;
972 #endif
973 }
974
975 static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
976 {
977    unser_declare;
978    if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
979       unser_begin(&ctx->buf[0], CRYPTO_LEN_SIZE);
980       unser_uint32(ctx->packet_len);
981       ctx->packet_len += CRYPTO_LEN_SIZE;
982    }
983 }
984
985 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
986 {
987    if (jcr->crypto.digest) {
988       crypto_digest_update(jcr->crypto.digest, (uint8_t *)data, length);
989    }
990    if (win32_decomp) {
991       if (!processWin32BackupAPIBlock(bfd, data, length)) {
992          berrno be;
993          Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"), 
994                jcr->last_fname, be.bstrerror(bfd->berrno));
995          return false;
996       }
997    } else if (bwrite(bfd, data, length) != (ssize_t)length) {
998       berrno be;
999       Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), 
1000             jcr->last_fname, be.bstrerror(bfd->berrno));
1001       return false;
1002    }
1003
1004    return true;
1005 }
1006
1007 /*
1008  * In the context of jcr, write data to bfd.
1009  * We write buflen bytes in buf at addr. addr is updated in place.
1010  * The flags specify whether to use sparse files or compression.
1011  * Return value is the number of bytes written, or -1 on errors.
1012  */
1013 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
1014       uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx)
1015 {
1016    char *wbuf;                        /* write buffer */
1017    uint32_t wsize;                    /* write size */
1018    uint32_t rsize;                    /* read size */
1019    uint32_t decrypted_len = 0;        /* Decryption output length */
1020    char ec1[50];                      /* Buffer printing huge values */
1021
1022    rsize = buflen;
1023    jcr->ReadBytes += rsize;
1024    wsize = rsize;
1025    wbuf = buf;
1026
1027    if (flags & FO_ENCRYPT) {
1028       ASSERT(cipher_ctx->cipher);
1029
1030       /* NOTE: We must implement block preserving semantics for the
1031        * non-streaming compression and sparse code. */
1032
1033       /*
1034        * Grow the crypto buffer, if necessary.
1035        * crypto_cipher_update() will process only whole blocks,
1036        * buffering the remaining input.
1037        */
1038       cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, 
1039                         cipher_ctx->buf_len + wsize + cipher_ctx->block_size);
1040
1041       /* Decrypt the input block */
1042       if (!crypto_cipher_update(cipher_ctx->cipher, 
1043                                 (const u_int8_t *)wbuf, 
1044                                 wsize, 
1045                                 (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len], 
1046                                 &decrypted_len)) {
1047          /* Decryption failed. Shouldn't happen. */
1048          Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
1049          return -1;
1050       }
1051
1052       if (decrypted_len == 0) {
1053          /* No full block of encrypted data available, write more data */
1054          return 0;
1055       }
1056
1057       Dmsg2(100, "decrypted len=%d encrypted len=%d\n", decrypted_len, wsize);
1058
1059       cipher_ctx->buf_len += decrypted_len;
1060       wbuf = cipher_ctx->buf;
1061
1062       /* If one full preserved block is available, write it to disk,
1063        * and then buffer any remaining data. This should be effecient
1064        * as long as Bacula's block size is not significantly smaller than the
1065        * encryption block size (extremely unlikely!) */
1066       unser_crypto_packet_len(cipher_ctx);
1067       Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1068
1069       if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
1070          /* No full preserved block is available. */
1071          return 0;
1072       }
1073
1074       /* We have one full block, set up the filter input buffers */
1075       wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1076       wbuf = &wbuf[CRYPTO_LEN_SIZE]; /* Skip the block length header */
1077       cipher_ctx->buf_len -= cipher_ctx->packet_len;
1078       Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1079    }
1080
1081    if (flags & FO_SPARSE) {
1082       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1083          return -1;
1084       }
1085    }
1086
1087    if (flags & FO_GZIP) {
1088       if (!decompress_data(jcr, &wbuf, &wsize)) {
1089          return -1;
1090       }
1091    }
1092
1093    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1094       return -1;
1095    }
1096    jcr->JobBytes += wsize;
1097    *addr += wsize;
1098    Dmsg2(30, "Write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1099
1100    /* Clean up crypto buffers */
1101    if (flags & FO_ENCRYPT) {
1102       /* Move any remaining data to start of buffer */
1103       if (cipher_ctx->buf_len > 0) {
1104          Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1105          memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1106             cipher_ctx->buf_len);
1107       }
1108       /* The packet was successfully written, reset the length so that the next
1109        * packet length may be re-read by unser_crypto_packet_len() */
1110       cipher_ctx->packet_len = 0;
1111    }
1112
1113    return wsize;
1114 }
1115
1116 /*
1117  * In the context of jcr, flush any remaining data from the cipher context,
1118  * writing it to bfd.
1119  * Return value is true on success, false on failure.
1120  */
1121 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
1122                   RESTORE_CIPHER_CTX *cipher_ctx)
1123 {
1124    uint32_t decrypted_len = 0;
1125    char *wbuf;                        /* write buffer */
1126    uint32_t wsize;                    /* write size */
1127    char ec1[50];                      /* Buffer printing huge values */
1128    bool second_pass = false;
1129
1130 again:
1131    /* Write out the remaining block and free the cipher context */
1132    cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len + 
1133                      cipher_ctx->block_size);
1134
1135    if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1136         &decrypted_len)) {
1137       /* Writing out the final, buffered block failed. Shouldn't happen. */
1138       Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"), 
1139             cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
1140    }
1141
1142    Dmsg2(30, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
1143    /* If nothing new was decrypted, and our output buffer is empty, return */
1144    if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
1145       return true;
1146    }
1147
1148    cipher_ctx->buf_len += decrypted_len;
1149
1150    unser_crypto_packet_len(cipher_ctx);
1151    Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1152    wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1153    wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE]; /* Decrypted, possibly decompressed output here. */
1154    cipher_ctx->buf_len -= cipher_ctx->packet_len;
1155    Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1156
1157    if (flags & FO_SPARSE) {
1158       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1159          return false;
1160       }
1161    }
1162
1163    if (flags & FO_GZIP) {
1164       if (!decompress_data(jcr, &wbuf, &wsize)) {
1165          return false;
1166       }
1167    }
1168
1169    Dmsg0(30, "Call store_data\n");
1170    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1171       return false;
1172    }
1173    jcr->JobBytes += wsize;
1174    Dmsg2(30, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1175
1176    /* Move any remaining data to start of buffer */
1177    if (cipher_ctx->buf_len > 0) {
1178       Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1179       memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1180          cipher_ctx->buf_len);
1181    }
1182    /* The packet was successfully written, reset the length so that the next
1183     * packet length may be re-read by unser_crypto_packet_len() */
1184    cipher_ctx->packet_len = 0;
1185
1186    if (cipher_ctx->buf_len >0 && !second_pass) {
1187       second_pass = true;
1188       goto again;
1189    }
1190
1191    /* Stop decryption */
1192    cipher_ctx->buf_len = 0;
1193    cipher_ctx->packet_len = 0;
1194
1195    return true;
1196 }
1197
1198 static void deallocate_cipher(r_ctx &rctx)
1199 {
1200    /* Flush and deallocate previous stream's cipher context */
1201    if (rctx.cipher_ctx.cipher) {
1202       flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx);
1203       crypto_cipher_free(rctx.cipher_ctx.cipher);
1204       rctx.cipher_ctx.cipher = NULL;
1205    }
1206 }
1207
1208 static void deallocate_fork_cipher(r_ctx &rctx)
1209 {
1210
1211    /* Flush and deallocate previous stream's fork cipher context */
1212    if (rctx.fork_cipher_ctx.cipher) {
1213       flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx);
1214       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
1215       rctx.fork_cipher_ctx.cipher = NULL;
1216    }
1217 }
1218
1219 static void free_signature(r_ctx &rctx)
1220 {
1221    if (rctx.sig) {
1222       crypto_sign_free(rctx.sig);
1223       rctx.sig = NULL;
1224    }
1225 }
1226
1227 static void free_session(r_ctx &rctx)
1228 {
1229    if (rctx.cs) {
1230       crypto_session_free(rctx.cs);
1231       rctx.cs = NULL;
1232    }
1233 }
1234
1235
1236 /* This code if implemented goes above */
1237 #ifdef stbernard_implemented
1238 /  #if defined(HAVE_WIN32)
1239    bool        bResumeOfmOnExit = FALSE;
1240    if (isOpenFileManagerRunning()) {
1241        if ( pauseOpenFileManager() ) {
1242           Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
1243           bResumeOfmOnExit = TRUE;
1244        }
1245        else {
1246           Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
1247        }
1248    }
1249    {
1250        char username[UNLEN+1];
1251        DWORD usize = sizeof(username);
1252        int privs = enable_backup_privileges(NULL, 1);
1253        if (GetUserName(username, &usize)) {
1254           Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
1255        } else {
1256           Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));
1257        }
1258    }
1259 #endif