Skip to content

Commit

Permalink
Turn keystore into an interface class
Browse files Browse the repository at this point in the history
Add an abstract rpm::keystore class and port our existing rpmdb and fs
keystores to that. The keystore code as such doesn't really change at
all in here, the bigger change is the way it's initialized because it's
an object instead of just an integer in the rpmts struct.

As a kind of side-effect, we introduce the rpm:: namespace here.

Fixes: rpm-software-management#3342
  • Loading branch information
pmatilai committed Oct 28, 2024
1 parent 86ea3d9 commit f674884
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 83 deletions.
71 changes: 15 additions & 56 deletions lib/keystore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
#include <rpm/rpmts.h>
#include <rpm/rpmtypes.h>

#include "keystore.hh"
#include "rpmts_internal.hh"

#include "debug.h"

using std::string;
using namespace rpm;

static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp);

static rpmRC rpmtsLoadKeyringFromFiles(rpmtxn txn, rpmKeyring keyring)
rpmRC keystore_fs::load_keys(rpmtxn txn, rpmKeyring keyring)
{
ARGV_t files = NULL;
/* XXX TODO: deal with chroot path issues */
Expand Down Expand Up @@ -55,7 +55,7 @@ static rpmRC rpmtsLoadKeyringFromFiles(rpmtxn txn, rpmKeyring keyring)
return RPMRC_OK;
}

static rpmRC rpmtsDeleteFSKey(rpmtxn txn, const string & keyid, const string & newname = "")
rpmRC keystore_fs::delete_key(rpmtxn txn, const string & keyid, const string & newname)
{
rpmRC rc = RPMRC_NOTFOUND;
string keyglob = "gpg-pubkey-" + keyid + "*.key";
Expand All @@ -74,12 +74,12 @@ static rpmRC rpmtsDeleteFSKey(rpmtxn txn, const string & keyid, const string & n
return rc;
}

static rpmRC rpmtsDeleteFSKey(rpmtxn txn, rpmPubkey key)
rpmRC keystore_fs::delete_key(rpmtxn txn, rpmPubkey key)
{
return rpmtsDeleteFSKey(txn, rpmPubkeyFingerprintAsHex(key));
return delete_key(txn, rpmPubkeyFingerprintAsHex(key));
}

static rpmRC rpmtsImportFSKey(rpmtxn txn, rpmPubkey key, rpmFlags flags, int replace)
rpmRC keystore_fs::import_key(rpmtxn txn, rpmPubkey key, rpmFlags flags, int replace)
{
rpmRC rc = RPMRC_FAIL;
const char *fp = rpmPubkeyFingerprintAsHex(key);
Expand Down Expand Up @@ -117,9 +117,9 @@ static rpmRC rpmtsImportFSKey(rpmtxn txn, rpmPubkey key, rpmFlags flags, int rep

if (!rc && replace) {
/* find and delete the old pubkey entry */
if (rpmtsDeleteFSKey(txn, fp, keyfmt) == RPMRC_NOTFOUND) {
if (delete_key(txn, fp, keyfmt) == RPMRC_NOTFOUND) {
/* make sure an old, short keyid version gets removed */
rpmtsDeleteFSKey(txn, fp+32, keyfmt);
delete_key(txn, fp+32, keyfmt);
}
}

Expand All @@ -131,7 +131,7 @@ static rpmRC rpmtsImportFSKey(rpmtxn txn, rpmPubkey key, rpmFlags flags, int rep
return rc;
}

static rpmRC rpmtsLoadKeyringFromDB(rpmtxn txn, rpmKeyring keyring)
rpmRC keystore_rpmdb::load_keys(rpmtxn txn, rpmKeyring keyring)
{
Header h;
rpmdbMatchIterator mi;
Expand Down Expand Up @@ -170,7 +170,7 @@ static rpmRC rpmtsLoadKeyringFromDB(rpmtxn txn, rpmKeyring keyring)
return RPMRC_OK;
}

static rpmRC rpmtsDeleteDBKey(rpmtxn txn, const string & keyid, unsigned int newinstance = 0)
rpmRC keystore_rpmdb::delete_key(rpmtxn txn, const string & keyid, unsigned int newinstance)
{
rpmts ts = rpmtxnTs(txn);
if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
Expand All @@ -194,12 +194,12 @@ static rpmRC rpmtsDeleteDBKey(rpmtxn txn, const string & keyid, unsigned int new
return rc;
}

static rpmRC rpmtsDeleteDBKey(rpmtxn txn, rpmPubkey key)
rpmRC keystore_rpmdb::delete_key(rpmtxn txn, rpmPubkey key)
{
return rpmtsDeleteDBKey(txn, rpmPubkeyFingerprintAsHex(key));
return delete_key(txn, rpmPubkeyFingerprintAsHex(key));
}

static rpmRC rpmtsImportDBKey(rpmtxn txn, rpmPubkey key, rpmFlags flags, int replace)
rpmRC keystore_rpmdb::import_key(rpmtxn txn, rpmPubkey key, rpmFlags flags, int replace)
{
Header h = NULL;
rpmRC rc = RPMRC_FAIL;
Expand All @@ -213,9 +213,9 @@ static rpmRC rpmtsImportDBKey(rpmtxn txn, rpmPubkey key, rpmFlags flags, int rep
/* find and delete the old pubkey entry */
unsigned int newinstance = headerGetInstance(h);
char *keyid = headerFormat(h, "%{version}", NULL);
if (rpmtsDeleteDBKey(txn, keyid, newinstance) == RPMRC_NOTFOUND) {
if (delete_key(txn, keyid, newinstance) == RPMRC_NOTFOUND) {
/* make sure an old, short keyid version gets removed */
rpmtsDeleteDBKey(txn, keyid+32, newinstance);
delete_key(txn, keyid+32, newinstance);
}
free(keyid);
}
Expand Down Expand Up @@ -372,44 +372,3 @@ static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp)

return rc;
}

rpmRC rpmKeystoreImportPubkey(rpmtxn txn, rpmPubkey key, int replace)
{
rpmRC rc = RPMRC_FAIL;
rpmts ts = rpmtxnTs(txn);

/* Add header to database. */
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
if (ts->keyringtype == KEYRING_FS)
rc = rpmtsImportFSKey(txn, key, 0, replace);
else
rc = rpmtsImportDBKey(txn, key, 0, replace);
} else {
rc = RPMRC_OK;
}
return rc;
}

rpmRC rpmKeystoreDeletePubkey(rpmtxn txn, rpmPubkey key)
{
rpmRC rc = RPMRC_FAIL;
rpmts ts = rpmtxnTs(txn);
if (ts->keyringtype == KEYRING_FS)
rc = rpmtsDeleteFSKey(txn, key);
else
rc = rpmtsDeleteDBKey(txn, key);
return rc;
}

rpmRC rpmKeystoreLoad(rpmtxn txn, rpmKeyring keyring)
{
rpmRC rc = RPMRC_FAIL;
rpmts ts = rpmtxnTs(txn);
if (ts->keyringtype == KEYRING_FS) {
rc = rpmtsLoadKeyringFromFiles(txn, keyring);
} else {
rc = rpmtsLoadKeyringFromDB(txn, keyring);
}
return rc;
}

40 changes: 31 additions & 9 deletions lib/keystore.hh
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
#ifndef _KEYSTORE_H
#define _KEYSTORE_H

#include <string>

#include <rpm/rpmtypes.h>
#include <rpm/rpmutil.h>

enum {
KEYRING_RPMDB = 1,
KEYRING_FS = 2,
namespace rpm {

class keystore {
public:
virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring) = 0;
virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, rpmFlags flags = 0, int replace = 1) = 0;
virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key) = 0;

virtual ~keystore() = default;
};

RPM_GNUC_INTERNAL
rpmRC rpmKeystoreLoad(rpmtxn txn, rpmKeyring keyring);
class keystore_fs : public keystore {
public:
virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring);
virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, rpmFlags flags = 0, int replace = 1);
virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key);

RPM_GNUC_INTERNAL
rpmRC rpmKeystoreImportPubkey(rpmtxn txn, rpmPubkey key, int replace = 0);
private:
rpmRC delete_key(rpmtxn txn, const std::string & keyid, const std::string & newname = "");
};

class keystore_rpmdb : public keystore {
public:
virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring);
virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, rpmFlags flags = 0, int replace = 1);
virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key);

private:
rpmRC delete_key(rpmtxn txn, const std::string & keyid, unsigned int newinstance = 0);
};

RPM_GNUC_INTERNAL
rpmRC rpmKeystoreDeletePubkey(rpmtxn txn, rpmPubkey key);
}; /* namespace */

#endif /* _KEYSTORE_H */
38 changes: 21 additions & 17 deletions lib/rpmts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "debug.h"

using std::string;
using namespace rpm;

/**
* Iterator across transaction elements, forward on install, backward on erase.
Expand Down Expand Up @@ -264,34 +265,37 @@ int rpmtsSetKeyring(rpmts ts, rpmKeyring keyring)
return 0;
}

static int getKeyringType(void)
static keystore *getKeystore(rpmts ts)
{
int kt = KEYRING_RPMDB;
char *krtype = rpmExpand("%{?_keyring}", NULL);
if (ts->keystore == NULL) {
char *krtype = rpmExpand("%{?_keyring}", NULL);

if (rstreq(krtype, "fs")) {
kt = KEYRING_FS;
} else if (*krtype && !rstreq(krtype, "rpmdb")) {
/* Fall back to using rpmdb if unknown, for now at least */
rpmlog(RPMLOG_WARNING,
_("unknown keyring type: %s, using rpmdb\n"), krtype);
if (rstreq(krtype, "fs")) {
ts->keystore = new keystore_fs();
} else if (rstreq(krtype, "rpmdb")) {
ts->keystore = new keystore_rpmdb();
} else {
/* Fall back to using rpmdb if unknown, for now at least */
rpmlog(RPMLOG_WARNING,
_("unknown keyring type: %s, using rpmdb\n"), krtype);
ts->keystore = new keystore_rpmdb();
}
free(krtype);
}
free(krtype);

return kt;
return ts->keystore;
}

static void loadKeyring(rpmts ts)
{
/* Never load the keyring if signature checking is disabled */
if ((rpmtsVSFlags(ts) & RPMVSF_MASK_NOSIGNATURES) !=
RPMVSF_MASK_NOSIGNATURES) {
if (!ts->keyringtype)
ts->keyringtype = getKeyringType();
ts->keystore = getKeystore(ts);
ts->keyring = rpmKeyringNew();
rpmtxn txn = rpmtxnBegin(ts, RPMTXN_READ);
if (txn) {
rpmKeystoreLoad(txn, ts->keyring);
ts->keystore->load_keys(txn, ts->keyring);
rpmtxnEnd(txn);
}
}
Expand Down Expand Up @@ -365,7 +369,7 @@ rpmRC rpmtxnImportPubkey(rpmtxn txn, const unsigned char * pkt, size_t pktlen)

/* If we dont already have the key, make a persistent record of it */
if (krc == 0) {
rc = rpmKeystoreImportPubkey(txn, pubkey, oldkey ? 1 : 0);
rc = ts->keystore->import_key(txn, pubkey, 0, oldkey ? 1 : 0);
} else {
rc = RPMRC_OK; /* already have key */
}
Expand Down Expand Up @@ -395,7 +399,7 @@ rpmRC rpmtxnDeletePubkey(rpmtxn txn, rpmPubkey key)
if ((rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
rc = RPMRC_OK;
} else {
rc = rpmKeystoreDeletePubkey(txn, key);
rc = ts->keystore->delete_key(txn, key);
}
rc = RPMRC_OK;
rpmKeyringFree(keyring);
Expand Down Expand Up @@ -554,6 +558,7 @@ rpmts rpmtsFree(rpmts ts)
(void) rpmtsCloseDB(ts);

delete ts->members;
delete ts->keystore;

if (ts->scriptFd != NULL) {
ts->scriptFd = fdFree(ts->scriptFd);
Expand Down Expand Up @@ -961,7 +966,6 @@ rpmts rpmtsCreate(void)

ts->rootDir = NULL;
ts->keyring = NULL;
ts->keyringtype = 0;
ts->vfyflags = rpmExpandNumeric("%{?_pkgverify_flags}");
ts->vfylevel = vfylevel_init();

Expand Down
3 changes: 2 additions & 1 deletion lib/rpmts_internal.hh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "rpmal.hh" /* XXX availablePackage */
#include "fprint.hh"
#include "keystore.hh"
#include "rpmlock.hh"
#include "rpmdb_internal.hh"
#include "rpmscript.hh"
Expand Down Expand Up @@ -84,7 +85,7 @@ struct rpmts_s {
rpmVSFlags vfyflags; /*!< Package verification flags */
int vfylevel; /*!< Package verification level */
rpmKeyring keyring; /*!< Keyring in use. */
int keyringtype; /*!< Keyring type */
rpm::keystore *keystore; /*! <Keystore in use. */

ARGV_t netsharedPaths; /*!< From %{_netsharedpath} */
ARGV_t installLangs; /*!< From %{_install_langs} */
Expand Down

0 comments on commit f674884

Please sign in to comment.