From d51e28e9e1a75a0155782fcc9ba0afeaf1f66cba Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 16 Jun 2007 08:25:03 +0000 Subject: [PATCH] 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 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 | 2 +- bacula/src/filed/backup.c | 129 ++++++++++++++++++------------------- bacula/src/filed/restore.c | 124 +++++++++++++++++++++++++---------- bacula/src/findlib/bfile.c | 34 ++++++---- bacula/src/lib/attr.h | 16 ++--- bacula/src/lib/crypto.c | 15 ++++- bacula/src/lib/lex.c | 19 ++++-- bacula/src/lib/protos.h | 3 +- bacula/src/version.h | 6 +- bacula/technotes-2.1 | 12 ++++ 10 files changed, 226 insertions(+), 134 deletions(-) diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 8816854b55..f32c738723 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -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) { diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 4d36218983..7b30be21a3 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -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 * */ - 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 * */ - 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; } diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 2adb8cb1c9..4b1157bccb 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -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; diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index 26908dc316..d98ba1afae 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -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; diff --git a/bacula/src/lib/attr.h b/bacula/src/lib/attr.h index d100fbe2f8..4167ef1548 100644 --- a/bacula/src/lib/attr.h +++ b/bacula/src/lib/attr.h @@ -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. @@ -32,6 +25,13 @@ (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 { diff --git a/bacula/src/lib/crypto.c b/bacula/src/lib/crypto.c index 1fa40656ac..66b377ff90 100644 --- a/bacula/src/lib/crypto.c +++ b/bacula/src/lib/crypto.c @@ -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; } diff --git a/bacula/src/lib/lex.c b/bacula/src/lib/lex.c index 2c438da08c..45758bf8c5 100644 --- a/bacula/src/lib/lex.c +++ b/bacula/src/lib/lex.c @@ -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), diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index b05edeaac6..e3b9340bdc 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -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); diff --git a/bacula/src/version.h b/bacula/src/version.h index 3c12d9a1ae..ca8702aeef 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -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 */ diff --git a/bacula/technotes-2.1 b/bacula/technotes-2.1 index 2b6dca093b..30ab95be25 100644 --- a/bacula/technotes-2.1 +++ b/bacula/technotes-2.1 @@ -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 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. -- 2.39.5