From 355c9b069f25d3a9c3dc224fb39a90522c04ca28 Mon Sep 17 00:00:00 2001 From: Lubos Kardos Date: Tue, 21 Jul 2015 16:01:46 +0200 Subject: [PATCH] Add rpmGetSubkeys() and pgpPrtParamsSubkeys() for getting gpg subkeys. pgpPrtParamSubkeys() parses gpg packets to get gpg subkeys parameters. rpmGetSubkeys() uses pgpPrtParamSubkeys() and it creates rpmPubkey objects that can be insterted into rpm keyring. --- rpmio/rpmkeyring.c | 32 ++++++++++++++++++++++++ rpmio/rpmkeyring.h | 8 ++++++ rpmio/rpmpgp.c | 62 ++++++++++++++++++++++++++++++++++++++++++++-- rpmio/rpmpgp.h | 12 +++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) diff --git a/rpmio/rpmkeyring.c b/rpmio/rpmkeyring.c index 368a1ec138..0333ea95a2 100644 --- a/rpmio/rpmkeyring.c +++ b/rpmio/rpmkeyring.c @@ -152,6 +152,38 @@ rpmPubkey rpmPubkeyNew(const uint8_t *pkt, size_t pktlen) return key; } +rpmPubkey *rpmGetSubkeys(rpmPubkey mainkey, int *count) +{ + rpmPubkey *subkeys = NULL; + pgpDigParams *pgpsubkeys = NULL; + int pgpsubkeysCount = 0; + int i; + + if (!pgpPrtParamsSubkeys(mainkey->pkt, mainkey->pktlen, mainkey->pgpkey, + &pgpsubkeys, &pgpsubkeysCount)) { + + + subkeys = xmalloc(pgpsubkeysCount * sizeof(*subkeys)); + + for (i = 0; i < pgpsubkeysCount; i++) { + rpmPubkey subkey = xcalloc(1, sizeof(*subkey)); + subkeys[i] = subkey; + + /* Packets with all subkeys already stored in main key */ + subkey->pkt = NULL; + subkey->pktlen = 0; + + subkey->pgpkey = pgpsubkeys[i]; + memcpy(subkey->keyid, pgpsubkeys[i]->signid, sizeof(subkey->keyid)); + subkey->nrefs = 1; + pthread_rwlock_init(&subkey->lock, NULL); + } + } + *count = pgpsubkeysCount; + + return subkeys; +} + rpmPubkey rpmPubkeyFree(rpmPubkey key) { if (key == NULL) diff --git a/rpmio/rpmkeyring.h b/rpmio/rpmkeyring.h index 9fcab5feb6..e8767de03a 100644 --- a/rpmio/rpmkeyring.h +++ b/rpmio/rpmkeyring.h @@ -64,6 +64,14 @@ rpmKeyring rpmKeyringLink(rpmKeyring keyring); */ rpmPubkey rpmPubkeyNew(const uint8_t *pkt, size_t pktlen); +/** \ingroupt rpmkeyring + * Return array of subkeys belonging to maikey + * param mainkey main rpmPubkey + * param count count of returned subkeys + * @return an array of subkey's handles + */ +rpmPubkey *rpmGetSubkeys(rpmPubkey mainkey, int *count); + /** \ingroup rpmkeyring * Create a new rpmPubkey from ASCII-armored pubkey file * @param filename Path to pubkey file diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c index cf97773cd0..f020650030 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c @@ -668,7 +668,9 @@ static int pgpPrtPubkeyParams(uint8_t pubkey_algo, rc = 0; /* We can't handle more than one key at a time */ - if (rc == 0 && keyp->alg == NULL && keyp->tag == PGPTAG_PUBLIC_KEY) + if (rc == 0 && keyp->alg == NULL && (keyp->tag == PGPTAG_PUBLIC_KEY || + keyp->tag == PGPTAG_PUBLIC_SUBKEY)) + keyp->alg = keyalg; else pgpDigAlgFree(keyalg); @@ -697,7 +699,8 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen, fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t); pgpPrtNL(); - if (_digp->tag == tag) { + /* If _digp->hash is not NULL then signature is already loaded */ + if (_digp->hash == NULL) { _digp->version = v->version; memcpy(_digp->time, v->time, sizeof(_digp->time)); _digp->pubkey_algo = v->pubkey_algo; @@ -983,6 +986,61 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, return rc; } +int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, + pgpDigParams mainkey, pgpDigParams **subkeys, + int *subkeysCount) +{ + const uint8_t *p = pkts; + const uint8_t *pend = pkts + pktlen; + pgpDigParams *digps = NULL; + int count = 0; + int alloced = 10; + struct pgpPkt pkt; + int rc, i; + + digps = xmalloc(alloced * sizeof(*digps)); + + while (p < pend) { + if (decodePkt(p, (pend - p), &pkt)) + break; + + p += (pkt.body - pkt.head) + pkt.blen; + + if (pkt.tag == PGPTAG_PUBLIC_SUBKEY) { + if (count == alloced) { + alloced <<= 1; + digps = xrealloc(digps, alloced * sizeof(*digps)); + } + + digps[count] = xcalloc(1, sizeof(**digps)); + digps[count]->tag = PGPTAG_PUBLIC_SUBKEY; + /* Copy UID from main key to subkey */ + digps[count]->userid = xstrdup(mainkey->userid); + + if(getFingerprint(pkt.body, pkt.blen, digps[count]->signid)) + continue; + + if(pgpPrtKey(pkt.tag, pkt.body, pkt.blen, digps[count])) { + pgpDigParamsFree(digps[count]); + continue; + } + count++; + } + } + rc = (p == pend) ? 0 : -1; + + if (rc == 0) { + *subkeys = xrealloc(digps, count * sizeof(*digps)); + *subkeysCount = count; + } else { + for (i = 0; i < count; i++) + pgpDigParamsFree(digps[i]); + free(digps); + } + + return rc; +} + int pgpPrtPkts(const uint8_t * pkts, size_t pktlen, pgpDig dig, int printing) { int rc; diff --git a/rpmio/rpmpgp.h b/rpmio/rpmpgp.h index e4966ed4ce..718fb5bee4 100644 --- a/rpmio/rpmpgp.h +++ b/rpmio/rpmpgp.h @@ -999,6 +999,18 @@ int pgpExtractPubkeyFingerprint(const char * b64pkt, pgpKeyID_t keyid); int pgpPrtParams(const uint8_t *pkts, size_t pktlen, unsigned int pkttype, pgpDigParams * ret); +/** \ingroup rpmpgp + * Parse subkey parameters from OpenPGP packet(s). + * @param pkts OpenPGP packet(s) + * @param pktlen OpenPGP packet(s) length (no. of bytes) + * @param mainkey parameters of main key + * @param subkeys array of subkey parameters (alloced) + * @param subkeysCount count of subkeys + * @return -1 on error, 0 on success + */ +int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, + pgpDigParams mainkey, pgpDigParams **subkeys, + int *subkeysCount); /** \ingroup rpmpgp * Print/parse a OpenPGP packet(s). * @param pkts OpenPGP packet(s)