summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-03-25 15:56:33 +0100
committerRainer Gerhards <rgerhards@adiscon.com>2013-03-25 15:56:33 +0100
commitc896a6ba7498e15ddfe869823a64434a4180d57b (patch)
tree04d665ab29ad27f115d1cf7854862b18b97eb75f
parent199630a5ef8f0c919fbbbd9e122415d1d72886a3 (diff)
downloadrsyslog-c896a6ba7498e15ddfe869823a64434a4180d57b.tar.gz
rsyslog-c896a6ba7498e15ddfe869823a64434a4180d57b.tar.bz2
rsyslog-c896a6ba7498e15ddfe869823a64434a4180d57b.zip
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.
-rw-r--r--runtime/librsgt.c4
-rw-r--r--runtime/librsgt.h6
-rw-r--r--runtime/librsgt_read.c75
-rw-r--r--tools/rsgtutil.c75
4 files changed, 132 insertions, 28 deletions
diff --git a/runtime/librsgt.c b/runtime/librsgt.c
index 40b46d9c..adcc2a8a 100644
--- a/runtime/librsgt.c
+++ b/runtime/librsgt.c
@@ -277,6 +277,10 @@ tlvWriteBlockSig(gtfile gf, uchar *der, uint16_t lenDer)
tlvbufAddOctetString(gf, der, lenDer);
}
+/* support for old platforms - graceful degrade */
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
/* read rsyslog log state file; if we cannot access it or the
* contents looks invalid, we flag it as non-present (and thus
* begin a new hash chain).
diff --git a/runtime/librsgt.h b/runtime/librsgt.h
index d1c2b521..d308d4c3 100644
--- a/runtime/librsgt.h
+++ b/runtime/librsgt.h
@@ -147,6 +147,9 @@ struct rsgtstatefile {
/* after that, the hash value is contained within the file */
};
+/* Flags and record types for TLV handling */
+#define RSGT_FLAG_TLV16 0x20
+
/* error states */
#define RSGTE_IO 1 /* any kind of io error */
#define RSGTE_FMT 2 /* data fromat error */
@@ -167,6 +170,7 @@ struct rsgtstatefile {
#define RSGTE_MISS_BLOCKSIG 16 /* block signature record missing when expected */
#define RSGTE_INVLD_TIMESTAMP 17 /* RFC3161 timestamp is invalid */
#define RSGTE_TS_DERDECODE 18 /* error DER-Decoding a timestamp */
+#define RSGTE_TS_DERENCODE 19 /* error DER-Encoding a timestamp */
/* the following function maps RSGTE_* state to a string - must be updated
* whenever a new state is added.
@@ -215,6 +219,8 @@ RSGTE2String(int err)
return "RFC3161 timestamp invalid";
case RSGTE_TS_DERDECODE:
return "error DER-decoding RFC3161 timestamp";
+ case RSGTE_TS_DERENCODE:
+ return "error DER-encoding RFC3161 timestamp";
default:
return "unknown error";
}
diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c
index 5469db4b..29a07e54 100644
--- a/runtime/librsgt_read.c
+++ b/runtime/librsgt_read.c
@@ -100,6 +100,8 @@ rsgt_errctxInit(gterrctx_t *ectx)
ectx->verbose = 0;
ectx->errRec = NULL;
ectx->frstRecInBlk = NULL;
+ ectx->fileHash = NULL;
+ ectx->lefthash = ectx->righthash = ectx->computedHash = NULL;
}
void
rsgt_errctxExit(gterrctx_t *ectx)
@@ -163,6 +165,16 @@ reportError(int errcode, gterrctx_t *ectx)
fprintf(ectx->fp, "\tGT Verify Timestamp: [%u]%s\n",
ectx->gtstate, GTHTTP_getErrorString(ectx->gtstate));
}
+ if(errcode == RSGTE_TS_EXTEND ||
+ errcode == RSGTE_TS_DERDECODE) {
+ fprintf(ectx->fp, "\tExtending Server...: %s\n", rsgt_extend_puburl);
+ fprintf(ectx->fp, "\tGT Extend Timestamp: [%u]%s\n",
+ ectx->gtstate, GTHTTP_getErrorString(ectx->gtstate));
+ }
+ if(errcode == RSGTE_TS_DERENCODE) {
+ fprintf(ectx->fp, "\tAPI return state...: [%u]%s\n",
+ ectx->gtstate, GTHTTP_getErrorString(ectx->gtstate));
+ }
}
}
@@ -947,37 +959,70 @@ done:
return r;
}
+
+/* helper for rsgt_extendSig: */
+#define COPY_SUBREC_TO_NEWREC \
+ memcpy(newrec.data+iWr, subrec.hdr, subrec.lenHdr); \
+ iWr += subrec.lenHdr; \
+ memcpy(newrec.data+iWr, subrec.data, subrec.tlvlen); \
+ iWr += subrec.tlvlen;
static inline int
-rsgt_extendSig(GTTimestamp *timestamp, tlvrecord_t *rec)
+rsgt_extendSig(GTTimestamp *timestamp, tlvrecord_t *rec, gterrctx_t *ectx)
{
GTTimestamp *out_timestamp;
uint8_t *der;
size_t lenDer;
int r, rgt;
+ tlvrecord_t newrec, subrec;
+ uint16_t iRd, iWr;
-printf("calling extend... ");fflush(stdout);
rgt = GTHTTP_extendTimestamp(timestamp, rsgt_extend_puburl, &out_timestamp);
-printf("done: %d\n", rgt);
if(rgt != GT_OK) {
+ ectx->gtstate = rgt;
r = RSGTE_TS_EXTEND;
- // TODO: use ectx and report via the usual method!
- fprintf(stderr, "GTHTTP_extendTimestamp() failed: %d (%s)\n",
- rgt, GTHTTP_getErrorString(rgt));
goto done;
}
r = GTTimestamp_getDEREncoded(out_timestamp, &der, &lenDer);
if(r != GT_OK) {
- // TODO: use rsyslog error reporting!
- fprintf(stderr, "GTTimestamp_getDEREncoded() failed: %d (%s)\n",
- r, GT_getErrorString(r));
+ r = RSGTE_TS_DERENCODE;
+ ectx->gtstate = rgt;
goto done;
}
/* update block_sig tlv record with new extended timestamp */
- rec->hdr[2] = (lenDer >> 8) & 0xff;
- rec->hdr[3] = lenDer & 0xff;
- rec->tlvlen = (uint16_t) lenDer;
- free(rec->data);
- memcpy(rec->data, der, lenDer);
+ /* we now need to copy all tlv records before the actual der
+ * encoded part.
+ */
+ iRd = iWr = 0;
+ // TODO; check tlvtypes at comment places below!
+ if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
+ /* HASH_ALGO */
+ COPY_SUBREC_TO_NEWREC
+ if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
+ /* BLOCK_IV */
+ COPY_SUBREC_TO_NEWREC
+ if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
+ /* LAST_HASH */
+ COPY_SUBREC_TO_NEWREC
+ if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
+ /* REC_COUNT */
+ COPY_SUBREC_TO_NEWREC
+ if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done;
+ /* actual sig! */
+ newrec.data[iWr++] = 0x09 | RSGT_FLAG_TLV16;
+ newrec.data[iWr++] = 0x06;
+ newrec.data[iWr++] = (lenDer >> 8) & 0xff;
+ newrec.data[iWr++] = lenDer & 0xff;
+ /* now we know how large the new main record is */
+ newrec.tlvlen = (uint16_t) iWr+lenDer;
+ newrec.tlvtype = rec->tlvtype;
+ newrec.hdr[0] = rec->hdr[0];
+ newrec.hdr[1] = rec->hdr[1];
+ newrec.hdr[2] = (newrec.tlvlen >> 8) & 0xff;
+ newrec.hdr[3] = newrec.tlvlen & 0xff;
+ newrec.lenHdr = 4;
+ memcpy(newrec.data+iWr, der, lenDer);
+ /* and finally copy back new record to existing one */
+ memcpy(rec, &newrec, sizeof(newrec)-sizeof(newrec.data)+newrec.tlvlen+4);
r = 0;
done:
return r;
@@ -1028,7 +1073,7 @@ verifyBLOCK_SIG(block_sig_t *bs, gtfile gf, FILE *sigfp, FILE *nsigfp,
if(rsgt_read_showVerified)
reportVerifySuccess(ectx, vrfyInf);
if(bExtend)
- if((r = rsgt_extendSig(timestamp, &rec)) != 0) goto done;
+ if((r = rsgt_extendSig(timestamp, &rec, ectx)) != 0) goto done;
if(nsigfp != NULL)
if((r = rsgt_tlvwrite(nsigfp, &rec)) != 0) goto done;
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 <stdio.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#include <gt_base.h>
#include <gt_http.h>
#include <getopt.h>
@@ -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);
}