#18 merge latest package from CentOS 9 Stream
Merged 4 months ago by dcavalca. Opened 4 months ago by teknoraver.
rpms/ teknoraver/rpm c9s-sig-hyperscale  into  c9s-sig-hyperscale

@@ -0,0 +1,124 @@ 

+ From 1dc9372821487ccace23ff1ae9cba6b30f02c91c Mon Sep 17 00:00:00 2001

+ From: Florian Festi <ffesti@redhat.com>

+ Date: Tue, 5 Jul 2022 16:34:08 +0200

+ Subject: [PATCH] Add SourceLicense tag to spec syntax

+ 

+ to set a separate license to the source RPM. This can be useful if the

+ sources have code under additional licenses that do not end up in the

+ binary packeges.

+ 

+ Resolves: #2079

+ 

+ Note on the backport:  The spec document on this branch is ancient and

+ doesn't even contain the License tag's description so this backport

+ leaves the documentation part out.

+ 

+ (backported from commit 9ed9d3fce34bc3c8121989e0cf263528e7e68756)

+ ---

+  build/parsePreamble.c       |  6 ++++++

+  lib/rpmtag.h                |  3 +++

+  tests/data/SPECS/foo.spec   |  1 +

+  tests/data/SPECS/hello.spec |  1 +

+  tests/rpmbuild.at           | 11 +++++++++++

+  tests/rpmspec.at            |  1 +

+  6 files changed, 23 insertions(+)

+ 

+ diff --git a/build/parsePreamble.c b/build/parsePreamble.c

+ index e7d6d8752..bd07ecdf0 100644

+ --- a/build/parsePreamble.c

+ +++ b/build/parsePreamble.c

+ @@ -831,6 +831,11 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,

+  	if (addLangTag(spec, pkg->header, tag, field, lang))

+  	    goto exit;

+  	break;

+ +    case RPMTAG_SOURCELICENSE:

+ +	if (addLangTag(spec, spec->sourcePackage->header,

+ +		       RPMTAG_LICENSE, field, lang))

+ +	    goto exit;

+ +	break;

+      case RPMTAG_BUILDROOT:

+  	/* just silently ignore BuildRoot */

+  	break;

+ @@ -1012,6 +1017,7 @@ static struct PreambleRec_s const preambleList[] = {

+      {RPMTAG_EPOCH,		0, 0, 1, LEN_AND_STR("epoch")},

+      {RPMTAG_SUMMARY,		1, 0, 1, LEN_AND_STR("summary")},

+      {RPMTAG_LICENSE,		0, 0, 1, LEN_AND_STR("license")},

+ +    {RPMTAG_SOURCELICENSE,	0, 0, 1, LEN_AND_STR("sourcelicense")},

+      {RPMTAG_DISTRIBUTION,	0, 0, 1, LEN_AND_STR("distribution")},

+      {RPMTAG_DISTURL,		0, 0, 1, LEN_AND_STR("disturl")},

+      {RPMTAG_VENDOR,		0, 0, 1, LEN_AND_STR("vendor")},

+ diff --git a/lib/rpmtag.h b/lib/rpmtag.h

+ index 7d1943835..1fd829118 100644

+ --- a/lib/rpmtag.h

+ +++ b/lib/rpmtag.h

+ @@ -375,6 +375,9 @@ typedef enum rpmTag_e {

+      RPMTAG_MODULARITYLABEL	= 5096, /* s */

+      RPMTAG_PAYLOADDIGESTALT	= 5097, /* s[] */

+  

+ +    /* Backports */

+ +    RPMTAG_SOURCELICENSE	= 5102, /* internal */

+ +

+      RPMTAG_FIRSTFREE_TAG	/*!< internal */

+  } rpmTag;

+  

+ diff --git a/tests/data/SPECS/foo.spec b/tests/data/SPECS/foo.spec

+ index 859e98142..9b1087094 100644

+ --- a/tests/data/SPECS/foo.spec

+ +++ b/tests/data/SPECS/foo.spec

+ @@ -8,6 +8,7 @@ Source: hello-2.0.tar.gz

+  Patch1: hello-1.0-modernize.patch

+  Group: Testing

+  License: GPLv2+

+ +SourceLicense: GPL, ASL 1.0

+  BuildArch: noarch

+  

+  %description

+ diff --git a/tests/data/SPECS/hello.spec b/tests/data/SPECS/hello.spec

+ index 5bc9cfaf7..4b9053aca 100644

+ --- a/tests/data/SPECS/hello.spec

+ +++ b/tests/data/SPECS/hello.spec

+ @@ -4,6 +4,7 @@ Version: 1.0

+  Release: 1

+  Group: Utilities

+  License: GPL

+ +SourceLicense: GPL, ASL 1.0

+  Distribution: RPM test suite.

+  Vendor: Red Hat Software

+  Packager: Red Hat Software <bugs@redhat.com>

+ diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at

+ index bff65303b..7680f1502 100644

+ --- a/tests/rpmbuild.at

+ +++ b/tests/rpmbuild.at

+ @@ -31,6 +31,17 @@ run rpmbuild \

+  [0],

+  [ignore],

+  [ignore])

+ +

+ +AT_CHECK([

+ +

+ +runroot rpm -qp --qf "%{license}\n" /build/SRPMS/hello-1.0-1.src.rpm

+ +runroot rpm -qp --qf "%{license}\n" /build/RPMS/*/hello-1.0-1.*.rpm

+ +],

+ +[0],

+ +[GPL, ASL 1.0

+ +GPL

+ +],

+ +[])

+  AT_CLEANUP

+  

+  AT_SETUP([rpmbuild -ba autosetup])

+ diff --git a/tests/rpmspec.at b/tests/rpmspec.at

+ index 2b11201db..c898ee654 100644

+ --- a/tests/rpmspec.at

+ +++ b/tests/rpmspec.at

+ @@ -243,6 +243,7 @@ Source: hello-2.0.tar.gz

+  Patch1: hello-1.0-modernize.patch

+  Group: Testing

+  License: GPLv2+

+ +SourceLicense: GPL, ASL 1.0

+  BuildArch: noarch

+  

+  %description

+ -- 

+ 2.45.2

+ 

@@ -0,0 +1,12 @@ 

+ diff -up rpm-4.16.1.3/lib/rpmts.c.orig rpm-4.16.1.3/lib/rpmts.c

+ --- rpm-4.16.1.3/lib/rpmts.c.orig	2024-07-11 13:55:35.430198126 +0200

+ +++ rpm-4.16.1.3/lib/rpmts.c	2024-07-11 13:55:59.243061182 +0200

+ @@ -482,6 +482,8 @@ static int makePubkeyHeader(rpmts ts, rp

+      int rc = -1;

+      int i;

+  

+ +    memset(&kd, 0, sizeof(kd));

+ +

+      if ((enc = rpmPubkeyBase64(key)) == NULL)

+  	goto exit;

+      if ((dig = rpmPubkeyDig(key)) == NULL)

@@ -0,0 +1,32 @@ 

+ From bff65aad8af719542c7b0c6429e09223c014a909 Mon Sep 17 00:00:00 2001

+ From: Michal Domonkos <mdomonko@redhat.com>

+ Date: Thu, 6 Jun 2024 09:15:02 +0200

+ Subject: [PATCH] Fix potential use of uninitialized pipe array

+ 

+ We only call pipe(2) after the script is written to disk so if the

+ latter fails, the array will be left uninitialized and subsequently read

+ after skipping to the exit label.  Fix by initializing it.

+ 

+ Found by Coverity.

+ 

+ Fixes: RHEL-22604

+ ---

+  lib/rpmscript.c | 2 +-

+  1 file changed, 1 insertion(+), 1 deletion(-)

+ 

+ diff --git a/lib/rpmscript.c b/lib/rpmscript.c

+ index 281c55c53..1de4acf8e 100644

+ --- a/lib/rpmscript.c

+ +++ b/lib/rpmscript.c

+ @@ -316,7 +316,7 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,

+      char * fn = NULL;

+      pid_t pid, reaped;

+      int status;

+ -    int inpipe[2];

+ +    int inpipe[2] = { -1, -1 };

+      FILE *in = NULL;

+      const char *line;

+      char *mline = NULL;

+ -- 

+ 2.45.2

+ 

@@ -0,0 +1,91 @@ 

+ From bce17e42f2301a88574d757740627480a38d86aa Mon Sep 17 00:00:00 2001

+ From: Michal Domonkos <mdomonko@redhat.com>

+ Date: Fri, 26 Jul 2024 10:44:04 +0200

+ Subject: [PATCH] Fix root relocation regression

+ 

+ When relocating the root directory, make sure we insert the new path's

+ dirname to dirNames[] even if the root itself is owned by the package.

+ 

+ This appears to have been the intention from the first version (largely

+ untouched since) of this code as we allow the root to pass through the

+ first checks (by setting len to 0 in that case) as well as the second

+ for loop where we do the relocations.

+ 

+ This allows fsm to properly create and remove the relocated directory

+ since we're now using fd-based calls (#1919) and the parent directory

+ needs to be opened first.

+ 

+ No need to do string comparison here, the empty basename signals that

+ we're processing the root directory, so just use that.

+ 

+ Building a relocatable package that owns the root directory seems to be

+ a handy way to create user-installable packages (see RHEL-28967) and it

+ happened to work before with the path-based calls so this technically

+ was a regression.  Add a test that emulates this use case.

+ 

+ Backported from commits:

+ 31c14ba6610568c2d634647fed1fb57221178da9

+ 308ac60677732e9979b9ce11e5a3085906da1901

+ 

+ Fixes: RHEL-28967

+ ---

+  lib/relocation.c | 14 ++++++++------

+  1 file changed, 8 insertions(+), 6 deletions(-)

+ 

+ diff --git a/lib/relocation.c b/lib/relocation.c

+ index 3ba4cfeab..8c35bc1a7 100644

+ --- a/lib/relocation.c

+ +++ b/lib/relocation.c

+ @@ -123,7 +123,7 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,

+      char ** baseNames;

+      char ** dirNames;

+      uint32_t * dirIndexes;

+ -    rpm_count_t fileCount, dirCount;

+ +    rpm_count_t fileCount, dirCount, dirCountOrig;

+      int nrelocated = 0;

+      int fileAlloced = 0;

+      char * fn = NULL;

+ @@ -162,7 +162,7 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,

+      baseNames = bnames.data;

+      dirIndexes = dindexes.data;

+      fileCount = rpmtdCount(&bnames);

+ -    dirCount = rpmtdCount(&dnames);

+ +    dirCount = dirCountOrig = rpmtdCount(&dnames);

+      /* XXX TODO: use rpmtdDup() instead */

+      dirNames = dnames.data = duparray(dnames.data, dirCount);

+      dnames.flags |= RPMTD_PTR_ALLOCED;

+ @@ -179,8 +179,9 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,

+  	rpmFileTypes ft;

+  	int fnlen;

+  

+ +	size_t baselen = strlen(baseNames[i]);

+  	size_t len = maxlen +

+ -		strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;

+ +		strlen(dirNames[dirIndexes[i]]) + baselen + 1;

+  	if (len >= fileAlloced) {

+  	    fileAlloced = len * 2;

+  	    fn = xrealloc(fn, fileAlloced);

+ @@ -242,8 +243,9 @@ assert(fn != NULL);		/* XXX can't happen */

+  	    continue;

+  	}

+  

+ -	/* Relocation on full paths only, please. */

+ -	if (fnlen != len) continue;

+ +	/* Relocation on '/' and full paths only, please. */

+ +	if (baselen && fnlen != len)

+ +	    continue;

+  

+  	rpmlog(RPMLOG_DEBUG, "relocating %s to %s\n",

+  	       fn, relocations[j].newPath);

+ @@ -294,7 +296,7 @@ assert(fn != NULL);		/* XXX can't happen */

+      }

+  

+      /* Finish off by relocating directories. */

+ -    for (i = dirCount - 1; i >= 0; i--) {

+ +    for (i = dirCountOrig - 1; i >= 0; i--) {

+  	for (j = numRelocations - 1; j >= 0; j--) {

+  

+  	    if (relocations[j].oldPath == NULL) /* XXX can't happen */

+ -- 

+ 2.45.2

+ 

The added file is too large to be shown here, see it at: 0001-RPM-with-Copy-on-Write.patch
@@ -0,0 +1,51 @@ 

+ From f6ffaacbbf7f5aca45139a612c5dd8db3f2094dc Mon Sep 17 00:00:00 2001

+ From: Michal Domonkos <mdomonko@redhat.com>

+ Date: Mon, 5 Aug 2024 14:40:57 +0200

+ Subject: [PATCH] Skip to hashed subpacket data directly

+ 

+ Let OpenScanHub grok the bigger picture instead of producing a spurious

+ overrun warning for v->hashlen when we're dereferencing p later.

+ 

+ Casting the v pointer back to uint8_t is unnecessary when we could just

+ use h directly but it's done this way in the if branch for pgp version 3

+ in this function as well as in pgpPrtKey() so copy that, just for the

+ sake of consistency.

+ 

+ Along the same lines (consistency), change the p pointer to a const

+ pointer.

+ 

+ No functional change.

+ 

+ Resolves: RHEL-22607

+ ---

+  rpmio/rpmpgp.c | 5 ++---

+  1 file changed, 2 insertions(+), 3 deletions(-)

+ 

+ diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c

+ index d0688ebe9..6f044eb1b 100644

+ --- a/rpmio/rpmpgp.c

+ +++ b/rpmio/rpmpgp.c

+ @@ -565,7 +565,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,

+  		     pgpDigParams _digp)

+  {

+      uint8_t version = 0;

+ -    uint8_t * p;

+ +    const uint8_t * p;

+      unsigned int plen;

+      int rc = 1;

+  

+ @@ -618,10 +618,9 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,

+  	pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);

+  	pgpPrtNL();

+  

+ -	p = &v->hashlen[0];

+  	if (pgpGet(v->hashlen, sizeof(v->hashlen), h + hlen, &plen))

+  	    return 1;

+ -	p += sizeof(v->hashlen);

+ +	p = ((uint8_t *)v) + sizeof(*v);

+  

+  	if ((p + plen) > (h + hlen))

+  	    return 1;

+ -- 

+ 2.46.0

+ 

@@ -0,0 +1,57 @@ 

+ From d29651be364ef72c7c0f468157602e4ed5cab4ff Mon Sep 17 00:00:00 2001

+ From: Florian Festi <ffesti@redhat.com>

+ Date: Wed, 12 Jun 2024 15:46:12 +0200

+ Subject: [PATCH] Talk about rpmsign in the rpmsign man page

+ 

+ In the past handling signatures was done by the rpm / rpmbuild binaries

+ directly. When this functionality was split into rpmsign the man page

+ was not adjusted accoringly. This is the long overdue update.

+ 

+ Resolves: # 3125

+ 

+ (backported from commit 8e1f55c7004e8c1a7d9140ab2dd9456a7ace3e77)

+ ---

+  doc/rpmsign.8 | 10 +++++-----

+  1 file changed, 5 insertions(+), 5 deletions(-)

+ 

+ diff --git a/doc/rpmsign.8 b/doc/rpmsign.8

+ index f7ceae89b..6c5bcc8ef 100644

+ --- a/doc/rpmsign.8

+ +++ b/doc/rpmsign.8

+ @@ -5,9 +5,9 @@ rpmsign \- RPM Package Signing

+  .SS "SIGNING PACKAGES:"

+  .PP

+  

+ -\fBrpm\fR \fB--addsign|--resign\fR [\fBrpmsign-options\fR] \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR

+ +\fBrpmsign\fR \fB--addsign|--resign\fR [\fBrpmsign-options\fR] \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR

+  

+ -\fBrpm\fR \fB--delsign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR

+ +\fBrpmsign\fR \fB--delsign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR

+  

+  .SS "rpmsign-options"

+  .PP

+ @@ -22,10 +22,10 @@ options generate and insert new signatures for each package

+  existing signatures. There are two options for historical reasons,

+  there is no difference in behavior currently.

+  

+ -To create a signature rpm needs to verify the package's checksum. As a result

+ +To create a signature rpmsign needs to verify the package's checksum. As a result

+  packages with a MD5/SHA1 checksums cannot be signed in FIPS mode.

+  

+ -\fBrpm\fR \fB--delsign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR

+ +\fBrpmsign\fR \fB--delsign\fR \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR

+  

+  .PP

+  Delete all signatures from each package \fIPACKAGE_FILE\fR given.

+ @@ -36,7 +36,7 @@ Delete all signatures from each package \fIPACKAGE_FILE\fR given.

+  \fB--rpmv3\fR

+  Force RPM V3 header+payload signature addition.

+  These are expensive and redundant baggage on packages where a separate

+ -payload digest exists (packages built with rpm >= 4.14).  Rpm will

+ +payload digest exists (packages built with rpm >= 4.14).  Rpmsign will

+  automatically detect the need for V3 signatures, but this option can be

+  used to force their creation if the packages must be fully 

+  signature verifiable with rpm < 4.14 or other interoperability reasons.

+ -- 

+ 2.45.2

+ 

@@ -0,0 +1,64 @@ 

+ From 845b5c3882b1eecb31d712b61a4e91fe0eb70712 Mon Sep 17 00:00:00 2001

+ From: Matthew Almond <malmond@fb.com>

+ Date: Sun, 31 Jan 2021 12:30:33 -0800

+ Subject: [PATCH 02/30] Remove use of bool type for consistency

+ 

+ ---

+  lib/fsm.c | 11 +++++------

+  1 file changed, 5 insertions(+), 6 deletions(-)

+ 

+ diff --git a/lib/fsm.c b/lib/fsm.c

+ index 90193c749..feda3750c 100644

+ --- a/lib/fsm.c

+ +++ b/lib/fsm.c

+ @@ -8,7 +8,6 @@

+  #include <inttypes.h>

+  #include <utime.h>

+  #include <errno.h>

+ -#include <stdbool.h>

+  #include <fcntl.h>

+  #ifdef WITH_CAP

+  #include <sys/capability.h>

+ @@ -56,7 +55,7 @@ struct filedata_s {

+      int stage;

+      int setmeta;

+      int skip;

+ -    bool plugin_contents;

+ +    int plugin_contents;

+      rpmFileAction action;

+      const char *suffix;

+      char *fpath;

+ @@ -890,10 +889,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,

+      struct diriter_s di = { -1, -1 };

+      Header h = rpmteHeader(te);

+      const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT);

+ -    bool cpio = true;

+ +    int cpio = 1;

+  

+      if (payloadfmt && rstreq(payloadfmt, "clon")) {

+ -	cpio = false;

+ +	cpio = 0;

+      }

+  

+      /* transaction id used for temporary path suffix while installing */

+ @@ -924,7 +923,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,

+  	    setFileState(fs, fx);

+  	    break;

+  	case RPMRC_PLUGIN_CONTENTS:

+ -	    fp->plugin_contents = true;

+ +	    fp->plugin_contents = 1;

+  	    // reduce reads on cpio to this value. Could be zero if

+  	    // this is from a hard link.

+  	    rc = RPMRC_OK;

+ @@ -986,7 +985,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,

+  		rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,

+  					      fp->sb.st_mode, fp->action);

+  		if (rc == RPMRC_PLUGIN_CONTENTS) {

+ -		    fp->plugin_contents = true;

+ +		    fp->plugin_contents = 1;

+  		    rc = RPMRC_OK;

+  		}

+  	    }

+ -- 

+ 2.35.1

+ 

The added file is too large to be shown here, see it at: 0003-Match-formatting-style-of-existing-code.patch
@@ -0,0 +1,27 @@ 

+ From 15127592f8cc3221129f61b79319d88c7727bec3 Mon Sep 17 00:00:00 2001

+ From: Matthew Almond <malmond@fb.com>

+ Date: Sun, 31 Jan 2021 15:24:25 -0800

+ Subject: [PATCH 04/30] Fix printf formatting in reflink.c

+ 

+ There were some mismatches on field "sizes". This should eliminate the

+ error messages.

+ ---

+  plugins/reflink.c | 2 +-

+  1 file changed, 1 insertion(+), 1 deletion(-)

+ 

+ diff --git a/plugins/reflink.c b/plugins/reflink.c

+ index 9eaa87094..513887604 100644

+ --- a/plugins/reflink.c

+ +++ b/plugins/reflink.c

+ @@ -316,7 +316,7 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,

+  		return RPMRC_FAIL;

+  	    }

+  	    rpmlog(RPMLOG_DEBUG,

+ -	           _("reflink: Reflinking %lu bytes at %lu to %s orig size=%lu, file=%ld\n"),

+ +	           _("reflink: Reflinking %llu bytes at %llu to %s orig size=%ld, file=%lld\n"),

+  		   fcr.src_length, fcr.src_offset, path, size, fcr.src_fd);

+  	    rc = ioctl(dst, FICLONERANGE, &fcr);

+  	    if (rc) {

+ -- 

+ 2.35.1

+ 

@@ -0,0 +1,73 @@ 

+ From fd4060dcfbe4127fb0d19f1878d0d8b9f34c7b9a Mon Sep 17 00:00:00 2001

+ From: chantra <chantr4@gmail.com>

+ Date: Fri, 28 Jan 2022 08:33:16 -0800

+ Subject: [PATCH 05/30] [tests][rpm2extents] Add basic tests for rpm2extents

+ 

+ ---

+  tests/Makefile.am    |  1 +

+  tests/rpm2extents.at | 31 +++++++++++++++++++++++++++++++

+  tests/rpmtests.at    |  1 +

+  3 files changed, 33 insertions(+)

+  create mode 100644 tests/rpm2extents.at

+ 

+ diff --git a/tests/Makefile.am b/tests/Makefile.am

+ index f78e17c3e..fc8a24a5e 100644

+ --- a/tests/Makefile.am

+ +++ b/tests/Makefile.am

+ @@ -36,6 +36,7 @@ TESTSUITE_AT += rpmio.at

+  TESTSUITE_AT += rpmio.at

+  TESTSUITE_AT += rpmorder.at

+  TESTSUITE_AT += rpmvfylevel.at

+ +TESTSUITE_AT += rpm2extents.at

+  EXTRA_DIST += $(TESTSUITE_AT)

+  

+  ## testsuite data

+ diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at

+ new file mode 100644

+ index 000000000..f943b9af4

+ --- /dev/null

+ +++ b/tests/rpm2extents.at

+ @@ -0,0 +1,31 @@

+ +#    rpm2extents.at: Some very basic checks

+ +#

+ +#    Copyright (C) 2022  Manu Bretelle <chantr4@gmail.com>

+ +#

+ +#    This program is free software; you can redistribute it and/or modify

+ +#    it under the terms of the GNU General Public License as published by

+ +#    the Free Software Foundation; either version 2 of the License, or

+ +#    (at your option) any later version.

+ +#

+ +#    This program is distributed in the hope that it will be useful,

+ +#    but WITHOUT ANY WARRANTY; without even the implied warranty of

+ +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ +#    GNU General Public License for more details.

+ +#

+ +#    You should have received a copy of the GNU General Public License

+ +#    along with this program; if not, write to the Free Software

+ +#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

+ +

+ +AT_BANNER([rpm2extents tests])

+ +

+ +# ------------------------------

+ +

+ +# check that transcoder write magic at the end

+ +AT_SETUP([rpm2extents magic])

+ +AT_KEYWORDS([rpm2extents])

+ +AT_CHECK([runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 | tail -c8],

+ +[0],

+ +[KWTSH100],

+ +[ignore])

+ +AT_CLEANUP

+ +

+ diff --git a/tests/rpmtests.at b/tests/rpmtests.at

+ index a1adab8e0..205fed6a3 100644

+ --- a/tests/rpmtests.at

+ +++ b/tests/rpmtests.at

+ @@ -22,3 +22,4 @@ m4_include([rpmreplace.at])

+  m4_include([rpmconfig.at])

+  m4_include([rpmconfig2.at])

+  m4_include([rpmconfig3.at])

+ +m4_include([rpm2extents.at])

+ -- 

+ 2.35.1

+ 

@@ -0,0 +1,431 @@ 

+ From ea1177fcef609519f0c2377ebee236001d2a8fae Mon Sep 17 00:00:00 2001

+ From: chantra <chantr4@gmail.com>

+ Date: Fri, 28 Jan 2022 08:31:39 -0800

+ Subject: [PATCH 06/30] [rpm2extents] verify package signature during

+  transcoding

+ 

+ ---

+  lib/rpmchecksig.c |  30 ++++++

+  lib/rpmcli.h      |   9 ++

+  rpm2extents.c     | 233 +++++++++++++++++++++++++++++++++++++++++-----

+  3 files changed, 248 insertions(+), 24 deletions(-)

+ 

+ diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c

+ index 40a3ab83f..1a6b95323 100644

+ --- a/lib/rpmchecksig.c

+ +++ b/lib/rpmchecksig.c

+ @@ -304,3 +304,33 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)

+      rpmKeyringFree(keyring);

+      return res;

+  }

+ +

+ +int rpmcliVerifySignaturesFD(rpmts ts, FD_t fdi)

+ +{

+ +    int res = 0;

+ +    rpmKeyring keyring = rpmtsGetKeyring(ts, 1);

+ +    rpmVSFlags vsflags = rpmtsVfyFlags(ts);

+ +    int vfylevel = rpmtsVfyLevel(ts);

+ +

+ +    vsflags |= rpmcliVSFlags;

+ +    if (rpmcliVfyLevelMask) {

+ +	vfylevel &= ~rpmcliVfyLevelMask;

+ +	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++;

+ +    }

+ +

+ +    lseek(Fileno(fd), SEEK_SET, 0);

+ +    Fclose(fd);

+ +    rpmsqPoll();

+ +

+ +    rpmKeyringFree(keyring);

+ +    return res;

+ +}

+ +

+ diff --git a/lib/rpmcli.h b/lib/rpmcli.h

+ index 906fe9951..52443e459 100644

+ --- a/lib/rpmcli.h

+ +++ b/lib/rpmcli.h

+ @@ -411,6 +411,15 @@ int rpmcliImportPubkeys(rpmts ts, ARGV_const_t argv);

+   */

+  int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv);

+  

+ +

+ +/** \ingroup rpmcli

+ + * Verify package signatures

+ + * @param ts		transaction set

+ + * @param fd		a file descriptor to verify

+ + * @return		0 on success

+ + */

+ +int rpmcliVerifySignaturesFD(rpmts ts, FD_t fd);

+ +

+  #ifdef __cplusplus

+  }

+  #endif

+ diff --git a/rpm2extents.c b/rpm2extents.c

+ index c111be0a2..d8e582676 100644

+ --- a/rpm2extents.c

+ +++ b/rpm2extents.c

+ @@ -2,7 +2,9 @@

+  

+  #include "system.h"

+  

+ +#include <rpm/rpmcli.h>

+  #include <rpm/rpmlib.h>		/* rpmReadPackageFile .. */

+ +#include <rpm/rpmlog.h>

+  #include <rpm/rpmfi.h>

+  #include <rpm/rpmtag.h>

+  #include <rpm/rpmio.h>

+ @@ -10,6 +12,7 @@

+  

+  #include <rpm/rpmts.h>

+  #include "lib/rpmlead.h"

+ +#include "lib/rpmts.h"

+  #include "lib/signature.h"

+  #include "lib/header_internal.h"

+  #include "rpmio/rpmio_internal.h"

+ @@ -51,6 +54,16 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit)

+      return (unit - (pos % unit)) % unit;

+  }

+  

+ +static struct poptOption optionsTable[] = {

+ +    { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,

+ +    N_("Common options for all rpm modes and executables:"), NULL },

+ +

+ +    POPT_AUTOALIAS

+ +    POPT_AUTOHELP

+ +    POPT_TABLEEND

+ +};

+ +

+ +

+  static int digestor(

+      FD_t fdi,

+      FD_t fdo,

+ @@ -120,7 +133,19 @@ exit:

+      return rc;

+  }

+  

+ -static rpmRC process_package(FD_t fdi, FD_t validationi)

+ +static rpmRC validator(FD_t fdi){

+ +    rpmts ts = rpmtsCreate();

+ +    rpmtsSetRootDir(ts, rpmcliRootDir);

+ +    /* rpmlog prints NOTICE to stdout */

+ +    // rpmlogSetFile(stderr);

+ +    if(rpmcliVerifySignaturesFD(ts, fdi)){

+ +	fprintf(stderr, _("Error validating package\n"));

+ +	return RPMRC_FAIL;

+ +    }

+ +    return RPMRC_OK;

+ +}

+ +

+ +static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)

+  {

+      uint32_t diglen;

+      /* GNU C extension: can use diglen from outer context */

+ @@ -148,7 +173,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)

+      rpm_mode_t mode;

+      char *rpmio_flags = NULL, *zeros;

+      const unsigned char *digest;

+ -    rpm_loff_t pos, size, pad, validation_pos;

+ +    rpm_loff_t pos, size, pad, digest_pos, validation_pos;

+      uint32_t offset_ix = 0;

+      size_t len;

+      int next = 0;

+ @@ -278,17 +303,26 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)

+  	    goto exit;

+  	}

+      }

+ -    validation_pos = (

+ +    digest_pos = (

+  	pos + sizeof(offset_ix) + sizeof(diglen) +

+  	offset_ix * (diglen + sizeof(rpm_loff_t))

+      );

+  

+ +    ssize_t digest_len = ufdCopy(digestori, fdo);

+ +    if (digest_len == -1) {

+ +	fprintf(stderr, _("digest table ufdCopy failed\n"));

+ +	rc = RPMRC_FAIL;

+ +	goto exit;

+ +    }

+ +

+ +    validation_pos = digest_pos + digest_len;

+      ssize_t validation_len = ufdCopy(validationi, fdo);

+      if (validation_len == -1) {

+ -	fprintf(stderr, _("digest table ufdCopy failed\n"));

+ +	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.

+ @@ -307,11 +341,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)

+  	rc = RPMRC_FAIL;

+  	goto exit;

+      }

+ -    if (Fwrite(&validation_pos, len, 1, fdo) != len) {

+ +    if (Fwrite(&digest_pos, len, 1, fdo) != len) {

+  	fprintf(stderr, _("Unable to write offset of validation 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"));

+ +	rc = RPMRC_FAIL;

+ +	goto exit;

+ +    }

+      uint64_t magic = MAGIC;

+      len = sizeof(magic);

+      if (Fwrite(&magic, len, 1, fdo) != len) {

+ @@ -327,10 +366,156 @@ exit:

+      return rc;

+  }

+  

+ +static off_t ufdTee(FD_t sfd, FD_t *fds, int len)

+ +{

+ +    char buf[BUFSIZ];

+ +    ssize_t rdbytes, wrbytes;

+ +    off_t total = 0;

+ +

+ +    while (1) {

+ +	rdbytes = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);

+ +

+ +	if (rdbytes > 0) {

+ +	    for(int i=0; i < len; i++) {

+ +		wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, fds[i]);

+ +		if (wrbytes != rdbytes) {

+ +		    fprintf(stderr, "Error wriing to FD %d: %s\n", i, Fstrerror(fds[i]));

+ +		    total = -1;

+ +		    break;

+ +		}

+ +	    }

+ +	    if(total == -1){

+ +		break;

+ +	    }

+ +	    total += wrbytes;

+ +	} else {

+ +	    if (rdbytes < 0)

+ +		total = -1;

+ +	    break;

+ +	}

+ +    }

+ +

+ +    return total;

+ +}

+ +

+ +static int teeRpm(FD_t fdi, FD_t digestori) {

+ +    rpmRC rc;

+ +    off_t offt = -1;

+ +    int processorpipefd[2];

+ +    int validatorpipefd[2];

+ +    int rpmsignpipefd[2];

+ +    pid_t cpids[2], w;

+ +    int wstatus;

+ +    FD_t fds[2];

+ +

+ +     if (pipe(processorpipefd) == -1) {

+ +	fprintf(stderr, _("Processor pipe failure\n"));

+ +	return RPMRC_FAIL;

+ +    }

+ +

+ +    if (pipe(validatorpipefd) == -1) {

+ +	fprintf(stderr, _("Validator pipe failure\n"));

+ +	return RPMRC_FAIL;

+ +    }

+ +

+ +    if (pipe(rpmsignpipefd) == -1) {

+ +	fprintf(stderr, _("Validator pipe failure\n"));

+ +	return RPMRC_FAIL;

+ +    }

+ +

+ +    cpids[0] = fork();

+ +    if (cpids[0] == 0) {

+ +	/* child: validator */

+ +	close(processorpipefd[0]);

+ +	close(processorpipefd[1]);

+ +	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);

+ +	if(rc != RPMRC_OK) {

+ +	    fprintf(stderr, _("Validator failed\n"));

+ +	}

+ +	Fclose(fdi);

+ +	Fclose(fdo);

+ +	if (rc != RPMRC_OK) {

+ +	    exit(EXIT_FAILURE);

+ +	}

+ +	exit(EXIT_SUCCESS);

+ +    } else {

+ +	/* parent: main program */

+ +	cpids[1] = fork();

+ +	if (cpids[1] == 0) {

+ +	    /* child: process_package */

+ +	    close(validatorpipefd[0]);

+ +	    close(validatorpipefd[1]);

+ +	    close(processorpipefd[1]);

+ +	    close(rpmsignpipefd[1]);

+ +	    FD_t fdi = fdDup(processorpipefd[0]);

+ +	    close(processorpipefd[0]);

+ +	    FD_t validatori = fdDup(rpmsignpipefd[0]);

+ +	    close(rpmsignpipefd[0]);

+ +

+ +	    rc = process_package(fdi, digestori, validatori);

+ +	    if(rc != RPMRC_OK) {

+ +		fprintf(stderr, _("Validator failed\n"));

+ +	    }

+ +	    Fclose(digestori);

+ +	    Fclose(validatori);

+ +	    /* fdi is normally closed through the stacked file gzdi in the

+ +	     * function

+ +	     */

+ +

+ +	    if (rc != RPMRC_OK) {

+ +		exit(EXIT_FAILURE);

+ +	    }

+ +	    exit(EXIT_SUCCESS);

+ +

+ +

+ +	} else {

+ +	    /* Actual parent. Read from fdi and write to both processes */

+ +	    close(processorpipefd[0]);

+ +	    close(validatorpipefd[0]);

+ +	    fds[0] = fdDup(processorpipefd[1]);

+ +	    fds[1] = fdDup(validatorpipefd[1]);

+ +	    close(validatorpipefd[1]);

+ +	    close(processorpipefd[1]);

+ +	    close(rpmsignpipefd[0]);

+ +	    close(rpmsignpipefd[1]);

+ +

+ +	    offt = ufdTee(fdi, fds, 2);

+ +	    if(offt == -1){

+ +		fprintf(stderr, _("Failed to tee RPM\n"));

+ +		rc = RPMRC_FAIL;

+ +	    }

+ +	    Fclose(fds[0]);

+ +	    Fclose(fds[1]);

+ +	    w = waitpid(cpids[0], &wstatus, 0);

+ +	    if (w == -1) {

+ +		fprintf(stderr, _("waitpid cpids[0] failed\n"));

+ +		rc = RPMRC_FAIL;

+ +	    }

+ +	    w = waitpid(cpids[1], &wstatus, 0);

+ +	    if (w == -1) {

+ +		fprintf(stderr, _("waitpid cpids[1] failed\n"));

+ +		rc = RPMRC_FAIL;

+ +	    }

+ +	}

+ +    }

+ +

+ +    return rc;

+ +}

+ +

+  int main(int argc, char *argv[]) {

+      rpmRC rc;

+      int cprc = 0;

+ -    uint8_t algos[argc - 1];

+ +    poptContext optCon = NULL;

+ +    const char **args = NULL;

+ +    int nb_algos = 0;

+ +

+      int mainpipefd[2];

+      int metapipefd[2];

+      pid_t cpid, w;

+ @@ -338,29 +523,30 @@ int main(int argc, char *argv[]) {

+  

+      xsetprogname(argv[0]);	/* Portability call -- see system.h */

+      rpmReadConfigFiles(NULL, NULL);

+ +    optCon = rpmcliInit(argc, argv, optionsTable);

+ +    poptSetOtherOptionHelp(optCon, "[OPTIONS]* <DIGESTALGO>");

+  

+ -    if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {

+ -	fprintf(stderr, _("Usage: %s [DIGESTALGO]...\n"), argv[0]);

+ -	exit(EXIT_FAILURE);

+ -    }

+ -

+ -    if (argc == 1) {

+ +    if (poptPeekArg(optCon) == NULL) {

+  	fprintf(stderr,

+  		_("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));

+ +	poptPrintUsage(optCon, stderr, 0);

+  	exit(EXIT_FAILURE);

+      }

+  

+ -    for (int x = 0; x < (argc - 1); x++) {

+ -	if (pgpStringVal(PGPVAL_HASHALGO, argv[x + 1], &algos[x]) != 0)

+ +    args = poptGetArgs(optCon);

+ +

+ +    for (nb_algos=0; args[nb_algos]; nb_algos++);

+ +    uint8_t algos[nb_algos];

+ +    for (int x = 0; x < nb_algos; x++) {

+ +	if (pgpStringVal(PGPVAL_HASHALGO, args[x], &algos[x]) != 0)

+  	{

+  	    fprintf(stderr,

+  		    _("Unable to resolve '%s' as a digest algorithm, exiting\n"),

+ -		    argv[x + 1]);

+ +		    args[x]);

+  	    exit(EXIT_FAILURE);

+  	}

+      }

+  

+ -

+      if (pipe(mainpipefd) == -1) {

+  	fprintf(stderr, _("Main pipe failure\n"));

+  	exit(EXIT_FAILURE);

+ @@ -369,6 +555,7 @@ int main(int argc, char *argv[]) {

+  	fprintf(stderr, _("Meta pipe failure\n"));

+  	exit(EXIT_FAILURE);

+      }

+ +

+      cpid = fork();

+      if (cpid == 0) {

+  	/* child: digestor */

+ @@ -377,7 +564,7 @@ int main(int argc, char *argv[]) {

+  	FD_t fdi = fdDup(STDIN_FILENO);

+  	FD_t fdo = fdDup(mainpipefd[1]);

+  	FD_t validationo = fdDup(metapipefd[1]);

+ -	rc = digestor(fdi, fdo, validationo, algos, argc - 1);

+ +	rc = digestor(fdi, fdo, validationo, algos, nb_algos);

+  	Fclose(validationo);

+  	Fclose(fdo);

+  	Fclose(fdi);

+ @@ -386,12 +573,10 @@ int main(int argc, char *argv[]) {

+  	close(mainpipefd[1]);

+  	close(metapipefd[1]);

+  	FD_t fdi = fdDup(mainpipefd[0]);

+ -	FD_t validationi = fdDup(metapipefd[0]);

+ -	rc = process_package(fdi, validationi);

+ -	Fclose(validationi);

+ -	/* fdi is normally closed through the stacked file gzdi in the

+ -	 * function.

+ -	 * Wait for child process (digestor for stdin) to complete.

+ +	FD_t digestori = fdDup(metapipefd[0]);

+ +	rc = teeRpm(fdi, digestori);

+ +	Fclose(digestori);

+ +	/* Wait for child process (digestor for stdin) to complete.

+  	 */

+  	if (rc != RPMRC_OK) {

+  	    if (kill(cpid, SIGTERM) != 0) {

+ @@ -402,7 +587,7 @@ int main(int argc, char *argv[]) {

+  	}

+  	w = waitpid(cpid, &wstatus, 0);

+  	if (w == -1) {

+ -	    fprintf(stderr, _("waitpid failed\n"));

+ +	    fprintf(stderr, _("waitpid %d failed %s\n"), cpid, strerror(errno));

+  	    cprc = EXIT_FAILURE;

+  	} else if (WIFEXITED(wstatus)) {

+  	    cprc = WEXITSTATUS(wstatus);

+ -- 

+ 2.35.1

+ 

@@ -0,0 +1,282 @@ 

+ 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

+ 

@@ -0,0 +1,116 @@ 

+ From c705a6287f8c7fb5e37dad0ac87257731a41fa69 Mon Sep 17 00:00:00 2001

+ From: chantra <chantr4@gmail.com>

+ Date: Sat, 29 Jan 2022 07:00:27 +0000

+ Subject: [PATCH 08/30] [rpm2extents] Add script to troubleshoot transcoded

+  file content This script is essentially dumping the metadata written at the

+  end of the transcoded files, it will also be used as part of the end-to-end

+  tests.

+ 

+ ---

+  scripts/rpm2extents_dump | 94 ++++++++++++++++++++++++++++++++++++++++

+  1 file changed, 94 insertions(+)

+  create mode 100755 scripts/rpm2extents_dump

+ 

+ diff --git a/scripts/rpm2extents_dump b/scripts/rpm2extents_dump

+ new file mode 100755

+ index 000000000..596a59a49

+ --- /dev/null

+ +++ b/scripts/rpm2extents_dump

+ @@ -0,0 +1,94 @@

+ +#!/usr/bin/env python3

+ +

+ +import argparse

+ +import binascii

+ +import os

+ +import struct

+ +import sys

+ +

+ +MAGIC_SIZE = 8

+ +MAGIC_STR = b'KWTSH100'

+ +

+ +POS_SIZE = 8

+ +

+ +def keep_position(func):

+ +    def wrapper(*args, **kwargs):

+ +        curr = args[0].tell()

+ +        res = func(*args, **kwargs)

+ +        f.seek(curr, os.SEEK_SET)

+ +        return res

+ +    return wrapper

+ +

+ +def read_validation_digest(f, validation_offset):

+ +	digests = []

+ +    # validation

+ +	f.seek(validation_offset, os.SEEK_SET)

+ +	val_content_len, val_digests_num = struct.unpack('=QI', f.read(8+4))

+ +	for i in range(val_digests_num):

+ +		algo_name_len, digest_len = struct.unpack('=II', f.read(8))

+ +		algo_name, digest = struct.unpack(f'{algo_name_len}s{digest_len}s', f.read(algo_name_len+digest_len))

+ +		digests.append((algo_name, binascii.hexlify(digest)))

+ +	return digests

+ +

+ +

+ +def read_digests_table(f, digest_offset):

+ +	digests = []

+ +    # validation

+ +	f.seek(digest_offset, os.SEEK_SET)

+ +	table_len, digest_len = struct.unpack('=II', f.read(8))

+ +

+ +	for i in range(table_len):

+ +		digest, pos = struct.unpack(f'{digest_len}sQ', f.read(digest_len + 8))

+ +		digests.append((pos, binascii.hexlify(digest)))

+ +	return digests

+ +

+ +def read_signature_output(f, signature_offset):

+ +    f.seek(signature_offset, os.SEEK_SET)

+ +    signature_rc, signature_output_len = struct.unpack('=IQ', f.read(12))

+ +    return signature_rc, f.read(signature_output_len)

+ +

+ +@keep_position

+ +def parse_file(f):

+ +	digests = []

+ +	pos_table_offset = f.seek(-8 - 3*POS_SIZE, os.SEEK_END)

+ +	signature_offset, digest_offset, validation_offset = struct.unpack('=QQQ', f.read(3*POS_SIZE))

+ +

+ +	validation_digests = read_validation_digest(f, validation_offset)

+ +	digests_table = read_digests_table(f, digest_offset)

+ +	signature_ouput = read_signature_output(f, signature_offset)

+ +

+ +	return validation_digests, digests_table, signature_ouput

+ +

+ +@keep_position

+ +def is_transcoded(f):

+ +    f.seek(-MAGIC_SIZE, os.SEEK_END)

+ +    magic = f.read(MAGIC_SIZE)

+ +    return magic == MAGIC_STR

+ +

+ +def arg_parse():

+ +    parser = argparse.ArgumentParser()

+ +    parser.add_argument('--dump-signature', action='store_true')

+ +    parser.add_argument('--dump-file-digest-table', action='store_true')

+ +    parser.add_argument('--dump-digests', action='store_true')

+ +    parser.add_argument('file')

+ +

+ +    return parser.parse_args()

+ +

+ +if __name__ == '__main__':

+ +    args = arg_parse()

+ +    f = open(args.file, 'rb')

+ +    if not is_transcoded(f):

+ +        sys.exit(1)

+ +

+ +    validation_digests, digests_table, signature_output = parse_file(f)

+ +    if(args.dump_file_digest_table):

+ +        for digest in digests_table:

+ +            print(f"FileDigest {hex(digest[0])}: {digest[1]}")

+ +

+ +    if(args.dump_digests):

+ +        for validation_digest in validation_digests:

+ +            print(f"HeaderDigest {validation_digest[0]} {validation_digest[1]}")

+ +

+ +    if(args.dump_signature):

+ +        print(f"RPMSignOutput RC {signature_output[0]}\nRPMSignOutput Content {signature_output[1].decode()}")

+ +

+ -- 

+ 2.35.1

+ 

@@ -0,0 +1,70 @@ 

+ From 44b86112136e4804eb606636cbcb4ae847cad773 Mon Sep 17 00:00:00 2001

+ From: chantra <chantr4@gmail.com>

+ Date: Sat, 29 Jan 2022 07:05:18 +0000

+ Subject: [PATCH 09/30] [rpm2extents] Add test verifying RC code and signature

+  validation text

+ 

+ When transcoding an RPM, the RPM signatures are being validated on the fly and the result from the signature validation is being written at the tail of the transcoded file.

+ This test check that we get the expected results and is based on the rpmsigdig.at test.

+ ---

+  Makefile.am          |  2 +-

+  tests/rpm2extents.at | 33 +++++++++++++++++++++++++++++++++

+  2 files changed, 34 insertions(+), 1 deletion(-)

+ 

+ diff --git a/Makefile.am b/Makefile.am

+ index 288668819..96542c8c8 100644

+ --- a/Makefile.am

+ +++ b/Makefile.am

+ @@ -203,7 +203,7 @@ bin_PROGRAMS +=		rpmgraph

+  rpmgraph_SOURCES =	tools/rpmgraph.c

+  rpmgraph_LDADD =	lib/librpm.la rpmio/librpmio.la @WITH_POPT_LIB@

+  

+ -dist_bin_SCRIPTS =	scripts/gendiff

+ +dist_bin_SCRIPTS =	scripts/gendiff scripts/rpm2extents_dump

+  

+  rpmconfig_DATA = rpmrc

+  rpmrc: $(top_srcdir)/rpmrc.in

+ diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at

+ index f943b9af4..baea987e4 100644

+ --- a/tests/rpm2extents.at

+ +++ b/tests/rpm2extents.at

+ @@ -29,3 +29,36 @@ AT_CHECK([runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rp

+  [ignore])

+  AT_CLEANUP

+  

+ +# Check that tailer writes checksig return code and content.

+ +#

+ +AT_SETUP([rpm2extents signature])

+ +AT_KEYWORDS([rpm2extents digest signature])

+ +AT_CHECK([

+ +RPMDB_INIT

+ +

+ +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > /tmp/hello-2.0-1.x86_64-signed.rpm 2> /dev/null

+ +rpm2extents_dump --dump-signature /tmp/hello-2.0-1.x86_64-signed.rpm

+ +runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub

+ +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > /tmp/hello-2.0-1.x86_64-signed.rpm

+ +rpm2extents_dump --dump-signature /tmp/hello-2.0-1.x86_64-signed.rpm

+ +],

+ +[0],

+ +[RPMSignOutput RC 2

+ +RPMSignOutput Content     Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY

+ +    Header SHA256 digest: OK

+ +    Header SHA1 digest: OK

+ +    Payload SHA256 digest: OK

+ +    V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY

+ +    MD5 digest: OK

+ +

+ +RPMSignOutput RC 0

+ +RPMSignOutput Content     Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK

+ +    Header SHA256 digest: OK

+ +    Header SHA1 digest: OK

+ +    Payload SHA256 digest: OK

+ +    V4 RSA/SHA256 Signature, key ID 1964c5fc: OK

+ +    MD5 digest: OK

+ +

+ +],

+ +[])

+ +AT_CLEANUP

+ -- 

+ 2.35.1

+ 

@@ -0,0 +1,204 @@ 

+ From 7da1e826ccb08fdd404524146736b3f12a473e31 Mon Sep 17 00:00:00 2001

+ From: chantra <chantr4@gmail.com>