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