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