]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/restore.c
First cut of plugin restore code
[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 some code in 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             set_attributes(jcr, attr, &rctx.bfd);
303             extract = false;
304
305             /* Verify the cryptographic signature, if any */
306             rctx.type = attr->type;
307             verify_signature(jcr, rctx);
308
309             /* Free Signature */
310             free_signature(rctx);
311             free_session(rctx);
312             jcr->ff->flags = 0;
313             Dmsg0(30, "Stop extracting.\n");
314          } else if (is_bopen(&rctx.bfd)) {
315             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
316             bclose(&rctx.bfd);
317          }
318
319          /*
320           * Unpack attributes and do sanity check them
321           */
322          if (!unpack_attributes_record(jcr, rctx.stream, sd->msg, attr)) {
323             goto bail_out;
324          }
325          if (file_index != attr->file_index) {
326             Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
327                  file_index, attr->file_index);
328             Dmsg0(100, "File index error\n");
329             goto bail_out;
330          }
331
332          Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
333                attr->attr, attr->attrEx);
334
335          attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
336
337          if (!is_restore_stream_supported(attr->data_stream)) {
338             if (!non_support_data++) {
339                Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
340                   stream_to_ascii(attr->data_stream));
341             }
342             continue;
343          }
344
345          build_attr_output_fnames(jcr, attr);
346
347          /*
348           * Now determine if we are extracting or not.
349           */
350          jcr->num_files_examined++;
351          extract = false;
352          stat = create_file(jcr, attr, &rctx.bfd, jcr->replace);
353          Dmsg2(30, "Outfile=%s create_file stat=%d\n", attr->ofname, stat);
354          switch (stat) {
355          case CF_ERROR:
356          case CF_SKIP:
357             break;
358          case CF_EXTRACT:        /* File created and we expect file data */
359             extract = true;
360             /* FALLTHROUGH */
361          case CF_CREATED:        /* File created, but there is no content */
362             jcr->lock();  
363             pm_strcpy(jcr->last_fname, attr->ofname);
364             jcr->last_type = attr->type;
365             jcr->JobFiles++;
366             jcr->unlock();
367             rctx.fileAddr = 0;
368             print_ls_output(jcr, attr);
369
370             if (have_darwin_os) {
371                /* Only restore the resource fork for regular files */
372                from_base64(&rsrc_len, attr->attrEx);
373                if (attr->type == FT_REG && rsrc_len > 0) {
374                   extract = true;
375                }
376             }
377             if (!extract) {
378                /* set attributes now because file will not be extracted */
379                set_attributes(jcr, attr, &rctx.bfd);
380             }
381             break;
382          }
383          break;
384
385       /* Data stream */
386       case STREAM_ENCRYPTED_SESSION_DATA:
387          crypto_error_t cryptoerr;
388
389          /* Is this an unexpected session data entry? */
390          if (rctx.cs) {
391             Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic session data stream.\n"));
392             extract = false;
393             bclose(&rctx.bfd);
394             continue;
395          }
396
397          /* Do we have any keys at all? */
398          if (!jcr->crypto.pki_recipients) {
399             Jmsg(jcr, M_ERROR, 0, _("No private decryption keys have been defined to decrypt encrypted backup data.\n"));
400             extract = false;
401             bclose(&rctx.bfd);
402             break;
403          }
404
405          if (jcr->crypto.digest) {
406             crypto_digest_free(jcr->crypto.digest);
407          }  
408          jcr->crypto.digest = crypto_digest_new(jcr, signing_algorithm);
409          if (!jcr->crypto.digest) {
410             Jmsg0(jcr, M_FATAL, 0, _("Could not create digest.\n"));
411             extract = false;
412             bclose(&rctx.bfd);
413             break;
414          }
415
416          /* Decode and save session keys. */
417          cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen, 
418                         jcr->crypto.pki_recipients, &rctx.cs);
419          switch(cryptoerr) {
420          case CRYPTO_ERROR_NONE:
421             /* Success */
422             break;
423          case CRYPTO_ERROR_NORECIPIENT:
424             Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data.\n"));
425             break;
426          case CRYPTO_ERROR_DECRYPTION:
427             Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed.\n"));
428             break;
429          default:
430             /* Shouldn't happen */
431             Jmsg1(jcr, M_ERROR, 0, _("An error occurred while decoding encrypted session data stream: %s\n"), crypto_strerror(cryptoerr));
432             break;
433          }
434
435          if (cryptoerr != CRYPTO_ERROR_NONE) {
436             extract = false;
437             bclose(&rctx.bfd);
438             continue;
439          }
440
441          break;
442
443       case STREAM_FILE_DATA:
444       case STREAM_SPARSE_DATA:
445       case STREAM_WIN32_DATA:
446       case STREAM_GZIP_DATA:
447       case STREAM_SPARSE_GZIP_DATA:
448       case STREAM_WIN32_GZIP_DATA:
449       case STREAM_ENCRYPTED_FILE_DATA:
450       case STREAM_ENCRYPTED_WIN32_DATA:
451       case STREAM_ENCRYPTED_FILE_GZIP_DATA:
452       case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
453          /* Force an expected, consistent stream type here */
454          if (extract && (rctx.prev_stream == rctx.stream 
455                          || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES
456                          || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES_EX
457                          || rctx.prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
458             rctx.flags = 0;
459
460             if (rctx.stream == STREAM_SPARSE_DATA || 
461                 rctx.stream == STREAM_SPARSE_GZIP_DATA) {
462                rctx.flags |= FO_SPARSE;
463             }
464
465             if (rctx.stream == STREAM_GZIP_DATA 
466                   || rctx.stream == STREAM_SPARSE_GZIP_DATA
467                   || rctx.stream == STREAM_WIN32_GZIP_DATA
468                   || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
469                   || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
470                rctx.flags |= FO_GZIP;
471             }
472
473             if (rctx.stream == STREAM_ENCRYPTED_FILE_DATA
474                   || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
475                   || rctx.stream == STREAM_ENCRYPTED_WIN32_DATA
476                   || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {               
477                /* Set up a decryption context */
478                if (!rctx.cipher_ctx.cipher) {
479                   if (!rctx.cs) {
480                      Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
481                      extract = false;
482                      bclose(&rctx.bfd);
483                      continue;
484                   }
485
486                   if ((rctx.cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false, 
487                            &rctx.cipher_ctx.block_size)) == NULL) {
488                      Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
489                      free_session(rctx);
490                      extract = false;
491                      bclose(&rctx.bfd);
492                      continue;
493                   }
494                }
495                rctx.flags |= FO_ENCRYPT;
496             }
497
498             if (is_win32_stream(rctx.stream) && !have_win32_api()) {
499                set_portable_backup(&rctx.bfd);
500                rctx.flags |= FO_WIN32DECOMP;    /* "decompose" BackupWrite data */
501             }
502
503             if (extract_data(jcr, &rctx.bfd, sd->msg, sd->msglen, &rctx.fileAddr, 
504                              rctx.flags, &rctx.cipher_ctx) < 0) {
505                extract = false;
506                bclose(&rctx.bfd);
507                continue;
508             }
509          }
510          break;
511
512       /* Resource fork stream - only recorded after a file to be restored */
513       /* Silently ignore if we cannot write - we already reported that */
514       case STREAM_ENCRYPTED_MACOS_FORK_DATA:
515       case STREAM_MACOS_FORK_DATA:
516 #ifdef HAVE_DARWIN_OS
517          rctx.fork_flags = 0;
518          jcr->ff->flags |= FO_HFSPLUS;
519
520          if (rctx.stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) {
521             rctx.fork_flags |= FO_ENCRYPT;
522
523             /* Set up a decryption context */
524             if (extract && !rctx.fork_cipher_ctx.cipher) {
525                if (!rctx.cs) {
526                   Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname);
527                   extract = false;
528                   bclose(&rctx.bfd);
529                   continue;
530                }
531
532                if ((rctx.fork_cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false, &rctx.fork_cipher_ctx.block_size)) == NULL) {
533                   Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
534                   free_session(rctx);
535                   extract = false;
536                   bclose(&rctx.bfd);
537                   continue;
538                }
539             }
540          }
541
542          if (extract) {
543             if (rctx.prev_stream != rctx.stream) {
544                if (bopen_rsrc(&rctx.forkbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
545                   Jmsg(jcr, M_ERROR, 0, _("     Cannot open resource fork for %s.\n"), jcr->last_fname);
546                   extract = false;
547                   continue;
548                }
549
550                rctx.fork_size = rsrc_len;
551                Dmsg0(30, "Restoring resource fork\n");
552             }
553
554             if (extract_data(jcr, &rctx.forkbfd, sd->msg, sd->msglen, &rctx.fork_addr, rctx.fork_flags, 
555                              &rctx.fork_cipher_ctx) < 0) {
556                extract = false;
557                bclose(&rctx.forkbfd);
558                continue;
559             }
560          }
561 #else
562          non_support_rsrc++;
563 #endif
564          break;
565
566       case STREAM_HFSPLUS_ATTRIBUTES:
567 #ifdef HAVE_DARWIN_OS
568          Dmsg0(30, "Restoring Finder Info\n");
569          jcr->ff->flags |= FO_HFSPLUS;
570          if (sd->msglen != 32) {
571             Jmsg(jcr, M_ERROR, 0, _("     Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
572             continue;
573          }
574          if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
575             Jmsg(jcr, M_ERROR, 0, _("     Could not set Finder Info on %s\n"), jcr->last_fname);
576             continue;
577          }
578 #else
579          non_support_finfo++;
580 #endif
581          break;
582
583       case STREAM_UNIX_ACCESS_ACL:
584          if (have_acl) {
585             pm_strcpy(jcr->acl_text, sd->msg);
586             Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
587             if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
588                Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
589             }
590          } else {
591             non_support_acl++;
592          }
593          break;
594
595       case STREAM_UNIX_DEFAULT_ACL:
596          if (have_acl) {
597             pm_strcpy(jcr->acl_text, sd->msg);
598             Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
599             if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
600                Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
601             }
602          } else {
603             non_support_acl++;
604          }
605          break;
606
607       case STREAM_SIGNED_DIGEST:
608          /* Is this an unexpected signature? */
609          if (rctx.sig) {
610             Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic signature data stream.\n"));
611             free_signature(rctx);
612             continue;
613          }
614          /* Save signature. */
615          if (extract && (rctx.sig = crypto_sign_decode(jcr, (uint8_t *)sd->msg, (uint32_t)sd->msglen)) == NULL) {
616             Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname);
617          }
618          break;
619
620       case STREAM_MD5_DIGEST:
621       case STREAM_SHA1_DIGEST:
622       case STREAM_SHA256_DIGEST:
623       case STREAM_SHA512_DIGEST:
624          break;
625
626       case STREAM_PROGRAM_NAMES:
627       case STREAM_PROGRAM_DATA:
628          if (!non_support_progname) {
629             Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
630             non_support_progname++;
631          }
632          break;
633
634       case STREAM_PLUGIN_NAME:
635          plugin_name_stream(jcr, sd->msg);
636          break;
637
638       default:
639          /* If extracting, wierd stream (not 1 or 2), close output file anyway */
640          if (extract) {
641             Dmsg1(30, "Found wierd stream %d\n", rctx.stream);
642             if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
643                Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
644             }
645             /* Flush and deallocate cipher context */
646             deallocate_cipher(rctx);
647             deallocate_fork_cipher(rctx);
648
649             set_attributes(jcr, attr, &rctx.bfd);
650
651             /* Verify the cryptographic signature if any */
652             rctx.type = attr->type;
653             verify_signature(jcr, rctx);
654             extract = false;
655          } else if (is_bopen(&rctx.bfd)) {
656             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
657             bclose(&rctx.bfd);
658          }
659          Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
660               rctx.stream);
661          Dmsg2(0, "Unknown stream=%d data=%s\n", rctx.stream, sd->msg);
662          break;
663       } /* end switch(stream) */
664
665    } /* end while get_msg() */
666
667    /* If output file is still open, it was the last one in the
668     * archive since we just hit an end of file, so close the file.
669     */
670    if (is_bopen(&rctx.forkbfd)) {
671       bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
672    }
673    if (extract) {
674       /* Flush and deallocate cipher context */
675       deallocate_cipher(rctx);
676       deallocate_fork_cipher(rctx);
677
678       set_attributes(jcr, attr, &rctx.bfd);
679
680       /* Verify the cryptographic signature on the last file, if any */
681       rctx.type = attr->type;
682       verify_signature(jcr, rctx);
683    }
684
685    if (is_bopen(&rctx.bfd)) {
686       bclose(&rctx.bfd);
687    }
688
689    set_jcr_job_status(jcr, JS_Terminated);
690    goto ok_out;
691
692 bail_out:
693    set_jcr_job_status(jcr, JS_ErrorTerminated);
694
695 ok_out:
696    /* Free Signature & Crypto Data */
697    free_signature(rctx);
698    free_session(rctx);
699    if (jcr->crypto.digest) {
700       crypto_digest_free(jcr->crypto.digest);
701       jcr->crypto.digest = NULL;
702    }
703
704    /* Free file cipher restore context */
705    if (rctx.cipher_ctx.cipher) {
706       crypto_cipher_free(rctx.cipher_ctx.cipher);
707       rctx.cipher_ctx.cipher = NULL;
708    }
709    if (rctx.cipher_ctx.buf) {
710       free_pool_memory(rctx.cipher_ctx.buf);
711       rctx.cipher_ctx.buf = NULL;
712    }
713
714    /* Free alternate stream cipher restore context */
715    if (rctx.fork_cipher_ctx.cipher) {
716       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
717       rctx.fork_cipher_ctx.cipher = NULL;
718    }
719    if (rctx.fork_cipher_ctx.buf) {
720       free_pool_memory(rctx.fork_cipher_ctx.buf);
721       rctx.fork_cipher_ctx.buf = NULL;
722    }
723
724    if (jcr->compress_buf) {
725       free(jcr->compress_buf);
726       jcr->compress_buf = NULL;
727       jcr->compress_buf_size = 0;
728    }
729    bclose(&rctx.forkbfd);
730    bclose(&rctx.bfd);
731    free_attr(attr);
732    free_pool_memory(jcr->acl_text);
733    Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
734       edit_uint64(jcr->JobBytes, ec1));
735    if (non_support_data > 1 || non_support_attr > 1) {
736       Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
737          non_support_data, non_support_attr);
738    }
739    if (non_support_rsrc) {
740       Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
741    }
742    if (non_support_finfo) {
743       Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
744    }
745    if (non_support_acl) {
746       Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
747    }
748    if (non_support_crypto) {
749       Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl);
750    }
751
752 }
753
754 #ifdef HAVE_LIBZ
755 /*
756  * Convert ZLIB error code into an ASCII message
757  */
758 static const char *zlib_strerror(int stat)
759 {
760    if (stat >= 0) {
761       return _("None");
762    }
763    switch (stat) {
764    case Z_ERRNO:
765       return _("Zlib errno");
766    case Z_STREAM_ERROR:
767       return _("Zlib stream error");
768    case Z_DATA_ERROR:
769       return _("Zlib data error");
770    case Z_MEM_ERROR:
771       return _("Zlib memory error");
772    case Z_BUF_ERROR:
773       return _("Zlib buffer error");
774    case Z_VERSION_ERROR:
775       return _("Zlib version error");
776    default:
777       return _("*none*");
778    }
779 }
780 #endif
781
782 static int do_file_digest(JCR *jcr, FF_PKT *ff_pkt, bool top_level) 
783 {
784    Dmsg1(50, "do_file_digest jcr=%p\n", jcr);
785    return (digest_file(jcr, ff_pkt, jcr->crypto.digest));
786 }
787
788 /*
789  * Verify the signature for the last restored file
790  * Return value is either true (signature correct)
791  * or false (signature could not be verified).
792  * TODO landonf: Implement without using find_one_file and
793  * without re-reading the file.
794  */
795 static bool verify_signature(JCR *jcr, r_ctx &rctx)
796 {
797    X509_KEYPAIR *keypair;
798    DIGEST *digest = NULL;
799    crypto_error_t err;
800    uint64_t saved_bytes;
801    crypto_digest_t signing_algorithm = have_sha2 ? 
802                                        CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
803    crypto_digest_t algorithm;
804    SIGNATURE *sig = rctx.sig;
805
806
807    if (!jcr->crypto.pki_sign) {
808       return true;                    /* no signature OK */
809    }
810    if (!sig) {
811       if (rctx.type == FT_REGE || rctx.type == FT_REG || rctx.type == FT_RAW) { 
812          Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), 
813                jcr->last_fname);
814          goto bail_out;
815       }
816       return true;
817    }
818
819    /* Iterate through the trusted signers */
820    foreach_alist(keypair, jcr->crypto.pki_signers) {
821       err = crypto_sign_get_digest(sig, jcr->crypto.pki_keypair, algorithm, &digest);
822       switch (err) {
823       case CRYPTO_ERROR_NONE:
824          Dmsg0(50, "== Got digest\n");
825          /*
826           * We computed jcr->crypto.digest using signing_algorithm while writing
827           * the file. If it is not the same as the algorithm used for 
828           * this file, punt by releasing the computed algorithm and 
829           * computing by re-reading the file.
830           */
831          if (algorithm != signing_algorithm) {
832             if (jcr->crypto.digest) {
833                crypto_digest_free(jcr->crypto.digest);
834                jcr->crypto.digest = NULL;
835             }  
836          }
837          if (jcr->crypto.digest) {
838              /* Use digest computed while writing the file to verify the signature */
839             if ((err = crypto_sign_verify(sig, keypair, jcr->crypto.digest)) != CRYPTO_ERROR_NONE) {
840                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
841                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
842                      jcr->last_fname, crypto_strerror(err));
843                goto bail_out;
844             }
845          } else {   
846             /* Signature found, digest allocated.  Old method, 
847              * re-read the file and compute the digest
848              */
849             jcr->crypto.digest = digest;
850
851             /* Checksum the entire file */
852             /* Make sure we don't modify JobBytes by saving and restoring it */
853             saved_bytes = jcr->JobBytes;                     
854             if (find_one_file(jcr, jcr->ff, do_file_digest, jcr->last_fname, (dev_t)-1, 1) != 0) {
855                Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"), 
856                     jcr->last_fname);
857                jcr->JobBytes = saved_bytes;
858                goto bail_out;
859             }
860             jcr->JobBytes = saved_bytes;
861
862             /* Verify the signature */
863             if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
864                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
865                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
866                      jcr->last_fname, crypto_strerror(err));
867                goto bail_out;
868             }
869             jcr->crypto.digest = NULL;
870          }
871
872          /* Valid signature */
873          Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
874          crypto_digest_free(digest);
875          return true;
876
877       case CRYPTO_ERROR_NOSIGNER:
878          /* Signature not found, try again */
879          if (digest) {
880             crypto_digest_free(digest);
881             digest = NULL;
882          }
883          continue;
884       default:
885          /* Something strange happened (that shouldn't happen!)... */
886          Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
887          goto bail_out;
888       }
889    }
890
891    /* No signer */
892    Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
893
894 bail_out:
895    if (digest) {
896       crypto_digest_free(digest);
897    }
898    return false;
899 }
900
901 bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *length)
902 {
903       unser_declare;
904       uint64_t faddr;
905       char ec1[50];
906       unser_begin(*data, SPARSE_FADDR_SIZE);
907       unser_uint64(faddr);
908       if (*addr != faddr) {
909          *addr = faddr;
910          if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
911             berrno be;
912             Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
913                   edit_uint64(*addr, ec1), jcr->last_fname, 
914                   be.bstrerror(bfd->berrno));
915             return false;
916          }
917       }
918       *data += SPARSE_FADDR_SIZE;
919       *length -= SPARSE_FADDR_SIZE;
920       return true;
921 }
922
923 bool decompress_data(JCR *jcr, char **data, uint32_t *length)
924 {
925 #ifdef HAVE_LIBZ
926    uLong compress_len;
927    int stat;
928    char ec1[50];                      /* Buffer printing huge values */
929
930    /* 
931     * NOTE! We only use uLong and Byte because they are
932     *  needed by the zlib routines, they should not otherwise
933     *  be used in Bacula.
934     */
935    compress_len = jcr->compress_buf_size;
936    Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, *length);
937    if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
938                (const Byte *)*data, (uLong)*length)) != Z_OK) {
939       Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
940             jcr->last_fname, zlib_strerror(stat));
941       return false;
942    }
943    *data = jcr->compress_buf;
944    *length = compress_len;
945    Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
946    return true;
947 #else
948    Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
949    return false;
950 #endif
951 }
952
953 static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
954 {
955    unser_declare;
956    if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
957       unser_begin(&ctx->buf[0], CRYPTO_LEN_SIZE);
958       unser_uint32(ctx->packet_len);
959       ctx->packet_len += CRYPTO_LEN_SIZE;
960    }
961 }
962
963 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
964 {
965    if (jcr->crypto.digest) {
966       crypto_digest_update(jcr->crypto.digest, (uint8_t *)data, length);
967    }
968    if (win32_decomp) {
969       if (!processWin32BackupAPIBlock(bfd, data, length)) {
970          berrno be;
971          Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"), 
972                jcr->last_fname, be.bstrerror(bfd->berrno));
973          return false;
974       }
975    } else if (bwrite(bfd, data, length) != (ssize_t)length) {
976       berrno be;
977       Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), 
978             jcr->last_fname, be.bstrerror(bfd->berrno));
979       return false;
980    }
981
982    return true;
983 }
984
985 /*
986  * In the context of jcr, write data to bfd.
987  * We write buflen bytes in buf at addr. addr is updated in place.
988  * The flags specify whether to use sparse files or compression.
989  * Return value is the number of bytes written, or -1 on errors.
990  */
991 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
992       uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx)
993 {
994    char *wbuf;                        /* write buffer */
995    uint32_t wsize;                    /* write size */
996    uint32_t rsize;                    /* read size */
997    uint32_t decrypted_len = 0;        /* Decryption output length */
998    char ec1[50];                      /* Buffer printing huge values */
999
1000    rsize = buflen;
1001    jcr->ReadBytes += rsize;
1002    wsize = rsize;
1003    wbuf = buf;
1004
1005    if (flags & FO_ENCRYPT) {
1006       ASSERT(cipher_ctx->cipher);
1007
1008       /* NOTE: We must implement block preserving semantics for the
1009        * non-streaming compression and sparse code. */
1010
1011       /*
1012        * Grow the crypto buffer, if necessary.
1013        * crypto_cipher_update() will process only whole blocks,
1014        * buffering the remaining input.
1015        */
1016       cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, 
1017                         cipher_ctx->buf_len + wsize + cipher_ctx->block_size);
1018
1019       /* Decrypt the input block */
1020       if (!crypto_cipher_update(cipher_ctx->cipher, 
1021                                 (const u_int8_t *)wbuf, 
1022                                 wsize, 
1023                                 (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len], 
1024                                 &decrypted_len)) {
1025          /* Decryption failed. Shouldn't happen. */
1026          Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
1027          return -1;
1028       }
1029
1030       if (decrypted_len == 0) {
1031          /* No full block of encrypted data available, write more data */
1032          return 0;
1033       }
1034
1035       Dmsg2(100, "decrypted len=%d encrypted len=%d\n", decrypted_len, wsize);
1036
1037       cipher_ctx->buf_len += decrypted_len;
1038       wbuf = cipher_ctx->buf;
1039
1040       /* If one full preserved block is available, write it to disk,
1041        * and then buffer any remaining data. This should be effecient
1042        * as long as Bacula's block size is not significantly smaller than the
1043        * encryption block size (extremely unlikely!) */
1044       unser_crypto_packet_len(cipher_ctx);
1045       Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1046
1047       if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
1048          /* No full preserved block is available. */
1049          return 0;
1050       }
1051
1052       /* We have one full block, set up the filter input buffers */
1053       wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1054       wbuf = &wbuf[CRYPTO_LEN_SIZE]; /* Skip the block length header */
1055       cipher_ctx->buf_len -= cipher_ctx->packet_len;
1056       Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1057    }
1058
1059    if (flags & FO_SPARSE) {
1060       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1061          return -1;
1062       }
1063    }
1064
1065    if (flags & FO_GZIP) {
1066       if (!decompress_data(jcr, &wbuf, &wsize)) {
1067          return -1;
1068       }
1069    }
1070
1071    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1072       return -1;
1073    }
1074    jcr->JobBytes += wsize;
1075    *addr += wsize;
1076    Dmsg2(30, "Write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1077
1078    /* Clean up crypto buffers */
1079    if (flags & FO_ENCRYPT) {
1080       /* Move any remaining data to start of buffer */
1081       if (cipher_ctx->buf_len > 0) {
1082          Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1083          memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1084             cipher_ctx->buf_len);
1085       }
1086       /* The packet was successfully written, reset the length so that the next
1087        * packet length may be re-read by unser_crypto_packet_len() */
1088       cipher_ctx->packet_len = 0;
1089    }
1090
1091    return wsize;
1092 }
1093
1094 /*
1095  * In the context of jcr, flush any remaining data from the cipher context,
1096  * writing it to bfd.
1097  * Return value is true on success, false on failure.
1098  */
1099 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
1100                   RESTORE_CIPHER_CTX *cipher_ctx)
1101 {
1102    uint32_t decrypted_len = 0;
1103    char *wbuf;                        /* write buffer */
1104    uint32_t wsize;                    /* write size */
1105    char ec1[50];                      /* Buffer printing huge values */
1106    bool second_pass = false;
1107
1108 again:
1109    /* Write out the remaining block and free the cipher context */
1110    cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len + 
1111                      cipher_ctx->block_size);
1112
1113    if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1114         &decrypted_len)) {
1115       /* Writing out the final, buffered block failed. Shouldn't happen. */
1116       Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"), 
1117             cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
1118    }
1119
1120    Dmsg2(30, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
1121    /* If nothing new was decrypted, and our output buffer is empty, return */
1122    if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
1123       return true;
1124    }
1125
1126    cipher_ctx->buf_len += decrypted_len;
1127
1128    unser_crypto_packet_len(cipher_ctx);
1129    Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1130    wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1131    wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE]; /* Decrypted, possibly decompressed output here. */
1132    cipher_ctx->buf_len -= cipher_ctx->packet_len;
1133    Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1134
1135    if (flags & FO_SPARSE) {
1136       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1137          return false;
1138       }
1139    }
1140
1141    if (flags & FO_GZIP) {
1142       if (!decompress_data(jcr, &wbuf, &wsize)) {
1143          return false;
1144       }
1145    }
1146
1147    Dmsg0(30, "Call store_data\n");
1148    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1149       return false;
1150    }
1151    jcr->JobBytes += wsize;
1152    Dmsg2(30, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1153
1154    /* Move any remaining data to start of buffer */
1155    if (cipher_ctx->buf_len > 0) {
1156       Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1157       memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1158          cipher_ctx->buf_len);
1159    }
1160    /* The packet was successfully written, reset the length so that the next
1161     * packet length may be re-read by unser_crypto_packet_len() */
1162    cipher_ctx->packet_len = 0;
1163
1164    if (cipher_ctx->buf_len >0 && !second_pass) {
1165       second_pass = true;
1166       goto again;
1167    }
1168
1169    /* Stop decryption */
1170    cipher_ctx->buf_len = 0;
1171    cipher_ctx->packet_len = 0;
1172
1173    return true;
1174 }
1175
1176 static void deallocate_cipher(r_ctx &rctx)
1177 {
1178    /* Flush and deallocate previous stream's cipher context */
1179    if (rctx.cipher_ctx.cipher) {
1180       flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx);
1181       crypto_cipher_free(rctx.cipher_ctx.cipher);
1182       rctx.cipher_ctx.cipher = NULL;
1183    }
1184 }
1185
1186 static void deallocate_fork_cipher(r_ctx &rctx)
1187 {
1188
1189    /* Flush and deallocate previous stream's fork cipher context */
1190    if (rctx.fork_cipher_ctx.cipher) {
1191       flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx);
1192       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
1193       rctx.fork_cipher_ctx.cipher = NULL;
1194    }
1195 }
1196
1197 static void free_signature(r_ctx &rctx)
1198 {
1199    if (rctx.sig) {
1200       crypto_sign_free(rctx.sig);
1201       rctx.sig = NULL;
1202    }
1203 }
1204
1205 static void free_session(r_ctx &rctx)
1206 {
1207    if (rctx.cs) {
1208       crypto_session_free(rctx.cs);
1209       rctx.cs = NULL;
1210    }
1211 }
1212
1213
1214 /* This code if implemented goes above */
1215 #ifdef stbernard_implemented
1216 /  #if defined(HAVE_WIN32)
1217    bool        bResumeOfmOnExit = FALSE;
1218    if (isOpenFileManagerRunning()) {
1219        if ( pauseOpenFileManager() ) {
1220           Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
1221           bResumeOfmOnExit = TRUE;
1222        }
1223        else {
1224           Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
1225        }
1226    }
1227    {
1228        char username[UNLEN+1];
1229        DWORD usize = sizeof(username);
1230        int privs = enable_backup_privileges(NULL, 1);
1231        if (GetUserName(username, &usize)) {
1232           Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
1233        } else {
1234           Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));
1235        }
1236    }
1237 #endif