diff options
-rw-r--r-- | runtime/librsgt.c | 4 | ||||
-rw-r--r-- | runtime/librsgt.h | 6 | ||||
-rw-r--r-- | runtime/librsgt_read.c | 75 | ||||
-rw-r--r-- | tools/rsgtutil.c | 75 |
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); } |