/* 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; }