From 06ba977249e6806571795d3257970c5f98fa0d16 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 13 Mar 2013 17:38:04 +0100 Subject: rsgtutil: begin to make rsgttlvdump a generic utility It will support various maintenaince operations, including verification of signatures in the future. To match its new scope, it also has been renamed. --- tools/rsgtutil.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 tools/rsgtutil.c (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c new file mode 100644 index 00000000..7b70a9a7 --- /dev/null +++ b/tools/rsgtutil.c @@ -0,0 +1,168 @@ +/* This is a tool for dumpoing the content of GuardTime TLV + * files in a (somewhat) human-readable manner. + * + * Copyright 2013 Adiscon GmbH + * + * This file is part of rsyslog. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either exprs or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "librsgt.h" + +typedef unsigned char uchar; + +static enum { MD_DUMP, MD_DETECT_FILE_TYPE, +} mode = MD_DUMP; +static int verbose = 0; + +static void +dumpFile(char *name) +{ + FILE *fp; + uchar hdr[9]; + uint16_t tlvtype, tlvlen; + void *obj; + int r = -1; + + if(!strcmp(name, "-")) + fp = stdin; + else { + printf("Processing file %s:\n", name); + if((fp = fopen(name, "r")) == NULL) { + perror(name); + goto err; + } + } + if((r = rsgt_tlvrdHeader(fp, hdr)) != 0) goto err; + printf("File Header: '%s'\n", hdr); + while(1) { /* we will err out on EOF */ + if((r = rsgt_tlvrd(fp, &tlvtype, &tlvlen, &obj)) != 0) { + if(feof(fp)) + break; + else + goto err; + } + rsgt_tlvprint(stdout, tlvtype, obj, verbose); + } + + if(fp != stdin) + fclose(fp); + return; +err: fprintf(stderr, "error %d processing file %s\n", r, name); +} + +static void +detectFileType(char *name) +{ + FILE *fp; + char *typeName; + char hdr[9]; + int r = -1; + + if(!strcmp(name, "-")) + fp = stdin; + else { + if((fp = fopen(name, "r")) == NULL) { + perror(name); + goto err; + } + } + if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto err; + if(!strcmp(hdr, "LOGSIG10")) + typeName = "Log Signature File, Version 10"; + else + typeName = "unknown"; + + printf("%s: %s [%s]\n", name, hdr, typeName); + + if(fp != stdin) + fclose(fp); + return; +err: fprintf(stderr, "error %d processing file %s\n", r, name); +} + +static void +processFile(char *name) +{ + switch(mode) { + case MD_DETECT_FILE_TYPE: + detectFileType(name); + break; + case MD_DUMP: + dumpFile(name); + break; + } +} + + +static struct option long_options[] = +{ + {"dump", no_argument, NULL, 'D'}, + {"verbose", no_argument, NULL, 'v'}, + {"version", no_argument, NULL, 'V'}, + {"detect-file-type", no_argument, NULL, 'T'}, + {NULL, 0, NULL, 0} +}; + +int +main(int argc, char *argv[]) +{ + int i; + int opt; + + while(1) { + opt = getopt_long(argc, argv, "v", long_options, NULL); + if(opt == -1) + break; + switch(opt) { + case 'v': + verbose = 1; + break; + case 'V': + fprintf(stderr, "rsgtutil " VERSION "\n"); + exit(0); + case 'D': + mode = MD_DUMP; + break; + case 'T': + mode = MD_DETECT_FILE_TYPE; + break; + case '?': + break; + default:fprintf(stderr, "getopt_long() returns unknown value %d\n", opt); + return 1; + } + } + + if(optind == argc) + processFile("-"); + else { + for(i = optind ; i < argc ; ++i) + processFile(argv[i]); + } + + return 0; +} -- cgit v1.2.3 From 44b4922825df794f678cd4ad18d940ff114b943f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 14 Mar 2013 12:32:03 +0100 Subject: rsgtutil: add --show-sigblock-params parameter --- tools/rsgtutil.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 7b70a9a7..3286163b 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -34,7 +34,7 @@ typedef unsigned char uchar; -static enum { MD_DUMP, MD_DETECT_FILE_TYPE, +static enum { MD_DUMP, MD_DETECT_FILE_TYPE, MD_SHOW_SIGBLK_PARAMS } mode = MD_DUMP; static int verbose = 0; @@ -74,6 +74,45 @@ dumpFile(char *name) err: fprintf(stderr, "error %d processing file %s\n", r, name); } +static void +showSigblkParams(char *name) +{ + FILE *fp; + block_sig_t *bs; + uint8_t bHasRecHashes, bHasIntermedHashes; + uint64_t blkCnt = 0; + int r = -1; + + if(!strcmp(name, "-")) + fp = stdin; + else { + if((fp = fopen(name, "r")) == NULL) { + perror(name); + goto err; + } + } + if((r = rsgt_chkFileHdr(fp, "LOGSIG10")) != 0) goto err; + + while(1) { /* we will err out on EOF */ + if((r = rsgt_getBlockParams(fp, 0, &bs, &bHasRecHashes, + &bHasIntermedHashes)) != 0) + goto err; + ++blkCnt; + rsgt_printBLOCK_SIG(stdout, bs, verbose); + printf("\t***META INFORMATION:\n"); + printf("\tBlock Nbr in File......: %llu\n", blkCnt); + printf("\tHas Record Hashes......: %d\n", bHasRecHashes); + printf("\tHas Intermediate Hashes: %d\n", bHasIntermedHashes); + } + + if(fp != stdin) + fclose(fp); + return; +err: + if(r != RSGTE_EOF) + fprintf(stderr, "error %d processing file %s\n", r, name); +} + static void detectFileType(char *name) { @@ -114,6 +153,9 @@ processFile(char *name) case MD_DUMP: dumpFile(name); break; + case MD_SHOW_SIGBLK_PARAMS: + showSigblkParams(name); + break; } } @@ -124,6 +166,7 @@ static struct option long_options[] = {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"detect-file-type", no_argument, NULL, 'T'}, + {"show-sigblock-params", no_argument, NULL, 'B'}, {NULL, 0, NULL, 0} }; @@ -147,6 +190,9 @@ main(int argc, char *argv[]) case 'D': mode = MD_DUMP; break; + case 'B': + mode = MD_SHOW_SIGBLK_PARAMS; + break; case 'T': mode = MD_DETECT_FILE_TYPE; break; -- cgit v1.2.3 From d2467c38d42f590deecd807741324fc0e5522a8a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sun, 17 Mar 2013 13:06:02 +0100 Subject: logsig: milestone/verfier: record hashes are verified --- tools/rsgtutil.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 3286163b..d94a63cd 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -34,7 +34,8 @@ typedef unsigned char uchar; -static enum { MD_DUMP, MD_DETECT_FILE_TYPE, MD_SHOW_SIGBLK_PARAMS +static enum { MD_DUMP, MD_DETECT_FILE_TYPE, MD_SHOW_SIGBLK_PARAMS, + MD_VERIFY } mode = MD_DUMP; static int verbose = 0; @@ -143,6 +144,91 @@ detectFileType(char *name) err: fprintf(stderr, "error %d processing file %s\n", r, name); } +static inline int +doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf) +{ + int r; + size_t lenRec; + char rec[128*1024]; + + fgets(rec, sizeof(rec), logfp); + lenRec = strlen(rec); + if(rec[lenRec-1] == '\n') + --lenRec; + + r = rsgt_vrfy_nextRec(bs, gf, sigfp, (unsigned char*)rec, lenRec); + return r; +} + +/* note: here we need to have the LOG file name, not signature! */ +static void +verify(char *name) +{ + FILE *logfp = NULL, *sigfp = NULL; + block_sig_t *bs; + gtfile gf; + uint8_t bHasRecHashes, bHasIntermedHashes; + uint8_t bInBlock; + int r = 0; + uint64_t nRecs; + char sigfname[4096]; + + if(!strcmp(name, "-")) { + fprintf(stderr, "verify mode cannot work on stdin\n"); + goto err; + } else { + snprintf(sigfname, sizeof(sigfname), "%s.gtsig", name); + sigfname[sizeof(sigfname)-1] = '\0'; + if((logfp = fopen(name, "r")) == NULL) { + perror(name); + goto err; + } + if((sigfp = fopen(sigfname, "r")) == NULL) { + perror(name); + goto err; + } + } + if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto err; + + gf = rsgt_vrfyConstruct_gf(); + if(gf == NULL) { + fprintf(stderr, "error initializing signature file structure\n"); + goto err; + } + + bInBlock = 0; + + while(!feof(logfp)) { + if(bInBlock == 0) { + if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bHasRecHashes, + &bHasIntermedHashes)) != 0) + goto err; + rsgt_vrfyBlkInit(gf, bs, bHasRecHashes, + bHasIntermedHashes); + nRecs = 0; + bInBlock = 1; + } + ++nRecs; + if((r = doVerifyRec(logfp, sigfp, bs, gf)) != 0) + goto err; + if(nRecs == bs->recCount) { + // verifyBLOCK_SIG(bs, gf); + bInBlock = 0; + } + } + + fclose(logfp); + fclose(sigfp); + return; +err: + if(logfp != NULL) + fclose(logfp); + if(sigfp != NULL) + fclose(sigfp); + if(r != RSGTE_EOF) + fprintf(stderr, "error %d processing file %s [%s]\n", r, name, sigfname); +} + static void processFile(char *name) { @@ -156,6 +242,9 @@ processFile(char *name) case MD_SHOW_SIGBLK_PARAMS: showSigblkParams(name); break; + case MD_VERIFY: + verify(name); + break; } } @@ -167,6 +256,7 @@ static struct option long_options[] = {"version", no_argument, NULL, 'V'}, {"detect-file-type", no_argument, NULL, 'T'}, {"show-sigblock-params", no_argument, NULL, 'B'}, + {"verify", no_argument, NULL, 't'}, /* 't' as in "test signatures" */ {NULL, 0, NULL, 0} }; @@ -196,6 +286,9 @@ main(int argc, char *argv[]) case 'T': mode = MD_DETECT_FILE_TYPE; break; + case 't': + mode = MD_VERIFY; + break; case '?': break; default:fprintf(stderr, "getopt_long() returns unknown value %d\n", opt); -- cgit v1.2.3 From 03901766c7f452c637ac57ec526b98895da510d5 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sun, 17 Mar 2013 14:29:17 +0100 Subject: logsig: milestone/verfier: tree hashes are verified; ALSO a bugfix bugfix: the initial vector was used incorrectly during hash computation. --- tools/rsgtutil.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index d94a63cd..d4c58d2d 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -151,12 +151,16 @@ doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf) size_t lenRec; char rec[128*1024]; - fgets(rec, sizeof(rec), logfp); + if(fgets(rec, sizeof(rec), logfp) == NULL) { + r = feof(logfp) ? RSGTE_EOF : RSGTE_IO; + goto done; + } lenRec = strlen(rec); if(rec[lenRec-1] == '\n') --lenRec; r = rsgt_vrfy_nextRec(bs, gf, sigfp, (unsigned char*)rec, lenRec); +done: return r; } -- cgit v1.2.3 From b09d37063fc155ff5ec38430c679da5be5de0dcc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sun, 17 Mar 2013 15:46:24 +0100 Subject: logsig: milestone/verfier: block timestamp verification almost complete unfortunately, there seems to be a problem with the GuardTime API, so that I need their support before being able to carry on. Once I receive it, it should be fairly quick to complete the function. I am commiting this work as I do not know how long it will take to receive an answer. --- tools/rsgtutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index d4c58d2d..cc045f8c 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -216,7 +216,7 @@ verify(char *name) if((r = doVerifyRec(logfp, sigfp, bs, gf)) != 0) goto err; if(nRecs == bs->recCount) { - // verifyBLOCK_SIG(bs, gf); + verifyBLOCK_SIG(bs, gf, sigfp, nRecs); bInBlock = 0; } } -- cgit v1.2.3 From 1125a60d3fcc5b64e0cc7abe54748b6d6ee2fb28 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 18 Mar 2013 14:41:11 +0100 Subject: logsig: implement timestamp verification We now use a higher-level verification function as suggested by GuardTime. --- tools/rsgtutil.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index cc045f8c..0ccfcd7b 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -192,6 +192,9 @@ verify(char *name) goto err; } } + + rsgtInit("rsyslog rsgtutil " VERSION); + if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto err; gf = rsgt_vrfyConstruct_gf(); @@ -231,6 +234,7 @@ err: fclose(sigfp); if(r != RSGTE_EOF) fprintf(stderr, "error %d processing file %s [%s]\n", r, name, sigfname); + rsgtExit(); } static void -- cgit v1.2.3 From 785e0c3c8b00614b6f780f902442025f4558a160 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 19 Mar 2013 15:26:21 +0100 Subject: logsig: complete initial version of verifier --- tools/rsgtutil.c | 61 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 18 deletions(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 0ccfcd7b..d9cce2f7 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -101,9 +101,9 @@ showSigblkParams(char *name) ++blkCnt; rsgt_printBLOCK_SIG(stdout, bs, verbose); printf("\t***META INFORMATION:\n"); - printf("\tBlock Nbr in File......: %llu\n", blkCnt); - printf("\tHas Record Hashes......: %d\n", bHasRecHashes); - printf("\tHas Intermediate Hashes: %d\n", bHasIntermedHashes); + printf("\tBlock Nbr in File...: %llu\n", blkCnt); + printf("\tHas Record Hashes...: %d\n", bHasRecHashes); + printf("\tHas Tree Hashes.....: %d\n", bHasIntermedHashes); } if(fp != stdin) @@ -145,7 +145,7 @@ err: fprintf(stderr, "error %d processing file %s\n", r, name); } static inline int -doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf) +doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf, gterrctx_t *ectx, uint8_t bInBlock) { int r; size_t lenRec; @@ -156,10 +156,19 @@ doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf) goto done; } lenRec = strlen(rec); - if(rec[lenRec-1] == '\n') + if(rec[lenRec-1] == '\n') { + rec[lenRec-1] = '\0'; --lenRec; + rsgt_errctxSetErrRec(ectx, rec); + } + + /* we need to preserve the first record of each block for + * error-reporting purposes (bInBlock==0 meanst start of block) + */ + if(bInBlock == 0) + rsgt_errctxFrstRecInBlk(ectx, rec); - r = rsgt_vrfy_nextRec(bs, gf, sigfp, (unsigned char*)rec, lenRec); + r = rsgt_vrfy_nextRec(bs, gf, sigfp, (unsigned char*)rec, lenRec, ectx); done: return r; } @@ -174,8 +183,8 @@ verify(char *name) uint8_t bHasRecHashes, bHasIntermedHashes; uint8_t bInBlock; int r = 0; - uint64_t nRecs; char sigfname[4096]; + gterrctx_t ectx; if(!strcmp(name, "-")) { fprintf(stderr, "verify mode cannot work on stdin\n"); @@ -194,6 +203,10 @@ verify(char *name) } rsgtInit("rsyslog rsgtutil " VERSION); + rsgt_errctxInit(&ectx); + ectx.verbose = verbose; + ectx.fp = stderr; + ectx.filename = strdup(sigfname); if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto err; @@ -204,28 +217,31 @@ verify(char *name) } bInBlock = 0; + ectx.blkNum = 0; + ectx.recNumInFile = 0; while(!feof(logfp)) { if(bInBlock == 0) { if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bHasRecHashes, &bHasIntermedHashes)) != 0) goto err; - rsgt_vrfyBlkInit(gf, bs, bHasRecHashes, - bHasIntermedHashes); - nRecs = 0; - bInBlock = 1; + rsgt_vrfyBlkInit(gf, bs, bHasRecHashes, bHasIntermedHashes); + ectx.recNum = 0; + ++ectx.blkNum; } - ++nRecs; - if((r = doVerifyRec(logfp, sigfp, bs, gf)) != 0) + ++ectx.recNum, ++ectx.recNumInFile; + if((r = doVerifyRec(logfp, sigfp, bs, gf, &ectx, bInBlock)) != 0) goto err; - if(nRecs == bs->recCount) { - verifyBLOCK_SIG(bs, gf, sigfp, nRecs); + if(ectx.recNum == bs->recCount) { + verifyBLOCK_SIG(bs, gf, sigfp, &ectx); bInBlock = 0; - } + } else bInBlock = 1; } fclose(logfp); fclose(sigfp); + rsgtExit(); + rsgt_errctxExit(&ectx); return; err: if(logfp != NULL) @@ -233,8 +249,9 @@ err: if(sigfp != NULL) fclose(sigfp); if(r != RSGTE_EOF) - fprintf(stderr, "error %d processing file %s [%s]\n", r, name, sigfname); + fprintf(stderr, "error %d processing file %s\n", r, name); rsgtExit(); + rsgt_errctxExit(&ectx); } static void @@ -265,6 +282,8 @@ static struct option long_options[] = {"detect-file-type", no_argument, NULL, 'T'}, {"show-sigblock-params", no_argument, NULL, 'B'}, {"verify", no_argument, NULL, 't'}, /* 't' as in "test signatures" */ + {"publications-server", optional_argument, NULL, 'P'}, + {"show-verified", no_argument, NULL, 's'}, {NULL, 0, NULL, 0} }; @@ -275,13 +294,16 @@ main(int argc, char *argv[]) int opt; while(1) { - opt = getopt_long(argc, argv, "v", long_options, NULL); + opt = getopt_long(argc, argv, "DvVTBtPs", long_options, NULL); if(opt == -1) break; switch(opt) { case 'v': verbose = 1; break; + case 's': + rsgt_read_showVerified = 1; + break; case 'V': fprintf(stderr, "rsgtutil " VERSION "\n"); exit(0); @@ -291,6 +313,9 @@ main(int argc, char *argv[]) case 'B': mode = MD_SHOW_SIGBLK_PARAMS; break; + case 'P': + rsgt_read_puburl = optarg; + break; case 'T': mode = MD_DETECT_FILE_TYPE; break; -- cgit v1.2.3 From 88c62b390eb5504772dd4fbb266054828dc4dc5d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 22 Mar 2013 13:33:18 +0100 Subject: rsgtutil: add new file type to file type detection --- tools/rsgtutil.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index d9cce2f7..9d9f3568 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -133,6 +133,8 @@ detectFileType(char *name) if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto err; if(!strcmp(hdr, "LOGSIG10")) typeName = "Log Signature File, Version 10"; + else if(!strcmp(hdr, "GTSTAT10")) + typeName = "rsyslog GuardTime Signature State File, Version 10"; else typeName = "unknown"; -- cgit v1.2.3 From 6bc94b09b219aee8ef81db78fe7f2b280cb40b6a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sat, 23 Mar 2013 12:24:23 +0100 Subject: logsig: refactor 'dump' mode in rsgtutil The way tlvrecords are processed is changed in order to provide better extensibility for further work. --- tools/rsgtutil.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 9d9f3568..c5ac5066 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -44,8 +44,8 @@ dumpFile(char *name) { FILE *fp; uchar hdr[9]; - uint16_t tlvtype, tlvlen; void *obj; + tlvrecord_t rec; int r = -1; if(!strcmp(name, "-")) @@ -60,13 +60,14 @@ dumpFile(char *name) if((r = rsgt_tlvrdHeader(fp, hdr)) != 0) goto err; printf("File Header: '%s'\n", hdr); while(1) { /* we will err out on EOF */ - if((r = rsgt_tlvrd(fp, &tlvtype, &tlvlen, &obj)) != 0) { + if((r = rsgt_tlvrd(fp, &rec, &obj)) != 0) { if(feof(fp)) break; else goto err; } - rsgt_tlvprint(stdout, tlvtype, obj, verbose); + rsgt_tlvprint(stdout, rec.tlvtype, obj, verbose); + rsgt_objfree(rec.tlvtype, obj); } if(fp != stdin) -- cgit v1.2.3 From c77a77a6c7919d17936e6ba2f71b0903cac9c890 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sat, 23 Mar 2013 13:07:12 +0100 Subject: rsgtutil: refactor 'verify' mode to use new tlv file read functions --- tools/rsgtutil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index c5ac5066..c78671c7 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -181,7 +181,7 @@ static void verify(char *name) { FILE *logfp = NULL, *sigfp = NULL; - block_sig_t *bs; + block_sig_t *bs = NULL; gtfile gf; uint8_t bHasRecHashes, bHasIntermedHashes; uint8_t bInBlock; @@ -225,6 +225,8 @@ verify(char *name) while(!feof(logfp)) { if(bInBlock == 0) { + if(bs != NULL) + rsgt_objfree(0x0902, bs); if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bHasRecHashes, &bHasIntermedHashes)) != 0) goto err; -- cgit v1.2.3 From 0b77585a10062117d1904c8c08db1fc4520ab16d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sat, 23 Mar 2013 14:59:50 +0100 Subject: rsgtutil: basic plumbing for extend mode does not contain actual implementation --- tools/rsgtutil.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index c78671c7..f65c46fd 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -35,7 +35,7 @@ typedef unsigned char uchar; static enum { MD_DUMP, MD_DETECT_FILE_TYPE, MD_SHOW_SIGBLK_PARAMS, - MD_VERIFY + MD_VERIFY, MD_EXTEND } mode = MD_DUMP; static int verbose = 0; @@ -155,7 +155,12 @@ doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf, gterrctx_t *ec char rec[128*1024]; if(fgets(rec, sizeof(rec), logfp) == NULL) { - r = feof(logfp) ? RSGTE_EOF : RSGTE_IO; + if(feof(logfp)) { + r = RSGTE_EOF; + } else { + perror("log file input"); + r = RSGTE_IO; + } goto done; } lenRec = strlen(rec); @@ -176,21 +181,27 @@ done: return r; } -/* note: here we need to have the LOG file name, not signature! */ +/* We handle both verify and extend with the same function as they + * are very similiar. + * + * note: here we need to have the LOG file name, not signature! + */ static void verify(char *name) { - FILE *logfp = NULL, *sigfp = NULL; + FILE *logfp = NULL, *sigfp = NULL, *nsigfp = NULL; block_sig_t *bs = NULL; gtfile gf; uint8_t bHasRecHashes, bHasIntermedHashes; uint8_t bInBlock; int r = 0; char sigfname[4096]; + char nsigfname[4096]; gterrctx_t ectx; if(!strcmp(name, "-")) { - fprintf(stderr, "verify mode cannot work on stdin\n"); + fprintf(stderr, "%s mode cannot work on stdin\n", + mode == MD_VERIFY ? "verify" : "extend"); goto err; } else { snprintf(sigfname, sizeof(sigfname), "%s.gtsig", name); @@ -200,9 +211,17 @@ verify(char *name) goto err; } if((sigfp = fopen(sigfname, "r")) == NULL) { - perror(name); + perror(sigfname); goto err; } + if(mode == MD_EXTEND) { + snprintf(nsigfname, sizeof(nsigfname), "%s.gtsig.new", name); + nsigfname[sizeof(nsigfname)-1] = '\0'; + if((nsigfp = fopen(nsigfname, "w")) == NULL) { + perror(nsigfname); + goto err; + } + } } rsgtInit("rsyslog rsgtutil " VERSION); @@ -245,6 +264,7 @@ verify(char *name) fclose(logfp); fclose(sigfp); + fclose(nsigfp); rsgtExit(); rsgt_errctxExit(&ectx); return; @@ -253,6 +273,8 @@ err: fclose(logfp); if(sigfp != NULL) fclose(sigfp); + if(nsigfp != NULL) + fclose(nsigfp); if(r != RSGTE_EOF) fprintf(stderr, "error %d processing file %s\n", r, name); rsgtExit(); @@ -273,6 +295,7 @@ processFile(char *name) showSigblkParams(name); break; case MD_VERIFY: + case MD_EXTEND: verify(name); break; } @@ -287,6 +310,7 @@ static struct option long_options[] = {"detect-file-type", no_argument, NULL, 'T'}, {"show-sigblock-params", no_argument, NULL, 'B'}, {"verify", no_argument, NULL, 't'}, /* 't' as in "test signatures" */ + {"extend", no_argument, NULL, 'e'}, {"publications-server", optional_argument, NULL, 'P'}, {"show-verified", no_argument, NULL, 's'}, {NULL, 0, NULL, 0} @@ -327,6 +351,9 @@ main(int argc, char *argv[]) case 't': mode = MD_VERIFY; break; + case 'e': + mode = MD_EXTEND; + break; case '?': break; default:fprintf(stderr, "getopt_long() returns unknown value %d\n", opt); -- cgit v1.2.3 From 199630a5ef8f0c919fbbbd9e122415d1d72886a3 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sat, 23 Mar 2013 18:39:03 +0100 Subject: rsgtutil/milestone: basic 'extend' mode implementation ... done up until the point where I need to wait for the timestamps to become extendible. So doing a milestone commit to make sure the work is inside the archive. Actual writing of the extended timestamp is missing. --- tools/rsgtutil.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index f65c46fd..1f475527 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -148,13 +148,14 @@ err: fprintf(stderr, "error %d processing file %s\n", r, name); } static inline int -doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf, gterrctx_t *ectx, uint8_t bInBlock) +doVerifyRec(FILE *logfp, FILE *sigfp, FILE *nsigfp, + block_sig_t *bs, gtfile gf, gterrctx_t *ectx, uint8_t bInBlock) { int r; size_t lenRec; - char rec[128*1024]; + char line[128*1024]; - if(fgets(rec, sizeof(rec), logfp) == NULL) { + if(fgets(line, sizeof(line), logfp) == NULL) { if(feof(logfp)) { r = RSGTE_EOF; } else { @@ -163,20 +164,20 @@ doVerifyRec(FILE *logfp, FILE *sigfp, block_sig_t *bs, gtfile gf, gterrctx_t *ec } goto done; } - lenRec = strlen(rec); - if(rec[lenRec-1] == '\n') { - rec[lenRec-1] = '\0'; + lenRec = strlen(line); + if(line[lenRec-1] == '\n') { + line[lenRec-1] = '\0'; --lenRec; - rsgt_errctxSetErrRec(ectx, rec); + rsgt_errctxSetErrRec(ectx, line); } - /* we need to preserve the first record of each block for + /* we need to preserve the first line (record) of each block for * error-reporting purposes (bInBlock==0 meanst start of block) */ if(bInBlock == 0) - rsgt_errctxFrstRecInBlk(ectx, rec); + rsgt_errctxFrstRecInBlk(ectx, line); - r = rsgt_vrfy_nextRec(bs, gf, sigfp, (unsigned char*)rec, lenRec, ectx); + r = rsgt_vrfy_nextRec(bs, gf, sigfp, nsigfp, (unsigned char*)line, lenRec, ectx); done: return r; } @@ -231,7 +232,13 @@ verify(char *name) ectx.filename = strdup(sigfname); if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto err; - + if(mode == MD_EXTEND) { + if(fwrite("LOGSIG10", 8, 1, nsigfp) != 1) { + perror(nsigfname); + r = RSGTE_IO; + goto err; + } + } gf = rsgt_vrfyConstruct_gf(); if(gf == NULL) { fprintf(stderr, "error initializing signature file structure\n"); @@ -254,10 +261,11 @@ verify(char *name) ++ectx.blkNum; } ++ectx.recNum, ++ectx.recNumInFile; - if((r = doVerifyRec(logfp, sigfp, bs, gf, &ectx, bInBlock)) != 0) + if((r = doVerifyRec(logfp, sigfp, nsigfp, bs, gf, &ectx, bInBlock)) != 0) goto err; if(ectx.recNum == bs->recCount) { - verifyBLOCK_SIG(bs, gf, sigfp, &ectx); + verifyBLOCK_SIG(bs, gf, sigfp, nsigfp, + (mode == MD_EXTEND) ? 1 : 0, &ectx); bInBlock = 0; } else bInBlock = 1; } -- cgit v1.2.3 From c896a6ba7498e15ddfe869823a64434a4180d57b Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 25 Mar 2013 15:56:33 +0100 Subject: rsgtsig: finish implementation of 'extend' mode This is tested as far as possible. However, the actual extend case can only be tested in about three weeks from now when the next publication is out. I have done module-testing with a mockup extend call, so chances are great the final test will be passed. --- tools/rsgtutil.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 13 deletions(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 1f475527..45106c00 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,7 @@ verify(char *name) uint8_t bInBlock; int r = 0; char sigfname[4096]; + char oldsigfname[4096]; char nsigfname[4096]; gterrctx_t ectx; @@ -222,6 +224,9 @@ verify(char *name) perror(nsigfname); goto err; } + snprintf(oldsigfname, sizeof(oldsigfname), + "%s.gtsig.old", name); + oldsigfname[sizeof(oldsigfname)-1] = '\0'; } } @@ -231,18 +236,18 @@ verify(char *name) ectx.fp = stderr; ectx.filename = strdup(sigfname); - if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto err; + if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto done; if(mode == MD_EXTEND) { if(fwrite("LOGSIG10", 8, 1, nsigfp) != 1) { perror(nsigfname); r = RSGTE_IO; - goto err; + goto done; } } gf = rsgt_vrfyConstruct_gf(); if(gf == NULL) { fprintf(stderr, "error initializing signature file structure\n"); - goto err; + goto done; } bInBlock = 0; @@ -255,36 +260,80 @@ verify(char *name) rsgt_objfree(0x0902, bs); if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bHasRecHashes, &bHasIntermedHashes)) != 0) - goto err; + goto done; rsgt_vrfyBlkInit(gf, bs, bHasRecHashes, bHasIntermedHashes); ectx.recNum = 0; ++ectx.blkNum; } ++ectx.recNum, ++ectx.recNumInFile; if((r = doVerifyRec(logfp, sigfp, nsigfp, bs, gf, &ectx, bInBlock)) != 0) - goto err; + goto done; if(ectx.recNum == bs->recCount) { - verifyBLOCK_SIG(bs, gf, sigfp, nsigfp, - (mode == MD_EXTEND) ? 1 : 0, &ectx); + if((r = verifyBLOCK_SIG(bs, gf, sigfp, nsigfp, + (mode == MD_EXTEND) ? 1 : 0, &ectx)) != 0) + goto done; bInBlock = 0; } else bInBlock = 1; } - fclose(logfp); - fclose(sigfp); - fclose(nsigfp); +done: + if(r != RSGTE_EOF) + goto err; + + fclose(logfp); logfp = NULL; + fclose(sigfp); sigfp = NULL; + fclose(nsigfp); nsigfp = NULL; + + /* everything went fine, so we rename files if we updated them */ + if(mode == MD_EXTEND) { + if(unlink(oldsigfname) != 0) { + if(errno != ENOENT) { + perror("unlink oldsig"); + r = RSGTE_IO; + goto err; + } + } + if(link(sigfname, oldsigfname) != 0) { + perror("link oldsig"); + r = RSGTE_IO; + goto err; + } + if(unlink(sigfname) != 0) { + perror("unlink cursig"); + r = RSGTE_IO; + goto err; + } + if(link(nsigfname, sigfname) != 0) { + perror("link newsig"); + fprintf(stderr, "WARNING: current sig file has been " + "renamed to %s - you need to manually recover " + "it.\n", oldsigfname); + r = RSGTE_IO; + goto err; + } + if(unlink(nsigfname) != 0) { + perror("unlink newsig"); + fprintf(stderr, "WARNING: current sig file has been " + "renamed to %s - you need to manually recover " + "it.\n", oldsigfname); + r = RSGTE_IO; + goto err; + } + } rsgtExit(); rsgt_errctxExit(&ectx); return; + err: + fprintf(stderr, "error %d processing file %s\n", r, name); if(logfp != NULL) fclose(logfp); if(sigfp != NULL) fclose(sigfp); - if(nsigfp != NULL) + if(nsigfp != NULL) { fclose(nsigfp); - if(r != RSGTE_EOF) - fprintf(stderr, "error %d processing file %s\n", r, name); + unlink(nsigfname); + } rsgtExit(); rsgt_errctxExit(&ectx); } -- cgit v1.2.3 From 7e0ab0a1fb8cbbf83ef6e8613b2051b7a0f49803 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 26 Mar 2013 15:33:54 +0100 Subject: logsig: handle error cases --- tools/rsgtutil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/rsgtutil.c') diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 45106c00..095b8066 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -282,7 +282,9 @@ done: fclose(logfp); logfp = NULL; fclose(sigfp); sigfp = NULL; - fclose(nsigfp); nsigfp = NULL; + if(nsigfp != NULL) { + fclose(nsigfp); nsigfp = NULL; + } /* everything went fine, so we rename files if we updated them */ if(mode == MD_EXTEND) { -- cgit v1.2.3