diff --git a/include/rpm/rpmkeyring.h b/include/rpm/rpmkeyring.h index d0764b6f81..cfcbe59342 100644 --- a/include/rpm/rpmkeyring.h +++ b/include/rpm/rpmkeyring.h @@ -23,7 +23,8 @@ extern "C" { typedef enum rpmKeyringModifyMode_e { RPMKEYRING_ADD = 1, RPMKEYRING_REPLACE = 2, - RPMKEYRING_DELETE = 3 + RPMKEYRING_DELETE = 3, + RPMKEYRING_MERGE = 4, } rpmKeyringModifyMode; diff --git a/rpmio/rpmkeyring.cc b/rpmio/rpmkeyring.cc index 4ed4facbb9..9dd9722fdd 100644 --- a/rpmio/rpmkeyring.cc +++ b/rpmio/rpmkeyring.cc @@ -120,11 +120,31 @@ rpmKeyringIterator rpmKeyringIteratorFree(rpmKeyringIterator iterator) int rpmKeyringModify(rpmKeyring keyring, rpmPubkey key, rpmKeyringModifyMode mode) { int rc = 1; /* assume already seen key */ + rpmPubkey mergedkey = NULL; if (keyring == NULL || key == NULL) return -1; - if (mode != RPMKEYRING_ADD && mode != RPMKEYRING_DELETE && mode != RPMKEYRING_REPLACE) + if (mode < RPMKEYRING_ADD || mode > RPMKEYRING_MERGE) return -1; + if (mode == RPMKEYRING_MERGE) { + rpmPubkey oldkey = rpmKeyringLookupKey(keyring, key); + if (oldkey) { + if (rpmPubkeyMerge(oldkey, key, &mergedkey) != RPMRC_OK) { + rpmPubkeyFree(oldkey); + return -1; + } + if (!mergedkey) { + mode = RPMKEYRING_ADD; + } else { + key = mergedkey; + mode = RPMKEYRING_REPLACE; + } + rpmPubkeyFree(oldkey); + } else { + mode = RPMKEYRING_ADD; + } + } + /* check if we already have this key, but always wrlock for simplicity */ wrlock lock(keyring->mutex); auto range = keyring->keys.equal_range(key->keyid); @@ -162,6 +182,8 @@ int rpmKeyringModify(rpmKeyring keyring, rpmPubkey key, rpmKeyringModifyMode mod free(subkeys); rc = 0; } + /* strip initial nref */ + rpmPubkeyFree(mergedkey); return rc; }