]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/restore.c
Don't attempt signature validation on non-files
[bacula/bacula] / bacula / src / filed / restore.c
1 /*
2  *  Bacula File Daemon  restore.c Restorefiles.
3  *
4  *    Kern Sibbald, November MM
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2005 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "filed.h"
26
27 #ifdef HAVE_DARWIN_OS
28 #include <sys/attr.h>
29 #endif
30
31 /* Data received from Storage Daemon */
32 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
33
34 /* Forward referenced functions */
35 #ifdef HAVE_LIBZ
36 static const char *zlib_strerror(int stat);
37 #endif
38
39 int verify_signature(JCR *jcr, SIGNATURE *sig);
40 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
41       uint64_t *addr, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size);
42 bool flush_cipher(JCR *jcr, BFILE *bfd, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size);
43
44 #define RETRY 10                      /* retry wait time */
45
46 /*
47  * Close a bfd check that we are at the expected file offset.
48  * Makes some code in set_attributes().
49  */
50 int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
51 {
52    char ec1[50], ec2[50];
53    off_t fsize;
54
55    fsize = blseek(bfd, 0, SEEK_CUR);
56    bclose(bfd);                              /* first close file */
57    if (fsize > 0 && fsize != osize) {
58       Qmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
59             jcr->last_fname, edit_uint64(osize, ec1),
60             edit_uint64(fsize, ec2));
61       return -1;
62    }
63    return 0;
64 }
65
66 /*
67  * Restore the requested files.
68  *
69  */
70 void do_restore(JCR *jcr)
71 {
72    BSOCK *sd;
73    int32_t stream = 0;
74    int32_t prev_stream;
75    uint32_t VolSessionId, VolSessionTime;
76    bool extract = false;
77    int32_t file_index;
78    char ec1[50];                      /* Buffer printing huge values */
79
80    BFILE bfd;                         /* File content */
81    uint64_t fileAddr = 0;             /* file write address */
82    uint32_t size;                     /* Size of file */
83    BFILE altbfd;                      /* Alternative data stream */
84    uint64_t alt_addr = 0;             /* Write address for alternative stream */
85    intmax_t alt_size = 0;             /* Size of alternate stream */
86    SIGNATURE *sig = NULL;             /* Cryptographic signature (if any) for file */
87    CRYPTO_SESSION *cs = NULL;         /* Cryptographic session data (if any) for file */
88    CIPHER_CONTEXT *cipher_ctx = NULL; /* Cryptographic cipher context (if any) for file */
89    size_t cipher_block_size = 0;      /* Cryptographic algorithm block size for file */
90    int flags = 0;                     /* Options for extract_data() */
91    int stat;
92    ATTR *attr;
93
94    /* The following variables keep track of "known unknowns" */
95    int non_support_data = 0;
96    int non_support_attr = 0;
97    int non_support_rsrc = 0;
98    int non_support_finfo = 0;
99    int non_support_acl = 0;
100    int non_support_progname = 0;
101
102    /* Finally, set up for special configurations */
103 #ifdef HAVE_DARWIN_OS
104    intmax_t rsrc_len = 0;             /* Original length of resource fork */
105    struct attrlist attrList;
106
107    memset(&attrList, 0, sizeof(attrList));
108    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
109    attrList.commonattr = ATTR_CMN_FNDRINFO;
110 #endif
111
112    sd = jcr->store_bsock;
113    set_jcr_job_status(jcr, JS_Running);
114
115    LockRes();
116    CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
117    UnlockRes();
118    uint32_t buf_size;
119    if (client) {
120       buf_size = client->max_network_buffer_size;
121    } else {
122       buf_size = 0;                   /* use default */
123    }
124    if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
125       set_jcr_job_status(jcr, JS_ErrorTerminated);
126       return;
127    }
128    jcr->buf_size = sd->msglen;
129
130 #ifdef HAVE_LIBZ
131    uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
132    jcr->compress_buf = (char *)bmalloc(compress_buf_size);
133    jcr->compress_buf_size = compress_buf_size;
134 #endif
135
136 #ifdef HAVE_CRYPTO
137    jcr->crypto_buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
138 #endif
139    
140    /*
141     * Get a record from the Storage daemon. We are guaranteed to
142     *   receive records in the following order:
143     *   1. Stream record header
144     *   2. Stream data
145     *        a. Attributes (Unix or Win32)
146     *        b. Possibly stream encryption session data (e.g., symmetric session key)
147     *    or  c. File data for the file
148     *    or  d. Alternate data stream (e.g. Resource Fork)
149     *    or  e. Finder info
150     *    or  f. ACLs
151     *    or  g. Possibly a cryptographic signature
152     *    or  h. Possibly MD5 or SHA1 record
153     *   3. Repeat step 1
154     *
155     * NOTE: We keep track of two bacula file descriptors:
156     *   1. bfd for file data.
157     *      This fd is opened for non empty files when an attribute stream is
158     *      encountered and closed when we find the next attribute stream.
159     *   2. alt_bfd for alternate data streams
160     *      This fd is opened every time we encounter a new alternate data
161     *      stream for the current file. When we find any other stream, we
162     *      close it again.
163     *      The expected size of the stream, alt_len, should be set when
164     *      opening the fd.
165     */
166    binit(&bfd);
167    binit(&altbfd);
168    attr = new_attr();
169    jcr->acl_text = get_pool_memory(PM_MESSAGE);
170
171    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
172       /* Remember previous stream type */
173       prev_stream = stream;
174
175       /* First we expect a Stream Record Header */
176       if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
177           &stream, &size) != 5) {
178          Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
179          goto bail_out;
180       }
181       Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
182
183       /* * Now we expect the Stream Data */
184       if (bget_msg(sd) < 0) {
185          Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
186          goto bail_out;
187       }
188       if (size != (uint32_t)sd->msglen) {
189          Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
190          goto bail_out;
191       }
192       Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
193
194       /* If we change streams, close and reset alternate data streams */
195       if (prev_stream != stream) {
196          if (is_bopen(&altbfd)) {
197             bclose_chksize(jcr, &altbfd, alt_size);
198          }
199          alt_size = -1; /* Use an impossible value and set a proper one below */
200          alt_addr = 0;
201       }
202
203       /* File Attributes stream */
204       switch (stream) {
205       case STREAM_UNIX_ATTRIBUTES:
206       case STREAM_UNIX_ATTRIBUTES_EX:
207          Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
208          /*
209           * If extracting, it was from previous stream, so
210           * close the output file and validate the signature.
211           */
212          if (extract) {
213             if (size > 0 && !is_bopen(&bfd)) {
214                Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
215             }
216             /* Flush and deallocate previous stream's cipher context */
217             if (cipher_ctx && prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
218                flush_cipher(jcr, &bfd, flags, cipher_ctx, cipher_block_size);
219                crypto_cipher_free(cipher_ctx);
220                cipher_ctx = NULL;
221             }
222             set_attributes(jcr, attr, &bfd);
223             extract = false;
224
225             /* Verify the cryptographic signature, if any */
226             if (jcr->pki_sign) {
227                if (sig) {
228                   // Failure is reported in verify_signature() ...
229                   verify_signature(jcr, sig);
230                } else {
231                   Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
232                }
233             }
234             /* Free Signature */
235             if (sig) {
236                crypto_sign_free(sig);
237                sig = NULL;
238             }
239             if (cs) {
240                crypto_session_free(cs);
241                cs = NULL;
242             }
243             Dmsg0(30, "Stop extracting.\n");
244          } else if (is_bopen(&bfd)) {
245             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
246             bclose(&bfd);
247          }
248
249          /*
250           * Unpack and do sanity check fo attributes.
251           */
252          if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
253             goto bail_out;
254          }
255          if (file_index != attr->file_index) {
256             Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
257                  file_index, attr->file_index);
258             Dmsg0(100, "File index error\n");
259             goto bail_out;
260          }
261
262          Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
263                attr->attr, attr->attrEx);
264
265          attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
266
267          if (!is_restore_stream_supported(attr->data_stream)) {
268             if (!non_support_data++) {
269                Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
270                   stream_to_ascii(attr->data_stream));
271             }
272             continue;
273          }
274
275          build_attr_output_fnames(jcr, attr);
276
277          /*
278           * Now determine if we are extracting or not.
279           */
280          jcr->num_files_examined++;
281          Dmsg1(30, "Outfile=%s\n", attr->ofname);
282          extract = false;
283          stat = create_file(jcr, attr, &bfd, jcr->replace);
284          switch (stat) {
285          case CF_ERROR:
286          case CF_SKIP:
287             break;
288          case CF_EXTRACT:        /* File created and we expect file data */
289             extract = true;
290             /* FALLTHROUGH */
291          case CF_CREATED:        /* File created, but there is no content */
292             P(jcr->mutex);
293             pm_strcpy(jcr->last_fname, attr->ofname);
294             V(jcr->mutex);
295             jcr->JobFiles++;
296             fileAddr = 0;
297             print_ls_output(jcr, attr);
298 #ifdef HAVE_DARWIN_OS
299             /* Only restore the resource fork for regular files */
300             from_base64(&rsrc_len, attr->attrEx);
301             if (attr->type == FT_REG && rsrc_len > 0) {
302                extract = true;
303             }
304 #endif
305             if (!extract) {
306                /* set attributes now because file will not be extracted */
307                set_attributes(jcr, attr, &bfd);
308             }
309             break;
310          }
311          break;
312
313       /* Data stream */
314       case STREAM_ENCRYPTED_SESSION_DATA:
315          crypto_error_t cryptoerr;
316
317          Dmsg1(30, "Stream=Encrypted Session Data, size: %d\n", sd->msglen);
318
319          /* Decode and save session keys. */
320          cryptoerr = crypto_session_decode(sd->msg, (size_t) sd->msglen, jcr->pki_recipients, &cs);
321          switch(cryptoerr) {
322          case CRYPTO_ERROR_NONE:
323             /* Success */
324             break;
325          case CRYPTO_ERROR_NORECIPIENT:
326             Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data."));
327             break;
328          case CRYPTO_ERROR_DECRYPTION:
329             Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed."));
330             break;
331          default:
332             /* Shouldn't happen */
333             Jmsg1(jcr, M_ERROR, 0, _("An error occured while decoding encrypted session data stream: %s"), crypto_strerror(cryptoerr));
334             break;
335          }
336
337          if (cryptoerr != CRYPTO_ERROR_NONE) {
338             extract = false;
339             bclose(&bfd);
340             continue;
341          }
342
343          /* Set up a decryption context */
344          if ((cipher_ctx = crypto_cipher_new(cs, false, &cipher_block_size)) == NULL) {
345             Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
346             crypto_session_free(cs);
347             cs = NULL;
348             extract = false;
349             bclose(&bfd);
350             continue;
351          }
352          break;
353
354       case STREAM_FILE_DATA:
355       case STREAM_SPARSE_DATA:
356       case STREAM_WIN32_DATA:
357       case STREAM_GZIP_DATA:
358       case STREAM_SPARSE_GZIP_DATA:
359       case STREAM_WIN32_GZIP_DATA:
360       case STREAM_ENCRYPTED_FILE_DATA:
361       case STREAM_ENCRYPTED_WIN32_DATA:
362       case STREAM_ENCRYPTED_FILE_GZIP_DATA:
363       case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
364          /* Force an expected, consistent stream type here */
365          if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
366                   || prev_stream == STREAM_UNIX_ATTRIBUTES_EX
367                   || prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
368             flags = 0;
369
370             if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
371                flags |= FO_SPARSE;
372             }
373
374             if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
375                   || stream == STREAM_WIN32_GZIP_DATA || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
376                   || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
377                flags |= FO_GZIP;
378             }
379
380             if (stream == STREAM_ENCRYPTED_FILE_DATA
381                   || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
382                   || stream == STREAM_ENCRYPTED_WIN32_DATA
383                   || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
384                flags |= FO_ENCRYPT;
385             }
386
387             if (is_win32_stream(stream) && !have_win32_api()) {
388                set_portable_backup(&bfd);
389                flags |= FO_WIN32DECOMP;    /* "decompose" BackupWrite data */
390             }
391
392             if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags, cipher_ctx, cipher_block_size) < 0) {
393                extract = false;
394                bclose(&bfd);
395                continue;
396             }
397          }
398          break;
399
400       /* Resource fork stream - only recorded after a file to be restored */
401       /* Silently ignore if we cannot write - we already reported that */
402       case STREAM_ENCRYPTED_MACOS_FORK_DATA:
403          flags |= FO_ENCRYPT;
404       case STREAM_MACOS_FORK_DATA:
405 #ifdef HAVE_DARWIN_OS
406          if (extract) {
407             if (prev_stream != stream) {
408                if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
409                   Jmsg(jcr, M_ERROR, 0, _("     Cannot open resource fork for %s.\n"), jcr->last_fname);
410                   extract = false;
411                   continue;
412                }
413                alt_size = rsrc_len;
414                Dmsg0(30, "Restoring resource fork\n");
415             }
416             flags = 0;
417             if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags, cipher_ctx, cipher_block_size) < 0) {
418                extract = false;
419                bclose(&altbfd);
420                continue;
421             }
422          }
423 #else
424          non_support_rsrc++;
425 #endif
426          break;
427
428       case STREAM_HFSPLUS_ATTRIBUTES:
429 #ifdef HAVE_DARWIN_OS
430          Dmsg0(30, "Restoring Finder Info\n");
431          if (sd->msglen != 32) {
432             Jmsg(jcr, M_ERROR, 0, _("     Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
433             continue;
434          }
435          if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
436             Jmsg(jcr, M_ERROR, 0, _("     Could not set Finder Info on %s\n"), jcr->last_fname);
437             continue;
438          }
439 #else
440          non_support_finfo++;
441 #endif
442
443       case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
444 #ifdef HAVE_ACL
445          pm_strcpy(jcr->acl_text, sd->msg);
446          Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
447          if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
448                Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
449          }
450 #else 
451          non_support_acl++;
452 #endif
453          break;
454
455       case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
456 #ifdef HAVE_ACL
457          pm_strcpy(jcr->acl_text, sd->msg);
458          Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
459          if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
460                Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
461          }
462 #else 
463          non_support_acl++;
464 #endif
465          break;
466
467       case STREAM_SIGNED_DIGEST:
468          /* Save signature. */
469          if ((sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen)) == NULL) {
470             Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname);
471          }
472          break;
473
474       case STREAM_MD5_DIGEST:
475       case STREAM_SHA1_DIGEST:
476       case STREAM_SHA256_DIGEST:
477       case STREAM_SHA512_DIGEST:
478          break;
479
480       case STREAM_PROGRAM_NAMES:
481       case STREAM_PROGRAM_DATA:
482          if (!non_support_progname) {
483             Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
484             non_support_progname++;
485          }
486          break;
487
488       default:
489          /* If extracting, wierd stream (not 1 or 2), close output file anyway */
490          if (extract) {
491             Dmsg1(30, "Found wierd stream %d\n", stream);
492             if (size > 0 && !is_bopen(&bfd)) {
493                Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
494             }
495             /* Flush and deallocate cipher context */
496             if (cipher_ctx) {
497                flush_cipher(jcr, &bfd, flags, cipher_ctx, cipher_block_size);
498                crypto_cipher_free(cipher_ctx);
499                cipher_ctx = NULL;
500             }
501             set_attributes(jcr, attr, &bfd);
502
503             /* Verify the cryptographic signature if any */
504             if (jcr->pki_sign) {
505                if (sig) {
506                   // Failure is reported in verify_signature() ...
507                   verify_signature(jcr, sig);
508                } else {
509                   Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
510                }
511             }
512
513             extract = false;
514          } else if (is_bopen(&bfd)) {
515             Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
516             bclose(&bfd);
517          }
518          Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
519          Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
520          break;
521       } /* end switch(stream) */
522
523    } /* end while get_msg() */
524
525    /* If output file is still open, it was the last one in the
526     * archive since we just hit an end of file, so close the file.
527     */
528    if (is_bopen(&altbfd)) {
529       bclose_chksize(jcr, &altbfd, alt_size);
530    }
531    if (extract) {
532       /* Flush and deallocate cipher context */
533       if (cipher_ctx) {
534          flush_cipher(jcr, &bfd, flags, cipher_ctx, cipher_block_size);
535          crypto_cipher_free(cipher_ctx);
536          cipher_ctx = NULL;
537       }
538       set_attributes(jcr, attr, &bfd);
539
540       /* Verify the cryptographic signature on the last file, if any */
541       if (jcr->pki_sign) {
542          if (sig) {
543             // Failure is reported in verify_signature() ...
544             verify_signature(jcr, sig);
545          } else {
546             Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
547          }
548       }
549    }
550
551    if (is_bopen(&bfd)) {
552       bclose(&bfd);
553    }
554
555    set_jcr_job_status(jcr, JS_Terminated);
556    goto ok_out;
557
558 bail_out:
559    set_jcr_job_status(jcr, JS_ErrorTerminated);
560 ok_out:
561
562    /* Free Signature & Crypto Data */
563    if (sig) {
564       crypto_sign_free(sig);
565       sig = NULL;
566    }
567    if (cs) {
568       crypto_session_free(cs);
569       cs = NULL;
570    }
571    if (cipher_ctx) {
572       crypto_cipher_free(cipher_ctx);
573       cipher_ctx = NULL;
574    }
575    if (jcr->compress_buf) {
576       free(jcr->compress_buf);
577       jcr->compress_buf = NULL;
578       jcr->compress_buf_size = 0;
579    }
580    if (jcr->crypto_buf) {
581       free_pool_memory(jcr->crypto_buf);
582       jcr->crypto_buf = NULL;
583    }
584    bclose(&altbfd);
585    bclose(&bfd);
586    free_attr(attr);
587    free_pool_memory(jcr->acl_text);
588    Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
589       edit_uint64(jcr->JobBytes, ec1));
590    if (non_support_data > 1 || non_support_attr > 1) {
591       Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
592          non_support_data, non_support_attr);
593    }
594    if (non_support_rsrc) {
595       Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
596    }
597    if (non_support_finfo) {
598       Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
599    }
600    if (non_support_acl) {
601       Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
602    }
603
604 }
605
606 #ifdef HAVE_LIBZ
607 /*
608  * Convert ZLIB error code into an ASCII message
609  */
610 static const char *zlib_strerror(int stat)
611 {
612    if (stat >= 0) {
613       return _("None");
614    }
615    switch (stat) {
616    case Z_ERRNO:
617       return _("Zlib errno");
618    case Z_STREAM_ERROR:
619       return _("Zlib stream error");
620    case Z_DATA_ERROR:
621       return _("Zlib data error");
622    case Z_MEM_ERROR:
623       return _("Zlib memory error");
624    case Z_BUF_ERROR:
625       return _("Zlib buffer error");
626    case Z_VERSION_ERROR:
627       return _("Zlib version error");
628    default:
629       return _("*none*");
630    }
631 }
632 #endif
633
634 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level) {
635    JCR *jcr = (JCR *) pkt;
636    return (digest_file(jcr, ff_pkt, jcr->digest));
637 }
638
639 /*
640  * Verify the signature for the last restored file
641  * Return value is either true (signature correct)
642  * or false (signature could not be verified).
643  * TODO landonf: Better signature failure handling.
644  */
645 int verify_signature(JCR *jcr, SIGNATURE *sig)
646 {
647    X509_KEYPAIR *keypair;
648    DIGEST *digest = NULL;
649    crypto_error_t err;
650
651    /* Iterate through the trusted signers */
652    foreach_alist(keypair, jcr->pki_signers) {
653       err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
654
655       switch (err) {
656       case CRYPTO_ERROR_NONE:
657          /* Signature found, digest allocated */
658          jcr->digest = digest;
659
660          /* Checksum the entire file */
661          if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
662             Qmsg(jcr, M_ERROR, 0, _("Signature validation failed for %s: \n"), jcr->last_fname);
663             return false;
664          }
665
666          /* Verify the signature */
667          if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
668             Dmsg1(100, "Bad signature on %s\n", jcr->last_fname);
669             Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
670             crypto_digest_free(digest);
671             return false;
672          }
673
674          /* Valid signature */
675          Dmsg1(100, "Signature good on %s\n", jcr->last_fname);
676          crypto_digest_free(digest);
677          return true;
678
679       case CRYPTO_ERROR_NOSIGNER:
680          /* Signature not found, try again */
681          continue;
682       default:
683          /* Something strange happened (that shouldn't happen!)... */
684          Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
685          if (digest) {
686             crypto_digest_free(digest);
687          }
688          return false;
689       }
690    }
691
692    /* No signer */
693    Dmsg1(100, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
694    crypto_digest_free(digest);
695    return false;
696 }
697
698 /*
699  * In the context of jcr, write data to bfd.
700  * We write buflen bytes in buf at addr. addr is updated in place.
701  * The flags specify whether to use sparse files or compression.
702  * Return value is the number of bytes written, or -1 on errors.
703  */
704 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
705       uint64_t *addr, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size)
706 {
707    int stat;
708    char *wbuf;                        /* write buffer */
709    uint32_t wsize;                    /* write size */
710    uint32_t rsize;                    /* read size */
711    char ec1[50];                      /* Buffer printing huge values */
712    const void *cipher_input;          /* Decryption input */
713    size_t cipher_input_len;           /* Decryption input length */
714    size_t decrypted_len = 0;          /* Decryption output length */
715
716    if (flags & FO_SPARSE) {
717       ser_declare;
718       uint64_t faddr;
719       char ec1[50];
720       wbuf = buf + SPARSE_FADDR_SIZE;
721       rsize = buflen - SPARSE_FADDR_SIZE;
722       ser_begin(buf, SPARSE_FADDR_SIZE);
723       unser_uint64(faddr);
724       if (*addr != faddr) {
725          *addr = faddr;
726          if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
727             berrno be;
728             Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
729                   edit_uint64(*addr, ec1), jcr->last_fname, 
730                   be.strerror(bfd->berrno));
731             return -1;
732          }
733       }
734    } else {
735       wbuf = buf;
736       rsize = buflen;
737    }
738    wsize = rsize;
739    cipher_input = wbuf;
740    cipher_input_len = wsize;
741
742    if (flags & FO_GZIP) {
743 #ifdef HAVE_LIBZ
744       uLong compress_len;
745       /* 
746        * NOTE! We only use uLong and Byte because they are
747        *  needed by the zlib routines, they should not otherwise
748        *  be used in Bacula.
749        */
750       compress_len = jcr->compress_buf_size;
751       Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
752       if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
753                   (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
754          Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
755                jcr->last_fname, zlib_strerror(stat));
756          return -1;
757       }
758       wbuf = jcr->compress_buf;
759       wsize = compress_len;
760       cipher_input = jcr->compress_buf; /* decrypt decompressed data */
761       cipher_input_len = compress_len;
762       Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
763 #else
764       Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
765       return -1;
766 #endif
767    } else {
768       Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
769    }
770
771    if (flags & FO_ENCRYPT) {
772       ASSERT(cipher);
773
774       /*
775        * Grow the crypto buffer, if necessary.
776        * crypto_cipher_update() will process only whole blocks,
777        * buffering the remaining input.
778        */
779       jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, cipher_input_len + cipher_block_size);
780
781
782       /* Encrypt the input block */
783       if (!crypto_cipher_update(cipher, cipher_input, cipher_input_len, jcr->crypto_buf, &decrypted_len)) {
784          /* Decryption failed. Shouldn't happen. */
785          Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
786          return -1;
787       }
788
789       if (decrypted_len == 0) {
790          /* No full block of data available, write more data */
791          goto ok;
792       }
793
794       Dmsg2(400, "decrypted len=%d undecrypted len=%d\n",
795          decrypted_len, cipher_input_len);
796       wsize = decrypted_len;
797       wbuf = jcr->crypto_buf; /* Decrypted, possibly decompressed output here. */
798    }
799
800
801    if (flags & FO_WIN32DECOMP) {
802       if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
803          berrno be;
804          Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"), 
805                jcr->last_fname, be.strerror(bfd->berrno));
806          return -1;
807       }
808    } else if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
809       berrno be;
810       Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), 
811             jcr->last_fname, be.strerror(bfd->berrno));
812       return -1;
813    }
814
815    if (decrypted_len && decrypted_len > wsize) {
816       /* If more than wsize is output, it was previously buffered
817        * and reported, and should not be reported again */
818       wsize = wsize - decrypted_len;
819    }
820
821 ok:
822    jcr->JobBytes += wsize;
823    jcr->ReadBytes += rsize;
824    *addr += wsize;
825
826    return wsize;
827 }
828
829 /*
830  * In the context of jcr, flush any remaining data from the cipher context,
831  * writing it to bfd.
832  * Return value is true on success, false on failure.
833  */
834 bool flush_cipher(JCR *jcr, BFILE *bfd, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size)
835 {
836    size_t decrypted_len;
837
838    /* Write out the remaining block and free the cipher context */
839    jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, cipher_block_size);
840
841    if (!crypto_cipher_finalize(cipher, jcr->crypto_buf, &decrypted_len)) {
842       /* Writing out the final, buffered block failed. Shouldn't happen. */
843       Jmsg1(jcr, M_FATAL, 0, _("Decryption error for %s\n"), jcr->last_fname);
844    }
845
846    if (flags & FO_WIN32DECOMP) {
847       if (!processWin32BackupAPIBlock(bfd, jcr->crypto_buf, decrypted_len)) {
848          berrno be;
849          Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"), 
850                jcr->last_fname, be.strerror(bfd->berrno));
851          return false;
852       }
853    } else if (bwrite(bfd, jcr->crypto_buf, decrypted_len) != (ssize_t)decrypted_len) {
854       berrno be;
855       Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), 
856             jcr->last_fname, be.strerror(bfd->berrno));
857       return false;
858    }
859
860    return true;
861 }