From a4755a5ed793ca439bb23b804ba7a8ab080ff110 Mon Sep 17 00:00:00 2001 From: chantra Date: Fri, 28 Jan 2022 19:19:45 -0800 Subject: [PATCH 07/30] [rpm2extents] write RC and output to transcodedfile metadata create a new rpmcliVerifySignaturesFD function which takes a custom callback that allows collecting a textual output of the validation, similar to what rpmsign command would give. --- lib/rpmchecksig.c | 67 +++++++++++++++++++++++++++++++++++-------- lib/rpmcli.h | 5 ++-- rpm2extents.c | 73 +++++++++++++++++++++++++++++++---------------- 3 files changed, 106 insertions(+), 39 deletions(-) diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c index 1a6b95323..fcdbb424f 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -260,6 +260,29 @@ exit: return rc; } +static int rpmpkgVerifySigsFD(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, + FD_t fd, rpmsinfoCb cb, void *cbdata) +{ + char *msg = NULL; + int rc; + struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); + + rc = rpmpkgRead(vs, fd, NULL, NULL, &msg); + + if (rc) + goto exit; + + rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata); + +exit: + if (rc && msg) + rpmlog(RPMLOG_ERR, "%s\n", msg); + rpmvsFree(vs); + free(msg); + return rc; +} + + /* Wrapper around rpmkVerifySigs to preserve API */ int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn) { @@ -305,12 +328,38 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv) return res; } -int rpmcliVerifySignaturesFD(rpmts ts, FD_t fdi) +struct vfydatafd_s { + size_t len; + char msg[BUFSIZ]; +}; + + +static int vfyFDCb(struct rpmsinfo_s *sinfo, void *cbdata) { - int res = 0; + struct vfydatafd_s *vd = cbdata; + char *vmsg, *msg; + size_t n; + size_t remainder = BUFSIZ - vd->len; + + vmsg = rpmsinfoMsg(sinfo); + rasprintf(&msg, " %s\n", vmsg); + n = rstrlcpy(vd->msg + vd->len, msg, remainder); + free(vmsg); + free(msg); + if(n <= remainder){ + vd->len += n; + } + return 1; +} + + +int rpmcliVerifySignaturesFD(rpmts ts, FD_t fdi, char **msg) +{ + rpmRC rc = RPMRC_FAIL; rpmKeyring keyring = rpmtsGetKeyring(ts, 1); rpmVSFlags vsflags = rpmtsVfyFlags(ts); int vfylevel = rpmtsVfyLevel(ts); + struct vfydatafd_s vd = {.len = 0}; vsflags |= rpmcliVSFlags; if (rpmcliVfyLevelMask) { @@ -318,19 +367,13 @@ int rpmcliVerifySignaturesFD(rpmts ts, FD_t fdi) rpmtsSetVfyLevel(ts, vfylevel); } - FD_t fd = fdDup(Fileno(fdi)); - if (fd == NULL || Ferror(fd)) { - rpmlog(RPMLOG_ERR, _("fdDup failed: %s\n"), Fstrerror(fd)); - res++; - } else if (rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, "stdin")) { - res++; + if (!rpmpkgVerifySigsFD(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) { + rc = RPMRC_OK; } - - lseek(Fileno(fd), SEEK_SET, 0); - Fclose(fd); + *msg = strdup(vd.msg); rpmsqPoll(); rpmKeyringFree(keyring); - return res; + return rc; } diff --git a/lib/rpmcli.h b/lib/rpmcli.h index 52443e459..7ff48b37a 100644 --- a/lib/rpmcli.h +++ b/lib/rpmcli.h @@ -413,12 +413,13 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv); /** \ingroup rpmcli - * Verify package signatures + * Verify package signatures. * @param ts transaction set * @param fd a file descriptor to verify + * @param msg a string containing textual information about the verification, similar to rpmcliVerifySignatures output. * @return 0 on success */ -int rpmcliVerifySignaturesFD(rpmts ts, FD_t fd); +int rpmcliVerifySignaturesFD(rpmts ts, FD_t fd, char **msg); #ifdef __cplusplus } diff --git a/rpm2extents.c b/rpm2extents.c index d8e582676..065a00306 100644 --- a/rpm2extents.c +++ b/rpm2extents.c @@ -133,16 +133,38 @@ exit: return rc; } -static rpmRC validator(FD_t fdi){ +static rpmRC validator(FD_t fdi, FD_t fdo){ + int rc; + char *msg = NULL; rpmts ts = rpmtsCreate(); + size_t len; + rpmtsSetRootDir(ts, rpmcliRootDir); - /* rpmlog prints NOTICE to stdout */ - // rpmlogSetFile(stderr); - if(rpmcliVerifySignaturesFD(ts, fdi)){ + rc = rpmcliVerifySignaturesFD(ts, fdi, &msg); + if(rc){ fprintf(stderr, _("Error validating package\n")); - return RPMRC_FAIL; } - return RPMRC_OK; + len = sizeof(rc); + if (Fwrite(&rc, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write validator RC code %d\n"), rc); + goto exit; + } + size_t validator_len = msg ? strlen(msg) : 0; + len = sizeof(validator_len); + if (Fwrite(&validator_len, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write validator output length code %zd\n"), validator_len); + goto exit; + } + if (Fwrite(msg, validator_len, 1, fdo) != validator_len) { + fprintf(stderr, _("Unable to write validator output %s\n"), msg); + goto exit; + } + +exit: + if(msg) { + free(msg); + } + return rc ? RPMRC_FAIL : RPMRC_OK; } static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) @@ -173,7 +195,7 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) rpm_mode_t mode; char *rpmio_flags = NULL, *zeros; const unsigned char *digest; - rpm_loff_t pos, size, pad, digest_pos, validation_pos; + rpm_loff_t pos, size, pad, digest_pos, validation_pos, digest_table_pos; uint32_t offset_ix = 0; size_t len; int next = 0; @@ -278,6 +300,16 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset), digestoffsetCmp); + validation_pos = pos; + ssize_t validation_len = ufdCopy(validationi, fdo); + if (validation_len == -1) { + fprintf(stderr, _("validation output ufdCopy failed\n")); + rc = RPMRC_FAIL; + goto exit; + } + + digest_table_pos = validation_pos + validation_len; + len = sizeof(offset_ix); if (Fwrite(&offset_ix, len, 1, fdo) != len) { fprintf(stderr, _("Unable to write length of table\n")); @@ -304,7 +336,7 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) } } digest_pos = ( - pos + sizeof(offset_ix) + sizeof(diglen) + + digest_table_pos + sizeof(offset_ix) + sizeof(diglen) + offset_ix * (diglen + sizeof(rpm_loff_t)) ); @@ -315,14 +347,6 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) goto exit; } - validation_pos = digest_pos + digest_len; - ssize_t validation_len = ufdCopy(validationi, fdo); - if (validation_len == -1) { - fprintf(stderr, _("validation output ufdCopy failed\n")); - rc = RPMRC_FAIL; - goto exit; - } - /* add more padding so the last file can be cloned. It doesn't matter that * the table and validation etc are in this space. In fact, it's pretty * efficient if it is. @@ -336,18 +360,18 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) goto exit; } zeros = _free(zeros); - if (Fwrite(&pos, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write offset of digest table\n")); + if (Fwrite(&validation_pos, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write offset of validation output\n")); rc = RPMRC_FAIL; goto exit; } - if (Fwrite(&digest_pos, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write offset of validation table\n")); + if (Fwrite(&digest_table_pos, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write offset of digest table\n")); rc = RPMRC_FAIL; goto exit; } - if (Fwrite(&validation_pos, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write offset of validation output\n")); + if (Fwrite(&digest_pos, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write offset of validation table\n")); rc = RPMRC_FAIL; goto exit; } @@ -431,11 +455,9 @@ static int teeRpm(FD_t fdi, FD_t digestori) { close(validatorpipefd[1]); close(rpmsignpipefd[0]); FD_t fdi = fdDup(validatorpipefd[0]); - // redirect STDOUT to the pipe - close(STDOUT_FILENO); FD_t fdo = fdDup(rpmsignpipefd[1]); close(rpmsignpipefd[1]); - rc = validator(fdi); + rc = validator(fdi, fdo); if(rc != RPMRC_OK) { fprintf(stderr, _("Validator failed\n")); } @@ -486,6 +508,7 @@ static int teeRpm(FD_t fdi, FD_t digestori) { close(rpmsignpipefd[0]); close(rpmsignpipefd[1]); + rc = RPMRC_OK; offt = ufdTee(fdi, fds, 2); if(offt == -1){ fprintf(stderr, _("Failed to tee RPM\n")); -- 2.35.1