Commit Graph

127 Commits

Author SHA1 Message Date
Panu Matilainen 64dea7618b Implement proper imaevm detection in the cmake build
Abort the build if imaevm enabled but header+library not present, use
detected values. Check for lsetxattr() availability. Drop unnecessary
imaevm linkage from the plugin, the plugin only manipulates xattrs and
does not need the IMA library.
2022-12-13 13:37:02 +02:00
Panu Matilainen 58ece20d33 Avoid unnecessary variables for cmake target data, part 1
The foo_SOURCES style isn't really in cmake ethos, and is wholly
unnecessary here: target_sources() achieves the same exact thing in a
slightly more straightforward way.
2022-11-28 13:55:07 +02:00
Panu Matilainen 71fe36cdc5 Use cmake imported targets to let it sort out the compiler flag details
These imported targets passed to target_link_library() are supposed to
handle all the pesky compilation, linkage etc details behind the scenes.
I was pretty sure I was missing a trick with this, but this sure isn't
exactly underlined in the documentation.

Unroll the supposedly helpful loop for handling plugins: turns out doing
this cmake native way is plenty shorter and more obvious too. The unroll
kinda belongs to a separate commit but that'd be rather painful for very
little if any gain.

Fixes: #2269 and a whole class of similar cases, allegedly
2022-11-28 11:31:21 +02:00
Panu Matilainen ee4356ef27 Issue a warning when signing created an OpenPGP v3 signature
https://bugzilla.redhat.com/show_bug.cgi?id=2141686 revealed that much
of the rpm-ecosystem is still using the obsolete v3 OpenPGP signature
format, I think largely due to workarounds for legacy rpm versions (from
around the turn of the millennium) that have just been forgotten in
place. Lets at least issue a wake-up warning when that happens.

Unfortunately this is can't really be tested as current GnuPG versions
just ignore any --force-v3-sigs arguments.

Fixes: #2286
2022-11-25 08:47:49 +01:00
Panu Matilainen cf02319645 Use proper name (OpenPGP) when referring to the standard in messages 2022-11-25 08:47:49 +01:00
Panu Matilainen e9f03dec40 Fix fsverity plugin build, obviously never worked with cmake before, doh 2022-11-03 14:45:49 +02:00
Panu Matilainen 6f1c67ffb1 Remove autotools build
There are some missing bits and pieces still to be done for cmake build,
but that is so much easier if you don't have to worry about keeping
compatibility with the system you're about to remove that it doesn't
make sense to drag this on any further. The sooner this is over, the
sooner it is over and we can start making use of cmake's advantages
instead of just trying to bend over backwards to maintain compatibility
with the autotools build.
2022-10-21 09:03:05 +03:00
Panu Matilainen 0e44664542 Fix fsverity (and imaevm) build under cmake 2022-10-20 13:44:18 +03:00
Panu Matilainen b5a0517481 Fix cmake build without IMAEVM and FSVERITY
The IMA define needs to match what the code expects. Conditionalize
the relevant sources.
2022-09-29 12:13:43 +03:00
Panu Matilainen 8c3fb5eb01 Add an experimental CMake build system
This is an incomplete release-early version, NOT intended or
suitable for production use. It is intended to replace the autotools
based buildsystem in rpm 4.20, until then it'll be developed alongside
it. This causes some extra complications of course, but then we avoid
a huge flag-day, and that matters more.

To those wondering why cmake and not ${myfavorite}: the community around
us effectively made that choice for us. We've made a lot of noise about
bootstrap dependencies. When libsolv, dnf and all the related stack is
powered by cmake build, it'd be just foolish to go with anything else.
This way people working on the rpm stack have only one build system to
learn, there's peer support available nearby and bootstrap dependencies
are reduced, not increased. It also doesn't hurt that cmake is actually
and actively maintained.
2022-06-28 16:33:33 +03:00
Demi Marie Obenour 40571a74cf Remove NSS references
RPM doesn’t use NSS anymore.
2022-03-18 16:35:11 +02:00
Panu Matilainen 650ba79f22 Eliminate the strange include pre-build install machinery
Introduced back in 2007 in 5831404601 the
point was to fake up a sane public header structure with minimal
internal disruption, TEMPORARILY. I think 15 years is temporary enough.

The machinery has worked rather well for what it is, but having the
headers appear in multiple locations is weird and confusing to people,
plus this "physical" separation makes it far more clearer what is
a public header and what isn't.
2022-03-10 08:40:07 +02:00
Panu Matilainen 3d97c19c6e Remove leading directories from doxygen notation
These don't represent the exported include structure so they're
probably more harmful than anything else.
2022-03-10 08:40:07 +02:00
Panu Matilainen 2f0f3be64d Use proper addressing for our public headers everywhere 2022-03-10 08:40:07 +02:00
Panu Matilainen 33edb9827e Fix missing include from d44be2cbc1
Somehow this managed to sneak past unnoticed
2022-03-03 12:20:58 +02:00
Panu Matilainen d44be2cbc1 Rename pgpHexStr() to rpmhex(), but preserve ABI for now
Fixup internal callers to use rpmhex(), deprecate pgpHexStr().
pgpHexStr() should be dropped at next soname bump, whenever that
happens.
2022-02-25 11:08:25 +01:00
Panu Matilainen dcfa7323a0 Move pgpHexStr() out of rpmpgp.h, it has nothing to do with PGP 2022-02-25 11:08:25 +01:00
Panu Matilainen 01d6605d93 Detach rpm's hash algorithm values from PGP hash algorith values
At this point this is quite literally merely a symbolic change,
as values from PGP hash algo are assumed equal to RPM hash algos,
but it's a necessary first step to supporting hashes not included
in RFC-4880.

Fixes: #1899
2022-02-25 11:08:25 +01:00
Panu Matilainen 07f1d3132f Fix IMA signature fubar, take III (#1833, RhBug:2018937)
At least ECDSA and RSA signatures can vary in length, but the IMA code
assumes constant lengths and thus may either place invalid signatures on
disk from either truncating or overshooting, and segfault if the stars are
just so.

As we can't assume static lengths and attempts to use maximum length
have proven problematic for other reasons, use a data structure that
can actually handle variable length data properly: store offsets into
the decoded binary blob and use them to calculate lengths when needed,
empty data is simply consequtive identical offsets. This avoids a whole
class of silly overflow issues with multiplying, makes zero-length data
actually presentable in the data structure and saves memory too.

Add tests to show behavior with variable length signatures and missing
signatures.

Additionally update the signing code to store the largest IMA signature
length rather than what happened to be last to be on the safe side.
We can't rely on this value due to invalid packages being out there,
but then we need to calculate the lengths on rpmfiles populate so there's
not a lot to gain anyhow.

Fixes: #1833
2022-02-11 15:09:08 +02:00
Panu Matilainen 9b8f573566 Revert whack-a-mole attempts to fix IMA as broken
This reverts commits a79d7ae0f0 and
31e9daf823 which are still dangerously
flawed.
2022-02-11 15:09:08 +02:00
Denys Vlasenko 8763969a4a Do not unset $MALLOC_CHECK_
How do we even _know_ user wants to debug malloc in rpmbuild,
maybe user wants to debug it in _the child_?

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2022-01-24 14:35:24 +02:00
Peter Pentchev 989d7c593c Fix __cplusplus misspelled as _cplusplus. 2022-01-18 12:17:40 +01:00
Evgeniy Taishev 9b4c50dd67 Close file before replacing signed 2022-01-18 11:06:58 +01:00
Michal Domonkos ae3d2d234a Fix use-after-free in haveSignature()
pgpPrtParams() may leave sig2 unchanged and if we're not in the very
first iteration of the while() loop, we could pass a freed pointer to
pgpDigParamsCmp().  Fix by setting it to NULL after freeing.

Found by Coverity, after commit bd36c5d (subkey binding validation),
although note that the commit didn't introduce this bug; it just seems
to have been a false negative that got "fixed" by the changes in
pgpPrtParams() in that commit.
2022-01-10 13:23:46 +02:00
Panu Matilainen a79d7ae0f0 Fix IMA signature lengths assumed constant (#1833, RhBug:2018937)
At least ECDSA and RSA signatures can vary in length, but the IMA code
assumes constant lengths and thus may either place invalid signatures on
disk from either truncating or overshooting, and segfault if the stars are
just so.

Luckily the signatures are stored as strings so we can calculate the
actual lengths at runtime and ignore the stored constant length info.
Extend hex2bin() to optionally calculate the lengths and maximum,
and use these for returning IMA data from the rpmfi(les) API.

Additionally update the signing code to store the largest IMA signature
length rather than what happened to be last to be on the safe side.
We can't rely on this value due to invalid packages being out there,
but then we need to calculate the lengths on rpmfiles populate so there's
not a lot to gain anyhow.

Fixes: #1833
2021-12-13 10:38:36 +02:00
Demi Marie Obenour 23770e1a4f rpmsign: support EdDSA signatures
They were previously rejected
2021-03-15 13:58:54 +02:00
Panu Matilainen 07858c0d60 Eliminate remaining uses of unsafe headerCopyLoad() in the codebase
There's no way to safely validate an object to which only a void
pointer is given. Use headerImport() and pass a size to make
verification possible, headerCopyLoad() has been long deprecated anyway.
2021-03-11 10:58:48 +02:00
Jes Sorensen ae4b1b1fe8 rpmsign: Add argument to specify algorithm for fsverity signatures
The argument --verity-algo can be used to specify the algorithm for
the fsverity signatures. If nothing is specified, this will default to
sha256. The available algorithms depend on libfsverity, currently
sha256 and sha512 are supported.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 7b2e7fc06a Add --delfilesign flag to delete IMA and fsverity file signatures
This allows a user to remove both types of file signatures from the
package. Previously there was no way to delete IMA signatures, only
replace them by first removing the package signature and then
resigning the package and the files.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 7e528e6650 fsverity - add tag for fsverity algorithm
The default algorith is SHA256, but fsverity allows for other
algorithms, so add a tag to handle this.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 8eb82a0bbc rpmsignverity.c: Clean up debug logging
Put most logging in one place and avoid printing the same info twice.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 201596f995 Generate a zero-length signature for symlinks
The fsverity utility follows the symlink when generating a signature.
Since we don't want to sign the same file twice, we need to skip these
links, and instead just generate a dummy zero-length signature here.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 131eeb2bbe Process verity tag on package read
This processes verity signature tags on package read, and provides
accessor functions to access them.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 174f083d1c rpmSignVerity: Generate signatures for files not present in archive
This generates signatures for all files in the archive, then picks up
ghost files from the header metadata and generates signatures for them
as well. It finally submits them to RPMTAG_VERITYSIGNATURES in header
file order as we cannot rely on archive order and header order being
the same.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 9644bbd5b3 rpmsignverity: Add verity signature headers to the package
This adds the array of verity signatures, and a signature length
header. We use 4K block for the Merkle tree, and rely on the kernel
doing the right thing.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen cc7e3c8830 Implement rpmSignVerity()
This generates the root Merkle tree hash and signs it using the
specified key and certificate.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen b296cbb67a Add basic autoconf and framework for fsverity support
Use the same signing key argument as is used for IMA file signing.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Panu Matilainen 8fefd2bd21 Work around buggy signature region preventing resigning (RhBug:1851508)
Various proprietary packages in the wild have subtly malformed data
in the signature header, in particular wrt the immutable region size,
presumably from using some in-house/3rd party signing tools which do
not understand the immutable region business at all. This can prevent
resigning and signature deletion on such packages due to the more
thorough checking that rpmsign does.

As the old wisdom goes, be liberal in what you accept... we can easily
work around the crud by just taking a fresh copy of the contents that
are legit as such (otherwise the package would be uninstallable).
2020-08-13 15:52:19 +02:00
Michal Domonkos 0268b6ef23 GPG: refactor: clean up exit label
Remove the redundant close()/fclose() and waitpid() calls.
2020-06-24 08:53:56 +03:00
Michal Domonkos 52c0198e24 GPG: Switch back to pipe(7) for signing
When it comes to IPC with the GPG subprocess that we spawn to sign
packages for us, there has been an evolution of changes over the years.

Initially, we used temporary files to dump package data (header+payload)
to disk, and pointed GPG to those.  That being an insanely expensive
operation, we later opted for a pipe bound to stdin on the reader side
[1] to avoid the unnecessary I/O.  When GPG 2.1 came along, our own
passphrase entry logic stopped working so we decided to offload [3] that
to GPG instead, for which we also needed to swap the pipe for a named
pipe (FIFO), to free [2] stdin for GPG's own passphrase entry program
(pinentry).

Fast forward to the present, it has become apparent that the FIFO
semantics is not the right choice for us either, as it brings about a
handful of synchronization issues, all of which stem from the fact that
the GPG subprocess, which we cannot control, may or may not open the
input file (our FIFO) for reading before it terminates, causing either
process to hang.  That's because an open(2) call on a FIFO blocks until
the other end is also opened.  One particular case where such a deadlock
can happen is an expired key [4]; GPG would error out without ever
opening the input file (and rightly so), making RPM stuck.

In a nutshell, here's what the two processes do:

RPM parent:
    * spawn GPG child
    * open FIFO for writing (blocks)
    * write data
    * close FIFO

GPG child:
    * check key validity    <-- may terminate here
    * open FIFO for reading (blocks)
    * read data
    * close FIFO

Which may result in the following execution order:

* parent:   spawn GPG child
* parent:   open FIFO for writing (blocks)
* child:    check key validity (key expired!)
* child:    terminate with an error (sends SIGCHLD)
* parent:   (continues blocking...)

Now, one way to unblock the parent would be to install a SIGCHLD handler
with SA_RESTART and make it open the FIFO for reading (with O_NONBLOCK)
iff the signal comes from our GPG child (note that RPM can also be used
as a library) so that the restarted open call unblocks right away.  This
would, however, still not be entirely safe from race conditions; if
there were other subprocesses, all terminating about the same time,
their SIGCHLD instances could prevent us from receiving the one from
GPG; this is because standard signals do not queue (see signal(7) for a
detailed explanation).

Another way would be to spawn GPG from a wrapper process whose sole
purpose would be to wait(2) for GPG and to open the FIFO if it failed
(without O_NONBLOCK, to ensure the wrapper doesn't exit before the
parent's open call).  This would work as long as we could tell exactly
which errors cause GPG to not open the input file, but since that's not
documented, we would have to rely on implementation details, not to
mention the added complexity and ugliness of such a solution, so that's
also a no-go.

Lastly, why not just use O_NONBLOCK in the parent, to prevent it from
blocking in the first place?  Since GPG does not use O_NONBLOCK, this
would just push the problem down to the child; if the parent is too fast
and manages to close the FIFO before the child gets a chance to open it,
the child would get stuck once it gets there (thus making the parent
stuck on the wait call).

Luckily, it turns out we actually can take over stdin *and* have GPG use
its pinentry program at the same time!  All we need is to make sure the
GPG_TTY environment variable is set to the current terminal (see
gpg-agent(1)).  This variable is used [5] by GPG as a fall-back when it
fails to obtain the terminal connected to stdin using ttyname(3), such
as when it is redirected to a pipe.

Thus, in this commit (mostly adapted from the reverse of [2]), we revert
to using the good old pipe(7) which not only avoids race conditions (as
it does not cause open to block), but is also more suitable for this
task in general.  (For the record, GPGme also uses [6] a regular pipe
for the IPC.)  Since we have access to the original stdin before
redirection, we set GPG_TTY accordingly (if previously unset), to keep
pinentry working.

This commit also resolves the RHBZ linked in [4].  Note that, in the
case of key expiration, GPG isn't particularly specific in the error
message or exit code; all it says is "Unusable secret key" and returns
code 2.  For that reason, we can't print anything helpful to stderr
either.

[1] commit 1aace27fb9
[2] commit 6a8924b4c9
[3] commit 0bce5fcf27
[4] https://bugzilla.redhat.com/show_bug.cgi?id=1746353
[5] f3df8dbb69/agent/gpg-agent.c (L1115)
[6] 52f930c1ed/src/engine-gpg.c (L1133)
2020-06-24 08:53:56 +03:00
Panu Matilainen d009ac4828 Remove support for NSS
NSS is a behemoth of a library which drags in a whole runtime subsystem
of its own which is often at odds with normal Unix system behavior
(hello SIGPIPE). Now that we have nicer alternatives available there's
little reason to lug this baggage along. NSS was deprecated in rpm 4.16
(commit 0b9efb93fb).
2020-05-29 08:54:56 +03:00
Panu Matilainen cf967331d3 Remove support for beecrypt
Beecrypt whose upstream is dead for more than ten years now, was deprecated
in rpm 4.16 (in commit 0910e6aa9e).
2020-05-29 08:54:56 +03:00
Panu Matilainen 8ed452dd86 Flush 1998 vintage fcntl-compatibility mess from system.h
fcntl.h is standard, include it from places that need it and drop
from system.h.
2020-04-02 13:53:38 +03:00
Panu Matilainen b1aeafef49 Stop adding rpm v3 header+payload signatures by default where not needed
On packages where a separate payload digest exists (ie those built with
rpm >= 4.14), rpm v3 header+payload signatures are nothing but expensive
legacy baggage, as the payload digest will be signed by a header-only
signature already, without having to recalculate the entire file.

Automatically detect the payload digest presence and only add V3
signatures on packages that need it, but also add an override switch
to force their addition if needed for compatibility or so. A particular
use-case would be ability to signature-level verify the entire package
on rpm older than 4.14.

Fixes: #863
2020-03-10 12:11:17 +02:00
Panu Matilainen 91834e86e0 Generalize file signing to use a generic flags field in signing arguments
There will be any number of signing flags in the future, and we don't
want to break the ABI for every single one of them by adding new
fields to the sign argument struct. Replace the signfiles field
with a bitfield in the common rpm style. No functional changes.

This is an API change of course, but we'll have to bump the soname for
the next release anyway so might as well do it now.
2020-03-10 12:11:17 +02:00
Panu Matilainen 592a99344b Rename variable to make its usage and the surrounding code clearer
Since commit 8f8fe71841, this array
is only used for checking for non-existent digest. No functional changes.
2019-06-05 10:33:07 +03:00
Panu Matilainen 143b9ead7f Fix --signfiles regression introduced when refactoring
Commit 8f8fe71841 changed file signing
to use the readily available binary digest from the file objects
instead of recalculating it from the header, but missed one teeny
weeny detail, causing us to pass an array of zeros to be signed on all
files.  Oops.

Closes: #723
2019-06-05 10:33:07 +03:00
Panu Matilainen df089e178d Verify packages before signing (RhBug:1646388)
Permitting corrupted packages to be signed is bad business for everybody
involved, this is something we should've always done. Besides being an
actual security risk, it can lead to odd results with verification
especially with the payload digest on signed packages.

One point worth noting is that this means that pre 4.14-packages cannot
be signed in FIPS mode now because there's no way to validate the package
payload range due to MD5 being disabled. This seems like a feature and
not a limitation, so disabler for the verify step intentionally left out.

Optimally we'd verify the package on the same read that's passed
to gpg but for simplicitys sake that's left as an future exercise,
now we simply read the package twice.
2019-03-18 15:56:34 +02:00
Panu Matilainen 5c279fb149 Simplify RPMSIGTAG_RESERVEDSPACE shrinking
Lotsa unnecessary stuff here:
- No need for rpmtdReset(), headerGet() takes care of that
- In this path, we're always modifying an existing tag so we can
  just use headerMod() instead of constructing a new tag
- As we're always shrinking the existing tag, we don't need to
  allocate new zeros, just reduce the size. Also make sure we *are*
  really shrinking, previously it was only assumed.

No functional changes expected.
2019-03-15 12:00:06 +02:00
Panu Matilainen 1290493169 Clean up includeFileSignatures() a bit
Initialize on declaration, thou shalt not waste perfectly good
screen estate. No functional changes.
2019-03-15 11:03:45 +02:00