From a4755a5ed793ca439bb23b804ba7a8ab080ff110 Mon Sep 17 00:00:00 2001
From: chantra <chantr4@gmail.com>
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