summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);
}