]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/restore.c
0996f9a9a73e12f678db7df12357fc775b939129
[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       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, "Unknown 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->crypto.digest) {
696       crypto_digest_free(jcr->crypto.digest);
697       jcr->crypto.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(JCR *jcr, FF_PKT *ff_pkt, bool top_level) 
779 {
780    Dmsg1(50, "do_file_digest jcr=%p\n", jcr);
781    return (digest_file(jcr, ff_pkt, jcr->crypto.digest));
782 }
783
784 /*
785  * Verify the signature for the last restored file
786  * Return value is either true (signature correct)
787  * or false (signature could not be verified).
788  * TODO landonf: Implement without using find_one_file and
789  * without re-reading the file.
790  */
791 static bool verify_signature(JCR *jcr, r_ctx &rctx)
792 {
793    X509_KEYPAIR *keypair;
794    DIGEST *digest = NULL;
795    crypto_error_t err;
796    uint64_t saved_bytes;
797    crypto_digest_t signing_algorithm = have_sha2 ? 
798                                        CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
799    crypto_digest_t algorithm;
800    SIGNATURE *sig = rctx.sig;
801
802
803    if (!jcr->crypto.pki_sign) {
804       return true;                    /* no signature OK */
805    }
806    if (!sig) {
807       if (rctx.type == FT_REGE || rctx.type == FT_REG || rctx.type == FT_RAW) { 
808          Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), 
809                jcr->last_fname);
810          goto bail_out;
811       }
812       return true;
813    }
814
815    /* Iterate through the trusted signers */
816    foreach_alist(keypair, jcr->crypto.pki_signers) {
817       err = crypto_sign_get_digest(sig, jcr->crypto.pki_keypair, algorithm, &digest);
818       switch (err) {
819       case CRYPTO_ERROR_NONE:
820          Dmsg0(50, "== Got digest\n");
821          /*
822           * We computed jcr->crypto.digest using signing_algorithm while writing
823           * the file. If it is not the same as the algorithm used for 
824           * this file, punt by releasing the computed algorithm and 
825           * computing by re-reading the file.
826           */
827          if (algorithm != signing_algorithm) {
828             if (jcr->crypto.digest) {
829                crypto_digest_free(jcr->crypto.digest);
830                jcr->crypto.digest = NULL;
831             }  
832          }
833          if (jcr->crypto.digest) {
834              /* Use digest computed while writing the file to verify the signature */
835             if ((err = crypto_sign_verify(sig, keypair, jcr->crypto.digest)) != CRYPTO_ERROR_NONE) {
836                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
837                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
838                      jcr->last_fname, crypto_strerror(err));
839                goto bail_out;
840             }
841          } else {   
842             /* Signature found, digest allocated.  Old method, 
843              * re-read the file and compute the digest
844              */
845             jcr->crypto.digest = digest;
846
847             /* Checksum the entire file */
848             /* Make sure we don't modify JobBytes by saving and restoring it */
849             saved_bytes = jcr->JobBytes;                     
850             if (find_one_file(jcr, jcr->ff, do_file_digest, jcr->last_fname, (dev_t)-1, 1) != 0) {
851                Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"), 
852                     jcr->last_fname);
853                jcr->JobBytes = saved_bytes;
854                goto bail_out;
855             }
856             jcr->JobBytes = saved_bytes;
857
858             /* Verify the signature */
859             if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
860                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
861                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
862                      jcr->last_fname, crypto_strerror(err));
863                goto bail_out;
864             }
865             jcr->crypto.digest = NULL;
866          }
867
868          /* Valid signature */
869          Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
870          crypto_digest_free(digest);
871          return true;
872
873       case CRYPTO_ERROR_NOSIGNER:
874          /* Signature not found, try again */
875          if (digest) {
876             crypto_digest_free(digest);
877             digest = NULL;
878          }
879          continue;
880       default:
881          /* Something strange happened (that shouldn't happen!)... */
882          Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
883          goto bail_out;
884       }
885    }
886
887    /* No signer */
888    Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
889
890 bail_out:
891    if (digest) {
892       crypto_digest_free(digest);
893    }
894    return false;
895 }
896
897 bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *length)
898 {
899       unser_declare;
900       uint64_t faddr;
901       char ec1[50];
902       unser_begin(*data, SPARSE_FADDR_SIZE);
903       unser_uint64(faddr);
904       if (*addr != faddr) {
905          *addr = faddr;
906          if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) {
907             berrno be;
908             Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
909                   edit_uint64(*addr, ec1), jcr->last_fname, 
910                   be.bstrerror(bfd->berrno));
911             return false;
912          }
913       }
914       *data += SPARSE_FADDR_SIZE;
915       *length -= SPARSE_FADDR_SIZE;
916       return true;
917 }
918
919 bool decompress_data(JCR *jcr, char **data, uint32_t *length)
920 {
921 #ifdef HAVE_LIBZ
922    uLong compress_len;
923    int stat;
924    char ec1[50];                      /* Buffer printing huge values */
925
926    /* 
927     * NOTE! We only use uLong and Byte because they are
928     *  needed by the zlib routines, they should not otherwise
929     *  be used in Bacula.
930     */
931    compress_len = jcr->compress_buf_size;
932    Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, *length);
933    if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
934                (const Byte *)*data, (uLong)*length)) != Z_OK) {
935       Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
936             jcr->last_fname, zlib_strerror(stat));
937       return false;
938    }
939    *data = jcr->compress_buf;
940    *length = compress_len;
941    Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
942    return true;
943 #else
944    Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
945    return false;
946 #endif
947 }
948
949 static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
950 {
951    unser_declare;
952    if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
953       unser_begin(&ctx->buf[0], CRYPTO_LEN_SIZE);
954       unser_uint32(ctx->packet_len);
955       ctx->packet_len += CRYPTO_LEN_SIZE;
956    }
957 }
958
959 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
960 {
961    if (jcr->crypto.digest) {
962       crypto_digest_update(jcr->crypto.digest, (uint8_t *)data, length);
963    }
964    if (win32_decomp) {
965       if (!processWin32BackupAPIBlock(bfd, data, length)) {
966          berrno be;
967          Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"), 
968                jcr->last_fname, be.bstrerror(bfd->berrno));
969          return false;
970       }
971    } else if (bwrite(bfd, data, length) != (ssize_t)length) {
972       berrno be;
973       Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), 
974             jcr->last_fname, be.bstrerror(bfd->berrno));
975       return false;
976    }
977
978    return true;
979 }
980
981 /*
982  * In the context of jcr, write data to bfd.
983  * We write buflen bytes in buf at addr. addr is updated in place.
984  * The flags specify whether to use sparse files or compression.
985  * Return value is the number of bytes written, or -1 on errors.
986  */
987 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
988       uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx)
989 {
990    char *wbuf;                        /* write buffer */
991    uint32_t wsize;                    /* write size */
992    uint32_t rsize;                    /* read size */
993    uint32_t decrypted_len = 0;        /* Decryption output length */
994    char ec1[50];                      /* Buffer printing huge values */
995
996    rsize = buflen;
997    jcr->ReadBytes += rsize;
998    wsize = rsize;
999    wbuf = buf;
1000
1001    if (flags & FO_ENCRYPT) {
1002       ASSERT(cipher_ctx->cipher);
1003
1004       /* NOTE: We must implement block preserving semantics for the
1005        * non-streaming compression and sparse code. */
1006
1007       /*
1008        * Grow the crypto buffer, if necessary.
1009        * crypto_cipher_update() will process only whole blocks,
1010        * buffering the remaining input.
1011        */
1012       cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, 
1013                         cipher_ctx->buf_len + wsize + cipher_ctx->block_size);
1014
1015       /* Decrypt the input block */
1016       if (!crypto_cipher_update(cipher_ctx->cipher, 
1017                                 (const u_int8_t *)wbuf, 
1018                                 wsize, 
1019                                 (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len], 
1020                                 &decrypted_len)) {
1021          /* Decryption failed. Shouldn't happen. */
1022          Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
1023          return -1;
1024       }
1025
1026       if (decrypted_len == 0) {
1027          /* No full block of encrypted data available, write more data */
1028          return 0;
1029       }
1030
1031       Dmsg2(100, "decrypted len=%d encrypted len=%d\n", decrypted_len, wsize);
1032
1033       cipher_ctx->buf_len += decrypted_len;
1034       wbuf = cipher_ctx->buf;
1035
1036       /* If one full preserved block is available, write it to disk,
1037        * and then buffer any remaining data. This should be effecient
1038        * as long as Bacula's block size is not significantly smaller than the
1039        * encryption block size (extremely unlikely!) */
1040       unser_crypto_packet_len(cipher_ctx);
1041       Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1042
1043       if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
1044          /* No full preserved block is available. */
1045          return 0;
1046       }
1047
1048       /* We have one full block, set up the filter input buffers */
1049       wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1050       wbuf = &wbuf[CRYPTO_LEN_SIZE]; /* Skip the block length header */
1051       cipher_ctx->buf_len -= cipher_ctx->packet_len;
1052       Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1053    }
1054
1055    if (flags & FO_SPARSE) {
1056       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1057          return -1;
1058       }
1059    }
1060
1061    if (flags & FO_GZIP) {
1062       if (!decompress_data(jcr, &wbuf, &wsize)) {
1063          return -1;
1064       }
1065    }
1066
1067    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1068       return -1;
1069    }
1070    jcr->JobBytes += wsize;
1071    *addr += wsize;
1072    Dmsg2(30, "Write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1073
1074    /* Clean up crypto buffers */
1075    if (flags & FO_ENCRYPT) {
1076       /* Move any remaining data to start of buffer */
1077       if (cipher_ctx->buf_len > 0) {
1078          Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1079          memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1080             cipher_ctx->buf_len);
1081       }
1082       /* The packet was successfully written, reset the length so that the next
1083        * packet length may be re-read by unser_crypto_packet_len() */
1084       cipher_ctx->packet_len = 0;
1085    }
1086
1087    return wsize;
1088 }
1089
1090 /*
1091  * In the context of jcr, flush any remaining data from the cipher context,
1092  * writing it to bfd.
1093  * Return value is true on success, false on failure.
1094  */
1095 bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
1096                   RESTORE_CIPHER_CTX *cipher_ctx)
1097 {
1098    uint32_t decrypted_len = 0;
1099    char *wbuf;                        /* write buffer */
1100    uint32_t wsize;                    /* write size */
1101    char ec1[50];                      /* Buffer printing huge values */
1102    bool second_pass = false;
1103
1104 again:
1105    /* Write out the remaining block and free the cipher context */
1106    cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len + 
1107                      cipher_ctx->block_size);
1108
1109    if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
1110         &decrypted_len)) {
1111       /* Writing out the final, buffered block failed. Shouldn't happen. */
1112       Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"), 
1113             cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
1114    }
1115
1116    Dmsg2(30, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
1117    /* If nothing new was decrypted, and our output buffer is empty, return */
1118    if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
1119       return true;
1120    }
1121
1122    cipher_ctx->buf_len += decrypted_len;
1123
1124    unser_crypto_packet_len(cipher_ctx);
1125    Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
1126    wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
1127    wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE]; /* Decrypted, possibly decompressed output here. */
1128    cipher_ctx->buf_len -= cipher_ctx->packet_len;
1129    Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
1130
1131    if (flags & FO_SPARSE) {
1132       if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
1133          return false;
1134       }
1135    }
1136
1137    if (flags & FO_GZIP) {
1138       if (!decompress_data(jcr, &wbuf, &wsize)) {
1139          return false;
1140       }
1141    }
1142
1143    Dmsg0(30, "Call store_data\n");
1144    if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
1145       return false;
1146    }
1147    jcr->JobBytes += wsize;
1148    Dmsg2(30, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
1149
1150    /* Move any remaining data to start of buffer */
1151    if (cipher_ctx->buf_len > 0) {
1152       Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
1153       memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len], 
1154          cipher_ctx->buf_len);
1155    }
1156    /* The packet was successfully written, reset the length so that the next
1157     * packet length may be re-read by unser_crypto_packet_len() */
1158    cipher_ctx->packet_len = 0;
1159
1160    if (cipher_ctx->buf_len >0 && !second_pass) {
1161       second_pass = true;
1162       goto again;
1163    }
1164
1165    /* Stop decryption */
1166    cipher_ctx->buf_len = 0;
1167    cipher_ctx->packet_len = 0;
1168
1169    return true;
1170 }
1171
1172 static void deallocate_cipher(r_ctx &rctx)
1173 {
1174    /* Flush and deallocate previous stream's cipher context */
1175    if (rctx.cipher_ctx.cipher) {
1176       flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx);
1177       crypto_cipher_free(rctx.cipher_ctx.cipher);
1178       rctx.cipher_ctx.cipher = NULL;
1179    }
1180 }
1181
1182 static void deallocate_fork_cipher(r_ctx &rctx)
1183 {
1184
1185    /* Flush and deallocate previous stream's fork cipher context */
1186    if (rctx.fork_cipher_ctx.cipher) {
1187       flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx);
1188       crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
1189       rctx.fork_cipher_ctx.cipher = NULL;
1190    }
1191 }
1192
1193 static void free_signature(r_ctx &rctx)
1194 {
1195    if (rctx.sig) {
1196       crypto_sign_free(rctx.sig);
1197       rctx.sig = NULL;
1198    }
1199 }
1200
1201 static void free_session(r_ctx &rctx)
1202 {
1203    if (rctx.cs) {
1204       crypto_session_free(rctx.cs);
1205       rctx.cs = NULL;
1206    }
1207 }
1208
1209
1210 /* This code if implemented goes above */
1211 #ifdef stbernard_implemented
1212 /  #if defined(HAVE_WIN32)
1213    bool        bResumeOfmOnExit = FALSE;
1214    if (isOpenFileManagerRunning()) {
1215        if ( pauseOpenFileManager() ) {
1216           Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
1217           bResumeOfmOnExit = TRUE;
1218        }
1219        else {
1220           Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
1221        }
1222    }
1223    {
1224        char username[UNLEN+1];
1225        DWORD usize = sizeof(username);
1226        int privs = enable_backup_privileges(NULL, 1);
1227        if (GetUserName(username, &usize)) {
1228           Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
1229        } else {
1230           Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));
1231        }
1232    }
1233 #endif