]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Remove a few malloc()s from the encryption code.
authorKern Sibbald <kern@sibbald.com>
Sat, 16 Jun 2007 08:25:03 +0000 (08:25 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 16 Jun 2007 08:25:03 +0000 (08:25 +0000)
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.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5018 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/dird/verify.c
bacula/src/filed/backup.c
bacula/src/filed/restore.c
bacula/src/findlib/bfile.c
bacula/src/lib/attr.h
bacula/src/lib/crypto.c
bacula/src/lib/lex.c
bacula/src/lib/protos.h
bacula/src/version.h
bacula/technotes-2.1

index 8816854b55aacb5cbc52306321dab4b86a699544..f32c73872311ce9e29d973680ddac6fcb75df213 100644 (file)
@@ -694,7 +694,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId)
       } 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) {
index 4d36218983070bd5167788fc85a8b99153cb0a17..7b30be21a352ed344145abacd27e8c63e8c9b024 100644 (file)
@@ -132,9 +132,6 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
 
       /* 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) {
@@ -167,7 +164,7 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
 
    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);
@@ -194,6 +191,7 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
    }
    if (jcr->pki_session_encoded) {
       free(jcr->pki_session_encoded);
+      jcr->pki_session_encoded = NULL;
    }
 
    Dmsg1(100, "end blast_data ok=%d\n", ok);
@@ -219,7 +217,6 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
    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
@@ -337,7 +334,14 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
    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);
@@ -407,7 +411,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
    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) {
@@ -420,8 +424,8 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
       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);
    }
 
    /*
@@ -513,7 +517,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
       }
 
       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;
@@ -523,8 +527,8 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
       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
 
@@ -550,60 +554,58 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
          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:
@@ -619,9 +621,6 @@ bail_out:
    if (sig) {
       crypto_sign_free(sig);        
    }
-   if (buf) {
-      free(buf);
-   }
    return rtnstat;
 }
 
@@ -728,9 +727,9 @@ int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest,
     * 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);
@@ -884,9 +883,9 @@ int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest,
          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);
@@ -919,9 +918,9 @@ int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest,
       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);
@@ -930,9 +929,9 @@ int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest,
       }
    }
 
-   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;
    }
 
@@ -976,9 +975,9 @@ static bool read_and_send_acl(JCR *jcr, int acltype, int stream)
    }
 
    /* 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;
    }
 
@@ -987,19 +986,19 @@ static bool read_and_send_acl(JCR *jcr, int acltype, int stream)
    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;
    }
 
@@ -1043,9 +1042,9 @@ static bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_strea
     * 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);
@@ -1065,15 +1064,15 @@ static bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_strea
    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);
@@ -1081,10 +1080,10 @@ static bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_strea
    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;
 }
 
index 2adb8cb1c996f62c9ffef3b9b20f2bc15e6fc16d..4b1157bccbb0d72270db7f69c01a4d4d51653631 100644 (file)
@@ -56,6 +56,13 @@ const bool have_acl = 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";
 
@@ -83,7 +90,7 @@ struct r_ctx {
 
    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 */
 };
 
@@ -147,7 +154,9 @@ void do_restore(JCR *jcr)
    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;
 
@@ -185,7 +194,7 @@ void do_restore(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;
@@ -204,15 +213,15 @@ void do_restore(JCR *jcr)
     * 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:
@@ -225,12 +234,16 @@ void do_restore(JCR *jcr)
     *      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;
@@ -246,7 +259,7 @@ void do_restore(JCR *jcr)
 
       /* * 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) {
@@ -387,6 +400,17 @@ void do_restore(JCR *jcr)
             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);
@@ -664,6 +688,10 @@ ok_out:
    /* 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) {
@@ -763,6 +791,10 @@ static bool verify_signature(JCR *jcr, SIGNATURE *sig)
    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 */
@@ -774,43 +806,67 @@ static bool verify_signature(JCR *jcr, SIGNATURE *sig)
 
    /* 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:
@@ -826,7 +882,6 @@ static bool verify_signature(JCR *jcr, SIGNATURE *sig)
 bail_out:
    if (digest) {
       crypto_digest_free(digest);
-      jcr->digest = NULL;
    }
    return false;
 }
@@ -895,6 +950,9 @@ static void unser_crypto_packet_len(RESTORE_CIPHER_CTX *ctx)
 
 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;
index 26908dc316a0ed5fc0bdf1a2de9ee33c94ffc039..d98ba1afaee5ff7f8661d6963a10070cd74f4ed7 100644 (file)
@@ -78,34 +78,38 @@ const char *stream_to_ascii(int stream)
    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:
@@ -114,14 +118,16 @@ const char *stream_to_ascii(int stream)
       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;
index d100fbe2f8a54b9b554ceaabdc89766f9dba29af..4167ef154829b4174eafd18190380707fc136bb6 100644 (file)
@@ -1,14 +1,7 @@
-/*
- *   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 {
index 1fa40656acc7856b66aa0f1aaa3178972f85ad38..66b377ff908e0389346c67ad1cde9cb1e57300f4 100644 (file)
@@ -713,11 +713,13 @@ SIGNATURE *crypto_sign_new(JCR *jcr)
 
 /*
  * 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;
@@ -732,20 +734,29 @@ crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, DIG
          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;
          }
index 2c438da08ca6f5dd88b497ed8fb3fe6eb5d1e562..45758bf8c5d64e49a4552e3881a6b81b72048fc8 100644 (file)
@@ -190,6 +190,11 @@ LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error)
       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));
@@ -594,18 +599,18 @@ lex_get_token(LEX *lf, int expect)
             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),
index b05edeaac605613d16b8eab9d4cc6bfe9634b26e..e3b9340bdc1928cc474193d2947f5f3d1b1b47e6 100644 (file)
@@ -139,7 +139,8 @@ bool               crypto_digest_update        (DIGEST *digest, const uint8_t *d
 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);
index 3c12d9a1aefd3bb77a9072c279f5f3ba8161505b..ca8702aeef1df6d3947b586111a2f32c79a7f99b 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #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 */
index 2b6dca093b0c29a9fcbe58730152feb23dbe3106..30ab95be2584bfbda7316a275f06d409afc26c34 100644 (file)
@@ -1,6 +1,18 @@
               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.