} else if (crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
          Dmsg2(400, "stream=Digest inx=%d Digest=%s\n", file_index, Opts_Digest);
          /*
-          * When ever we get a digest is MUST have been
+          * When ever we get a digest it MUST have been
           * preceded by an attributes record, which sets attr_file_index
           */
          if (jcr->FileIndex != (uint32_t)file_index) {
 
 
       /* Allocate buffer */
       jcr->pki_session_encoded = (uint8_t *)malloc(size);
-      if (!jcr->pki_session_encoded) {
-         return 0;
-      }
 
       /* Encode session data */
       if (crypto_session_encode(jcr->pki_session, jcr->pki_session_encoded, &size) == false) {
 
    stop_heartbeat_monitor(jcr);
 
-   bnet_sig(sd, BNET_EOD);            /* end of sending data */
+   sd->signal(BNET_EOD);            /* end of sending data */
 
    if (jcr->big_buf) {
       free(jcr->big_buf);
    }
    if (jcr->pki_session_encoded) {
       free(jcr->pki_session_encoded);
+      jcr->pki_session_encoded = NULL;
    }
 
    Dmsg1(100, "end blast_data ok=%d\n", ok);
    DIGEST *signing_digest = NULL;
    int digest_stream = STREAM_NONE;
    SIGNATURE *sig = NULL;
-   uint8_t *buf = NULL;
    bool has_file_data = false;
    // TODO landonf: Allow the user to specify the digest algorithm
 #ifdef HAVE_SHA2
    if (has_file_data) {
       /*
        * Setup for digest handling. If this fails, the digest will be set to NULL
-       * and not used.
+       * and not used. Note, the digest (file hash) can be any one of the four
+       * algorithms below.
+       *
+       * The signing digest is a single algorithm depending on
+       * whether or not we have SHA2.              
+       *   ****FIXME****  the signing algoritm should really be
+       *   determined a different way!!!!!!  What happens if
+       *   sha2 was available during backup but not restore?
        */
       if (ff_pkt->flags & FO_MD5) {
          digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5);
    if (has_file_data && jcr->pki_encrypt) {
       /* Send our header */
       Dmsg2(100, "Send hdr fi=%ld stream=%d\n", jcr->JobFiles, STREAM_ENCRYPTED_SESSION_DATA);
-      bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_ENCRYPTED_SESSION_DATA);
+      sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_ENCRYPTED_SESSION_DATA);
 
       /* Grow the bsock buffer to fit our message if necessary */
       if (sizeof_pool_memory(sd->msg) < jcr->pki_session_encoded_size) {
       jcr->JobBytes += sd->msglen;
 
       Dmsg1(100, "Send data len=%d\n", sd->msglen);
-      bnet_send(sd);
-      bnet_sig(sd, BNET_EOD);
+      sd->send();
+      sd->signal(BNET_EOD);
    }
 
    /*
       }
 
       Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
-      bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
+      sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
       Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
       memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
       sd->msglen = 32;
       if (signing_digest) {
          crypto_digest_update(signing_digest, (uint8_t *)sd->msg, sd->msglen);
       }
-      bnet_send(sd);
-      bnet_sig(sd, BNET_EOD);
+      sd->send();
+      sd->signal(BNET_EOD);
    }
 #endif
 
          goto bail_out;
       }
 
-      if (crypto_sign_add_signer(sig, signing_digest, jcr->pki_keypair) == false) {
+      if (!crypto_sign_add_signer(sig, signing_digest, jcr->pki_keypair)) {
          Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
          goto bail_out;
       }
 
       /* Get signature size */
-      if (crypto_sign_encode(sig, NULL, &size) == false) {
+      if (!crypto_sign_encode(sig, NULL, &size)) {
          Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
          goto bail_out;
       }
 
-      /* Allocate signature data buffer */
-      buf = (uint8_t *)malloc(size);
-      if (!buf) {
-         goto bail_out;
-      }
-
-      /* Encode signature data */
-      if (crypto_sign_encode(sig, buf, &size) == false) {
-         Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
-         goto bail_out;
+      /* Grow the bsock buffer to fit our message if necessary */
+      if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
+         sd->msg = realloc_pool_memory(sd->msg, size);
       }
 
       /* Send our header */
-      bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_SIGNED_DIGEST);
+      sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_SIGNED_DIGEST);
       Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
 
-      /* Grow the bsock buffer to fit our message if necessary */
-      if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
-         sd->msg = realloc_pool_memory(sd->msg, size);
+      /* Encode signature data */
+      if (!crypto_sign_encode(sig, (uint8_t *)sd->msg, &size)) {
+         Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
+         goto bail_out;
       }
 
-      /* Copy our message over and send it */
-      memcpy(sd->msg, buf, size);
       sd->msglen = size;
-      bnet_send(sd);
-      bnet_sig(sd, BNET_EOD);              /* end of checksum */
+      sd->send();
+      sd->signal(BNET_EOD);              /* end of checksum */
    }
 
    /* Terminate any digest and send it to Storage daemon and the Director */
    if (digest) {
-      uint8_t md[CRYPTO_DIGEST_MAX_SIZE];
       uint32_t size;
 
-      size = sizeof(md);
+      sd->fsend("%ld %d 0", jcr->JobFiles, digest_stream);
+      Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
+
+      size = sizeof(CRYPTO_DIGEST_MAX_SIZE);
+      /* Grow the bsock buffer to fit our message if necessary */
+      if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
+         sd->msg = realloc_pool_memory(sd->msg, size);
+      }
 
-      if (crypto_digest_finalize(digest, md, &size)) {
-         bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, digest_stream);
-         Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
-         memcpy(sd->msg, md, size);
-         sd->msglen = size;
-         bnet_send(sd);
-         bnet_sig(sd, BNET_EOD);              /* end of checksum */
+      if (!crypto_digest_finalize(digest, (uint8_t *)sd->msg, &size)) {
+         Jmsg(jcr, M_FATAL, 0, _("An error occurred finalizing signing the stream.\n"));
+         goto bail_out;
       }
+
+      sd->msglen = size;
+      sd->send();
+      sd->signal(BNET_EOD);              /* end of checksum */
    }
 
 good_rtn:
    if (sig) {
       crypto_sign_free(sig);        
    }
-   if (buf) {
-      free(buf);
-   }
    return rtnstat;
 }
 
     * Send Data header to Storage daemon
     *    <file-index> <stream> <info>
     */
-   if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
+   if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       goto err;
    }
    Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
          sd->msglen += SPARSE_FADDR_SIZE; /* include fileAddr in size */
       }
       sd->msg = wbuf;              /* set correct write buffer */
-      if (!bnet_send(sd)) {
+      if (!sd->send()) {
          Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-               bnet_strerror(sd));
+               sd->bstrerror());
          goto err;
       }
       Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
       if (encrypted_len > 0) {
          sd->msglen = encrypted_len;      /* set encrypted length */
          sd->msg = jcr->crypto_buf;       /* set correct write buffer */
-         if (!bnet_send(sd)) {
+         if (!sd->send()) {
             Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-                  bnet_strerror(sd));
+                  sd->bstrerror());
             goto err;
          }
          Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
       }
    }
 
-   if (!bnet_sig(sd, BNET_EOD)) {        /* indicate end of file data */
+   if (!sd->signal(BNET_EOD)) {        /* indicate end of file data */
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       goto err;
    }
 
    }
 
    /* Send header */
-   if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
+   if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       return false;
    }
 
    msgsave = sd->msg;
    sd->msg = jcr->acl_text;
    sd->msglen = len + 1;
-   if (!bnet_send(sd)) {
+   if (!sd->send()) {
       sd->msg = msgsave;
       sd->msglen = 0;
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       return false;
    }
 
    jcr->JobBytes += sd->msglen;
    sd->msg = msgsave;
-   if (!bnet_sig(sd, BNET_EOD)) {
+   if (!sd->signal(BNET_EOD)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       return false;
    }
 
     * Send Attributes header to Storage daemon
     *    <file-index> <stream> <info>
     */
-   if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, attr_stream)) {
+   if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       return false;
    }
    Dmsg1(300, ">stored: attrhdr %s\n", sd->msg);
    strip_path(ff_pkt);
    if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
       Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link);
-      stat = bnet_fsend(sd, "%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles,
+      stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles,
                ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0,
                attribsEx, 0);
    } else if (ff_pkt->type == FT_DIREND) {
       /* Here link is the canonical filename (i.e. with trailing slash) */
-      stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
+      stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
                ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
    } else {
-      stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
+      stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
                ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0);
    }
    unstrip_path(ff_pkt);
    Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
    if (!stat) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            bnet_strerror(sd));
+            sd->bstrerror());
       return false;
    }
-   bnet_sig(sd, BNET_EOD);            /* indicate end of attributes data */
+   sd->signal(BNET_EOD);            /* indicate end of attributes data */
    return true;
 }
 
 
 const bool have_acl = false;
 #endif
 
+#ifdef HAVE_SHA2
+   const bool have_sha2 = true;
+#else
+   const bool have_sha2 = false;
+#endif
+
+
 /* Data received from Storage Daemon */
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
 
    SIGNATURE *sig;                     /* Cryptographic signature (if any) for file */
    CRYPTO_SESSION *cs;                 /* Cryptographic session data (if any) for file */
-   RESTORE_CIPHER_CTX cipher_ctx;     /* Cryptographic restore context (if any) for file */
+   RESTORE_CIPHER_CTX cipher_ctx;      /* Cryptographic restore context (if any) for file */
    RESTORE_CIPHER_CTX fork_cipher_ctx; /* Cryptographic restore context (if any) for alternative stream */
 };
 
    ATTR *attr;
    intmax_t rsrc_len = 0;             /* Original length of resource fork */
    r_ctx rctx;
-
+   /* ***FIXME*** make configurable */
+   crypto_digest_t signing_algorithm = have_sha2 ? 
+                                       CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
    memset(&rctx, 0, sizeof(rctx));
    rctx.jcr = jcr;
 
    }
    jcr->buf_size = sd->msglen;
 
-   /* St Bernard code goes here if implemented */
+   /* St Bernard code goes here if implemented -- see end of file */
 
    if (have_libz) {
       uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
     * Get a record from the Storage daemon. We are guaranteed to
     *   receive records in the following order:
     *   1. Stream record header
-    *   2. Stream data
+    *   2. Stream data (one or more of the following in the order given)
     *        a. Attributes (Unix or Win32)
     *        b. Possibly stream encryption session data (e.g., symmetric session key)
-    *    or  c. File data for the file
-    *    or  d. Alternate data stream (e.g. Resource Fork)
-    *    or  e. Finder info
-    *    or  f. ACLs
-    *    or  g. Possibly a cryptographic signature
-    *    or  h. Possibly MD5 or SHA1 record
+    *        c. File data for the file
+    *        d. Alternate data stream (e.g. Resource Fork)
+    *        e. Finder info
+    *        f. ACLs
+    *        g. Possibly a cryptographic signature
+    *        h. Possibly MD5 or SHA1 record
     *   3. Repeat step 1
     *
     * NOTE: We keep track of two bacula file descriptors:
     *      close it again.
     *      The expected size of the stream, fork_len, should be set when
     *      opening the fd.
+    *   3. Not all the stream data records are required -- e.g. if there
+    *      is no fork, there is no alternate data stream, no ACL, ...
     */
    binit(&rctx.bfd);
    binit(&rctx.forkbfd);
    attr = new_attr();
    jcr->acl_text = get_pool_memory(PM_MESSAGE);
 
+   
+
    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
       /* Remember previous stream type */
       rctx.prev_stream = rctx.stream;
 
       /* * Now we expect the Stream Data */
       if (bget_msg(sd) < 0) {
-         Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
+         Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
          goto bail_out;
       }
       if (rctx.size != (uint32_t)sd->msglen) {
             break;
          }
 
+         if (jcr->digest) {
+            crypto_digest_free(jcr->digest);
+         }  
+         jcr->digest = crypto_digest_new(jcr, signing_algorithm);
+         if (!jcr->digest) {
+            Jmsg0(jcr, M_FATAL, 0, _("Could not create digest.\n"));
+            extract = false;
+            bclose(&rctx.bfd);
+            break;
+         }
+
          /* Decode and save session keys. */
          cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen, 
                         jcr->pki_recipients, &rctx.cs);
    /* Free Signature & Crypto Data */
    free_signature(rctx);
    free_session(rctx);
+   if (jcr->digest) {
+      crypto_digest_free(jcr->digest);
+      jcr->digest = NULL;
+   }
 
    /* Free file cipher restore context */
    if (rctx.cipher_ctx.cipher) {
    DIGEST *digest = NULL;
    crypto_error_t err;
    uint64_t saved_bytes;
+   crypto_digest_t signing_algorithm = have_sha2 ? 
+                                       CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
+   crypto_digest_t algorithm;
+
 
    if (!jcr->pki_sign) {
       return true;                    /* no signature OK */
 
    /* Iterate through the trusted signers */
    foreach_alist(keypair, jcr->pki_signers) {
-      err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
+      err = crypto_sign_get_digest(sig, jcr->pki_keypair, algorithm, &digest);
       switch (err) {
       case CRYPTO_ERROR_NONE:
          Dmsg0(50, "== Got digest\n");
-         /* Signature found, digest allocated */
-         jcr->digest = digest;
-
-         /* Checksum the entire file */
-         /* Make sure we don't modify JobBytes by saving and restoring it */
-         saved_bytes = jcr->JobBytes;                     
-         if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
-            Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"), 
-                 jcr->last_fname);
-            jcr->JobBytes = saved_bytes;
-            goto bail_out;
+         /*
+          * We computed jcr->digest using signing_algorithm while writing
+          * the file. If it is not the same as the algorithm used for 
+          * this file, punt by releasing the computed algorithm and 
+          * computing by re-reading the file.
+          */
+         if (algorithm != signing_algorithm) {
+            if (jcr->digest) {
+               crypto_digest_free(jcr->digest);
+               jcr->digest = NULL;
+            }  
          }
-         jcr->JobBytes = saved_bytes;
+         if (jcr->digest) {
+             /* Use digest computed while writing the file to verify the signature */
+            if ((err = crypto_sign_verify(sig, keypair, jcr->digest)) != CRYPTO_ERROR_NONE) {
+               Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
+               Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
+                     jcr->last_fname, crypto_strerror(err));
+               goto bail_out;
+            }
+         } else {   
+            /* Signature found, digest allocated.  Old method, 
+             * re-read the file and compute the digest
+             */
+            jcr->digest = digest;
+
+            /* Checksum the entire file */
+            /* Make sure we don't modify JobBytes by saving and restoring it */
+            saved_bytes = jcr->JobBytes;                     
+            if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
+               Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"), 
+                    jcr->last_fname);
+               jcr->JobBytes = saved_bytes;
+               goto bail_out;
+            }
+            jcr->JobBytes = saved_bytes;
 
-         /* Verify the signature */
-         if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
-            Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
-            Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
-                  jcr->last_fname, crypto_strerror(err));
-            goto bail_out;
+            /* Verify the signature */
+            if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
+               Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
+               Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"), 
+                     jcr->last_fname, crypto_strerror(err));
+               goto bail_out;
+            }
+            jcr->digest = NULL;
          }
 
          /* Valid signature */
          Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
          crypto_digest_free(digest);
-         jcr->digest = NULL;
          return true;
 
       case CRYPTO_ERROR_NOSIGNER:
          /* Signature not found, try again */
          if (digest) {
             crypto_digest_free(digest);
-            jcr->digest = NULL;
+            digest = NULL;
          }
          continue;
       default:
 bail_out:
    if (digest) {
       crypto_digest_free(digest);
-      jcr->digest = NULL;
    }
    return false;
 }
 
 bool store_data(JCR *jcr, BFILE *bfd, char *data, const int32_t length, bool win32_decomp)
 {
+   if (jcr->digest) {
+      crypto_digest_update(jcr->digest, (uint8_t *)data, length);
+   }
    if (win32_decomp) {
       if (!processWin32BackupAPIBlock(bfd, data, length)) {
          berrno be;
 
    static char buf[20];
 
    switch (stream) {
-   case STREAM_GZIP_DATA:
-      return _("GZIP data");
-   case STREAM_SPARSE_GZIP_DATA:
-      return _("GZIP sparse data");
-   case STREAM_WIN32_DATA:
-      return _("Win32 data");
-   case STREAM_WIN32_GZIP_DATA:
-      return _("Win32 GZIP data");
    case STREAM_UNIX_ATTRIBUTES:
-      return _("File attributes");
+      return _("Unix attributes");
    case STREAM_FILE_DATA:
       return _("File data");
    case STREAM_MD5_DIGEST:
       return _("MD5 digest");
+   case STREAM_GZIP_DATA:
+      return _("GZIP data");
    case STREAM_UNIX_ATTRIBUTES_EX:
       return _("Extended attributes");
    case STREAM_SPARSE_DATA:
       return _("Sparse data");
+   case STREAM_SPARSE_GZIP_DATA:
+      return _("GZIP sparse data");
    case STREAM_PROGRAM_NAMES:
       return _("Program names");
    case STREAM_PROGRAM_DATA:
       return _("Program data");
    case STREAM_SHA1_DIGEST:
       return _("SHA1 digest");
+   case STREAM_WIN32_DATA:
+      return _("Win32 data");
+   case STREAM_WIN32_GZIP_DATA:
+      return _("Win32 GZIP data");
    case STREAM_MACOS_FORK_DATA:
-      return _("HFS+ resource fork");
+      return _("MacOS Fork data");
    case STREAM_HFSPLUS_ATTRIBUTES:
-      return _("HFS+ Finder Info");
+      return _("HFS+ attribs");
+   case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
+      return _("Standard Unix ACL attribs");
+   case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
+      return _("Default Unix ACL attribs");
    case STREAM_SHA256_DIGEST:
       return _("SHA256 digest");
    case STREAM_SHA512_DIGEST:
       return _("Signed digest");
    case STREAM_ENCRYPTED_FILE_DATA:
       return _("Encrypted File data");
-   case STREAM_ENCRYPTED_FILE_GZIP_DATA:
-      return _("Encrypted GZIP data");
    case STREAM_ENCRYPTED_WIN32_DATA:
       return _("Encrypted Win32 data");
+   case STREAM_ENCRYPTED_SESSION_DATA:
+      return _("Encrypted session data");
+   case STREAM_ENCRYPTED_FILE_GZIP_DATA:
+      return _("Encrypted GZIP data");
    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
       return _("Encrypted Win32 GZIP data");
    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
-      return _("Encrypted HFS+ resource fork");
+      return _("Encrypted MacOS fork data");
    default:
       sprintf(buf, "%d", stream);
       return (const char *)buf;
 
-/*
- *   attr.h Definition of attributes packet for unpacking from tape
- *
- *    Kern Sibbald, June MMIII
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2003-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ *   attr.h Definition of attributes packet for unpacking from tape
+ *
+ *    Kern Sibbald, June MMIII
+ *
+ *   Version $Id$
+ */
 
 
 struct ATTR {
 
 
 /*
  * For a given public key, find the associated SignatureInfo record
- * and create a digest context for signature validation
+ *   and create a digest context for signature validation
+ *
  * Returns: CRYPTO_ERROR_NONE on success, with the newly allocated DIGEST in digest.
  *          A crypto_error_t value on failure.
  */
-crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST **digest)
+crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, 
+                                      crypto_digest_t &type, DIGEST **digest)
 {
    STACK_OF(SignerInfo) *signers;
    SignerInfo *si;
          Dmsg1(50, "crypto_sign_get_digest jcr=%p\n", sig->jcr);
          switch (OBJ_obj2nid(si->digestAlgorithm)) {
          case NID_md5:
+            Dmsg0(100, "sign digest algorithm is MD5\n");
+            type = CRYPTO_DIGEST_MD5;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_MD5);
             break;
          case NID_sha1:
+            Dmsg0(100, "sign digest algorithm is SHA1\n");
+            type = CRYPTO_DIGEST_SHA1;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_SHA1);
             break;
 #ifdef HAVE_SHA2
          case NID_sha256:
+            Dmsg0(100, "sign digest algorithm is SHA256\n");
+            type = CRYPTO_DIGEST_SHA256;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_SHA256);
             break;
          case NID_sha512:
+            Dmsg0(100, "sign digest algorithm is SHA512\n");
+            type = CRYPTO_DIGEST_SHA512;
             *digest = crypto_digest_new(sig->jcr, CRYPTO_DIGEST_SHA512);
             break;
 #endif
          default:
+            type = CRYPTO_DIGEST_NONE;
             *digest = NULL;
             return CRYPTO_ERROR_INVALID_DIGEST;
          }
 
       memset(lf, 0, sizeof(LEX));
       lf->next = nf;                  /* if have lf, push it behind new one */
       lf->options = nf->options;      /* preserve user options */
+      /*
+       * preserve err_type to prevent bacula exiting on 'reload' 
+       * if config is invalid. Fixes bug #877         
+       */
+      lf->err_type = nf->err_type;    
    } else {
       lf = nf;                        /* start new packet */
       memset(lf, 0, sizeof(LEX));
             lf->state = lex_none;
          } else {
             token = T_ERROR;
-        }
+         }
          break;
       case lex_utf16_le_bom:
          /* we only end up in this state if we have read an 0xFF 
             as the first byte of the file -- indicating that we are
             probably dealing with an Intel based (little endian) UTF-16 file*/
-        if (ch == 0xFE) {
-           token = T_UTF16_BOM;
-           lf->state = lex_none;
-        } else {
-           token = T_ERROR;
-        }
+         if (ch == 0xFE) {
+            token = T_UTF16_BOM;
+            lf->state = lex_none;
+         } else {
+            token = T_ERROR;
+         }
          break;
       }
       Dmsg4(dbglvl, "ch=%d state=%s token=%s %c\n", ch, lex_state_to_str(lf->state),
 
 bool               crypto_digest_finalize      (DIGEST *digest, uint8_t *dest, uint32_t *length);
 void               crypto_digest_free          (DIGEST *digest);
 SIGNATURE *        crypto_sign_new             (JCR *jcr);
-crypto_error_t     crypto_sign_get_digest      (SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST **digest);
+crypto_error_t     crypto_sign_get_digest      (SIGNATURE *sig, X509_KEYPAIR *keypair, 
+                                                crypto_digest_t &algorithm, DIGEST **digest);
 crypto_error_t     crypto_sign_verify          (SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST *digest);
 int                crypto_sign_add_signer      (SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair);
 int                crypto_sign_encode          (SIGNATURE *sig, uint8_t *dest, uint32_t *length);
 
  */
 
 #undef  VERSION
-#define VERSION "2.1.14"
-#define BDATE   "14 June 2007"
-#define LSMDATE "14Jun07"
+#define VERSION "2.1.16"
+#define BDATE   "16 June 2007"
+#define LSMDATE "16Jun07"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2007"       /* year for copyright messages in progs */
 
               Technical notes on version 2.1
 
 General:
+16Jun07
+kes  Remove a few malloc()s from the encryption code.
+kes  Use the class calls to bsock in filed/backup.c and restore.c in
+     place of the old bnet_xxx code.
+kes  Implement code that does an on the fly calculation of the  
+     signing digest during restore of encrypted files.  It makes
+     a best guess at the algorithm, and if it is not correct, will
+     then revert to the old code which reads the file after it is
+     restored.
+kes  Implement at least one missing crypto stream in stream_to_ascii()
+kes  Apply patch from William <chowmeined@gmail.com> that fixes bug
+     #877 where a reload with bad syntax causes Dir to exit.
 14Jun07
 kes  Do not free a volume on a tape drive until another volume is
      mounted and read, or the autochanger unloads the volume.