]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/restore.c
Add rctx prefix to Mac OS X references
[bacula/bacula] / bacula / src / filed / restore.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 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();
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->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->digest) {
406             crypto_digest_free(jcr->digest);
407          }  
408          jcr->digest = crypto_digest_new(jcr, signing_algorithm);
409          if (!jcr->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->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.rctxfork_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_ATTRIBUTES_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_ATTRIBUTES_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       default:
635          /* If extracting, wierd stream (not 1 or 2), close output file anyway */
636          if (extract) {
637             Dmsg1(30, "Found wierd stream %d\n", rctx.stream);
638             if (rctx.size > 0 && !is_bopen(&rctx.bfd)) {
639                Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
640             }
641             /* Flush and deallocate cipher context */
642             deallocate_cipher(rctx);
643             deallocate_fork_cipher(rctx);
644
645             set_attributes(jcr, attr, &rctx.bfd);
646
647             /* Verify the cryptographic signature if any */
648             rctx.type = attr->type;
649             verify_signature(jcr, rctx);
650             extract = false;
651          } else if (is_bopen(&rctx.bfd)) {
652             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
653             bclose(&rctx.bfd);
654          }
655          Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"),
656               rctx.stream);
657          Dmsg2(0, "None of above!!! stream=%d data=%s\n", rctx.stream,sd->msg);
658          break;
659       } /* end switch(stream) */
660
661    } /* end while get_msg() */
662
663    /* If output file is still open, it was the last one in the
664     * archive since we just hit an end of file, so close the file.
665     */
666    if (is_bopen(&rctx.forkbfd)) {
667       bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size);
668    }
669    if (extract) {
670       /* Flush and deallocate cipher context */
671       deallocate_cipher(rctx);
672       deallocate_fork_cipher(rctx);
673
674       set_attributes(jcr, attr, &rctx.bfd);
675
676       /* Verify the cryptographic signature on the last file, if any */
677       rctx.type = attr->type;
678       verify_signature(jcr, rctx);
679    }
680
681    if (is_bopen(&rctx.bfd)) {
682       bclose(&rctx.bfd);
683    }
684
685    set_jcr_job_status(jcr, JS_Terminated);
686    goto ok_out;
687
688 bail_out:
689    set_jcr_job_status(jcr, JS_ErrorTerminated);
690
691 ok_out:
692    /* Free Signature & Crypto Data */
693    free_signature(rctx);
694    free_session(rctx);
695    if (jcr->digest) {
696       crypto_digest_free(jcr->digest);
697       jcr->digest = NULL;
698    }
699
700    /* Free file cipher restore context */
701    if (rctx.cipher_ctx.cipher) {
702       crypto_cipher_free(rctx.cipher_ctx.cipher);
703       rctx.cipher_ctx.cipher = NULL;
704    }
705    if (rctx.cipher_ctx.buf) {
706       free_pool_memory(rctx.cipher_ctx.buf);
707       rctx.cipher_ctx.buf = NULL;
708    }
709
710    /* Free alternate stream cipher restore context */
711    if (rctx.fork_cipher_ctx.cipher) {
712       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
713       rctx.fork_cipher_ctx.cipher = NULL;
714    }
715    if (rctx.fork_cipher_ctx.buf) {
716       free_pool_memory(rctx.fork_cipher_ctx.buf);
717       rctx.fork_cipher_ctx.buf = NULL;
718    }
719
720    if (jcr->compress_buf) {
721       free(jcr->compress_buf);
722       jcr->compress_buf = NULL;
723       jcr->compress_buf_size = 0;
724    }
725    bclose(&rctx.forkbfd);
726    bclose(&rctx.bfd);
727    free_attr(attr);
728    free_pool_memory(jcr->acl_text);
729    Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
730       edit_uint64(jcr->JobBytes, ec1));
731    if (non_support_data > 1 || non_support_attr > 1) {
732       Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
733          non_support_data, non_support_attr);
734    }
735    if (non_support_rsrc) {
736       Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
737    }
738    if (non_support_finfo) {
739       Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
740    }
741    if (non_support_acl) {
742       Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
743    }
744    if (non_support_crypto) {
745       Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl);
746    }
747
748 }
749
750 #ifdef HAVE_LIBZ
751 /*
752  * Convert ZLIB error code into an ASCII message
753  */
754 static const char *zlib_strerror(int stat)
755 {
756    if (stat >= 0) {
757       return _("None");
758    }
759    switch (stat) {
760    case Z_ERRNO:
761       return _("Zlib errno");
762    case Z_STREAM_ERROR:
763       return _("Zlib stream error");
764    case Z_DATA_ERROR:
765       return _("Zlib data error");
766    case Z_MEM_ERROR:
767       return _("Zlib memory error");
768    case Z_BUF_ERROR:
769       return _("Zlib buffer error");
770    case Z_VERSION_ERROR:
771       return _("Zlib version error");
772    default:
773       return _("*none*");
774    }
775 }
776 #endif
777
778 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level) 
779 {
780    JCR *jcr = (JCR *)pkt;
781    Dmsg1(50, "do_file_digest jcr=%p\n", jcr);
782    return (digest_file(jcr, ff_pkt, jcr->digest));
783 }
784
785 /*
786  * Verify the signature for the last restored file
787  * Return value is either true (signature correct)
788  * or false (signature could not be verified).
789  * TODO landonf: Implement without using find_one_file and
790  * without re-reading the file.
791  */
792 static bool verify_signature(JCR *jcr, r_ctx &rctx)
793 {
794    X509_KEYPAIR *keypair;
795    DIGEST *digest = NULL;
796    crypto_error_t err;
797    uint64_t saved_bytes;
798    crypto_digest_t signing_algorithm = have_sha2 ? 
799                                        CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
800    crypto_digest_t algorithm;
801    SIGNATURE *sig = rctx.sig;
802
803
804    if (!jcr->pki_sign) {
805       return true;                    /* no signature OK */
806    }
807    if (!sig) {
808       if (rctx.type == FT_REGE || rctx.type == FT_REG || rctx.type == FT_RAW) { 
809          Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), 
810                jcr->last_fname);
811          goto bail_out;
812       }
813       return true;
814    }
815
816    /* Iterate through the trusted signers */
817    foreach_alist(keypair, jcr->pki_signers) {
818       err = crypto_sign_get_digest(sig, jcr->pki_keypair, algorithm, &digest);
819       switch (err) {
820       case CRYPTO_ERROR_NONE:
821          Dmsg0(50, "== Got digest\n");
822          /*
823           * We computed jcr->digest using signing_algorithm while writing
824           * the file. If it is not the same as the algorithm used for 
825           * this file, punt by releasing the computed algorithm and 
826           * computing by re-reading the file.
827           */
828          if (algorithm != signing_algorithm) {
829             if (jcr->digest) {
830                crypto_digest_free(jcr->digest);
831                jcr->digest = NULL;
832             }  
833          }
834          if (jcr->digest) {
835              /* Use digest computed while writing the file to verify the signature */
836             if ((err = crypto_sign_verify(sig, keypair, jcr->digest)) != CRYPTO_ERROR_NONE) {
837                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
838                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
839                      jcr->last_fname, crypto_strerror(err));
840                goto bail_out;
841             }
842          } else {   
843             /* Signature found, digest allocated.  Old method, 
844              * re-read the file and compute the digest
845              */
846             jcr->digest = digest;
847
848             /* Checksum the entire file */
849             /* Make sure we don't modify JobBytes by saving and restoring it */
850             saved_bytes = jcr->JobBytes;                     
851             if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
852                Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"), 
853                     jcr->last_fname);
854                jcr->JobBytes = saved_bytes;
855                goto bail_out;
856             }
857             jcr->JobBytes = saved_bytes;
858
859             /* Verify the signature */
860             if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
861                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
862                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
863                      jcr->last_fname, crypto_strerror(err));
864                goto bail_out;
865             }
866             jcr->digest = NULL;
867          }
868
869          /* Valid signature */
870          Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
871          crypto_digest_free(digest);
872          return true;
873
874       case CRYPTO_ERROR_NOSIGNER:
875          /* Signature not found, try again */
876          if (digest) {
877             crypto_digest_free(digest);
878             digest = NULL;
879          }
880          continue;
881       default:
882          /* Something strange happened (that shouldn't happen!)... */
883          Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
884          goto bail_out;
885       }
886    }
887
888    /* No signer */
889    Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
890
891 bail_out:
892    if (digest) {
893       crypto_digest_free(digest);
894    }
895    return false;
896 }
897
898 bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *length)
899 {
900       unser_declare;
901       uint64_t faddr;
902       char ec1[50];
903       unser_begin(*data, SPARSE_FADDR_SIZE);
904       unser_uint64(faddr);
905       if (*addr != faddr) {
906          *addr = faddr;
907          if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
908             berrno be;
909             Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
910                   edit_uint64(*addr, ec1), jcr->last_fname, 
911                   be.bstrerror(bfd->berrno));
912             return false;
913          }
914       }
915       *data += SPARSE_FADDR_SIZE;
916       *length -= SPARSE_FADDR_SIZE;
917       return true;
918 }
919
920 bool decompress_data(JCR *jcr, char **data, uint32_t *length)
921 {
922 #ifdef HAVE_LIBZ
923    uLong compress_len;
924    int stat;
925    char ec1[50];                      /* Buffer printing huge values */
926
927    /* 
928     * NOTE! We only use uLong and Byte because they are
929     *  needed by the zlib routines, they should not otherwise
930     *  be used in Bacula.
931     */
932    compress_len = jcr->compress_buf_size;
933    Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, *length);
934    if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
935                (const Byte *)*data, (uLong)*length)) != Z_OK) {
936       Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
937             jcr->last_fname, zlib_strerror(stat));
938       return false;
939    }
940    *data = jcr->compress_buf;
941    *length = compress_len;
942    Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
943    return true;
944 #else
945    Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
946    return false;
947 #endif
948 }
949
950 static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
951 {
952    unser_declare;
953    if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
954       unser_begin(&ctx->buf[0], CRYPTO_LEN_SIZE);
955       unser_uint32(ctx->packet_len);
956       ctx->packet_len += CRYPTO_LEN_SIZE;
957    }
958 }
959
960 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
961 {
962    if (jcr->digest) {
963       crypto_digest_update(jcr->digest, (uint8_t *)data, length);
964    }
965    if (win32_decomp) {
966       if (!processWin32BackupAPIBlock(bfd, data, length)) {
967          berrno be;
968          Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"), 
969                jcr->last_fname, be.bstrerror(bfd->berrno));
970          return false;
971       }
972    } else if (bwrite(bfd, data, length) != (ssize_t)length) {
973       berrno be;
974       Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), 
975             jcr->last_fname, be.bstrerror(bfd->berrno));
976       return false;
977    }
978
979    return true;
980 }
981
982 /*
983  * In the context of jcr, write data to bfd.
984  * We write buflen bytes in buf at addr. addr is updated in place.
985  * The flags specify whether to use sparse files or compression.
986  * Return value is the number of bytes written, or -1 on errors.
987  */
988 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
989       uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx)
990 {
991    char *wbuf;                        /* write buffer */
992    uint32_t wsize;                    /* write size */
993    uint32_t rsize;                    /* read size */
994    uint32_t decrypted_len = 0;        /* Decryption output length */
995    char ec1[50];                      /* Buffer printing huge values */
996
997    rsize = buflen;
998    jcr->ReadBytes += rsize;
999    wsize = rsize;
1000    wbuf = buf;
1001
1002    if (flags & FO_ENCRYPT) {
1003       ASSERT(cipher_ctx->cipher);
1004
1005       /* NOTE: We must implement block preserving semantics for the
1006        * non-streaming compression and sparse code. */
1007
1008       /*
1009        * Grow the crypto buffer, if necessary.
1010        * crypto_cipher_update() will process only whole blocks,
1011        * buffering the remaining input.
1012        */
1013       cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, 
1014                         cipher_ctx->buf_len + wsize + cipher_ctx->block_size);
1015
1016       /* Decrypt the input block */
1017       if (!crypto_cipher_update(cipher_ctx->cipher, 
1018                                 (const u_int8_t *)wbuf, 
1019                                 wsize, 
1020                                 (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len], 
1021                                 &decrypted_len)) {
1022          /* Decryption failed. Shouldn't happen. */
1023          Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
1024          return -1;
1025       }
1026
1027       if (decrypted_len == 0) {
1028          /* No full block of encrypted data available, write more data */
1029          return 0;
1030       }
1031
1032       Dmsg2(100, "decrypted len=%d encrypted len=%d\n", decrypted_len, wsize);
1033
1034       cipher_ctx->buf_len += decrypted_len;
1035       wbuf = cipher_ctx->buf;
1036
1037       /* If one full preserved block is available, write it to disk,
1038        * and then buffer any remaining data. This should be effecient
1039        * as long as Bacula's block size is not significantly smaller than the
1040        * encryption block size (extremely unlikely!) */
1041       unser_crypto_packet_len(cipher_ctx);
1042       Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1043
1044       if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
1045          /* No full preserved block is available. */
1046          return 0;
1047       }
1048
1049       /* We have one full block, set up the filter input buffers */
1050       wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1051       wbuf = &wbuf[CRYPTO_LEN_SIZE]; /* Skip the block length header */
1052       cipher_ctx->buf_len -= cipher_ctx->packet_len;
1053       Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1054    }
1055
1056    if (flags & FO_SPARSE) {
1057       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1058          return -1;
1059       }
1060    }
1061
1062    if (flags & FO_GZIP) {
1063       if (!decompress_data(jcr, &wbuf, &wsize)) {
1064          return -1;
1065       }
1066    }
1067
1068    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1069       return -1;
1070    }
1071    jcr->JobBytes += wsize;
1072    *addr += wsize;
1073    Dmsg2(30, "Write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1074
1075    /* Clean up crypto buffers */
1076    if (flags & FO_ENCRYPT) {
1077       /* Move any remaining data to start of buffer */
1078       if (cipher_ctx->buf_len > 0) {
1079          Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1080          memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1081             cipher_ctx->buf_len);
1082       }
1083       /* The packet was successfully written, reset the length so that the next
1084        * packet length may be re-read by unser_crypto_packet_len() */
1085       cipher_ctx->packet_len = 0;
1086    }
1087
1088    return wsize;
1089 }
1090
1091 /*
1092  * In the context of jcr, flush any remaining data from the cipher context,
1093  * writing it to bfd.
1094  * Return value is true on success, false on failure.
1095  */
1096 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
1097                   RESTORE_CIPHER_CTX *cipher_ctx)
1098 {
1099    uint32_t decrypted_len = 0;
1100    char *wbuf;                        /* write buffer */
1101    uint32_t wsize;                    /* write size */
1102    char ec1[50];                      /* Buffer printing huge values */
1103    bool second_pass = false;
1104
1105 again:
1106    /* Write out the remaining block and free the cipher context */
1107    cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len + 
1108                      cipher_ctx->block_size);
1109
1110    if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1111         &decrypted_len)) {
1112       /* Writing out the final, buffered block failed. Shouldn't happen. */
1113       Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"), 
1114             cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
1115    }
1116
1117    Dmsg2(30, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
1118    /* If nothing new was decrypted, and our output buffer is empty, return */
1119    if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
1120       return true;
1121    }
1122
1123    cipher_ctx->buf_len += decrypted_len;
1124
1125    unser_crypto_packet_len(cipher_ctx);
1126    Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1127    wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1128    wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE]; /* Decrypted, possibly decompressed output here. */
1129    cipher_ctx->buf_len -= cipher_ctx->packet_len;
1130    Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1131
1132    if (flags & FO_SPARSE) {
1133       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1134          return false;
1135       }
1136    }
1137
1138    if (flags & FO_GZIP) {
1139       if (!decompress_data(jcr, &wbuf, &wsize)) {
1140          return false;
1141       }
1142    }
1143
1144    Dmsg0(30, "Call store_data\n");
1145    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1146       return false;
1147    }
1148    jcr->JobBytes += wsize;
1149    Dmsg2(30, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1150
1151    /* Move any remaining data to start of buffer */
1152    if (cipher_ctx->buf_len > 0) {
1153       Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1154       memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1155          cipher_ctx->buf_len);
1156    }
1157    /* The packet was successfully written, reset the length so that the next
1158     * packet length may be re-read by unser_crypto_packet_len() */
1159    cipher_ctx->packet_len = 0;
1160
1161    if (cipher_ctx->buf_len >0 && !second_pass) {
1162       second_pass = true;
1163       goto again;
1164    }
1165
1166    /* Stop decryption */
1167    cipher_ctx->buf_len = 0;
1168    cipher_ctx->packet_len = 0;
1169
1170    return true;
1171 }
1172
1173 static void deallocate_cipher(r_ctx &rctx)
1174 {
1175    /* Flush and deallocate previous stream's cipher context */
1176    if (rctx.cipher_ctx.cipher) {
1177       flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx);
1178       crypto_cipher_free(rctx.cipher_ctx.cipher);
1179       rctx.cipher_ctx.cipher = NULL;
1180    }
1181 }
1182
1183 static void deallocate_fork_cipher(r_ctx &rctx)
1184 {
1185
1186    /* Flush and deallocate previous stream's fork cipher context */
1187    if (rctx.fork_cipher_ctx.cipher) {
1188       flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx);
1189       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
1190       rctx.fork_cipher_ctx.cipher = NULL;
1191    }
1192 }
1193
1194 static void free_signature(r_ctx &rctx)
1195 {
1196    if (rctx.sig) {
1197       crypto_sign_free(rctx.sig);
1198       rctx.sig = NULL;
1199    }
1200 }
1201
1202 static void free_session(r_ctx &rctx)
1203 {
1204    if (rctx.cs) {
1205       crypto_session_free(rctx.cs);
1206       rctx.cs = NULL;
1207    }
1208 }
1209
1210
1211 /* This code if implemented goes above */
1212 #ifdef stbernard_implemented
1213 /  #if defined(HAVE_WIN32)
1214    bool        bResumeOfmOnExit = FALSE;
1215    if (isOpenFileManagerRunning()) {
1216        if ( pauseOpenFileManager() ) {
1217           Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
1218           bResumeOfmOnExit = TRUE;
1219        }
1220        else {
1221           Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
1222        }
1223    }
1224    {
1225        char username[UNLEN+1];
1226        DWORD usize = sizeof(username);
1227        int privs = enable_backup_privileges(NULL, 1);
1228        if (GetUserName(username, &usize)) {
1229           Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
1230        } else {
1231           Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));
1232        }
1233    }
1234 #endif