diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c index babbe76..d6150a4 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -381,37 +381,59 @@ exit: return res; } -/** \ingroup rpmcli - * Import public key(s). - * @todo Implicit --update policy for gpg-pubkey headers. - * @param ts transaction set - * @param qva mode flags and parameters - * @param argv array of pubkey file names (NULL terminated) - * @return 0 on success - */ -static int rpmcliImportPubkeys(const rpmts ts, QVA_t qva, ARGV_const_t argv) +static int doImport(rpmts ts, const char *fn, char *buf, ssize_t blen) { - const char * fn; - unsigned char * pkt = NULL; - size_t pktlen = 0; - char * t = NULL; + char const * const pgpmark = "-----BEGIN PGP "; + size_t marklen = strlen(pgpmark); int res = 0; - rpmRC rpmrc; - int rc; - - if (argv == NULL) return res; + int keyno = 1; + char *start = strstr(buf, pgpmark); + + while (start) { + uint8_t *pkt = NULL; + size_t pktlen = 0; + + /* Read pgp packet. */ + if (pgpParsePkts(start, &pkt, &pktlen) == PGPARMOR_PUBKEY) { + /* Import pubkey packet(s). */ + if (rpmtsImportPubkey(ts, pkt, pktlen) != RPMRC_OK) { + rpmlog(RPMLOG_ERR, _("%s: key %d import failed.\n"), fn, keyno); + res++; + } + } else { + rpmlog(RPMLOG_ERR, _("%s: key %d not an armored public key.\n"), + fn, keyno); + res++; + } + + /* See if there are more keys in the buffer */ + if (start + marklen < buf + blen) { + start = strstr(start + marklen, pgpmark); + } else { + start = NULL; + } - while ((fn = *argv++) != NULL) { + keyno++; + free(pkt); + } + return res; +} - rpmtsClean(ts); - pkt = _free(pkt); - t = _free(t); +static int rpmcliImportPubkeys(rpmts ts, ARGV_const_t argv) +{ + int res = 0; + for (ARGV_const_t arg = argv; arg && *arg; arg++) { + const char *fn = *arg; + uint8_t *buf = NULL; + ssize_t blen = 0; + char *t = NULL; + int iorc; /* If arg looks like a keyid, then attempt keyserver retrieve. */ - if (fn[0] == '0' && fn[1] == 'x') { - const char * s; + if (rstreqn(fn, "0x", 2)) { + const char * s = fn + 2; int i; - for (i = 0, s = fn+2; *s && isxdigit(*s); s++, i++) + for (i = 0; *s && isxdigit(*s); s++, i++) {}; if (i == 8 || i == 16) { t = rpmExpand("%{_hkp_keyserver_query}", fn+2, NULL); @@ -420,30 +442,18 @@ static int rpmcliImportPubkeys(const rpmts ts, QVA_t qva, ARGV_const_t argv) } } - /* Read pgp packet. */ - if ((rc = pgpReadPkts(fn, &pkt, &pktlen)) <= 0) { - rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, rc); - res++; - continue; - } - if (rc != PGPARMOR_PUBKEY) { - rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn); - res++; - continue; - } - - /* Import pubkey packet(s). */ - if ((rpmrc = rpmtsImportPubkey(ts, pkt, pktlen)) != RPMRC_OK) { - rpmlog(RPMLOG_ERR, _("%s: import failed.\n"), fn); + /* Read the file and try to import all contained keys */ + iorc = rpmioSlurp(fn, &buf, &blen); + if (iorc || buf == NULL || blen < 64) { + rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, iorc); res++; - continue; + } else { + res += doImport(ts, fn, (char *)buf, blen); } - + + free(t); + free(buf); } - -rpmtsClean(ts); - pkt = _free(pkt); - t = _free(t); return res; } @@ -799,7 +809,7 @@ int rpmcliSign(rpmts ts, QVA_t qva, ARGV_const_t argv) case RPMSIGN_CHK_SIGNATURE: break; case RPMSIGN_IMPORT_PUBKEY: - return rpmcliImportPubkeys(ts, qva, argv); + return rpmcliImportPubkeys(ts, argv); break; case RPMSIGN_NEW_SIGNATURE: case RPMSIGN_ADD_SIGNATURE: