From b29a4a5430344451e18d4f9c741062c26d8357f2 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 3 Dec 2007 19:27:21 +0000 Subject: [PATCH] 03Dec07 kes This patch fixes bcopy so that it produces correct Volumes. It fixes bug #1022. kes This patch eliminates spurious output to the console during a VerifyVolume job that contains encrypted data. It fixes bug #1024. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6016 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/patches/2.2.6-bcopy.patch | 78 +++++++++++++++++++++++++++ bacula/patches/2.2.6-verify-vol.patch | 51 ++++++++++++++++++ bacula/src/filed/verify_vol.c | 16 +----- bacula/src/jcr.h | 1 + bacula/src/lib/protos.h | 2 + bacula/src/lib/util.c | 65 ++++++++++++++++------ bacula/src/stored/bcopy.c | 59 +++++++++++++++++--- bacula/technotes-2.3 | 8 ++- 8 files changed, 242 insertions(+), 38 deletions(-) create mode 100644 bacula/patches/2.2.6-bcopy.patch create mode 100644 bacula/patches/2.2.6-verify-vol.patch diff --git a/bacula/patches/2.2.6-bcopy.patch b/bacula/patches/2.2.6-bcopy.patch new file mode 100644 index 0000000000..a02dec4bda --- /dev/null +++ b/bacula/patches/2.2.6-bcopy.patch @@ -0,0 +1,78 @@ + + This patch fixes bcopy so that it produces correct Volumes. + It fixes bug #1022. + + Apply this patch to version 2.2.6 and possibly any 2.2.x version with: + + cd + patch -p0 2.2.6-bcopy.patch + ./configure + make + ... + make install + + +Index: src/stored/bcopy.c +=================================================================== +--- src/stored/bcopy.c (revision 6010) ++++ src/stored/bcopy.c (working copy) +@@ -89,6 +89,7 @@ + char *iVolumeName = NULL; + char *oVolumeName = NULL; + bool ignore_label_errors = false; ++ bool ok; + + setlocale(LC_ALL, ""); + bindtextdomain("bacula", LOCALEDIR); +@@ -199,9 +200,11 @@ + } + out_block = out_jcr->dcr->block; + +- read_records(in_jcr->dcr, record_cb, mount_next_read_volume); +- if (!write_block_to_device(out_jcr->dcr)) { +- Pmsg0(000, _("Write of last block failed.\n")); ++ ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume); ++ if (ok || out_dev->can_write()) { ++ if (!write_block_to_device(out_jcr->dcr)) { ++ Pmsg0(000, _("Write of last block failed.\n")); ++ } + } + + Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records); +@@ -253,6 +256,7 @@ + out_dev->print_name(), out_dev->bstrerror()); + Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + out_dev->bstrerror()); ++ return false; + } + } + if (!write_block_to_device(out_jcr->dcr)) { +@@ -260,8 +264,9 @@ + out_dev->print_name(), out_dev->bstrerror()); + Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + out_dev->bstrerror()); ++ return false; + } +- break; ++ return true; + case EOM_LABEL: + Pmsg0(000, _("EOM label not copied.\n")); + return true; +@@ -269,7 +274,7 @@ + Pmsg0(000, _("EOT label not copied.\n")); + return true; + default: +- break; ++ return true; + } + } + +@@ -283,7 +288,7 @@ + out_dev->print_name(), out_dev->bstrerror()); + Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + out_dev->bstrerror()); +- break; ++ return false; + } + } + return true; diff --git a/bacula/patches/2.2.6-verify-vol.patch b/bacula/patches/2.2.6-verify-vol.patch new file mode 100644 index 0000000000..264d108842 --- /dev/null +++ b/bacula/patches/2.2.6-verify-vol.patch @@ -0,0 +1,51 @@ + + This patch eliminates spurious output to the console during a VerifyVolume + job that contains encrypted data. + It fixes bug #1024. + + Apply this patch to Bacula version 2.2.6 and previous 2.2.x versions with: + + cd + patch -p0 <2.2.6-verify-vol.patch + ./configure + make + ... + make install + + +Index: src/filed/verify_vol.c +=================================================================== +--- src/filed/verify_vol.c (revision 6010) ++++ src/filed/verify_vol.c (working copy) +@@ -211,19 +211,6 @@ + } + break; + +- /* Data streams to ignore */ +- case STREAM_ENCRYPTED_SESSION_DATA: +- case STREAM_FILE_DATA: +- case STREAM_SPARSE_DATA: +- case STREAM_WIN32_DATA: +- case STREAM_WIN32_GZIP_DATA: +- case STREAM_GZIP_DATA: +- case STREAM_SPARSE_GZIP_DATA: +- case STREAM_SIGNED_DIGEST: +- +- /* Do nothing */ +- break; +- + case STREAM_MD5_DIGEST: + bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true); + Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest); +@@ -256,9 +243,10 @@ + Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg); + break; + ++ /* Ignore everything else */ + default: +- Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); + break; ++ + } /* end switch */ + } /* end while bnet_get */ + set_jcr_job_status(jcr, JS_Terminated); diff --git a/bacula/src/filed/verify_vol.c b/bacula/src/filed/verify_vol.c index bd94ad3a65..efc7ea4d18 100644 --- a/bacula/src/filed/verify_vol.c +++ b/bacula/src/filed/verify_vol.c @@ -211,19 +211,6 @@ void do_verify_volume(JCR *jcr) } break; - /* Data streams to ignore */ - case STREAM_ENCRYPTED_SESSION_DATA: - case STREAM_FILE_DATA: - case STREAM_SPARSE_DATA: - case STREAM_WIN32_DATA: - case STREAM_WIN32_GZIP_DATA: - case STREAM_GZIP_DATA: - case STREAM_SPARSE_GZIP_DATA: - case STREAM_SIGNED_DIGEST: - - /* Do nothing */ - break; - case STREAM_MD5_DIGEST: bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true); Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest); @@ -256,9 +243,10 @@ void do_verify_volume(JCR *jcr) Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg); break; + /* Ignore everything else */ default: - Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); break; + } /* end switch */ } /* end while bnet_get */ set_jcr_job_status(jcr, JS_Terminated); diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 8812594861..58b92d2ab2 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -308,6 +308,7 @@ public: /* Storage Daemon specific part of JCR */ JCR *next_dev; /* next JCR attached to device */ JCR *prev_dev; /* previous JCR attached to device */ + char *dir_auth_key; /* Dir auth key */ pthread_cond_t job_start_wait; /* Wait for FD to start Job */ int type; DCR *read_dcr; /* device context for reading */ diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 6f555ed5f1..93f1a20a7d 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -316,6 +316,8 @@ const char * job_type_to_str (int type); const char * job_status_to_str (int stat); const char * job_level_to_str (int level); void make_session_key (char *key, char *seed, int mode); +void encode_session_key (char *encode, char *session, char *key, int maxlen); +void decode_session_key (char *decode, char *session, char *key, int maxlen); POOLMEM * edit_job_codes (JCR *jcr, char *omsg, char *imsg, const char *to); void set_working_directory (char *wd); const char * last_path_separator (const char *str); diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index f1560a8cc9..74cbfe6e75 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -474,6 +474,8 @@ void make_session_key(char *key, char *seed, int mode) unsigned char md5key[16], md5key1[16]; char s[1024]; +#define ss sizeof(s) + s[0] = 0; if (seed != NULL) { bstrncat(s, seed, sizeof(s)); @@ -494,41 +496,41 @@ void make_session_key(char *key, char *seed, int mode) char *p; p = s; - sprintf(s + strlen(s), "%lu", (unsigned long)GetCurrentProcessId()); + sprintf(s + strlen(s), "%lu", (uint32_t)GetCurrentProcessId()); (void)getcwd(s + strlen(s), 256); - sprintf(s + strlen(s), "%lu", (unsigned long)GetTickCount()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)GetTickCount()); QueryPerformanceCounter(&li); - sprintf(s + strlen(s), "%lu", (unsigned long)li.LowPart); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)li.LowPart); GetSystemTimeAsFileTime(&ft); - sprintf(s + strlen(s), "%lu", (unsigned long)ft.dwLowDateTime); - sprintf(s + strlen(s), "%lu", (unsigned long)ft.dwHighDateTime); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)ft.dwLowDateTime); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)ft.dwHighDateTime); length = 256; GetComputerName(s + strlen(s), &length); length = 256; GetUserName(s + strlen(s), &length); } #else - sprintf(s + strlen(s), "%lu", (unsigned long)getpid()); - sprintf(s + strlen(s), "%lu", (unsigned long)getppid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getpid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getppid()); (void)getcwd(s + strlen(s), 256); - sprintf(s + strlen(s), "%lu", (unsigned long)clock()); - sprintf(s + strlen(s), "%lu", (unsigned long)time(NULL)); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)clock()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)time(NULL)); #if defined(Solaris) sysinfo(SI_HW_SERIAL,s + strlen(s), 12); #endif #if defined(HAVE_GETHOSTID) - sprintf(s + strlen(s), "%lu", (unsigned long) gethostid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t) gethostid()); #endif gethostname(s + strlen(s), 256); - sprintf(s + strlen(s), "%u", (unsigned)getuid()); - sprintf(s + strlen(s), "%u", (unsigned)getgid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getuid()); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)getgid()); #endif MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)s, strlen(s)); + MD5Update(&md5c, (uint8_t *)s, strlen(s)); MD5Final(md5key, &md5c); - sprintf(s + strlen(s), "%lu", (unsigned long)((time(NULL) + 65121) ^ 0x375F)); + bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)((time(NULL) + 65121) ^ 0x375F)); MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)s, strlen(s)); + MD5Update(&md5c, (uint8_t *)s, strlen(s)); MD5Final(md5key1, &md5c); #define nextrand (md5key[j] ^ md5key1[j]) if (mode) { @@ -552,6 +554,39 @@ void make_session_key(char *key, char *seed, int mode) } #undef nextrand +void encode_session_key(char *encode, char *session, char *key, int maxlen) +{ + int i; + for (i=0; (i < maxlen-1) && session[i]; i++) { + if (session[i] == '-') { + encode[i] = '-'; + } else { + encode[i] = ((session[i] - 'A' + key[i]) & 0xF) + 'A'; + } + } + encode[i] = 0; + Dmsg3(000, "Session=%s key=%s encode=%s\n", session, key, encode); +} + +void decode_session_key(char *decode, char *session, char *key, int maxlen) +{ + int i, x; + + for (i=0; (i < maxlen-1) && session[i]; i++) { + if (session[i] == '-') { + decode[i] = '-'; + } else { + x = (session[i] - 'A' - key[i]) & 0xF; + if (x < 0) { + x += 16; + } + decode[i] = x + 'A'; + } + } + decode[i] = 0; + Dmsg3(000, "Session=%s key=%s decode=%s\n", session, key, decode); +} + /* diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index 0faaf89d73..2397838333 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -42,6 +42,7 @@ int generate_daemon_event(JCR *jcr, const char *event) { return 1; } /* Forward referenced functions */ +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); static bool record_cb(DCR *dcr, DEV_RECORD *rec); @@ -52,10 +53,11 @@ static JCR *in_jcr; /* input jcr */ static JCR *out_jcr; /* output jcr */ static BSR *bsr = NULL; static const char *wd = "/tmp"; -static int list_records = 0; +static bool list_records = false; static uint32_t records = 0; static uint32_t jobs = 0; static DEV_BLOCK *out_block; +static SESSION_LABEL sessrec; #define CONFIG_FILE "bacula-sd.conf" char *configfile = NULL; @@ -90,6 +92,7 @@ int main (int argc, char *argv[]) char *iVolumeName = NULL; char *oVolumeName = NULL; bool ignore_label_errors = false; + bool ok; setlocale(LC_ALL, ""); bindtextdomain("bacula", LOCALEDIR); @@ -205,9 +208,12 @@ int main (int argc, char *argv[]) } out_block = out_jcr->dcr->block; - read_records(in_jcr->dcr, record_cb, mount_next_read_volume); - if (!write_block_to_device(out_jcr->dcr)) { - Pmsg0(000, _("Write of last block failed.\n")); + ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume); + + if (ok || out_dev->can_write()) { + if (!write_block_to_device(out_jcr->dcr)) { + Pmsg0(000, _("Write of last block failed.\n")); + } } Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records); @@ -236,6 +242,7 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) * */ if (rec->FileIndex < 0) { + get_session_record(in_dcr->dev, rec, &sessrec); if (verbose > 1) { dump_label_record(in_dcr->dev, rec, 1); @@ -259,6 +266,7 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) out_dev->print_name(), out_dev->bstrerror()); Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), out_dev->bstrerror()); + return false; } } if (!write_block_to_device(out_jcr->dcr)) { @@ -266,8 +274,9 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) out_dev->print_name(), out_dev->bstrerror()); Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), out_dev->bstrerror()); + return false; } - break; + return true; case EOM_LABEL: Pmsg0(000, _("EOM label not copied.\n")); return true; @@ -275,7 +284,7 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) Pmsg0(000, _("EOT label not copied.\n")); return true; default: - break; + return true; } } @@ -289,12 +298,48 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) out_dev->print_name(), out_dev->bstrerror()); Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), out_dev->bstrerror()); - break; + return false; } } return true; } +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) +{ + const char *rtype; + memset(sessrec, 0, sizeof(sessrec)); + switch (rec->FileIndex) { + case PRE_LABEL: + rtype = _("Fresh Volume Label"); + break; + case VOL_LABEL: + rtype = _("Volume Label"); + unser_volume_label(dev, rec); + break; + case SOS_LABEL: + rtype = _("Begin Job Session"); + unser_session_label(sessrec, rec); + break; + case EOS_LABEL: + rtype = _("End Job Session"); + unser_session_label(sessrec, rec); + break; + case 0: + case EOM_LABEL: + rtype = _("End of Medium"); + break; + default: + rtype = _("Unknown"); + break; + } + Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); + if (verbose) { + Pmsg5(-1, _("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n"), + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); + } +} + /* Dummies to replace askdir.c */ bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} diff --git a/bacula/technotes-2.3 b/bacula/technotes-2.3 index 7bae8283cc..48b273800b 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -1,6 +1,11 @@ Technical notes on version 2.3 General: +03Dec07 +kes This patch fixes bcopy so that it produces correct Volumes. + It fixes bug #1022. +kes This patch eliminates spurious output to the console during a VerifyVolume + job that contains encrypted data. It fixes bug #1024. 02Dec07 kes This patch prevents the 'status dir' command from trying to use a scratch volume and possibly moving it from one pool to another. This patch fixes @@ -26,8 +31,7 @@ kes This patch should fix the Mac OS X build problem on the latest due to a change in the Mac headers). The solution was to explicitly ensure that it is defined for the ./configure. This patch also has a rebuild of configure that includes the Debian - qt4 kludge (look for alternate qt4 names). - This patch fixes bug #1020. + qt4 patch to check for qmake-qt4. This patch fixes bug #1020. kes This patch should ensure that queued messages to the console are displayed as soon as possible. It should fix bug 1007, but has been reported not to work. -- 2.39.5