diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b05ad46559..3674d0b839 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -29,6 +29,7 @@ target_sources(librpm PRIVATE backend/dbi.cc backend/dbi.hh backend/dummydb.cc backend/dbiset.cc backend/dbiset.hh headerutil.cc header.cc headerfmt.cc header_internal.hh + keystore.cc keystore.hh rpmdb.cc rpmdb_internal.hh fprint.cc fprint.hh tagname.cc rpmtd.cc tagtbl.inc cpio.cc cpio.hh depends.cc order.cc formats.cc tagexts.cc fsm.cc fsm.hh diff --git a/lib/keystore.cc b/lib/keystore.cc new file mode 100644 index 0000000000..760be44891 --- /dev/null +++ b/lib/keystore.cc @@ -0,0 +1,471 @@ +#include "system.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "keystore.hh" +#include "rpmts_internal.hh" + +#include "debug.h" + +using std::string; + +enum { + KEYRING_RPMDB = 1, + KEYRING_FS = 2, +}; + +static int rpmtsLoadKeyringFromFiles(rpmts ts, rpmKeyring keyring) +{ + ARGV_t files = NULL; + /* XXX TODO: deal with chroot path issues */ + char *pkpath = rpmGetPath(ts->rootDir, "%{_keyringpath}/*.key", NULL); + int nkeys = 0; + + rpmlog(RPMLOG_DEBUG, "loading keyring from pubkeys in %s\n", pkpath); + if (rpmGlob(pkpath, NULL, &files)) { + rpmlog(RPMLOG_DEBUG, "couldn't find any keys in %s\n", pkpath); + goto exit; + } + + for (char **f = files; *f; f++) { + int subkeysCount, i; + rpmPubkey *subkeys; + rpmPubkey key = rpmPubkeyRead(*f); + + if (!key) { + rpmlog(RPMLOG_ERR, _("%s: reading of public key failed.\n"), *f); + continue; + } + if (rpmKeyringAddKey(keyring, key) == 0) { + nkeys++; + rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", *f); + } + subkeys = rpmGetSubkeys(key, &subkeysCount); + rpmPubkeyFree(key); + + for (i = 0; i < subkeysCount; i++) { + rpmPubkey subkey = subkeys[i]; + + if (rpmKeyringAddKey(keyring, subkey) == 0) { + rpmlog(RPMLOG_DEBUG, + "added subkey %d of main key %s to keyring\n", + i, *f); + + nkeys++; + } + rpmPubkeyFree(subkey); + } + free(subkeys); + } +exit: + free(pkpath); + argvFree(files); + return nkeys; +} + +static rpmRC rpmtsDeleteFSKey(rpmtxn txn, const string & keyid, const string & newname = "") +{ + rpmRC rc = RPMRC_NOTFOUND; + string keyglob = "gpg-pubkey-" + keyid + "-*.key"; + ARGV_t files = NULL; + char *pkpath = rpmGenPath(rpmtxnRootDir(txn), "%{_keyringpath}/", keyglob.c_str()); + if (rpmGlob(pkpath, NULL, &files) == 0) { + char **f; + for (f = files; *f; f++) { + char *bf = strrchr(*f, '/'); + if (newname.empty() || (bf && strcmp(bf + 1, newname.c_str()) != 0)) + rc = unlink(*f) ? RPMRC_FAIL : RPMRC_OK; + } + argvFree(files); + } + free(pkpath); + return rc; +} + +static rpmRC rpmtsDeleteFSKey(rpmtxn txn, rpmPubkey key) +{ + return rpmtsDeleteFSKey(txn, rpmPubkeyFingerprintAsHex(key)); +} + +static rpmRC rpmtsImportFSKey(rpmtxn txn, Header h, rpmFlags flags, int replace) +{ + rpmRC rc = RPMRC_FAIL; + char *keyfmt = headerFormat(h, "%{nvr}.key", NULL); + char *keyval = headerGetAsString(h, RPMTAG_DESCRIPTION); + char *path = rpmGenPath(rpmtxnRootDir(txn), "%{_keyringpath}/", keyfmt); + char *tmppath = NULL; + + if (replace) { + rasprintf(&tmppath, "%s.new", path); + unlink(tmppath); + } + + if (rpmMkdirs(rpmtxnRootDir(txn), "%{_keyringpath}")) { + rpmlog(RPMLOG_ERR, _("failed to create keyring directory %s: %s\n"), + path, strerror(errno)); + goto exit; + } + + if (FD_t fd = Fopen(tmppath ? tmppath : path, "wx")) { + size_t keylen = strlen(keyval); + if (Fwrite(keyval, 1, keylen, fd) == keylen) + rc = RPMRC_OK; + Fclose(fd); + } + if (!rc && tmppath && rename(tmppath, path) != 0) + rc = RPMRC_FAIL; + + if (rc) { + rpmlog(RPMLOG_ERR, _("failed to import key: %s: %s\n"), + tmppath ? tmppath : path, strerror(errno)); + if (tmppath) + unlink(tmppath); + } + + if (!rc && replace) { + /* find and delete the old pubkey entry */ + char *keyid = headerFormat(h, "%{version}", NULL); + if (rpmtsDeleteFSKey(txn, keyid, keyfmt) == RPMRC_NOTFOUND) { + /* make sure an old, short keyid version gets removed */ + rpmtsDeleteFSKey(txn, keyid+32, keyfmt); + } + free(keyid); + + } + +exit: + free(path); + free(keyval); + free(keyfmt); + free(tmppath); + return rc; +} + +static int rpmtsLoadKeyringFromDB(rpmts ts, rpmKeyring keyring) +{ + Header h; + rpmdbMatchIterator mi; + int nkeys = 0; + + rpmlog(RPMLOG_DEBUG, "loading keyring from rpmdb\n"); + mi = rpmtsInitIterator(ts, RPMDBI_NAME, "gpg-pubkey", 0); + while ((h = rpmdbNextIterator(mi)) != NULL) { + struct rpmtd_s pubkeys; + const char *key; + + if (!headerGet(h, RPMTAG_PUBKEYS, &pubkeys, HEADERGET_MINMEM)) + continue; + + while ((key = rpmtdNextString(&pubkeys))) { + uint8_t *pkt; + size_t pktlen; + + if (rpmBase64Decode(key, (void **) &pkt, &pktlen) == 0) { + rpmPubkey key = rpmPubkeyNew(pkt, pktlen); + int subkeysCount, i; + rpmPubkey *subkeys = rpmGetSubkeys(key, &subkeysCount); + + if (rpmKeyringAddKey(keyring, key) == 0) { + char *nvr = headerGetAsString(h, RPMTAG_NVR); + rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", nvr); + free(nvr); + nkeys++; + } + rpmPubkeyFree(key); + + for (i = 0; i < subkeysCount; i++) { + rpmPubkey subkey = subkeys[i]; + + if (rpmKeyringAddKey(keyring, subkey) == 0) { + char *nvr = headerGetAsString(h, RPMTAG_NVR); + rpmlog(RPMLOG_DEBUG, + "added subkey %d of main key %s to keyring\n", + i, nvr); + + free(nvr); + nkeys++; + } + rpmPubkeyFree(subkey); + } + free(subkeys); + free(pkt); + } + } + rpmtdFreeData(&pubkeys); + } + rpmdbFreeIterator(mi); + + return nkeys; +} + +static rpmRC rpmtsDeleteDBKey(rpmtxn txn, const string & keyid, unsigned int newinstance = 0) +{ + rpmts ts = rpmtxnTs(txn); + if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT))) + return RPMRC_FAIL; + + rpmRC rc = RPMRC_NOTFOUND; + unsigned int otherinstance = 0; + Header oh; + string label = "gpg-pubkey-" + keyid; + rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_LABEL, label.c_str(), 0); + + while (otherinstance == 0 && (oh = rpmdbNextIterator(mi)) != NULL) + if (headerGetInstance(oh) != newinstance) + otherinstance = headerGetInstance(oh); + rpmdbFreeIterator(mi); + if (otherinstance) { + rc = rpmdbRemove(rpmtsGetRdb(ts), otherinstance) ? + RPMRC_FAIL : RPMRC_OK; + } + + return rc; +} + +static rpmRC rpmtsDeleteDBKey(rpmtxn txn, rpmPubkey key) +{ + return rpmtsDeleteDBKey(txn, rpmPubkeyFingerprintAsHex(key)); +} + +static rpmRC rpmtsImportDBKey(rpmtxn txn, Header h, rpmFlags flags, int replace) +{ + rpmRC rc = rpmtsImportHeader(txn, h, 0); + + if (!rc && replace) { + /* 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) { + /* make sure an old, short keyid version gets removed */ + rpmtsDeleteDBKey(txn, keyid+32, newinstance); + } + free(keyid); + } + + return rc; +} + +static void addGpgProvide(Header h, const char *n, const char *v) +{ + rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL); + char * nsn = rstrscat(NULL, "gpg(", n, ")", NULL); + + headerPutString(h, RPMTAG_PROVIDENAME, nsn); + headerPutString(h, RPMTAG_PROVIDEVERSION, v); + headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); + + free(nsn); +} + +struct pgpdata_s { + const char *fingerprint; + const char *signid; + char *timestr; + char *verid; + const char *userid; + const char *shortid; + uint32_t time; +}; + +static void initPgpData(rpmPubkey key, struct pgpdata_s *pd) +{ + pgpDigParams pubp = rpmPubkeyPgpDigParams(key); + memset(pd, 0, sizeof(*pd)); + pd->fingerprint = rpmPubkeyFingerprintAsHex(key); + pd->signid = rpmPubkeyKeyIDAsHex(key); + pd->shortid = pd->signid + 8; + pd->userid = pgpDigParamsUserID(pubp); + if (! pd->userid) { + pd->userid = "none"; + } + pd->time = pgpDigParamsCreationTime(pubp); + + rasprintf(&pd->timestr, "%x", pd->time); + rasprintf(&pd->verid, "%d:%s-%s", pgpDigParamsVersion(pubp), pd->fingerprint, pd->timestr); +} + +static void finiPgpData(struct pgpdata_s *pd) +{ + free(pd->timestr); + free(pd->verid); + memset(pd, 0, sizeof(*pd)); +} + +static Header makeImmutable(Header h) +{ + h = headerReload(h, RPMTAG_HEADERIMMUTABLE); + if (h != NULL) { + char *sha1 = NULL; + char *sha256 = NULL; + unsigned int blen = 0; + void *blob = headerExport(h, &blen); + + /* XXX FIXME: bah, this code is repeated in way too many places */ + rpmDigestBundle bundle = rpmDigestBundleNew(); + rpmDigestBundleAdd(bundle, RPM_HASH_SHA1, RPMDIGEST_NONE); + rpmDigestBundleAdd(bundle, RPM_HASH_SHA256, RPMDIGEST_NONE); + + rpmDigestBundleUpdate(bundle, rpm_header_magic, sizeof(rpm_header_magic)); + rpmDigestBundleUpdate(bundle, blob, blen); + + rpmDigestBundleFinal(bundle, RPM_HASH_SHA1, (void **)&sha1, NULL, 1); + rpmDigestBundleFinal(bundle, RPM_HASH_SHA256, (void **)&sha256, NULL, 1); + + if (sha1 && sha256) { + headerPutString(h, RPMTAG_SHA1HEADER, sha1); + headerPutString(h, RPMTAG_SHA256HEADER, sha256); + } else { + h = headerFree(h); + } + free(sha1); + free(sha256); + free(blob); + rpmDigestBundleFree(bundle); + } + return h; +} + +/* Build pubkey header. */ +static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp) +{ + Header h = headerNew(); + const char * afmt = "%{pubkeys:armor}"; + const char * group = "Public Keys"; + const char * license = "pubkey"; + const char * buildhost = "localhost"; + uint32_t zero = 0; + struct pgpdata_s kd; + char * d = NULL; + char * enc = NULL; + char * s = NULL; + int rc = -1; + + memset(&kd, 0, sizeof(kd)); + + if ((enc = rpmPubkeyBase64(key)) == NULL) + goto exit; + + /* Build header elements. */ + initPgpData(key, &kd); + + rasprintf(&s, "%s public key", kd.userid); + headerPutString(h, RPMTAG_PUBKEYS, enc); + + if ((d = headerFormat(h, afmt, NULL)) == NULL) + goto exit; + + headerPutString(h, RPMTAG_NAME, "gpg-pubkey"); + headerPutString(h, RPMTAG_VERSION, kd.fingerprint); + headerPutString(h, RPMTAG_RELEASE, kd.timestr); + headerPutString(h, RPMTAG_DESCRIPTION, d); + headerPutString(h, RPMTAG_GROUP, group); + headerPutString(h, RPMTAG_LICENSE, license); + headerPutString(h, RPMTAG_SUMMARY, s); + headerPutString(h, RPMTAG_PACKAGER, kd.userid); + headerPutUint32(h, RPMTAG_SIZE, &zero, 1); + headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION); + headerPutString(h, RPMTAG_BUILDHOST, buildhost); + headerPutUint32(h, RPMTAG_BUILDTIME, &kd.time, 1); + headerPutString(h, RPMTAG_SOURCERPM, "(none)"); + + addGpgProvide(h, kd.userid, kd.verid); + addGpgProvide(h, kd.shortid, kd.verid); + addGpgProvide(h, kd.signid, kd.verid); + + /* Reload it into immutable region and stomp standard digests on it */ + h = makeImmutable(h); + if (h != NULL) { + *hdrp = headerLink(h); + rc = 0; + } + +exit: + headerFree(h); + finiPgpData(&kd); + free(enc); + free(d); + free(s); + + return rc; +} + +rpmRC rpmKeystoreImportPubkey(rpmtxn txn, rpmPubkey key, int replace) +{ + rpmRC rc = RPMRC_FAIL; + rpmts ts = rpmtxnTs(txn); + Header h = NULL; + + if (makePubkeyHeader(ts, key, &h) != 0) + return rc; + + rpm_tid_t tid = rpmtsGetTid(ts); + headerPutUint32(h, RPMTAG_INSTALLTIME, &tid, 1); + headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1); + + /* Add header to database. */ + if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { + if (ts->keyringtype == KEYRING_FS) + rc = rpmtsImportFSKey(txn, h, 0, replace); + else + rc = rpmtsImportDBKey(txn, h, 0, replace); + } else { + rc = RPMRC_OK; + } + headerFree(h); + 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; +} + +static int getKeyringType(void) +{ + int kt = KEYRING_RPMDB; + 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); + } + free(krtype); + + return kt; +} + +int rpmKeystoreLoad(rpmts ts, rpmKeyring keyring) +{ + int nkeys = 0; + if (!ts->keyringtype) + ts->keyringtype = getKeyringType(); + if (ts->keyringtype == KEYRING_FS) { + nkeys = rpmtsLoadKeyringFromFiles(ts, keyring); + } else { + nkeys = rpmtsLoadKeyringFromDB(ts, keyring); + } + return nkeys; +} + diff --git a/lib/keystore.hh b/lib/keystore.hh new file mode 100644 index 0000000000..625989d5aa --- /dev/null +++ b/lib/keystore.hh @@ -0,0 +1,15 @@ +#ifndef _KEYSTORE_H + +#include +#include + +RPM_GNUC_INTERNAL +int rpmKeystoreLoad(rpmts ts, rpmKeyring keyring); + +RPM_GNUC_INTERNAL +rpmRC rpmKeystoreImportPubkey(rpmtxn txn, rpmPubkey key, int replace = 0); + +RPM_GNUC_INTERNAL +rpmRC rpmKeystoreDeletePubkey(rpmtxn txn, rpmPubkey key); + +#endif /* _KEYSTORE_H */ diff --git a/lib/rpmts.cc b/lib/rpmts.cc index f869c1764f..4d2fe079cf 100644 --- a/lib/rpmts.cc +++ b/lib/rpmts.cc @@ -15,7 +15,6 @@ #include /* rpmtsOpenDB() needs rpmGetPath */ #include #include -#include #include #include @@ -24,6 +23,7 @@ #include #include +#include "keystore.hh" #include "rpmpgpval.hh" #include "rpmal.hh" #include "rpmchroot.hh" @@ -37,11 +37,6 @@ using std::string; -enum { - KEYRING_RPMDB = 1, - KEYRING_FS = 2, -}; - /** * Iterator across transaction elements, forward on install, backward on erase. */ @@ -269,142 +264,6 @@ int rpmtsSetKeyring(rpmts ts, rpmKeyring keyring) return 0; } -static int rpmtsLoadKeyringFromFiles(rpmts ts, rpmKeyring keyring) -{ - ARGV_t files = NULL; - /* XXX TODO: deal with chroot path issues */ - char *pkpath = rpmGetPath(ts->rootDir, "%{_keyringpath}/*.key", NULL); - int nkeys = 0; - - rpmlog(RPMLOG_DEBUG, "loading keyring from pubkeys in %s\n", pkpath); - if (rpmGlob(pkpath, NULL, &files)) { - rpmlog(RPMLOG_DEBUG, "couldn't find any keys in %s\n", pkpath); - goto exit; - } - - for (char **f = files; *f; f++) { - int subkeysCount, i; - rpmPubkey *subkeys; - rpmPubkey key = rpmPubkeyRead(*f); - - if (!key) { - rpmlog(RPMLOG_ERR, _("%s: reading of public key failed.\n"), *f); - continue; - } - if (rpmKeyringAddKey(keyring, key) == 0) { - nkeys++; - rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", *f); - } - subkeys = rpmGetSubkeys(key, &subkeysCount); - rpmPubkeyFree(key); - - for (i = 0; i < subkeysCount; i++) { - rpmPubkey subkey = subkeys[i]; - - if (rpmKeyringAddKey(keyring, subkey) == 0) { - rpmlog(RPMLOG_DEBUG, - "added subkey %d of main key %s to keyring\n", - i, *f); - - nkeys++; - } - rpmPubkeyFree(subkey); - } - free(subkeys); - } -exit: - free(pkpath); - argvFree(files); - return nkeys; -} - -static int rpmtsLoadKeyringFromDB(rpmts ts, rpmKeyring keyring) -{ - Header h; - rpmdbMatchIterator mi; - int nkeys = 0; - - rpmlog(RPMLOG_DEBUG, "loading keyring from rpmdb\n"); - mi = rpmtsInitIterator(ts, RPMDBI_NAME, "gpg-pubkey", 0); - while ((h = rpmdbNextIterator(mi)) != NULL) { - struct rpmtd_s pubkeys; - const char *key; - - if (!headerGet(h, RPMTAG_PUBKEYS, &pubkeys, HEADERGET_MINMEM)) - continue; - - while ((key = rpmtdNextString(&pubkeys))) { - uint8_t *pkt; - size_t pktlen; - - if (rpmBase64Decode(key, (void **) &pkt, &pktlen) == 0) { - rpmPubkey key = rpmPubkeyNew(pkt, pktlen); - int subkeysCount, i; - rpmPubkey *subkeys = rpmGetSubkeys(key, &subkeysCount); - - if (rpmKeyringAddKey(keyring, key) == 0) { - char *nvr = headerGetAsString(h, RPMTAG_NVR); - rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", nvr); - free(nvr); - nkeys++; - } - rpmPubkeyFree(key); - - for (i = 0; i < subkeysCount; i++) { - rpmPubkey subkey = subkeys[i]; - - if (rpmKeyringAddKey(keyring, subkey) == 0) { - char *nvr = headerGetAsString(h, RPMTAG_NVR); - rpmlog(RPMLOG_DEBUG, - "added subkey %d of main key %s to keyring\n", - i, nvr); - - free(nvr); - nkeys++; - } - rpmPubkeyFree(subkey); - } - free(subkeys); - free(pkt); - } - } - rpmtdFreeData(&pubkeys); - } - rpmdbFreeIterator(mi); - - return nkeys; -} - -static int getKeyringType(void) -{ - int kt = KEYRING_RPMDB; - 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); - } - free(krtype); - - return kt; -} - -static int rpmKeystoreLoad(rpmts ts, rpmKeyring keyring) -{ - int nkeys = 0; - if (!ts->keyringtype) - ts->keyringtype = getKeyringType(); - if (ts->keyringtype == KEYRING_FS) { - nkeys = rpmtsLoadKeyringFromFiles(ts, keyring); - } else { - nkeys = rpmtsLoadKeyringFromDB(ts, keyring); - } - return nkeys; -} - static void loadKeyring(rpmts ts) { /* Never load the keyring if signature checking is disabled */ @@ -415,150 +274,6 @@ static void loadKeyring(rpmts ts) } } -static void addGpgProvide(Header h, const char *n, const char *v) -{ - rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL); - char * nsn = rstrscat(NULL, "gpg(", n, ")", NULL); - - headerPutString(h, RPMTAG_PROVIDENAME, nsn); - headerPutString(h, RPMTAG_PROVIDEVERSION, v); - headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); - - free(nsn); -} - -struct pgpdata_s { - const char *fingerprint; - const char *signid; - char *timestr; - char *verid; - const char *userid; - const char *shortid; - uint32_t time; -}; - -static void initPgpData(rpmPubkey key, struct pgpdata_s *pd) -{ - pgpDigParams pubp = rpmPubkeyPgpDigParams(key); - memset(pd, 0, sizeof(*pd)); - pd->fingerprint = rpmPubkeyFingerprintAsHex(key); - pd->signid = rpmPubkeyKeyIDAsHex(key); - pd->shortid = pd->signid + 8; - pd->userid = pgpDigParamsUserID(pubp); - if (! pd->userid) { - pd->userid = "none"; - } - pd->time = pgpDigParamsCreationTime(pubp); - - rasprintf(&pd->timestr, "%x", pd->time); - rasprintf(&pd->verid, "%d:%s-%s", pgpDigParamsVersion(pubp), pd->fingerprint, pd->timestr); -} - -static void finiPgpData(struct pgpdata_s *pd) -{ - free(pd->timestr); - free(pd->verid); - memset(pd, 0, sizeof(*pd)); -} - -static Header makeImmutable(Header h) -{ - h = headerReload(h, RPMTAG_HEADERIMMUTABLE); - if (h != NULL) { - char *sha1 = NULL; - char *sha256 = NULL; - unsigned int blen = 0; - void *blob = headerExport(h, &blen); - - /* XXX FIXME: bah, this code is repeated in way too many places */ - rpmDigestBundle bundle = rpmDigestBundleNew(); - rpmDigestBundleAdd(bundle, RPM_HASH_SHA1, RPMDIGEST_NONE); - rpmDigestBundleAdd(bundle, RPM_HASH_SHA256, RPMDIGEST_NONE); - - rpmDigestBundleUpdate(bundle, rpm_header_magic, sizeof(rpm_header_magic)); - rpmDigestBundleUpdate(bundle, blob, blen); - - rpmDigestBundleFinal(bundle, RPM_HASH_SHA1, (void **)&sha1, NULL, 1); - rpmDigestBundleFinal(bundle, RPM_HASH_SHA256, (void **)&sha256, NULL, 1); - - if (sha1 && sha256) { - headerPutString(h, RPMTAG_SHA1HEADER, sha1); - headerPutString(h, RPMTAG_SHA256HEADER, sha256); - } else { - h = headerFree(h); - } - free(sha1); - free(sha256); - free(blob); - rpmDigestBundleFree(bundle); - } - return h; -} - -/* Build pubkey header. */ -static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp) -{ - Header h = headerNew(); - const char * afmt = "%{pubkeys:armor}"; - const char * group = "Public Keys"; - const char * license = "pubkey"; - const char * buildhost = "localhost"; - uint32_t zero = 0; - struct pgpdata_s kd; - char * d = NULL; - char * enc = NULL; - char * s = NULL; - int rc = -1; - - memset(&kd, 0, sizeof(kd)); - - if ((enc = rpmPubkeyBase64(key)) == NULL) - goto exit; - - /* Build header elements. */ - initPgpData(key, &kd); - - rasprintf(&s, "%s public key", kd.userid); - headerPutString(h, RPMTAG_PUBKEYS, enc); - - if ((d = headerFormat(h, afmt, NULL)) == NULL) - goto exit; - - headerPutString(h, RPMTAG_NAME, "gpg-pubkey"); - headerPutString(h, RPMTAG_VERSION, kd.fingerprint); - headerPutString(h, RPMTAG_RELEASE, kd.timestr); - headerPutString(h, RPMTAG_DESCRIPTION, d); - headerPutString(h, RPMTAG_GROUP, group); - headerPutString(h, RPMTAG_LICENSE, license); - headerPutString(h, RPMTAG_SUMMARY, s); - headerPutString(h, RPMTAG_PACKAGER, kd.userid); - headerPutUint32(h, RPMTAG_SIZE, &zero, 1); - headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION); - headerPutString(h, RPMTAG_BUILDHOST, buildhost); - headerPutUint32(h, RPMTAG_BUILDTIME, &kd.time, 1); - headerPutString(h, RPMTAG_SOURCERPM, "(none)"); - - addGpgProvide(h, kd.userid, kd.verid); - addGpgProvide(h, kd.shortid, kd.verid); - addGpgProvide(h, kd.signid, kd.verid); - - /* Reload it into immutable region and stomp standard digests on it */ - h = makeImmutable(h); - if (h != NULL) { - *hdrp = headerLink(h); - rc = 0; - } - -exit: - headerFree(h); - finiPgpData(&kd); - free(enc); - free(d); - free(s); - - return rc; -} - rpmRC rpmtsImportHeader(rpmtxn txn, Header h, rpmFlags flags) { rpmRC rc = RPMRC_FAIL; @@ -571,157 +286,6 @@ rpmRC rpmtsImportHeader(rpmtxn txn, Header h, rpmFlags flags) return rc; } -static rpmRC rpmtsDeleteFSKey(rpmtxn txn, const string & keyid, const string & newname = "") -{ - rpmRC rc = RPMRC_NOTFOUND; - string keyglob = "gpg-pubkey-" + keyid + "-*.key"; - ARGV_t files = NULL; - char *pkpath = rpmGenPath(rpmtxnRootDir(txn), "%{_keyringpath}/", keyglob.c_str()); - if (rpmGlob(pkpath, NULL, &files) == 0) { - char **f; - for (f = files; *f; f++) { - char *bf = strrchr(*f, '/'); - if (newname.empty() || (bf && strcmp(bf + 1, newname.c_str()) != 0)) - rc = unlink(*f) ? RPMRC_FAIL : RPMRC_OK; - } - argvFree(files); - } - free(pkpath); - return rc; -} - -static rpmRC rpmtsDeleteFSKey(rpmtxn txn, rpmPubkey key) -{ - return rpmtsDeleteFSKey(txn, rpmPubkeyFingerprintAsHex(key)); -} - -static rpmRC rpmtsImportFSKey(rpmtxn txn, Header h, rpmFlags flags, int replace) -{ - rpmRC rc = RPMRC_FAIL; - char *keyfmt = headerFormat(h, "%{nvr}.key", NULL); - char *keyval = headerGetAsString(h, RPMTAG_DESCRIPTION); - char *path = rpmGenPath(rpmtxnRootDir(txn), "%{_keyringpath}/", keyfmt); - char *tmppath = NULL; - - if (replace) { - rasprintf(&tmppath, "%s.new", path); - unlink(tmppath); - } - - if (rpmMkdirs(rpmtxnRootDir(txn), "%{_keyringpath}")) { - rpmlog(RPMLOG_ERR, _("failed to create keyring directory %s: %s\n"), - path, strerror(errno)); - goto exit; - } - - if (FD_t fd = Fopen(tmppath ? tmppath : path, "wx")) { - size_t keylen = strlen(keyval); - if (Fwrite(keyval, 1, keylen, fd) == keylen) - rc = RPMRC_OK; - Fclose(fd); - } - if (!rc && tmppath && rename(tmppath, path) != 0) - rc = RPMRC_FAIL; - - if (rc) { - rpmlog(RPMLOG_ERR, _("failed to import key: %s: %s\n"), - tmppath ? tmppath : path, strerror(errno)); - if (tmppath) - unlink(tmppath); - } - - if (!rc && replace) { - /* find and delete the old pubkey entry */ - char *keyid = headerFormat(h, "%{version}", NULL); - if (rpmtsDeleteFSKey(txn, keyid, keyfmt) == RPMRC_NOTFOUND) { - /* make sure an old, short keyid version gets removed */ - rpmtsDeleteFSKey(txn, keyid+32, keyfmt); - } - free(keyid); - - } - -exit: - free(path); - free(keyval); - free(keyfmt); - free(tmppath); - return rc; -} - -static rpmRC rpmtsDeleteDBKey(rpmtxn txn, const string & keyid, unsigned int newinstance = 0) -{ - rpmts ts = rpmtxnTs(txn); - if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT))) - return RPMRC_FAIL; - - rpmRC rc = RPMRC_NOTFOUND; - unsigned int otherinstance = 0; - Header oh; - string label = "gpg-pubkey-" + keyid; - rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_LABEL, label.c_str(), 0); - - while (otherinstance == 0 && (oh = rpmdbNextIterator(mi)) != NULL) - if (headerGetInstance(oh) != newinstance) - otherinstance = headerGetInstance(oh); - rpmdbFreeIterator(mi); - if (otherinstance) { - rc = rpmdbRemove(rpmtsGetRdb(ts), otherinstance) ? - RPMRC_FAIL : RPMRC_OK; - } - - return rc; -} - -static rpmRC rpmtsDeleteDBKey(rpmtxn txn, rpmPubkey key) -{ - return rpmtsDeleteDBKey(txn, rpmPubkeyFingerprintAsHex(key)); -} - -static rpmRC rpmtsImportDBKey(rpmtxn txn, Header h, rpmFlags flags, int replace) -{ - rpmRC rc = rpmtsImportHeader(txn, h, 0); - - if (!rc && replace) { - /* 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) { - /* make sure an old, short keyid version gets removed */ - rpmtsDeleteDBKey(txn, keyid+32, newinstance); - } - free(keyid); - } - - return rc; -} - -static rpmRC rpmKeystoreImportPubkey(rpmtxn txn, rpmPubkey key, int replace = 0) -{ - rpmRC rc = RPMRC_FAIL; - rpmts ts = rpmtxnTs(txn); - Header h = NULL; - - if (makePubkeyHeader(ts, key, &h) != 0) - return rc; - - rpm_tid_t tid = rpmtsGetTid(ts); - headerPutUint32(h, RPMTAG_INSTALLTIME, &tid, 1); - headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1); - - /* Add header to database. */ - if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { - if (ts->keyringtype == KEYRING_FS) - rc = rpmtsImportFSKey(txn, h, 0, replace); - else - rc = rpmtsImportDBKey(txn, h, 0, replace); - } else { - rc = RPMRC_OK; - } - headerFree(h); - return rc; -} - rpmRC rpmtxnImportPubkey(rpmtxn txn, const unsigned char * pkt, size_t pktlen) { rpmRC rc = RPMRC_FAIL; /* assume failure */ @@ -801,17 +365,6 @@ rpmRC rpmtxnImportPubkey(rpmtxn txn, const unsigned char * pkt, size_t pktlen) return rc; } -static 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 rpmtxnDeletePubkey(rpmtxn txn, rpmPubkey key) { rpmRC rc = RPMRC_FAIL;