From fba5161a866a233d5eacc1827e649f921590709f Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 27 Jan 2003 12:02:40 +0000 Subject: [PATCH] SHA1 implementation git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@325 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 2 + bacula/src/baconfig.h | 8 ++ bacula/src/cats/bdb.c | 3 + bacula/src/cats/bdb_update.c | 2 +- bacula/src/cats/cats.h | 3 +- bacula/src/cats/protos.h | 2 +- bacula/src/cats/sql_get.c | 2 +- bacula/src/cats/sql_update.c | 5 +- bacula/src/dird/catreq.c | 26 +++-- bacula/src/dird/dird_conf.c | 20 +++- bacula/src/dird/dird_conf.h | 34 +++--- bacula/src/dird/fd_cmds.c | 19 ++-- bacula/src/dird/verify.c | 56 ++++++---- bacula/src/filed/backup.c | 21 +++- bacula/src/filed/restore.c | 4 +- bacula/src/filed/verify.c | 28 +++-- bacula/src/filed/verify_vol.c | 10 +- bacula/src/findlib/find.h | 2 + bacula/src/findlib/match.c | 3 + bacula/src/lib/Makefile.in | 6 +- bacula/src/lib/lib.h | 3 +- bacula/src/lib/md5.c | 33 ++++++ bacula/src/lib/sha1.c | 194 +++++++++++++++++----------------- bacula/src/lib/sha1.h | 50 ++++----- bacula/src/stored/append.c | 2 +- bacula/src/stored/bextract.c | 3 +- bacula/src/stored/bscan.c | 27 +++-- bacula/src/stored/mount.c | 6 ++ bacula/src/stored/record.c | 4 + 29 files changed, 369 insertions(+), 209 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index dca4df3e5e..3420d0843a 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -15,6 +15,8 @@ Testing to do: (painful) - blocksize recognition code. For 1.30 release: +- Add Signature type to File DB record. + - CD into subdirectory when open()ing files for backup to speed up things. Test with testfind(). - Add prefixlinks to where or not where absolute links to FD. diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index cc21842f88..a077b5b6bb 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -102,6 +102,14 @@ #define STREAM_SPARSE_GZIP_DATA 7 #define STREAM_PROGRAM_NAMES 8 /* program names for program data */ #define STREAM_PROGRAM_DATA 9 /* Data needing program */ +#define STREAM_SHA1_SIGNATURE 10 /* SHA1 signature for the file */ + +/* + * Internal code for Signature types + */ +#define NO_SIG 0 +#define MD5_SIG 1 +#define SHA1_SIG 2 /* Size of File Address stored in STREAM_SPARSE_DATA. Do NOT change! */ #define SPARSE_FADDR_SIZE (sizeof(uint64_t)) diff --git a/bacula/src/cats/bdb.c b/bacula/src/cats/bdb.c index 7ed4282616..d35bc53dac 100644 --- a/bacula/src/cats/bdb.c +++ b/bacula/src/cats/bdb.c @@ -128,6 +128,9 @@ db_init_database(void *jcr, char *db_name, char *db_user, char *db_password) Dmsg0(200, "Done db_open_database()\n"); mdb->cfd = -1; V(mutex); + Jmsg(jcr, M_WARNING, 0, _("WARNING!!!! The Internal Database is for TESTING ONLY!\n")); + Jmsg(jcr, M_WARNING, 0, _("You should use either SQLite or MySQL\n")); + return mdb; } diff --git a/bacula/src/cats/bdb_update.c b/bacula/src/cats/bdb_update.c index 0a82099b49..0b043af65e 100755 --- a/bacula/src/cats/bdb_update.c +++ b/bacula/src/cats/bdb_update.c @@ -192,7 +192,7 @@ int db_update_pool_record(void *jcr, B_DB *mdb, POOL_DBR *pr) return stat; } -int db_add_MD5_to_file_record(void *jcr, B_DB *mdb, FileId_t FileId, char *MD5) +int db_add_SIG_to_file_record(void *jcr, B_DB *mdb, FileId_t FileId, char *SIG, int type) { return 1; } diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index c65ca3362f..abd39a2404 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -365,7 +365,8 @@ typedef struct { JobId_t MarkId; char LStat[256]; /* int Status; */ - char MD5[50]; + char SIG[50]; + int SigType; /* NO_SIG/MD5_SIG/SHA1_SIG */ } FILE_DBR; /* Pool record -- same format as database */ diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index c1c4111dc8..a212423604 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -94,7 +94,7 @@ int db_update_job_start_record(void *jcr, B_DB *db, JOB_DBR *jr); int db_update_job_end_record(void *jcr, B_DB *db, JOB_DBR *jr); int db_update_pool_record(void *jcr, B_DB *db, POOL_DBR *pr); int db_update_media_record(void *jcr, B_DB *db, MEDIA_DBR *mr); -int db_add_MD5_to_file_record(void *jcr, B_DB *mdb, FileId_t FileId, char *MD5); +int db_add_SIG_to_file_record(void *jcr, B_DB *mdb, FileId_t FileId, char *SIG, int type); int db_mark_file_record(void *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId); #endif /* __SQL_PROTOS_H */ diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 3568f1bf04..bc6af6899d 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -128,7 +128,7 @@ File.FilenameId=%u", fdbr->JobId, fdbr->PathId, fdbr->FilenameId); } else { fdbr->FileId = (FileId_t)str_to_int64(row[0]); bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat)); - bstrncpy(fdbr->MD5, row[2], sizeof(fdbr->MD5)); + bstrncpy(fdbr->SIG, row[2], sizeof(fdbr->SIG)); stat = 1; } } else { diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index 0029261496..e127ae1467 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -55,12 +55,13 @@ extern int UpdateDB(char *file, int line, void *jcr, B_DB *db, char *update_cmd) */ /* Update the attributes record by adding the MD5 signature */ int -db_add_MD5_to_file_record(void *jcr, B_DB *mdb, FileId_t FileId, char *MD5) +db_add_SIG_to_file_record(void *jcr, B_DB *mdb, FileId_t FileId, char *SIG, + int type) { int stat; db_lock(mdb); - Mmsg(&mdb->cmd, "UPDATE File SET MD5='%s' WHERE FileId=%u", MD5, FileId); + Mmsg(&mdb->cmd, "UPDATE File SET MD5='%s' WHERE FileId=%u", SIG, FileId); stat = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return stat; diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 0a74a5b79a..f944bfaf33 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -382,20 +382,28 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) if (!db_create_file_attributes_record(jcr, jcr->db, &ar)) { Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db)); } - /* Save values for MD5 update */ + /* Save values for SIG update */ jcr->FileId = ar.FileId; jcr->FileIndex = FileIndex; - } else if (Stream == STREAM_MD5_SIGNATURE) { + } else if (Stream == STREAM_MD5_SIGNATURE || Stream == STREAM_SHA1_SIGNATURE) { fname = p; if (jcr->FileIndex != FileIndex) { - Jmsg(jcr, M_WARNING, 0, "Got MD5 but not same File as attributes\n"); + Jmsg(jcr, M_WARNING, 0, "Got MD5/SHA1 but not same File as attributes\n"); } else { - /* Update MD5 signature in catalog */ - char MD5buf[50]; /* 24 bytes should be enough */ - bin_to_base64(MD5buf, fname, 16); - Dmsg2(190, "MD5len=%d MD5=%s\n", strlen(MD5buf), MD5buf); - if (!db_add_MD5_to_file_record(jcr, jcr->db, jcr->FileId, MD5buf)) { - Jmsg(jcr, M_ERROR, 0, _("Catalog error updating MD5. %s"), + /* Update signature in catalog */ + char SIGbuf[50]; /* 24 bytes should be enough */ + int len, type; + if (Stream == STREAM_MD5_SIGNATURE) { + len = 16; + type = MD5_SIG; + } else { + len = 20; + type = SHA1_SIG; + } + bin_to_base64(SIGbuf, fname, len); + Dmsg3(190, "SIGlen=%d SIG=%s type=%d\n", strlen(SIGbuf), SIGbuf, Stream); + if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIGbuf, type)) { + Jmsg(jcr, M_ERROR, 0, _("Catalog error updating MD5/SHA1. %s"), db_strerror(jcr->db)); } } diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index c0ec70f10c..136b4e25a2 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -189,6 +189,18 @@ static struct res_items job_items[] = { {NULL, NULL, NULL, 0, 0, 0} }; +/* FileOptions resource + * + * name handler value code flags default_value + */ +static struct res_items fo_items[] = { + {"name", store_name, ITEM(res_fo.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(res_fo.hdr.desc), 0, 0, 0}, + {"replace", store_replace, ITEM(res_fo.replace), REPLACE_ALWAYS, ITEM_DEFAULT, 0}, + {NULL, NULL, NULL, 0, 0, 0} +}; + + /* FileSet resource * * name handler value code flags default_value @@ -278,6 +290,7 @@ struct s_res resources[] = { {"storage", store_items, R_STORAGE, NULL}, {"catalog", cat_items, R_CATALOG, NULL}, {"schedule", sch_items, R_SCHEDULE, NULL}, + {"fileoptions", fo_items, R_FILEOPTIONS, NULL}, {"fileset", fs_items, R_FILESET, NULL}, {"group", group_items, R_GROUP, NULL}, {"pool", pool_items, R_POOL, NULL}, @@ -384,6 +397,7 @@ struct s_fs_opt { /* Options permitted for each keyword and resulting value */ static struct s_fs_opt FS_options[] = { {"md5", INC_KW_SIGNATURE, "M"}, + {"sha1", INC_KW_SIGNATURE, "S"}, {"gzip", INC_KW_COMPRESSION, "Z6"}, {"gzip1", INC_KW_COMPRESSION, "Z1"}, {"gzip2", INC_KW_COMPRESSION, "Z2"}, @@ -1333,7 +1347,7 @@ static void store_inc(LEX *lc, struct res_items *item, int index, int pass) case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: - fname = (char *) malloc(lc->str_len + inc_opts_len + 1); + fname = (char *)malloc(lc->str_len + inc_opts_len + 1); strcpy(fname, inc_opts); strcat(fname, lc->str); if (res_all.res_fs.have_MD5) { @@ -1355,9 +1369,9 @@ static void store_inc(LEX *lc, struct res_items *item, int index, int pass) if (res_all.res_fs.num_excludes == res_all.res_fs.exclude_size) { res_all.res_fs.exclude_size += 10; if (res_all.res_fs.exclude_array == NULL) { - res_all.res_fs.exclude_array = (char **) malloc(sizeof(char *) * res_all.res_fs.exclude_size); + res_all.res_fs.exclude_array = (char **)malloc(sizeof(char *) * res_all.res_fs.exclude_size); } else { - res_all.res_fs.exclude_array = (char **) realloc(res_all.res_fs.exclude_array, + res_all.res_fs.exclude_array = (char **)realloc(res_all.res_fs.exclude_array, sizeof(char *) * res_all.res_fs.exclude_size); } } diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index d72a1b6319..c76ef353ec 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -6,7 +6,7 @@ * Version $Id$ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2003 2002 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -180,6 +180,24 @@ struct s_res_job { }; typedef struct s_res_job JOB; +/* + * File Options Resource (options for Includes) + */ +struct s_res_fo { + RES hdr; + + char opts[20]; /* Options string */ + int replace; /* How (overwrite, ...) */ + struct s_applyto *applyto; /* applyto strings */ +}; +typedef struct s_res_fo FILEOPTIONS; + +struct s_incexc_item { + char opts[20]; /* options string */ + struct s_res_fo *fileopts; /* file options */ + char name[1]; /* include/exclude name */ +}; + /* * FileSet Resource * @@ -187,6 +205,7 @@ typedef struct s_res_job JOB; struct s_res_fs { RES hdr; + /* ***FIXME*** each include must have chain of FileOptions */ char **include_array; int num_includes; int include_size; @@ -195,22 +214,11 @@ struct s_res_fs { int exclude_size; int have_MD5; /* set if MD5 initialized */ struct MD5Context md5c; /* MD5 of include/exclude */ - char MD5[50]; /* base 64 representation of MD5 */ + char MD5[30]; /* base 64 representation of MD5 */ }; typedef struct s_res_fs FILESET; -/* - * FileOptions Resource (options for Includes) - */ -struct s_res_fo { - RES hdr; - - char opts[50]; /* Options string */ - struct s_applyto *applyto; /* applyto strings */ -}; -typedef struct s_res_fo FILEOPTIONS; - /* * Schedule Resource * diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index fdeecd0cef..421f7b8c9c 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -270,11 +270,11 @@ int get_attributes_and_put_in_catalog(JCR *jcr) long file_index; int stream, len; char *attr, *p, *fn; - char Opts_MD5[MAXSTRING]; /* either Verify opts or MD5 signature */ - char MD5[MAXSTRING]; + char Opts_SIG[MAXSTRING]; /* either Verify opts or MD5/SHA1 signature */ + char SIG[MAXSTRING]; jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen); - if ((len = sscanf(fd->msg, "%ld %d %s", &file_index, &stream, Opts_MD5)) != 3) { + if ((len = sscanf(fd->msg, "%ld %d %s", &file_index, &stream, Opts_SIG)) != 3) { Jmsg(jcr, M_FATAL, 0, _("msglen, fd->msg); set_jcr_job_status(jcr, JS_ErrorTerminated); @@ -285,7 +285,7 @@ msglen=%d msg=%s\n"), len, fd->msglen, fd->msg); skip_spaces(&p); skip_nonspaces(&p); /* skip Stream */ skip_spaces(&p); - skip_nonspaces(&p); /* skip Opts_MD5 */ + skip_nonspaces(&p); /* skip Opts_SHA1 */ p++; /* skip space */ fn = jcr->fname; while (*p != 0) { @@ -316,16 +316,17 @@ msglen=%d msg=%s\n"), len, fd->msglen, fd->msg); continue; } jcr->FileId = ar.FileId; - } else if (stream == STREAM_MD5_SIGNATURE) { + } else if (stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE) { if (jcr->FileIndex != (uint32_t)file_index) { - Jmsg2(jcr, M_ERROR, 0, _("MD5 index %d not same as attributes %d\n"), + Jmsg2(jcr, M_ERROR, 0, _("MD5/SHA1 index %d not same as attributes %d\n"), file_index, jcr->FileIndex); set_jcr_job_status(jcr, JS_Error); continue; } - db_escape_string(MD5, Opts_MD5, strlen(Opts_MD5)); - Dmsg2(120, "MD5len=%d MD5=%s\n", strlen(MD5), MD5); - if (!db_add_MD5_to_file_record(jcr, jcr->db, jcr->FileId, MD5)) { + db_escape_string(SIG, Opts_SIG, strlen(Opts_SIG)); + Dmsg2(120, "SIGlen=%d SIG=%s\n", strlen(SIG), SIG); + if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIG, + stream==STREAM_MD5_SIGNATURE?MD5_SIG:SHA1_SIG)) { Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); set_jcr_job_status(jcr, JS_Error); } diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 027e30af5c..cc62515d0e 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -377,7 +377,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) int stat = JS_Terminated; char buf[MAXSTRING]; POOLMEM *fname = get_pool_memory(PM_MESSAGE); - int do_MD5 = FALSE; + int do_SIG = NO_SIG; long file_index = 0; memset(&fdbr, 0, sizeof(FILE_DBR)); @@ -387,11 +387,11 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) Dmsg0(20, "bdird: waiting to receive file attributes\n"); /* - * Get Attributes and MD5 Signature from File daemon + * Get Attributes and Signature from File daemon * We expect: * FileIndex * Stream - * Options or MD5 + * Options or SIG (MD5/SHA1) * Filename * Attributes * Link name ??? @@ -399,23 +399,28 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) while ((n=bget_msg(fd, 0)) >= 0 && !job_cancelled(jcr)) { int stream; char *attr, *p, *fn; - char Opts_MD5[MAXSTRING]; /* Verify Opts or MD5 signature */ + char Opts_SIG[MAXSTRING]; /* Verify Opts or MD5/SHA1 signature */ fname = check_pool_memory_size(fname, fd->msglen); jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen); - Dmsg1(400, "Atts+MD5=%s\n", fd->msg); + Dmsg1(400, "Atts+SIG=%s\n", fd->msg); if ((len = sscanf(fd->msg, "%ld %d %100s", &file_index, &stream, - Opts_MD5)) != 3) { + fname)) != 3) { Jmsg3(jcr, M_FATAL, 0, _("birdmsglen, fd->msg); goto bail_out; } + /* + * We read the Options or Signature into fname + * to prevent overrun, now copy it to proper location. + */ + bstrncpy(Opts_SIG, fname, sizeof(Opts_SIG)); p = fd->msg; skip_nonspaces(&p); /* skip FileIndex */ skip_spaces(&p); skip_nonspaces(&p); /* skip Stream */ skip_spaces(&p); - skip_nonspaces(&p); /* skip Opts_MD5 */ + skip_nonspaces(&p); /* skip Opts_SIG */ p++; /* skip space */ fn = fname; while (*p != 0) { @@ -431,7 +436,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) jcr->JobFiles++; jcr->FileIndex = file_index; /* remember attribute file_index */ decode_stat(attr, &statf); /* decode file stat packet */ - do_MD5 = FALSE; + do_SIG = NO_SIG; jcr->fn_printed = FALSE; strcpy(jcr->fname, fname); /* move filename into JCR */ @@ -456,13 +461,13 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) } Dmsg3(400, "Found %s in catalog. inx=%d Opts=%s\n", jcr->fname, - file_index, Opts_MD5); + file_index, Opts_SIG); decode_stat(fdbr.LStat, &statc); /* decode catalog stat */ /* * Loop over options supplied by user and verify the * fields he requests. */ - for (p=Opts_MD5; *p; p++) { + for (p=Opts_SIG; *p; p++) { char ed1[30], ed2[30]; switch (*p) { case 'i': /* compare INODEs */ @@ -547,7 +552,10 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) break; case '5': /* compare MD5 */ Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname); - do_MD5 = TRUE; + do_SIG = MD5_SIG; + break; + case '1': /* compare SHA1 */ + do_SIG = SHA1_SIG; break; case ':': case 'V': @@ -556,32 +564,34 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) } } /* - * Got MD5 Signature from Storage daemon - * It came across in the Opts_MD5 field. + * Got SIG Signature from Storage daemon + * It came across in the Opts_SIG field. */ - } else if (stream == STREAM_MD5_SIGNATURE) { - Dmsg2(400, "stream=MD5 inx=%d MD5=%s\n", file_index, Opts_MD5); + } else if (stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE) { + Dmsg2(400, "stream=SIG inx=%d SIG=%s\n", file_index, Opts_SIG); /* - * When ever we get an MD5 signature is MUST have been + * When ever we get a signature is MUST have been * preceded by an attributes record, which sets attr_file_index */ if (jcr->FileIndex != (uint32_t)file_index) { - Jmsg2(jcr, M_FATAL, 0, _("MD5 index %d not same as attributes %d\n"), + Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"), file_index, jcr->FileIndex); goto bail_out; } - if (do_MD5) { - db_escape_string(buf, Opts_MD5, strlen(Opts_MD5)); - if (strcmp(buf, fdbr.MD5) != 0) { + if (do_SIG) { + db_escape_string(buf, Opts_SIG, strlen(Opts_SIG)); + if (strcmp(buf, fdbr.SIG) != 0) { prt_fname(jcr); if (debug_level >= 10) { - Jmsg(jcr, M_INFO, 0, _(" MD5 not same. File=%s Cat=%s\n"), buf, fdbr.MD5); + Jmsg(jcr, M_INFO, 0, _(" %s not same. File=%s Cat=%s\n"), + stream==STREAM_MD5_SIGNATURE?"MD5":"SHA1", buf, fdbr.SIG); } else { - Jmsg(jcr, M_INFO, 0, _(" MD5 differs.\n")); + Jmsg(jcr, M_INFO, 0, _(" %s differs.\n"), + stream==STREAM_MD5_SIGNATURE?"MD5":"SHA1"); } stat = JS_Differences; } - do_MD5 = FALSE; + do_SIG = FALSE; } } jcr->JobFiles = file_index; diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 4d7e009229..75a5da3e02 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -99,8 +99,10 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) char attribsEx[MAXSTRING]; int stat, stream; struct MD5Context md5c; + struct SHA1Context sha1c; int gotMD5 = 0; - unsigned char signature[16]; + int gotSHA1 = 0; + unsigned char signature[25]; /* large enough for either signature */ BSOCK *sd; JCR *jcr = (JCR *)ijcr; POOLMEM *msgsave; @@ -312,6 +314,8 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) if (ff_pkt->flags & FO_MD5) { MD5Init(&md5c); + } else if (ff_pkt->flags & FO_SHA1) { + SHA1Init(&sha1c); } /* @@ -348,6 +352,9 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) if (ff_pkt->flags & FO_MD5) { MD5Update(&md5c, (unsigned char *)rbuf, sd->msglen); gotMD5 = 1; + } else if (ff_pkt->flags & FO_SHA1) { + SHA1Update(&sha1c, (unsigned char *)rbuf, sd->msglen); + gotSHA1 = 1; } #ifdef HAVE_LIBZ @@ -422,6 +429,18 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) sd->msglen = 16; bnet_send(sd); bnet_sig(sd, BNET_EOD); /* end of MD5 */ +#endif + gotMD5 = 0; + } else if (gotSHA1 && ff_pkt->flags & FO_SHA1) { + /* Terminate any SHA1 signature and send it to Storage daemon and the Director */ + SHA1Final(&sha1c, signature); +#ifndef NO_FD_SEND_TEST + bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_SHA1_SIGNATURE); + Dmsg1(100, "bfiled>stored:header %s\n", sd->msg); + memcpy(sd->msg, signature, 20); + sd->msglen = 20; + bnet_send(sd); + bnet_sig(sd, BNET_EOD); /* end of SHA1 */ #endif gotMD5 = 0; } diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 206cf33f27..7447678834 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -90,7 +90,7 @@ void do_restore(JCR *jcr) * 2. Stream data * a. Attributes (Unix or Win32) * or b. File data for the file - * or c. Possibly MD5 record + * or c. Possibly MD5 or SHA1 record * 3. Repeat step 1 */ while (bnet_recv(sd) >= 0 && !job_cancelled(jcr)) { @@ -365,7 +365,7 @@ void do_restore(JCR *jcr) set_attributes(jcr, fname, ofile, lname, type, stream, &statp, attribsEx, &ofd); extract = FALSE; - } else if (stream != STREAM_MD5_SIGNATURE) { + } else if (!(stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE)) { Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); } } diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 410eaaa58c..20214f086d 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -61,7 +61,7 @@ void do_verify(JCR *jcr) /* * Called here by find() for each file. * - * Find the file, compute the MD5 and send it back to the Director + * Find the file, compute the MD5 or SHA1 and send it back to the Director */ static int verify_file(FF_PKT *ff_pkt, void *pkt) { @@ -69,7 +69,8 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) int32_t n; int fid, stat; struct MD5Context md5c; - unsigned char signature[20]; + struct SHA1Context sha1c; + unsigned char signature[25]; /* large enough for either */ BSOCK *dir; JCR *jcr = (JCR *)pkt; @@ -189,10 +190,8 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) /* If file opened, compute MD5 */ if (fid >= 0 && ff_pkt->flags & FO_MD5) { - char MD5buf[50]; /* 24 should do */ - + char MD5buf[40]; /* 24 should do */ MD5Init(&md5c); - while ((n=read(fid, jcr->big_buf, jcr->buf_size)) > 0) { MD5Update(&md5c, ((unsigned char *) jcr->big_buf), n); jcr->JobBytes += n; @@ -201,7 +200,6 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) Jmsg(jcr, M_WARNING, -1, _("Error reading file %s: ERR=%s\n"), ff_pkt->fname, strerror(errno)); } - MD5Final(signature, &md5c); bin_to_base64(MD5buf, (char *)signature, 16); /* encode 16 bytes */ @@ -209,6 +207,24 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_SIGNATURE, MD5buf, jcr->JobFiles); Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg); + } else if (fid >= 0 && ff_pkt->flags & FO_SHA1) { + char SHA1buf[40]; /* 24 should do */ + SHA1Init(&sha1c); + while ((n=read(fid, jcr->big_buf, jcr->buf_size)) > 0) { + SHA1Update(&sha1c, ((unsigned char *) jcr->big_buf), n); + jcr->JobBytes += n; + } + if (n < 0) { + Jmsg(jcr, M_WARNING, -1, _("Error reading file %s: ERR=%s\n"), + ff_pkt->fname, strerror(errno)); + } + SHA1Final(&sha1c, signature); + + bin_to_base64(SHA1buf, (char *)signature, 20); /* encode 20 bytes */ + Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf); + bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE, + SHA1buf, jcr->JobFiles); + Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg); } if (fid >= 0) { close(fid); diff --git a/bacula/src/filed/verify_vol.c b/bacula/src/filed/verify_vol.c index fff1f556d9..59f7a7533b 100644 --- a/bacula/src/filed/verify_vol.c +++ b/bacula/src/filed/verify_vol.c @@ -213,7 +213,15 @@ void do_verify_volume(JCR *jcr) jcr->JobFiles); Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg); - } else if (stream != STREAM_MD5_SIGNATURE) { + /* If SHA1 stream */ + } else if (stream == STREAM_SHA1_SIGNATURE) { + char SHA1buf[30]; + bin_to_base64(SHA1buf, (char *)sd->msg, 20); /* encode 20 bytes */ + Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf); + bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE, + SHA1buf, jcr->JobFiles); + Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg); + } else { Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); } } diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 38e84430fe..00c17cb49b 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -84,6 +84,7 @@ #define FO_IF_NEWER 0x020 /* replace if newer */ #define FO_NOREPLACE 0x040 /* never replace */ #define FO_READFIFO 0x080 /* read data from fifo */ +#define FO_SHA1 0x100 /* Do SHA1 checksum */ /* * Options saved in "options" of include list @@ -100,6 +101,7 @@ #define OPT_replace_if_newer 0x20 /* replace file if newer */ #define OPT_never_replace 0x40 /* never replace */ #define OPT_read_fifo 0x80 /* read data from fifo (named pipe) */ +#define OPT_compute_SHA1 0x100 /* compute SHA1 of file's data */ struct s_included_file { diff --git a/bacula/src/findlib/match.c b/bacula/src/findlib/match.c index b22d2883b3..fcb59daa0d 100644 --- a/bacula/src/findlib/match.c +++ b/bacula/src/findlib/match.c @@ -115,6 +115,9 @@ void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname) case 'M': /* MD5 */ inc->options |= OPT_compute_MD5; break; + case 'S': + inc->options |= OPT_compute_SHA1; + break; case 'n': inc->options |= OPT_never_replace; break; diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 3429ff9c10..58a4aec748 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -36,7 +36,7 @@ LIBSRCS = alloc.c base64.c bmisc.c bnet.c bnet_server.c \ cram-md5.c crc32.c daemon.c edit.c fnmatch.c \ hmac.c idcache.c jcr.c lex.c \ md5.c message.c mem_pool.c parse_conf.c \ - queue.c rwlock.c serial.c \ + queue.c rwlock.c serial.c sha1.c \ signal.c smartall.c tree.c util.c watchdog.c workq.c # immortal.c filesys.c @@ -46,7 +46,7 @@ LIBOBJS = alloc.o base64.o bmisc.o bnet.o bnet_server.o \ cram-md5.o crc32.o daemon.o edit.o fnmatch.o \ hmac.o idcache.o jcr.o lex.o \ md5.o message.o mem_pool.o parse_conf.o \ - queue.o rwlock.o serial.o \ + queue.o rwlock.o serial.o sha1.o \ signal.o smartall.o tree.o util.o watchdog.o workq.o # immortal.o filesys.o @@ -107,7 +107,7 @@ uninstall: clean: $(RMF) *.a core a.out *.o *.bak *.tex *.pdf *~ *.intpro *.extpro 1 2 3 - $(RMF) rwlock_test + $(RMF) rwlock_test md5 sha1 realclean: clean $(RMF) tags diff --git a/bacula/src/lib/lib.h b/bacula/src/lib/lib.h index b36100dc03..b9bd672830 100644 --- a/bacula/src/lib/lib.h +++ b/bacula/src/lib/lib.h @@ -9,7 +9,7 @@ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2003 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -45,6 +45,7 @@ #include "fnmatch.h" #endif #include "md5.h" +#include "sha1.h" #include "tree.h" #include "watchdog.h" #include "bpipe.h" diff --git a/bacula/src/lib/md5.c b/bacula/src/lib/md5.c index ec48a43ee4..f5a68abc1c 100644 --- a/bacula/src/lib/md5.c +++ b/bacula/src/lib/md5.c @@ -249,3 +249,36 @@ void MD5Transform(uint32_t buf[4], uint32_t in[16]) buf[2] += c; buf[3] += d; } + +#ifdef MD5_SUM +/* + * Reads a single ASCII file and prints the HEX md5 sum. + */ +#include +int main(int argc, char *argv[]) +{ + FILE *fd; + MD5Context ctx; + char buf[5000]; + char signature[20]; + + if (argc < 1) { + printf("Must have filename\n"); + exit(1); + } + fd = fopen(argv[1], "r"); + if (!fd) { + printf("Could not open %s: ERR=%s\n", argv[1], strerror(errno)); + exit(1); + } + MD5Init(&ctx); + while (fgets(buf, sizeof(buf), fd)) { + MD5Update(&ctx, (unsigned char *)buf, strlen(buf)); + } + MD5Final((unsigned char *)signature, &ctx); + for (int i=0; i < 16; i++) { + printf("%02x", signature[i]& 0xFF); + } + printf(" %s\n", argv[1]); +} +#endif diff --git a/bacula/src/lib/sha1.c b/bacula/src/lib/sha1.c index 78877489bb..1d4ed9c95d 100644 --- a/bacula/src/lib/sha1.c +++ b/bacula/src/lib/sha1.c @@ -39,11 +39,11 @@ (((word) << (bits)) | ((word) >> (32-(bits)))) /* Local Function Prototyptes */ -void SHA1PadMessage(SHA1Context *); -void SHA1ProcessMessageBlock(SHA1Context *); +static void SHA1PadMessage(SHA1Context *); +static void SHA1ProcessMessageBlock(SHA1Context *); /* - * SHA1Reset + * SHA1Init * * Description: * This function will initialize the SHA1Context in preparation @@ -57,7 +57,7 @@ void SHA1ProcessMessageBlock(SHA1Context *); * sha Error Code. * */ -int SHA1Reset(SHA1Context *context) +int SHA1Init(SHA1Context *context) { if (!context) { @@ -81,7 +81,7 @@ int SHA1Reset(SHA1Context *context) } /* - * SHA1Result + * SHA1Final * * Description: * This function will return the 160-bit message digest into the @@ -99,26 +99,22 @@ int SHA1Reset(SHA1Context *context) * sha Error Code. * */ -int SHA1Result( SHA1Context *context, - uint8_t Message_Digest[SHA1HashSize]) +int SHA1Final(SHA1Context *context, + uint8_t Message_Digest[SHA1HashSize]) { int i; - if (!context || !Message_Digest) - { + if (!context || !Message_Digest) { return shaNull; } - if (context->Corrupted) - { + if (context->Corrupted) { return context->Corrupted; } - if (!context->Computed) - { + if (!context->Computed) { SHA1PadMessage(context); - for(i=0; i<64; ++i) - { + for(i=0; i<64; ++i) { /* message may be sensitive, clear it out */ context->Message_Block[i] = 0; } @@ -128,17 +124,16 @@ int SHA1Result( SHA1Context *context, } - for(i = 0; i < SHA1HashSize; ++i) - { + for(i = 0; i < SHA1HashSize; ++i) { Message_Digest[i] = context->Intermediate_Hash[i>>2] - >> 8 * ( 3 - ( i & 0x03 ) ); + >> 8 * ( 3 - ( i & 0x03 ) ); } return shaSuccess; } /* - * SHA1Input + * SHA1Update * * Description: * This function accepts an array of octets as the next portion @@ -157,53 +152,45 @@ int SHA1Result( SHA1Context *context, * sha Error Code. * */ -int SHA1Input( SHA1Context *context, - const uint8_t *message_array, - unsigned length) +int SHA1Update(SHA1Context *context, + const uint8_t *message_array, + unsigned length) { - if (!length) - { + if (!length) { return shaSuccess; } - if (!context || !message_array) - { + if (!context || !message_array) { return shaNull; } - if (context->Computed) - { + if (context->Computed) { context->Corrupted = shaStateError; return shaStateError; } - if (context->Corrupted) - { + if (context->Corrupted) { return context->Corrupted; } - while(length-- && !context->Corrupted) - { - context->Message_Block[context->Message_Block_Index++] = - (*message_array & 0xFF); - - context->Length_Low += 8; - if (context->Length_Low == 0) - { - context->Length_High++; - if (context->Length_High == 0) - { - /* Message is too long */ - context->Corrupted = 1; - } - } - - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); - } - - message_array++; + while(length-- && !context->Corrupted) { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) { + context->Length_High++; + if (context->Length_High == 0) { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) { + SHA1ProcessMessageBlock(context); + } + + message_array++; } return shaSuccess; @@ -230,7 +217,7 @@ int SHA1Input( SHA1Context *context, * * */ -void SHA1ProcessMessageBlock(SHA1Context *context) +static void SHA1ProcessMessageBlock(SHA1Context *context) { const uint32_t K[] = { /* Constants defined in SHA-1 */ 0x5A827999, @@ -246,16 +233,14 @@ void SHA1ProcessMessageBlock(SHA1Context *context) /* * Initialize the first 16 words in the array W */ - for(t = 0; t < 16; t++) - { + for(t = 0; t < 16; t++) { W[t] = context->Message_Block[t * 4] << 24; W[t] |= context->Message_Block[t * 4 + 1] << 16; W[t] |= context->Message_Block[t * 4 + 2] << 8; W[t] |= context->Message_Block[t * 4 + 3]; } - for(t = 16; t < 80; t++) - { + for(t = 16; t < 80; t++) { W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); } @@ -265,10 +250,9 @@ void SHA1ProcessMessageBlock(SHA1Context *context) D = context->Intermediate_Hash[3]; E = context->Intermediate_Hash[4]; - for(t = 0; t < 20; t++) - { + for(t = 0; t < 20; t++) { temp = SHA1CircularShift(5,A) + - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; E = D; D = C; C = SHA1CircularShift(30,B); @@ -277,8 +261,7 @@ void SHA1ProcessMessageBlock(SHA1Context *context) A = temp; } - for(t = 20; t < 40; t++) - { + for(t = 20; t < 40; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; E = D; D = C; @@ -287,10 +270,9 @@ void SHA1ProcessMessageBlock(SHA1Context *context) A = temp; } - for(t = 40; t < 60; t++) - { + for(t = 40; t < 60; t++) { temp = SHA1CircularShift(5,A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; E = D; D = C; C = SHA1CircularShift(30,B); @@ -298,8 +280,7 @@ void SHA1ProcessMessageBlock(SHA1Context *context) A = temp; } - for(t = 60; t < 80; t++) - { + for(t = 60; t < 80; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; E = D; D = C; @@ -341,7 +322,7 @@ void SHA1ProcessMessageBlock(SHA1Context *context) * */ -void SHA1PadMessage(SHA1Context *context) +static void SHA1PadMessage(SHA1Context *context) { /* * Check to see if the current message block is too small to hold @@ -349,26 +330,20 @@ void SHA1PadMessage(SHA1Context *context) * block, process it, and then continue padding into a second * block. */ - if (context->Message_Block_Index > 55) - { + if (context->Message_Block_Index > 55) { context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 64) - { + while(context->Message_Block_Index < 64) { context->Message_Block[context->Message_Block_Index++] = 0; } SHA1ProcessMessageBlock(context); - while(context->Message_Block_Index < 56) - { + while(context->Message_Block_Index < 56) { context->Message_Block[context->Message_Block_Index++] = 0; } - } - else - { + } else { context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 56) - { + while(context->Message_Block_Index < 56) { context->Message_Block[context->Message_Block_Index++] = 0; } @@ -448,36 +423,31 @@ int main() /* * Perform SHA-1 tests */ - for(j = 0; j < 4; ++j) - { + for(j = 0; j < 4; ++j) { printf( "\nTest %d: %d, '%s'\n", j+1, repeatcount[j], testarray[j]); - err = SHA1Reset(&sha); - if (err) - { + err = SHA1Init(&sha); + if (err) { fprintf(stderr, "SHA1Reset Error %d.\n", err ); break; /* out of for j loop */ } - for(i = 0; i < repeatcount[j]; ++i) - { + for(i = 0; i < repeatcount[j]; ++i) { - err = SHA1Input(&sha, + err = SHA1Input(&sha, (const unsigned char *) testarray[j], strlen(testarray[j])); - if (err) - { + if (err) { fprintf(stderr, "SHA1Input Error %d.\n", err ); break; /* out of for i loop */ } } - err = SHA1Result(&sha, Message_Digest); - if (err) - { + err = SHA1Final(&sha, Message_Digest); + if (err) { fprintf(stderr, "SHA1Result Error %d, could not compute message digest.\n", err ); @@ -485,8 +455,7 @@ int main() else { printf("\t"); - for(i = 0; i < 20 ; ++i) - { + for(i = 0; i < 20 ; ++i) { printf("%02X ", Message_Digest[i]); } printf("\n"); @@ -496,11 +465,44 @@ int main() } /* Test some error returns */ - err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1); + err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1); printf ("\nError %d. Should be %d.\n", err, shaStateError ); - err = SHA1Reset(0); + err = SHA1Init(0); printf ("\nError %d. Should be %d.\n", err, shaNull ); return 0; } #endif /* TEST_DRIVER */ + +#ifdef SHA1_SUM +/* + * Reads a single ASCII file and prints the HEX sha1 sum. + */ +#include +int main(int argc, char *argv[]) +{ + FILE *fd; + SHA1Context ctx; + char buf[5000]; + char signature[25]; + + if (argc < 1) { + printf("Must have filename\n"); + exit(1); + } + fd = fopen(argv[1], "r"); + if (!fd) { + printf("Could not open %s: ERR=%s\n", argv[1], strerror(errno)); + exit(1); + } + SHA1Init(&ctx); + while (fgets(buf, sizeof(buf), fd)) { + SHA1Update(&ctx, (unsigned char *)buf, strlen(buf)); + } + SHA1Final(&ctx, (unsigned char *)signature); + for (int i=0; i < 20; i++) { + printf("%02x", signature[i]& 0xFF); + } + printf(" %s\n", argv[1]); +} +#endif diff --git a/bacula/src/lib/sha1.h b/bacula/src/lib/sha1.h index 35e53d979d..dc10392e22 100644 --- a/bacula/src/lib/sha1.h +++ b/bacula/src/lib/sha1.h @@ -2,15 +2,15 @@ * sha1.h * * Description: - * This is the header file for code which implements the Secure - * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published - * April 17, 1995. + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. * - * Many of the variable names in this code, especially the - * single character names, were used because those were the names - * used in the publication. + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. * - * Please read the file sha1.c for more information. + * Please read the file sha1.c for more information. * * Full Copyright Statement * @@ -55,9 +55,9 @@ /* * If you do not have the ISO standard stdint.h header file, then you * must typdef the following: - * name meaning - * uint32_t unsigned 32 bit integer - * uint8_t unsigned 8 bit integer (i.e., unsigned char) + * name meaning + * uint32_t unsigned 32 bit integer + * uint8_t unsigned 8 bit integer (i.e., unsigned char) * int_least16_t integer of >= 16 bits * */ @@ -67,9 +67,9 @@ enum { shaSuccess = 0, - shaNull, /* Null pointer parameter */ - shaInputTooLong, /* input data too long */ - shaStateError /* called Input after Result */ + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ }; #endif #define SHA1HashSize 20 @@ -82,26 +82,26 @@ typedef struct SHA1Context { uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ - uint32_t Length_Low; /* Message length in bits */ - uint32_t Length_High; /* Message length in bits */ + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ - /* Index into message block array */ + /* Index into message block array */ int_least16_t Message_Block_Index; - uint8_t Message_Block[64]; /* 512-bit message blocks */ + uint8_t Message_Block[64]; /* 512-bit message blocks */ - int Computed; /* Is the digest computed? */ - int Corrupted; /* Is the message digest corrupted? */ + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ } SHA1Context; /* * Function Prototypes */ -int SHA1Reset( SHA1Context *); -int SHA1Input( SHA1Context *, - const uint8_t *, - unsigned int); -int SHA1Result( SHA1Context *, - uint8_t Message_Digest[SHA1HashSize]); +int SHA1Init(SHA1Context *); +int SHA1Update(SHA1Context *, + const uint8_t *, + unsigned int); +int SHA1Final(SHA1Context *, + uint8_t Message_Digest[SHA1HashSize]); #endif diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 2c375a2297..c3ea57e560 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -190,7 +190,7 @@ int do_append_data(JCR *jcr) /* Send attributes and MD5 to Director for Catalog */ if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE || - stream == STREAM_WIN32_ATTRIBUTES) { + stream == STREAM_WIN32_ATTRIBUTES || stream == STREAM_SHA1_SIGNATURE) { if (!jcr->no_attributes) { if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) { jcr->dir_bsock->spool = 1; diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 3ecadbdc56..be9b1fa5ad 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -467,7 +467,8 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n"); prog_name_msg = 1; } - } else if (rec->Stream != STREAM_MD5_SIGNATURE) { + } else if (!(rec->Stream == STREAM_MD5_SIGNATURE || + rec->Stream == STREAM_SHA1_SIGNATURE)) { Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data); } } diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index e5878af641..ebc4977aca 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -50,7 +50,7 @@ static int create_client_record(B_DB *db, CLIENT_DBR *cr); static int create_fileset_record(B_DB *db, FILESET_DBR *fsr); static int create_jobmedia_record(B_DB *db, JCR *jcr); static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId); -static int update_MD5_record(B_DB *db, char *MD5buf, DEV_RECORD *rec); +static int update_SIG_record(B_DB *db, char *SIGbuf, DEV_RECORD *rec, int type); /* Global variables */ @@ -620,12 +620,21 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } else if (rec->Stream == STREAM_MD5_SIGNATURE) { - char MD5buf[30]; + char MD5buf[50]; bin_to_base64(MD5buf, (char *)rec->data, 16); /* encode 16 bytes */ if (verbose > 1) { Pmsg1(000, _("Got MD5 record: %s\n"), MD5buf); } - update_MD5_record(db, MD5buf, rec); + update_SIG_record(db, MD5buf, rec, MD5_SIG); + + } else if (rec->Stream == STREAM_SHA1_SIGNATURE) { + char SIGbuf[50]; + bin_to_base64(SIGbuf, (char *)rec->data, 20); /* encode 20 bytes */ + if (verbose > 1) { + Pmsg1(000, _("Got SHA1 record: %s\n"), SIGbuf); + } + update_SIG_record(db, SIGbuf, rec, SHA1_SIG); + } else if (rec->Stream == STREAM_PROGRAM_NAMES) { if (verbose) { @@ -1038,16 +1047,16 @@ static int create_jobmedia_record(B_DB *db, JCR *mjcr) } /* - * Simulate the database call that updates the MD5 record + * Simulate the database call that updates the MD5/SHA1 record */ -static int update_MD5_record(B_DB *db, char *MD5buf, DEV_RECORD *rec) +static int update_SIG_record(B_DB *db, char *SIGbuf, DEV_RECORD *rec, int type) { JCR *mjcr; mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { if (mr.VolJobs > 0) { - Pmsg2(000, _("Could not find SessId=%d SessTime=%d for MD5 record.\n"), + Pmsg2(000, _("Could not find SessId=%d SessTime=%d for MD5/SHA1 record.\n"), rec->VolSessionId, rec->VolSessionTime); } else { ignored_msgs++; @@ -1060,13 +1069,13 @@ static int update_MD5_record(B_DB *db, char *MD5buf, DEV_RECORD *rec) return 1; } - if (!db_add_MD5_to_file_record(bjcr, db, mjcr->FileId, MD5buf)) { - Pmsg1(0, _("Could not add MD5 to File record. ERR=%s\n"), db_strerror(db)); + if (!db_add_SIG_to_file_record(bjcr, db, mjcr->FileId, SIGbuf, type)) { + Pmsg1(0, _("Could not add MD5/SHA1 to File record. ERR=%s\n"), db_strerror(db)); free_jcr(mjcr); return 0; } if (verbose > 1) { - Pmsg0(000, _("Updated MD5 record\n")); + Pmsg0(000, _("Updated MD5/SHA1 record\n")); } free_jcr(mjcr); return 1; diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index e87833ae27..ab69174604 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -460,6 +460,12 @@ int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir) changer = edit_device_codes(jcr, changer, jcr->device->changer_command, "load"); status = run_program(changer, timeout, NULL); + if (status == 0) { + Jmsg(jcr, M_INFO, 0, _("Autochanger \"load slot\" status is OK.\n")); + } else { + Jmsg(jcr, M_INFO, 0, _("Bad autochanger \"load slot\" status = %d.\n"), + status); + } Dmsg2(100, "load slot %d status=%d\n", slot, status); } free_pool_memory(changer); diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index a78dcc6f4a..2257a1b63e 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -94,6 +94,8 @@ char *stream_to_ascii(int stream, int fi) return "DATA"; case STREAM_MD5_SIGNATURE: return "MD5"; + case STREAM_SHA1_SIGNATURE: + return "SHA1"; case STREAM_GZIP_DATA: return "GZIP"; case STREAM_WIN32_ATTRIBUTES: @@ -112,6 +114,8 @@ char *stream_to_ascii(int stream, int fi) return "contDATA"; case -STREAM_MD5_SIGNATURE: return "contMD5"; + case -STREAM_SHA1_SIGNATURE: + return "contSHA1"; case -STREAM_GZIP_DATA: return "contGZIP"; case -STREAM_WIN32_ATTRIBUTES: -- 2.39.2