static void detectFileType(char *name) { FILE *fp; char *typeName; char hdr[9]; int r = -1; if(!strcmp(name, "-")) fp = stdin; else { if((fp = fopen(name, "r")) == NULL) { perror(name); goto err; } } if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto err; if(!strcmp(hdr, "LOGSIG10")) typeName = "Log Signature File, Version 10"; else if(!strcmp(hdr, "GTSTAT10")) typeName = "rsyslog GuardTime Signature State File, Version 10"; else typeName = "unknown"; printf("%s: %s [%s]\n", name, hdr, typeName); if(fp != stdin) fclose(fp); return; err: fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); }
static void reportError(int errcode, gterrctx_t *ectx) { if(ectx->fp != NULL) { fprintf(ectx->fp, "%s[%llu:%llu:%llu]: error[%u]: %s\n", ectx->filename, (long long unsigned) ectx->blkNum, (long long unsigned) ectx->recNum, (long long unsigned) ectx->recNumInFile, errcode, RSGTE2String(errcode)); if(ectx->frstRecInBlk != NULL) fprintf(ectx->fp, "\tBlock Start Record.: '%s'\n", ectx->frstRecInBlk); if(ectx->errRec != NULL) fprintf(ectx->fp, "\tRecord in Question.: '%s'\n", ectx->errRec); if(ectx->computedHash != NULL) { outputHash(ectx->fp, "\tComputed Hash......: ", ectx->computedHash->digest, ectx->computedHash->digest_length, ectx->verbose); } if(ectx->fileHash != NULL) { outputHash(ectx->fp, "\tSignature File Hash: ", ectx->fileHash->data, ectx->fileHash->len, ectx->verbose); } if(errcode == RSGTE_INVLD_TREE_HASH || errcode == RSGTE_INVLD_TREE_HASHID) { fprintf(ectx->fp, "\tTree Level.........: %d\n", (int) ectx->treeLevel); outputHash(ectx->fp, "\tTree Left Hash.....: ", ectx->lefthash->digest, ectx->lefthash->digest_length, ectx->verbose); outputHash(ectx->fp, "\tTree Right Hash....: ", ectx->righthash->digest, ectx->righthash->digest_length, ectx->verbose); } if(errcode == RSGTE_INVLD_TIMESTAMP || errcode == RSGTE_TS_DERDECODE) { fprintf(ectx->fp, "\tPublication Server.: %s\n", rsgt_read_puburl); 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)); } } }
static void dumpFile(char *name) { FILE *fp; char hdr[9]; void *obj; tlvrecord_t rec; int r = -1; if(!strcmp(name, "-")) fp = stdin; else { printf("Processing file %s:\n", name); if((fp = fopen(name, "r")) == NULL) { perror(name); goto err; } } if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto err; if(!strcmp(hdr, "LOGSIG10")) printf("File Header: Version 10 (deprecated) - conversion needed.\n"); else if(!strcmp(hdr, "LOGSIG11")) printf("File Header: Version 11\n"); else printf("File Header: '%s'\n", hdr); while(1) { /* we will err out on EOF */ if((r = rsgt_tlvrd(fp, &rec, &obj)) != 0) { if(feof(fp)) break; else goto err; } rsgt_tlvprint(stdout, rec.tlvtype, obj, verbose); rsgt_objfree(rec.tlvtype, obj); } if(fp != stdin) fclose(fp); return; err: fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); }
static void showSigblkParams(char *name) { FILE *fp; block_sig_t *bs; block_hdr_t *bh; 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, "LOGSIG11")) != 0) goto err; while(1) { /* we will err out on EOF */ if((r = rsgt_getBlockParams(fp, 0, &bs, &bh, &bHasRecHashes, &bHasIntermedHashes)) != 0) goto err; ++blkCnt; rsgt_printBLOCK_HDR(stdout, bh, verbose); rsgt_printBLOCK_SIG(stdout, bs, verbose); printf("\t***META INFORMATION:\n"); printf("\tBlock Nbr in File...: %llu\n", (long long unsigned) blkCnt); printf("\tHas Record Hashes...: %d\n", bHasRecHashes); printf("\tHas Tree Hashes.....: %d\n", bHasIntermedHashes); } if(fp != stdin) fclose(fp); return; err: if(r != RSGTE_EOF) fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); }
/* We handle both verify and extend with the same function as they * are very similiar. * * note: here we need to have the LOG file name, not signature! */ static void verify(char *name) { FILE *logfp = NULL, *sigfp = NULL, *nsigfp = NULL; block_sig_t *bs = NULL; gtfile gf; uint8_t bHasRecHashes, bHasIntermedHashes; uint8_t bInBlock; int r = 0; char sigfname[4096]; char oldsigfname[4096]; char nsigfname[4096]; gterrctx_t ectx; if(!strcmp(name, "-")) { fprintf(stderr, "%s mode cannot work on stdin\n", mode == MD_VERIFY ? "verify" : "extend"); goto err; } else { snprintf(sigfname, sizeof(sigfname), "%s.gtsig", name); sigfname[sizeof(sigfname)-1] = '\0'; if((logfp = fopen(name, "r")) == NULL) { perror(name); goto err; } if((sigfp = fopen(sigfname, "r")) == NULL) { perror(sigfname); goto err; } if(mode == MD_EXTEND) { snprintf(nsigfname, sizeof(nsigfname), "%s.gtsig.new", name); nsigfname[sizeof(nsigfname)-1] = '\0'; if((nsigfp = fopen(nsigfname, "w")) == NULL) { perror(nsigfname); goto err; } snprintf(oldsigfname, sizeof(oldsigfname), "%s.gtsig.old", name); oldsigfname[sizeof(oldsigfname)-1] = '\0'; } } rsgtInit("rsyslog rsgtutil " VERSION); rsgt_errctxInit(&ectx); ectx.verbose = verbose; ectx.fp = stderr; ectx.filename = strdup(sigfname); 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 done; } } gf = rsgt_vrfyConstruct_gf(); if(gf == NULL) { fprintf(stderr, "error initializing signature file structure\n"); goto done; } bInBlock = 0; ectx.blkNum = 0; ectx.recNumInFile = 0; while(!feof(logfp)) { if(bInBlock == 0) { if(bs != NULL) rsgt_objfree(0x0902, bs); if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bHasRecHashes, &bHasIntermedHashes)) != 0) 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 done; if(ectx.recNum == bs->recCount) { if((r = verifyBLOCK_SIG(bs, gf, sigfp, nsigfp, (mode == MD_EXTEND) ? 1 : 0, &ectx)) != 0) goto done; bInBlock = 0; } else bInBlock = 1; } done: if(r != RSGTE_EOF) goto err; fclose(logfp); logfp = NULL; fclose(sigfp); sigfp = NULL; if(nsigfp != 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 (%s) processing file %s\n", r, RSGTE2String(r), name); if(logfp != NULL) fclose(logfp); if(sigfp != NULL) fclose(sigfp); if(nsigfp != NULL) { fclose(nsigfp); unlink(nsigfname); } rsgtExit(); rsgt_errctxExit(&ectx); }
/* VERIFY Function using GT API * We handle both verify and extend with the same function as they * are very similiar. * * note: here we need to have the LOG file name, not signature! */ static int verifyGT(char *name, char *errbuf, char *sigfname, char *oldsigfname, char *nsigfname, FILE *logfp, FILE *sigfp, FILE *nsigfp) { block_sig_t *bs = NULL; block_hdr_t *bh = NULL; gtfile gf; uint8_t bHasRecHashes, bHasIntermedHashes; uint8_t bInBlock; int r = 0; int bInitDone = 0; gterrctx_t ectx; rsgt_errctxInit(&ectx); rsgtInit("rsyslog rsgtutil " VERSION); bInitDone = 1; ectx.verbose = verbose; ectx.fp = stderr; ectx.filename = strdup(sigfname); if((r = rsgt_chkFileHdr(sigfp, "LOGSIG11")) != 0) { if (debug) fprintf(stderr, "error %d in rsgt_chkFileHdr\n", r); goto done; } if(mode == MD_EXTEND) { if(fwrite("LOGSIG11", 8, 1, nsigfp) != 1) { perror(nsigfname); r = RSGTE_IO; goto done; } } gf = rsgt_vrfyConstruct_gf(); if(gf == NULL) { fprintf(stderr, "error initializing signature file structure\n"); goto done; } bInBlock = 0; ectx.blkNum = 0; ectx.recNumInFile = 0; while(!feof(logfp)) { if(bInBlock == 0) { if(bs != NULL) rsgt_objfree(0x0904, bs); if (bh != NULL) rsgt_objfree(0x0901, bh); if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bh, &bHasRecHashes, &bHasIntermedHashes)) != 0) { if(ectx.blkNum == 0) { fprintf(stderr, "EOF before finding any signature block - " "is the file still open and being written to?\n"); } else { if(verbose) fprintf(stderr, "EOF after signature block %lld\n", (long long unsigned) ectx.blkNum); } goto done; } /* Copy block header */ if ((r = verifyBLOCK_HDR(sigfp, nsigfp)) != 0) goto done; rsgt_vrfyBlkInit(gf, bh, bHasRecHashes, bHasIntermedHashes); ectx.recNum = 0; ++ectx.blkNum; } ++ectx.recNum, ++ectx.recNumInFile; if((r = doVerifyRec(logfp, sigfp, nsigfp, gf, &ectx, bInBlock)) != 0) goto done; if(ectx.recNum == bs->recCount) { if((r = verifyBLOCK_SIG(bs, gf, sigfp, nsigfp, (mode == MD_EXTEND) ? 1 : 0, &ectx)) != 0) goto done; bInBlock = 0; } else bInBlock = 1; } done: if(r != RSGTE_EOF) goto err; /* Make sure we've reached the end of file in both log and signature file */ if (fgetc(logfp) != EOF) { fprintf(stderr, "There are unsigned records in the end of log.\n"); fprintf(stderr, "Last signed record: %s\n", ectx.errRec); r = RSGTE_END_OF_SIG; goto err; } if (fgetc(sigfp) != EOF) { fprintf(stderr, "There are records missing from the end of the log file.\n"); r = RSGTE_END_OF_LOG; goto err; } fclose(logfp); logfp = NULL; fclose(sigfp); sigfp = NULL; if(nsigfp != 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 1; err: if(r != 0) sprintf(errbuf, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); else errbuf[0] = '\0'; if(logfp != NULL) fclose(logfp); if(sigfp != NULL) fclose(sigfp); if(nsigfp != NULL) { fclose(nsigfp); unlink(nsigfname); } if(bInitDone) { rsgtExit(); rsgt_errctxExit(&ectx); } return 0; }
static void convertFile(char *name) { FILE *oldsigfp = NULL, *newsigfp = NULL; char hdr[9]; int r = -1; char newsigfname[4096]; char oldsigfname[4096]; if(!strcmp(name, "-")) oldsigfp = stdin; else { printf("Processing file %s:\n", name); if((oldsigfp = fopen(name, "r")) == NULL) { perror(name); goto err; } } if((r = rsgt_tlvrdHeader(oldsigfp, (uchar*)hdr)) != 0) goto err; if(!strcmp(hdr, "LOGSIG10")) { printf("Found Signature File with Version 10 - starting conversion.\n"); snprintf(newsigfname, sizeof(newsigfname), "%s.LOGSIG11", name); snprintf(oldsigfname, sizeof(oldsigfname), "%s.LOGSIG10", name); if((newsigfp = fopen(newsigfname, "w")) == NULL) { perror(newsigfname); r = RSGTE_IO; goto err; } else { /* Write FileHeader first */ if ( fwrite(LOGSIGHDR, sizeof(LOGSIGHDR)-1, 1, newsigfp) != 1) goto err; } if ((r = rsgt_ConvertSigFile(oldsigfp, newsigfp, verbose)) != 0) goto err; else { /* Close FILES */ if(oldsigfp != stdin) fclose(oldsigfp); if (newsigfp != NULL) fclose(newsigfp); /* Delete OLDFILE if there is one*/ if(unlink(oldsigfname) != 0) { if(errno != ENOENT) { perror("Error removing old file"); r = RSGTE_IO; goto err; } } /* Copy main sigfile to oldfile */ if(link(name, oldsigfname) != 0) { perror("Error moving old file"); r = RSGTE_IO; goto err; } /* Delete current sigfile*/ if(unlink(name) != 0) { if(errno != ENOENT) { perror("Error removing old file"); r = RSGTE_IO; goto err; } } /* Copy new sigfile to main sigfile */ if(link(newsigfname, name) != 0) { perror("Error moving new file"); r = RSGTE_IO; goto err; } /* Delete temporary new sigfile*/ if(unlink(newsigfname) != 0) { if(errno != ENOENT) { perror("Error removing new file"); r = RSGTE_IO; goto err; } } printf("File %s was converted to Version 11.\n", name); } } else printf("File does not need to be converted, File Header is: '%s'\n", hdr); return; err: fprintf(stderr, "error %d (%s) converting file %s\n", r, RSGTE2String(r), name); }