From: Kern Sibbald Date: Mon, 28 May 2007 18:03:50 +0000 (+0000) Subject: kes Minor refactoring of restore decryption code. X-Git-Tag: Release-2.2.0~368 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6067011f47ec083e9c57ba05d9fe0abf3bb181d8;p=bacula%2Fbacula kes Minor refactoring of restore decryption code. kes Add code to smartall.c to detect double free of a buffer. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4926 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/scripts/bacula-ctl-dir.in b/bacula/scripts/bacula-ctl-dir.in index 37d22aff86..fdebdfbe21 100644 --- a/bacula/scripts/bacula-ctl-dir.in +++ b/bacula/scripts/bacula-ctl-dir.in @@ -208,7 +208,11 @@ case "$1" in OPTIONS="${OPTIONS} -g ${DIR_GROUP}" fi - ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/bacula-dir.conf + if [ "${VALGRIND}" != '' ]; then + valgrind --leak-check=full ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/bacula-dir.conf + else + ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/bacula-dir.conf + fi } ;; diff --git a/bacula/scripts/devel_bacula.in b/bacula/scripts/devel_bacula.in index bddb7705ee..4a68501db2 100755 --- a/bacula/scripts/devel_bacula.in +++ b/bacula/scripts/devel_bacula.in @@ -230,8 +230,11 @@ case "$1" in OPTIONS="${OPTIONS} -g ${DIR_GROUP}" fi -# valgrind --leak-check=full ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/dird.conf - ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/dird.conf + if [ "${VALGRIND}" != '' ]; then + valgrind --leak-check=full ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/dird.conf + else + ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/dird.conf + fi } ;; diff --git a/bacula/src/filed/acl.c b/bacula/src/filed/acl.c index 5ee3e034e8..bd4124aaeb 100644 --- a/bacula/src/filed/acl.c +++ b/bacula/src/filed/acl.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2004-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. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation plus additions + that are listed in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * Functions to handle ACL for bacula. * @@ -28,33 +55,6 @@ * * Version $Id$ */ -/* - Bacula® - The Network Backup Solution - - Copyright (C) 2004-2006 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. - This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public - License as published by the Free Software Foundation plus additions - that are listed in the file LICENSE. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - - Bacula® is a registered trademark of John Walker. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. -*/ #ifndef TEST_PROGRAM @@ -71,8 +71,8 @@ */ #if !defined(HAVE_ACL) /* ACL support is required, of course */ \ || !( defined(HAVE_AIX_OS) /* man page -- may need flags */ \ - || defined(HAVE_FREEBSD_OS) /* tested -- compile wihtout flags */ \ - || defined(HAVE_DARWIN_OS) /* tested -- compile wihtout flags */ \ + || defined(HAVE_FREEBSD_OS) /* tested -- compile without flags */ \ + || defined(HAVE_DARWIN_OS) /* tested -- compile without flags */ \ || defined(HAVE_IRIX_OS) /* man page -- compile without flags */ \ || defined(HAVE_OSF1_OS) /* man page -- may need -lpacl */ \ || defined(HAVE_LINUX_OS) /* tested -- compile with -lacl */ \ @@ -88,6 +88,7 @@ * with what we have and give all ACL streams a new number/type. */ #endif + #if !defined(HAVE_ACL) \ || !( defined(HAVE_LINUX_OS) \ || defined(HAVE_FREEBSD_OS) \ diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 6f5cf607c7..2a197a5116 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -39,6 +39,9 @@ #ifdef HAVE_DARWIN_OS #include +const bool have_darwin_os = true; +#else +const bool have_darwin_os = false; #endif #if defined(HAVE_CRYPTO) @@ -47,9 +50,44 @@ const bool have_crypto = true; const bool have_crypto = false; #endif +#if defined(HAVE_ACL) +const bool have_acl = true; +#else +const bool have_acl = false; +#endif + /* Data received from Storage Daemon */ static char rec_header[] = "rechdr %ld %ld %ld %ld %ld"; +typedef struct restore_cipher_ctx { + CIPHER_CONTEXT *cipher; + uint32_t block_size; + + POOLMEM *buf; /* Pointer to descryption buffer */ + int32_t buf_len; /* Count of bytes currently in buf */ + int32_t packet_len; /* Total bytes in packet */ +} RESTORE_CIPHER_CTX; + +struct r_ctx { + JCR *jcr; + int32_t stream; + int32_t prev_stream; + BFILE bfd; /* File content */ + uint64_t fileAddr; /* file write address */ + uint32_t size; /* Size of file */ + int flags; /* Options for extract_data() */ + BFILE forkbfd; /* Alternative data stream */ + uint64_t fork_addr; /* Write address for alternative stream */ + intmax_t fork_size; /* Size of alternate stream */ + int fork_flags; /* Options for extract_data() */ + + 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 fork_cipher_ctx; /* Cryptographic restore context (if any) for alternative stream */ +}; + + /* Forward referenced functions */ #if defined(HAVE_LIBZ) static const char *zlib_strerror(int stat); @@ -58,21 +96,19 @@ const bool have_libz = true; const bool have_libz = false; #endif -typedef struct restore_cipher_ctx { - CIPHER_CONTEXT *cipher; - uint32_t block_size; +static void deallocate_cipher(r_ctx &rctx); +static void deallocate_fork_cipher(r_ctx &rctx); +static void free_signature(r_ctx &rctx); +static void free_session(r_ctx &rctx); + - POOLMEM *buf; /* Pointer to descryption buffer */ - int32_t buf_len; /* Count of bytes currently in buf */ - int32_t packet_len; /* Total bytes in packet */ -} RESTORE_CIPHER_CTX; static bool verify_signature(JCR *jcr, SIGNATURE *sig); int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen, - uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx); -bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx); + uint64_t *addr, int flags, RESTORE_CIPHER_CTX *cipher_ctx); +bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags, + RESTORE_CIPHER_CTX *cipher_ctx); -#define RETRY 10 /* retry wait time */ /* * Close a bfd check that we are at the expected file offset. @@ -94,6 +130,7 @@ int bclose_chksize(JCR *jcr, BFILE *bfd, boffset_t osize) return 0; } + /* * Restore the requested files. * @@ -101,26 +138,18 @@ int bclose_chksize(JCR *jcr, BFILE *bfd, boffset_t osize) void do_restore(JCR *jcr) { BSOCK *sd; - int32_t stream = 0; - int32_t prev_stream; uint32_t VolSessionId, VolSessionTime; bool extract = false; int32_t file_index; char ec1[50]; /* Buffer printing huge values */ - BFILE bfd; /* File content */ - uint64_t fileAddr = 0; /* file write address */ - uint32_t size; /* Size of file */ - BFILE altbfd; /* Alternative data stream */ - uint64_t alt_addr = 0; /* Write address for alternative stream */ - intmax_t alt_size = 0; /* Size of alternate stream */ - SIGNATURE *sig = NULL; /* Cryptographic signature (if any) for file */ - CRYPTO_SESSION *cs = NULL; /* Cryptographic session data (if any) for file */ - RESTORE_CIPHER_CTX cipher_ctx; /* Cryptographic restore context (if any) for file */ - RESTORE_CIPHER_CTX alt_cipher_ctx; /* Cryptographic restore context (if any) for alternative stream */ - int flags = 0; /* Options for extract_data() */ - int alt_flags = 0; /* Options for extract_data() */ + uint32_t buf_size; /* client buffer size */ int stat; ATTR *attr; + intmax_t rsrc_len = 0; /* Original length of resource fork */ + r_ctx rctx; + + memset(&rctx, 0, sizeof(rctx)); + rctx.jcr = jcr; /* The following variables keep track of "known unknowns" */ int non_support_data = 0; @@ -129,24 +158,22 @@ void do_restore(JCR *jcr) int non_support_finfo = 0; int non_support_acl = 0; int non_support_progname = 0; + int non_support_crypto = 0; - /* Finally, set up for special configurations */ #ifdef HAVE_DARWIN_OS - intmax_t rsrc_len = 0; /* Original length of resource fork */ struct attrlist attrList; - memset(&attrList, 0, sizeof(attrList)); attrList.bitmapcount = ATTR_BIT_MAP_COUNT; attrList.commonattr = ATTR_CMN_FNDRINFO; #endif + sd = jcr->store_bsock; set_jcr_job_status(jcr, JS_Running); LockRes(); CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL); UnlockRes(); - uint32_t buf_size; if (client) { buf_size = client->max_network_buffer_size; } else { @@ -158,29 +185,7 @@ void do_restore(JCR *jcr) } jcr->buf_size = sd->msglen; -#ifdef stbernard_implemented -/ #if defined(HAVE_WIN32) - bool bResumeOfmOnExit = FALSE; - if (isOpenFileManagerRunning()) { - if ( pauseOpenFileManager() ) { - Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") ); - bResumeOfmOnExit = TRUE; - } - else { - Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") ); - } - } - { - char username[UNLEN+1]; - DWORD usize = sizeof(username); - int privs = enable_backup_privileges(NULL, 1); - if (GetUserName(username, &usize)) { - Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username, - } else { - Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n")); - } - } -#endif + /* St Bernard code goes here if implemented */ if (have_libz) { uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100; @@ -188,19 +193,11 @@ void do_restore(JCR *jcr) jcr->compress_buf_size = compress_buf_size; } - cipher_ctx.cipher = NULL; - alt_cipher_ctx.cipher = NULL; if (have_crypto) { - cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE); - cipher_ctx.buf_len = 0; - cipher_ctx.packet_len = 0; - - alt_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE); - alt_cipher_ctx.buf_len = 0; - alt_cipher_ctx.packet_len = 0; - } else { - cipher_ctx.buf = NULL; - alt_cipher_ctx.buf = NULL; + rctx.cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE); + if (have_darwin_os) { + rctx.fork_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE); + } } /* @@ -222,59 +219,56 @@ void do_restore(JCR *jcr) * 1. bfd for file data. * This fd is opened for non empty files when an attribute stream is * encountered and closed when we find the next attribute stream. - * 2. alt_bfd for alternate data streams + * 2. fork_bfd for alternate data streams * This fd is opened every time we encounter a new alternate data * stream for the current file. When we find any other stream, we * close it again. - * The expected size of the stream, alt_len, should be set when + * The expected size of the stream, fork_len, should be set when * opening the fd. */ - binit(&bfd); - binit(&altbfd); + 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 */ - prev_stream = stream; + rctx.prev_stream = rctx.stream; /* First we expect a Stream Record Header */ if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index, - &stream, &size) != 5) { + &rctx.stream, &rctx.size) != 5) { Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg); goto bail_out; } Dmsg4(30, "Got hdr: Files=%d FilInx=%d Stream=%d, %s.\n", - jcr->JobFiles, file_index, stream, stream_to_ascii(stream)); + jcr->JobFiles, file_index, rctx.stream, stream_to_ascii(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)); goto bail_out; } - if (size != (uint32_t)sd->msglen) { - Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size); + if (rctx.size != (uint32_t)sd->msglen) { + Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), + sd->msglen, rctx.size); goto bail_out; } - Dmsg3(30, "Got stream: %s len=%d extract=%d\n", stream_to_ascii(stream), + Dmsg3(30, "Got stream: %s len=%d extract=%d\n", stream_to_ascii(rctx.stream), sd->msglen, extract); /* If we change streams, close and reset alternate data streams */ - if (prev_stream != stream) { - if (is_bopen(&altbfd)) { - if (alt_cipher_ctx.cipher) { - flush_cipher(jcr, &altbfd, &alt_addr, alt_flags, &alt_cipher_ctx); - crypto_cipher_free(alt_cipher_ctx.cipher); - alt_cipher_ctx.cipher = NULL; - } - bclose_chksize(jcr, &altbfd, alt_size); + if (rctx.prev_stream != rctx.stream) { + if (is_bopen(&rctx.forkbfd)) { + deallocate_fork_cipher(rctx); + bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size); } - alt_size = -1; /* Use an impossible value and set a proper one below */ - alt_addr = 0; + rctx.fork_size = -1; /* Use an impossible value and set a proper one below */ + rctx.fork_addr = 0; } /* File Attributes stream */ - switch (stream) { + switch (rctx.stream) { case STREAM_UNIX_ATTRIBUTES: case STREAM_UNIX_ATTRIBUTES_EX: /* @@ -282,48 +276,35 @@ void do_restore(JCR *jcr) * close the output file and validate the signature. */ if (extract) { - if (size > 0 && !is_bopen(&bfd)) { + if (rctx.size > 0 && !is_bopen(&rctx.bfd)) { Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n")); } - /* Flush and deallocate previous stream's cipher context */ - if (cipher_ctx.cipher && prev_stream != STREAM_ENCRYPTED_SESSION_DATA) { - flush_cipher(jcr, &bfd, &fileAddr, flags, &cipher_ctx); - crypto_cipher_free(cipher_ctx.cipher); - cipher_ctx.cipher = NULL; - } - /* Flush and deallocate previous stream's alt cipher context */ - if (alt_cipher_ctx.cipher && prev_stream != STREAM_ENCRYPTED_SESSION_DATA) { - flush_cipher(jcr, &altbfd, &alt_addr, alt_flags, &alt_cipher_ctx); - crypto_cipher_free(alt_cipher_ctx.cipher); - alt_cipher_ctx.cipher = NULL; + if (rctx.prev_stream != STREAM_ENCRYPTED_SESSION_DATA) { + deallocate_cipher(rctx); + deallocate_fork_cipher(rctx); } - set_attributes(jcr, attr, &bfd); + + set_attributes(jcr, attr, &rctx.bfd); extract = false; /* Verify the cryptographic signature, if any */ - verify_signature(jcr, sig); + verify_signature(jcr, rctx.sig); /* Free Signature */ - if (sig) { - crypto_sign_free(sig); - sig = NULL; - } - if (cs) { - crypto_session_free(cs); - cs = NULL; - } + free_signature(rctx); + free_session(rctx); jcr->ff->flags = 0; Dmsg0(30, "Stop extracting.\n"); - } else if (is_bopen(&bfd)) { + } else if (is_bopen(&rctx.bfd)) { Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n")); - bclose(&bfd); + bclose(&rctx.bfd); } /* - * Unpack and do sanity check fo attributes. + * Unpack attributes and do sanity check them */ - if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) { + if (!unpack_attributes_record(jcr, rctx.stream, sd->msg, attr)) { goto bail_out; } if (file_index != attr->file_index) { @@ -353,7 +334,7 @@ void do_restore(JCR *jcr) */ jcr->num_files_examined++; extract = false; - stat = create_file(jcr, attr, &bfd, jcr->replace); + stat = create_file(jcr, attr, &rctx.bfd, jcr->replace); Dmsg2(30, "Outfile=%s create_file stat=%d\n", attr->ofname, stat); switch (stat) { case CF_ERROR: @@ -368,19 +349,19 @@ void do_restore(JCR *jcr) jcr->last_type = attr->type; jcr->JobFiles++; jcr->unlock(); - fileAddr = 0; + rctx.fileAddr = 0; print_ls_output(jcr, attr); -#ifdef HAVE_DARWIN_OS - /* Only restore the resource fork for regular files */ - from_base64(&rsrc_len, attr->attrEx); - if (attr->type == FT_REG && rsrc_len > 0) { - extract = true; + if (have_darwin_os) { + /* Only restore the resource fork for regular files */ + from_base64(&rsrc_len, attr->attrEx); + if (attr->type == FT_REG && rsrc_len > 0) { + extract = true; + } } -#endif if (!extract) { /* set attributes now because file will not be extracted */ - set_attributes(jcr, attr, &bfd); + set_attributes(jcr, attr, &rctx.bfd); } break; } @@ -391,10 +372,10 @@ void do_restore(JCR *jcr) crypto_error_t cryptoerr; /* Is this an unexpected session data entry? */ - if (cs) { + if (rctx.cs) { Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic session data stream.\n")); extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } @@ -402,12 +383,13 @@ void do_restore(JCR *jcr) if (!jcr->pki_recipients) { Jmsg(jcr, M_ERROR, 0, _("No private decryption keys have been defined to decrypt encrypted backup data.\n")); extract = false; - bclose(&bfd); + bclose(&rctx.bfd); break; } /* Decode and save session keys. */ - cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen, jcr->pki_recipients, &cs); + cryptoerr = crypto_session_decode((uint8_t *)sd->msg, (uint32_t)sd->msglen, + jcr->pki_recipients, &rctx.cs); switch(cryptoerr) { case CRYPTO_ERROR_NONE: /* Success */ @@ -426,7 +408,7 @@ void do_restore(JCR *jcr) if (cryptoerr != CRYPTO_ERROR_NONE) { extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } @@ -443,55 +425,59 @@ void do_restore(JCR *jcr) case STREAM_ENCRYPTED_FILE_GZIP_DATA: case STREAM_ENCRYPTED_WIN32_GZIP_DATA: /* Force an expected, consistent stream type here */ - if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES - || prev_stream == STREAM_UNIX_ATTRIBUTES_EX - || prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) { - flags = 0; - - if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) { - flags |= FO_SPARSE; + if (extract && (rctx.prev_stream == rctx.stream + || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES + || rctx.prev_stream == STREAM_UNIX_ATTRIBUTES_EX + || rctx.prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) { + rctx.flags = 0; + + if (rctx.stream == STREAM_SPARSE_DATA || + rctx.stream == STREAM_SPARSE_GZIP_DATA) { + rctx.flags |= FO_SPARSE; } - if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA - || stream == STREAM_WIN32_GZIP_DATA || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA - || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) { - flags |= FO_GZIP; + if (rctx.stream == STREAM_GZIP_DATA + || rctx.stream == STREAM_SPARSE_GZIP_DATA + || rctx.stream == STREAM_WIN32_GZIP_DATA + || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA + || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) { + rctx.flags |= FO_GZIP; } - if (stream == STREAM_ENCRYPTED_FILE_DATA - || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA - || stream == STREAM_ENCRYPTED_WIN32_DATA - || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) { + if (rctx.stream == STREAM_ENCRYPTED_FILE_DATA + || rctx.stream == STREAM_ENCRYPTED_FILE_GZIP_DATA + || rctx.stream == STREAM_ENCRYPTED_WIN32_DATA + || rctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) { /* Set up a decryption context */ - if (!cipher_ctx.cipher) { - if (!cs) { + if (!rctx.cipher_ctx.cipher) { + if (!rctx.cs) { Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname); extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } - if ((cipher_ctx.cipher = crypto_cipher_new(cs, false, &cipher_ctx.block_size)) == NULL) { + if ((rctx.cipher_ctx.cipher = crypto_cipher_new(rctx.cs, false, + &rctx.cipher_ctx.block_size)) == NULL) { Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname); - crypto_session_free(cs); - cs = NULL; + free_session(rctx); extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } } - flags |= FO_ENCRYPT; + rctx.flags |= FO_ENCRYPT; } - if (is_win32_stream(stream) && !have_win32_api()) { - set_portable_backup(&bfd); - flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */ + if (is_win32_stream(rctx.stream) && !have_win32_api()) { + set_portable_backup(&rctx.bfd); + rctx.flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */ } - if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags, - &cipher_ctx) < 0) { + if (extract_data(jcr, &rctx.bfd, sd->msg, sd->msglen, &rctx.fileAddr, + rctx.flags, &rctx.cipher_ctx) < 0) { extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } } @@ -502,27 +488,26 @@ void do_restore(JCR *jcr) case STREAM_ENCRYPTED_MACOS_FORK_DATA: case STREAM_MACOS_FORK_DATA: #ifdef HAVE_DARWIN_OS - alt_flags = 0; + fork_flags = 0; jcr->ff->flags |= FO_HFSPLUS; if (stream == STREAM_ENCRYPTED_MACOS_FORK_DATA) { - alt_flags |= FO_ENCRYPT; + fork_flags |= FO_ENCRYPT; /* Set up a decryption context */ - if (extract && !alt_cipher_ctx.cipher) { + if (extract && !rctx.fork_cipher_ctx.cipher) { if (!cs) { Jmsg1(jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), jcr->last_fname); extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } - if ((alt_cipher_ctx.cipher = crypto_cipher_new(cs, false, &alt_cipher_ctx.block_size)) == NULL) { + if ((rctx.fork_cipher_ctx.cipher = crypto_cipher_new(cs, false, &rctx.fork_cipher_ctx.block_size)) == NULL) { Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname); - crypto_session_free(cs); - cs = NULL; + free_session(rctx); extract = false; - bclose(&bfd); + bclose(&rctx.bfd); continue; } } @@ -530,20 +515,20 @@ void do_restore(JCR *jcr) if (extract) { if (prev_stream != stream) { - if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) { + if (bopen_rsrc(&forkbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) { Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname); extract = false; continue; } - alt_size = rsrc_len; + fork_size = rsrc_len; Dmsg0(30, "Restoring resource fork\n"); } - if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, alt_flags, - &alt_cipher_ctx) < 0) { + if (extract_data(jcr, &forkbfd, sd->msg, sd->msglen, &rctx.fork_addr, fork_flags, + &rctxfork_cipher_ctx) < 0) { extract = false; - bclose(&altbfd); + bclose(&forkbfd); continue; } } @@ -570,41 +555,38 @@ void do_restore(JCR *jcr) break; case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL: -#ifdef HAVE_ACL - pm_strcpy(jcr->acl_text, sd->msg); - Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text); - if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) { + if (have_acl) { + pm_strcpy(jcr->acl_text, sd->msg); + Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text); + if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) { Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname); + } + } else { + non_support_acl++; } -#else - non_support_acl++; -#endif break; case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL: -#ifdef HAVE_ACL - pm_strcpy(jcr->acl_text, sd->msg); - Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text); - if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) { + if (have_acl) { + pm_strcpy(jcr->acl_text, sd->msg); + Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text); + if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) { Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname); + } + } else { + non_support_acl++; } -#else - non_support_acl++; -#endif break; case STREAM_SIGNED_DIGEST: - /* Is this an unexpected signature? */ - if (sig) { + if (rctx.sig) { Jmsg0(jcr, M_ERROR, 0, _("Unexpected cryptographic signature data stream.\n")); - crypto_sign_free(sig); - sig = NULL; + free_signature(rctx); continue; } - /* Save signature. */ - if (extract && (sig = crypto_sign_decode(jcr, (uint8_t *)sd->msg, (uint32_t)sd->msglen)) == NULL) { + if (extract && (rctx.sig = crypto_sign_decode(jcr, (uint8_t *)sd->msg, (uint32_t)sd->msglen)) == NULL) { Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname); } break; @@ -626,35 +608,26 @@ void do_restore(JCR *jcr) default: /* If extracting, wierd stream (not 1 or 2), close output file anyway */ if (extract) { - Dmsg1(30, "Found wierd stream %d\n", stream); - if (size > 0 && !is_bopen(&bfd)) { + Dmsg1(30, "Found wierd stream %d\n", rctx.stream); + if (rctx.size > 0 && !is_bopen(&rctx.bfd)) { Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n")); } /* Flush and deallocate cipher context */ - if (cipher_ctx.cipher) { - flush_cipher(jcr, &bfd, &fileAddr, flags, &cipher_ctx); - crypto_cipher_free(cipher_ctx.cipher); - cipher_ctx.cipher = NULL; - } - - /* Flush and deallocate alt cipher context */ - if (alt_cipher_ctx.cipher) { - flush_cipher(jcr, &altbfd, &alt_addr, alt_flags, &alt_cipher_ctx); - crypto_cipher_free(alt_cipher_ctx.cipher); - alt_cipher_ctx.cipher = NULL; - } + deallocate_cipher(rctx); + deallocate_fork_cipher(rctx); - set_attributes(jcr, attr, &bfd); + set_attributes(jcr, attr, &rctx.bfd); /* Verify the cryptographic signature if any */ - verify_signature(jcr, sig); + verify_signature(jcr, rctx.sig); extract = false; - } else if (is_bopen(&bfd)) { + } else if (is_bopen(&rctx.bfd)) { Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n")); - bclose(&bfd); + bclose(&rctx.bfd); } - Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream); - Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); + Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), + rctx.stream); + Dmsg2(0, "None of above!!! stream=%d data=%s\n", rctx.stream,sd->msg); break; } /* end switch(stream) */ @@ -663,32 +636,22 @@ void do_restore(JCR *jcr) /* If output file is still open, it was the last one in the * archive since we just hit an end of file, so close the file. */ - if (is_bopen(&altbfd)) { - bclose_chksize(jcr, &altbfd, alt_size); + if (is_bopen(&rctx.forkbfd)) { + bclose_chksize(jcr, &rctx.forkbfd, rctx.fork_size); } if (extract) { /* Flush and deallocate cipher context */ - if (cipher_ctx.cipher) { - flush_cipher(jcr, &bfd, &fileAddr, flags, &cipher_ctx); - crypto_cipher_free(cipher_ctx.cipher); - cipher_ctx.cipher = NULL; - } - - /* Flush and deallocate alt cipher context */ - if (alt_cipher_ctx.cipher) { - flush_cipher(jcr, &altbfd, &alt_addr, alt_flags, &alt_cipher_ctx); - crypto_cipher_free(alt_cipher_ctx.cipher); - alt_cipher_ctx.cipher = NULL; - } + deallocate_cipher(rctx); + deallocate_fork_cipher(rctx); - set_attributes(jcr, attr, &bfd); + set_attributes(jcr, attr, &rctx.bfd); /* Verify the cryptographic signature on the last file, if any */ - verify_signature(jcr, sig); + verify_signature(jcr, rctx.sig); } - if (is_bopen(&bfd)) { - bclose(&bfd); + if (is_bopen(&rctx.bfd)) { + bclose(&rctx.bfd); } set_jcr_job_status(jcr, JS_Terminated); @@ -699,33 +662,27 @@ bail_out: ok_out: /* Free Signature & Crypto Data */ - if (sig) { - crypto_sign_free(sig); - sig = NULL; - } - if (cs) { - crypto_session_free(cs); - cs = NULL; - } + free_signature(rctx); + free_session(rctx); /* Free file cipher restore context */ - if (cipher_ctx.cipher) { - crypto_cipher_free(cipher_ctx.cipher); - cipher_ctx.cipher = NULL; + if (rctx.cipher_ctx.cipher) { + crypto_cipher_free(rctx.cipher_ctx.cipher); + rctx.cipher_ctx.cipher = NULL; } - if (cipher_ctx.buf) { - free_pool_memory(cipher_ctx.buf); - cipher_ctx.buf = NULL; + if (rctx.cipher_ctx.buf) { + free_pool_memory(rctx.cipher_ctx.buf); + rctx.cipher_ctx.buf = NULL; } /* Free alternate stream cipher restore context */ - if (alt_cipher_ctx.cipher) { - crypto_cipher_free(alt_cipher_ctx.cipher); - alt_cipher_ctx.cipher = NULL; + if (rctx.fork_cipher_ctx.cipher) { + crypto_cipher_free(rctx.fork_cipher_ctx.cipher); + rctx.fork_cipher_ctx.cipher = NULL; } - if (alt_cipher_ctx.buf) { - free_pool_memory(alt_cipher_ctx.buf); - alt_cipher_ctx.buf = NULL; + if (rctx.fork_cipher_ctx.buf) { + free_pool_memory(rctx.fork_cipher_ctx.buf); + rctx.fork_cipher_ctx.buf = NULL; } if (jcr->compress_buf) { @@ -733,8 +690,8 @@ ok_out: jcr->compress_buf = NULL; jcr->compress_buf_size = 0; } - bclose(&altbfd); - bclose(&bfd); + bclose(&rctx.forkbfd); + bclose(&rctx.bfd); free_attr(attr); free_pool_memory(jcr->acl_text); Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles, @@ -752,6 +709,9 @@ ok_out: if (non_support_acl) { Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl); } + if (non_support_crypto) { + Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl); + } } @@ -1142,3 +1102,66 @@ again: return true; } + +static void deallocate_cipher(r_ctx &rctx) +{ + /* Flush and deallocate previous stream's cipher context */ + if (rctx.cipher_ctx.cipher) { + flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx); + crypto_cipher_free(rctx.cipher_ctx.cipher); + rctx.cipher_ctx.cipher = NULL; + } +} + +static void deallocate_fork_cipher(r_ctx &rctx) +{ + + /* Flush and deallocate previous stream's fork cipher context */ + if (rctx.fork_cipher_ctx.cipher) { + flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx); + crypto_cipher_free(rctx.fork_cipher_ctx.cipher); + rctx.fork_cipher_ctx.cipher = NULL; + } +} + +static void free_signature(r_ctx &rctx) +{ + if (rctx.sig) { + crypto_sign_free(rctx.sig); + rctx.sig = NULL; + } +} + +static void free_session(r_ctx &rctx) +{ + if (rctx.cs) { + crypto_session_free(rctx.cs); + rctx.cs = NULL; + } +} + + +/* This code if implemented goes above */ +#ifdef stbernard_implemented +/ #if defined(HAVE_WIN32) + bool bResumeOfmOnExit = FALSE; + if (isOpenFileManagerRunning()) { + if ( pauseOpenFileManager() ) { + Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") ); + bResumeOfmOnExit = TRUE; + } + else { + Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") ); + } + } + { + char username[UNLEN+1]; + DWORD usize = sizeof(username); + int privs = enable_backup_privileges(NULL, 1); + if (GetUserName(username, &usize)) { + Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username, + } else { + Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n")); + } + } +#endif diff --git a/bacula/src/lib/address_conf.c b/bacula/src/lib/address_conf.c index b79ae3b487..678056c698 100644 --- a/bacula/src/lib/address_conf.c +++ b/bacula/src/lib/address_conf.c @@ -1,14 +1,7 @@ -/* - * Configuration file parser for IP-Addresse ipv4 and ipv6 - * - * Written by Meno Abels, June MMIV - * - * Version $Id$ - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2004-2006 Free Software Foundation Europe e.V. + Copyright (C) 2004-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. */ +/* + * Configuration file parser for IP-Addresse ipv4 and ipv6 + * + * Written by Meno Abels, June MMIV + * + * Version $Id$ + */ #include "bacula.h" @@ -43,7 +43,7 @@ #endif static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family, - const char *hostname_str, const char *port_str, char **errstr); + const char *hostname_str, const char *port_str, char *buf, int buflen); IPADDR::IPADDR(const IPADDR &src) : type(src.type) @@ -233,12 +233,12 @@ const char *build_addresses_str(dlist *addrs, char *buf, int blen) return buf; } -const char *get_first_address(dlist * addrs, char *outputbuf, int outlen) +const char *get_first_address(dlist *addrs, char *outputbuf, int outlen) { return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen); } -int get_first_port_net_order(dlist * addrs) +int get_first_port_net_order(dlist *addrs) { if (!addrs) { return 0; @@ -247,7 +247,7 @@ int get_first_port_net_order(dlist * addrs) } } -int get_first_port_host_order(dlist * addrs) +int get_first_port_host_order(dlist *addrs) { if (!addrs) { return 0; @@ -258,16 +258,15 @@ int get_first_port_host_order(dlist * addrs) void init_default_addresses(dlist **out, int port) { - char *errstr; + char buf[1024]; unsigned short sport = port; - if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, &errstr)) { - Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), errstr); - free(errstr); + if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) { + Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), buf); } } static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family, - const char *hostname_str, const char *port_str, char **errstr) + const char *hostname_str, const char *port_str, char *buf, int buflen) { IPADDR *iaddr; IPADDR *jaddr; @@ -275,6 +274,7 @@ static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultp unsigned short port; IPADDR::i_type intype = type; + buf[0] = 0; dlist *addrs = (dlist *)(*(out)); if (!addrs) { IPADDR *tmp = 0; @@ -289,8 +289,7 @@ static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultp if (iaddr->get_type() == IPADDR::R_DEFAULT) { def = iaddr; } else if (iaddr->get_type() != type) { - *errstr = (char *)malloc(1024); - bsnprintf(*errstr, 1023, + bsnprintf(buf, buflen, _("the old style addresses cannot be mixed with new style")); return 0; } @@ -301,7 +300,6 @@ static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultp } } - if (!port_str || port_str[0] == '\0') { port = defaultport; } else { @@ -313,8 +311,7 @@ static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultp if (s) { port = s->s_port; } else { - *errstr = (char *)malloc(1024); - bsnprintf(*errstr, 1023, _("can't resolve service(%s)"), port_str); + bsnprintf(buf, buflen, _("can't resolve service(%s)"), port_str); return 0; } } @@ -323,8 +320,7 @@ static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultp const char *myerrstr; hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr); if (!hostaddrs) { - *errstr = (char *)malloc(1024); - bsnprintf(*errstr, 1023, _("can't resolve hostname(%s) %s"), hostname_str, + bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str, myerrstr); return 0; } @@ -344,7 +340,7 @@ static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultp addr->set_port_net(port); } if (intype == IPADDR::R_SINGLE_ADDR) { - addr->copy_addr((IPADDR *) (hostaddrs->first())); + addr->copy_addr((IPADDR *)(hostaddrs->first())); } } else { foreach_dlist(iaddr, hostaddrs) { @@ -409,6 +405,7 @@ void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass) char hostname_str[1024]; char port_str[128]; int family = 0; + char errmsg[1024]; token = lex_get_token(lc, T_SKIP_EOL); @@ -499,12 +496,11 @@ void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass) scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str); } - char *errstr; if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE, - htons(item->default_value), family, hostname_str, port_str, &errstr)) { + htons(item->default_value), family, hostname_str, port_str, + errmsg, sizeof(errmsg))) { scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"), - hostname_str, port_str, errstr); - free(errstr); + hostname_str, port_str, errmsg); } token = scan_to_next_not_eol(lc); } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING)); @@ -515,30 +511,29 @@ void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass) void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass) { - + char errmsg[1024]; int token = lex_get_token(lc, T_SKIP_EOL); if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) { scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str); } - char *errstr; - if (pass == 1 && !add_address((dlist **) (item->value), IPADDR::R_SINGLE_ADDR, - htons(item->default_value), AF_INET, lc->str, 0, &errstr)) { - scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr); - free(errstr); + if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR, + htons(item->default_value), AF_INET, lc->str, 0, + errmsg, sizeof(errmsg))) { + scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg); } } void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass) { + char errmsg[1024]; int token = lex_get_token(lc, T_SKIP_EOL); if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) { scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str); } - char *errstr; if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT, - htons(item->default_value), AF_INET, 0, lc->str, &errstr)) { - scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr); - free(errstr); + htons(item->default_value), AF_INET, 0, lc->str, + errmsg, sizeof(errmsg))) { + scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg); } } diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index 0c741c4b0b..bbfaf6eeea 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -234,7 +234,11 @@ void bfree(void *buf) void *brealloc (void *buf, size_t size) { +#ifdef SMARTALOC + buf = sm_realloc(__FILE__, __LINE__, buf, size); +#else buf = realloc(buf, size); +#endif if (buf == NULL) { berrno be; Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), be.bstrerror()); @@ -243,7 +247,7 @@ void *brealloc (void *buf, size_t size) } -void *bcalloc (size_t size1, size_t size2) +void *bcalloc(size_t size1, size_t size2) { void *buf; diff --git a/bacula/src/lib/btime.c b/bacula/src/lib/btime.c index fbaacafdce..58487769b2 100644 --- a/bacula/src/lib/btime.c +++ b/bacula/src/lib/btime.c @@ -94,12 +94,19 @@ char *bstrftime_nc(char *dt, int maxlen, utime_t tim) { time_t ttime = (time_t)tim; struct tm tm; + char *p, *q; /* ***FIXME**** the format and localtime_r() should be user configurable */ (void)localtime_r(&ttime, &tm); /* NOTE! since the compiler complains about %y, I use %y and cut the century */ strftime(dt, maxlen, "%d-%b-%Y %H:%M", &tm); - strcpy(dt+7, dt+9); /* overlay the century */ + /* overlay the century */ + p = dt+7; + q = dt+9; + while (*q) { + *p++ = *q++; + } + *p = 0; return dt; } diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index f5a624af82..f395122b31 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -301,7 +301,7 @@ void init_signals(void terminate(int sig)) sigaction(SIGEMT, &sighandle, NULL); #endif #ifdef SIGIOT -/* sigaction(SIGIOT, &sighandle, NULL); used by debugger */ + sigaction(SIGIOT, &sighandle, NULL); #endif sigaction(SIGBUS, &sighandle, NULL); sigaction(SIGFPE, &sighandle, NULL); diff --git a/bacula/src/lib/smartall.c b/bacula/src/lib/smartall.c index 8101067eac..7f2ed1b2f8 100644 --- a/bacula/src/lib/smartall.c +++ b/bacula/src/lib/smartall.c @@ -91,6 +91,7 @@ struct abufhead { unsigned ablen; /* Buffer length in bytes */ const char *abfname; /* File name pointer */ sm_ushort ablineno; /* Line number of allocation */ + bool abin_use; /* set when malloced and cleared when free */ }; static struct b_queue abqueue = { /* Allocated buffer queue */ @@ -128,7 +129,8 @@ static void *smalloc(const char *fname, int lineno, unsigned int nbytes) qinsert(&abqueue, (struct b_queue *) buf); head->ablen = nbytes; head->abfname = bufimode ? NULL : fname; - head->ablineno = (sm_ushort) lineno; + head->ablineno = (sm_ushort)lineno; + head->abin_use = true; /* Emplace end-clobber detector at end of buffer */ buf[nbytes - 1] = (uint8_t)((((long) buf) & 0xFF) ^ 0xC5); buf += HEAD_SIZE; /* Increment to user data start */ @@ -160,6 +162,7 @@ void sm_new_owner(const char *fname, int lineno, char *buf) buf -= HEAD_SIZE; /* Decrement to header */ ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname; ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno; + ((struct abufhead *)buf)->abin_use = true; return; } @@ -186,6 +189,12 @@ void sm_free(const char *file, int line, void *fp) head->ablen, fp, head->abfname, head->ablineno); + if (!head->abin_use) { + V(mutex); + Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, line); + } + head->abin_use = false; + /* The following assertions will catch virtually every release of an address which isn't an allocated buffer. */ if (qp->qnext->qprev != qp) { @@ -217,9 +226,13 @@ void sm_free(const char *file, int line, void *fp) "designer garbage" (Duff Kurland's phrase) of alternating bits. This is intended to ruin the day for any miscreant who attempts to access data through a pointer into storage that's - been previously released. */ + been previously released. + + Modified, kes May, 2007 to not zap the header. This allows us + to check the in_use bit and detect doubly freed buffers. + */ - memset(cp, 0xAA, (int) head->ablen); + memset(cp+HEAD_SIZE, 0xAA, (int)(head->ablen - HEAD_SIZE)); free(cp); } @@ -282,14 +295,12 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) /* If the old block pointer is NULL, treat realloc() as a malloc(). SVID is silent on this, but many C libraries permit this. */ - if (ptr == NULL) { return sm_malloc(fname, lineno, size); } /* If the old and new sizes are the same, be a nice guy and just return the buffer passed in. */ - cp -= HEAD_SIZE; struct abufhead *head = (struct abufhead *)cp; osize = head->ablen - (HEAD_SIZE + 1); @@ -306,7 +317,7 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) // sm_bytes -= head->ablen; if ((buf = smalloc(fname, lineno, size)) != NULL) { - memcpy(buf, ptr, (int) sm_min(size, osize)); + memcpy(buf, ptr, (int)sm_min(size, osize)); /* If the new buffer is larger than the old, fill the balance of it with "designer garbage". */ if (size > osize) { @@ -314,7 +325,6 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size) } /* All done. Free and dechain the original buffer. */ - sm_free(__FILE__, __LINE__, ptr); } Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno); diff --git a/bacula/src/version.h b/bacula/src/version.h index 70a4f489b3..0b2b7c6222 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "2.1.11" -#define BDATE "26 May 2007" -#define LSMDATE "26May07" +#define BDATE "28 May 2007" +#define LSMDATE "28May07" #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 64f75bbb85..0249a337e6 100644 --- a/bacula/technotes-2.1 +++ b/bacula/technotes-2.1 @@ -1,6 +1,9 @@ Technical notes on version 2.1 General: +28May07 +kes Minor refactoring of restore decryption code. +kes Add code to smartall.c to detect double free of a buffer. 27May07 kes Add < > around %r in from field on mail command of bacula-dir.conf.in so that bsmtp will create a correct email address (mailbox only).