summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-03-14 12:32:03 +0100
committerRainer Gerhards <rgerhards@adiscon.com>2013-03-14 12:32:03 +0100
commit44b4922825df794f678cd4ad18d940ff114b943f (patch)
tree45ef6523bac5e382b6a93c1750178382c9bb5892
parent06ba977249e6806571795d3257970c5f98fa0d16 (diff)
downloadrsyslog-44b4922825df794f678cd4ad18d940ff114b943f.tar.gz
rsyslog-44b4922825df794f678cd4ad18d940ff114b943f.tar.bz2
rsyslog-44b4922825df794f678cd4ad18d940ff114b943f.zip
rsgtutil: add --show-sigblock-params parameter
-rw-r--r--runtime/librsgt.h10
-rw-r--r--runtime/librsgt_read.c127
-rw-r--r--tools/rsgtutil.c48
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;