diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2013-03-14 12:32:03 +0100 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2013-03-14 12:32:03 +0100 |
commit | 44b4922825df794f678cd4ad18d940ff114b943f (patch) | |
tree | 45ef6523bac5e382b6a93c1750178382c9bb5892 | |
parent | 06ba977249e6806571795d3257970c5f98fa0d16 (diff) | |
download | rsyslog-44b4922825df794f678cd4ad18d940ff114b943f.tar.gz rsyslog-44b4922825df794f678cd4ad18d940ff114b943f.tar.bz2 rsyslog-44b4922825df794f678cd4ad18d940ff114b943f.zip |
rsgtutil: add --show-sigblock-params parameter
-rw-r--r-- | runtime/librsgt.h | 10 | ||||
-rw-r--r-- | runtime/librsgt_read.c | 127 | ||||
-rw-r--r-- | tools/rsgtutil.c | 48 |
3 files changed, 175 insertions, 10 deletions
diff --git a/runtime/librsgt.h b/runtime/librsgt.h index b2de73bd..d9d221ea 100644 --- a/runtime/librsgt.h +++ b/runtime/librsgt.h @@ -110,11 +110,16 @@ struct rsgtstatefile { }; /* error states */ -#define RSGTE_IO 1 /* any kind of io error, including EOF */ +#define RSGTE_IO 1 /* any kind of io error */ #define RSGTE_FMT 2 /* data fromat error */ #define RSGTE_INVLTYP 3 /* invalid TLV type record (unexcpected at this point) */ #define RSGTE_OOM 4 /* ran out of memory */ #define RSGTE_LEN 5 /* error related to length records */ +#define RSGTE_NO_BLKSIG 6/* block signature record is missing --> invalid block */ +#define RSGTE_INVLD_RECCNT 7/* mismatch between actual records and records + given in block-sig record */ +#define RSGTE_INVLHDR 8/* invalid file header */ +#define RSGTE_EOF 9 /* specific EOF */ static inline uint16_t @@ -225,5 +230,8 @@ void sigblkFinish(gtfile gf); int rsgt_tlvrdHeader(FILE *fp, unsigned char *hdr); int rsgt_tlvrd(FILE *fp, uint16_t *tlvtype, uint16_t *tlvlen, void *obj); void rsgt_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose); +void rsgt_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose); +int rsgt_getBlockParams(FILE *fp, uint8_t bRewind, block_sig_t **bs, uint8_t *bHasRecHashes, uint8_t *bHasIntermedHashes); +int rsgt_chkFileHdr(FILE *fp, char *expect); #endif /* #ifndef INCLUDED_LIBRSGT_H */ diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c index be78580d..961e50c5 100644 --- a/runtime/librsgt_read.c +++ b/runtime/librsgt_read.c @@ -50,7 +50,7 @@ static int rsgt_read_debug = 0; /* macro to obtain next char from file including error tracking */ #define NEXTC if((c = fgetc(fp)) == EOF) { \ - r = RSGTE_IO; \ + r = feof(fp) ? RSGTE_EOF : RSGTE_IO; \ goto done; \ } @@ -118,6 +118,17 @@ rsgt_tlvrdOctetString(FILE *fp, uint8_t **data, size_t len) done: return r; } static int +rsgt_tlvrdSkipVal(FILE *fp, size_t len) +{ + size_t i; + int c, r = 1; + for(i = 0 ; i < len ; ++i) { + NEXTC; + } + r = 0; +done: return r; +} +static int rsgt_tlvrdHASH_ALGO(FILE *fp, uint8_t *hashAlg) { int r = 1; @@ -314,14 +325,14 @@ done: return r; * otherwise everything. */ static void -outputHexBlob(uint8_t *blob, uint16_t len, uint8_t verbose) +outputHexBlob(FILE *fp, uint8_t *blob, uint16_t len, uint8_t verbose) { unsigned i; if(verbose || len <= 6) { for(i = 0 ; i < len ; ++i) - printf("%2.2x", blob[i]); + fprintf(fp, "%2.2x", blob[i]); } else { - printf("%2.2x%2.2x[...]%2.2x%2.2x", + fprintf(fp, "%2.2x%2.2x[...]%2.2x%2.2x", blob[0], blob[1], blob[len-2], blob[len-2]); } @@ -342,7 +353,7 @@ static void rsgt_printIMPRINT(FILE *fp, char *name, imprint_t *imp, uint8_t verbose) { fprintf(fp, "%s", name); - outputHexBlob(imp->data, imp->len, verbose); + outputHexBlob(fp, imp->data, imp->len, verbose); fputc('\n', fp); } @@ -376,19 +387,19 @@ rsgt_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose) fprintf(fp, "\tPrevious Block Hash:\n"); fprintf(fp, "\t Algorithm..: %s\n", hashAlgName(bs->lastHash.hashID)); fprintf(fp, "\t Hash.......: "); - outputHexBlob(bs->lastHash.data, bs->lastHash.len, verbose); + outputHexBlob(fp, bs->lastHash.data, bs->lastHash.len, verbose); fputc('\n', fp); if(blobIsZero(bs->lastHash.data, bs->lastHash.len)) fprintf(fp, "\t NOTE: New Hash Chain Start!\n"); fprintf(fp, "\tHash Algorithm: %s\n", hashAlgName(bs->hashID)); fprintf(fp, "\tIV............: "); - outputHexBlob(bs->iv, getIVLen(bs), verbose); + outputHexBlob(fp, bs->iv, getIVLen(bs), verbose); fputc('\n', fp); fprintf(fp, "\tRecord Count..: %llu\n", bs->recCount); fprintf(fp, "\tSignature Type: %s\n", sigTypeName(bs->sigID)); fprintf(fp, "\tSignature Len.: %u\n", bs->sig.der.len); fprintf(fp, "\tSignature.....: "); - outputHexBlob(bs->sig.der.data, bs->sig.der.len, verbose); + outputHexBlob(fp, bs->sig.der.data, bs->sig.der.len, verbose); fputc('\n', fp); } @@ -417,3 +428,103 @@ rsgt_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose) break; } } + + +/** + * Read block parameters. This detects if the block contains the + * individual log hashes, the intermediate hashes and the overall + * block paramters (from the signature block). As we do not have any + * begin of block record, we do not know e.g. the hash algorithm or IV + * until reading the block signature record. And because the file is + * purely sequential and variable size, we need to read all records up to + * the next signature record. + * If a caller intends to verify a log file based on the parameters, + * he must re-read the file from the begining (we could keep things + * in memory, but this is impractical for large blocks). In order + * to facitate this, the function permits to rewind to the original + * read location when it is done. + * + * @param[in] fp file pointer of tlv file + * @param[in] bRewind 0 - do not rewind at end of procesing, 1 - do so + * @param[out] bs block signature record + * @param[out] bHasRecHashes 0 if record hashes are present, 1 otherwise + * @param[out] bHasIntermedHashes 0 if intermediate hashes are present, + * 1 otherwise + * + * @returns 0 if ok, something else otherwise + */ +int +rsgt_getBlockParams(FILE *fp, uint8_t bRewind, block_sig_t **bs, + uint8_t *bHasRecHashes, uint8_t *bHasIntermedHashes) +{ + int r; + uint64_t nRecs = 0; + uint16_t tlvtype, tlvlen; + uint8_t bDone = 0; + off_t rewindPos = 0; + + if(bRewind) + rewindPos = ftello(fp); + *bHasRecHashes = 0; + *bHasIntermedHashes = 0; + *bs = NULL; + + while(!bDone) { /* we will err out on EOF */ + if((r = rsgt_tlvrdTL(fp, &tlvtype, &tlvlen)) != 0) goto done; + switch(tlvtype) { + case 0x0900: + ++nRecs; + *bHasRecHashes = 1; + rsgt_tlvrdSkipVal(fp, tlvlen); + break; + case 0x0901: + *bHasIntermedHashes = 1; + rsgt_tlvrdSkipVal(fp, tlvlen); + break; + case 0x0902: + r = rsgt_tlvrdBLOCK_SIG(fp, bs, tlvlen); + if(r != 0) goto done; + bDone = 1; + break; + default:fprintf(fp, "unknown tlv record %4.4x\n", tlvtype); + break; + } + } + + if(*bHasRecHashes && (nRecs != (*bs)->recCount)) { + r = RSGTE_INVLD_RECCNT; + goto done; + } + + if(bRewind) { + if(fseeko(fp, rewindPos, SEEK_SET) != 0) { + r = RSGTE_IO; + goto done; + } + } +done: + return r; +} + + +/** + * Read the file header and compare it to the expected value. + * The file pointer is placed right after the header. + * @param[in] fp file pointer of tlv file + * @param[in] excpect expected header (e.g. "LOGSIG10") + * @returns 0 if ok, something else otherwise + */ +int +rsgt_chkFileHdr(FILE *fp, char *expect) +{ + int r; + char hdr[9]; + + if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto done; + if(strcmp(hdr, expect)) + r = RSGTE_INVLHDR; + else + r = 0; +done: + return r; +} 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; @@ -75,6 +75,45 @@ 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) { FILE *fp; @@ -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; |