/** * dnf_keyring_add_public_key: * @keyring: a #rpmKeyring instance. * @filename: The public key filename. * @error: a #GError or %NULL. * * Adds a specific public key to the keyring. * * Returns: %TRUE for success, %FALSE otherwise * * Since: 0.1.0 **/ gboolean dnf_keyring_add_public_key(rpmKeyring keyring, const gchar *filename, GError **error) { gboolean ret = TRUE; gint rc; gsize len; pgpArmor armor; pgpDig dig = NULL; rpmPubkey pubkey = NULL; uint8_t *pkt = NULL; g_autofree gchar *data = NULL; /* ignore symlinks and directories */ if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) goto out; if (g_file_test(filename, G_FILE_TEST_IS_SYMLINK)) goto out; /* get data */ ret = g_file_get_contents(filename, &data, &len, error); if (!ret) goto out; /* rip off the ASCII armor and parse it */ armor = pgpParsePkts(data, &pkt, &len); if (armor < 0) { ret = FALSE; g_set_error(error, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID, "failed to parse PKI file %s", filename); goto out; } /* make sure it's something we can add to rpm */ if (armor != PGPARMOR_PUBKEY) { ret = FALSE; g_set_error(error, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID, "PKI file %s is not a public key", filename); goto out; } /* test each one */ pubkey = rpmPubkeyNew(pkt, len); if (pubkey == NULL) { ret = FALSE; g_set_error(error, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID, "failed to parse public key for %s", filename); goto out; } /* does the key exist in the keyring */ dig = rpmPubkeyDig(pubkey); rc = rpmKeyringLookup(keyring, dig); if (rc == RPMRC_OK) { ret = TRUE; g_debug("%s is already present", filename); goto out; } /* add to rpmdb automatically, without a prompt */ rc = rpmKeyringAddKey(keyring, pubkey); if (rc == 1) { ret = TRUE; g_debug("%s is already added", filename); goto out; } else if (rc < 0) { ret = FALSE; g_set_error(error, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID, "failed to add public key %s to rpmdb", filename); goto out; } /* success */ g_debug("added missing public key %s to rpmdb", filename); ret = TRUE; out: if (pkt != NULL) free(pkt); /* yes, free() */ if (pubkey != NULL) rpmPubkeyFree(pubkey); if (dig != NULL) pgpFreeDig(dig); return ret; }
uint32_t AddKeyToKeyRing( const char* pszFile, rpmKeyring pKeyring ) { uint32_t dwError = 0; pgpArmor nArmor = PGPARMOR_NONE; pgpDig pDig = NULL; rpmPubkey pPubkey = NULL; uint8_t* pPkt = NULL; size_t nPktLen = 0; char* pszKeyData = NULL; if(IsNullOrEmptyString(pszFile) || !pKeyring) { dwError = ERROR_TDNF_INVALID_PARAMETER; BAIL_ON_TDNF_ERROR(dwError); } dwError = ReadGPGKey(pszFile, &pszKeyData); BAIL_ON_TDNF_ERROR(dwError); nArmor = pgpParsePkts(pszKeyData, &pPkt, &nPktLen); if(nArmor != PGPARMOR_PUBKEY) { dwError = ERROR_TDNF_INVALID_PUBKEY_FILE; BAIL_ON_TDNF_ERROR(dwError); } pPubkey = rpmPubkeyNew (pPkt, nPktLen); if(!pPubkey) { dwError = ERROR_TDNF_CREATE_PUBKEY_FAILED; BAIL_ON_TDNF_ERROR(dwError); } pDig = rpmPubkeyDig(pPubkey); if(!pDig) { dwError = ERROR_TDNF_CREATE_PUBKEY_FAILED; BAIL_ON_TDNF_ERROR(dwError); } dwError = rpmKeyringLookup(pKeyring, pDig); if(dwError == RPMRC_OK) { dwError = 0;//key exists } else { dwError = rpmKeyringAddKey(pKeyring, pPubkey); if(dwError == 1) { dwError = 0;//Already added. ignore } BAIL_ON_TDNF_ERROR(dwError); } cleanup: return dwError; error: TDNF_SAFE_FREE_MEMORY(pszKeyData); if(pPubkey) { rpmPubkeyFree(pPubkey); } goto cleanup; }
/* 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"; const char * userid; rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL); uint32_t zero = 0; uint32_t keytime = 0; pgpDig dig = NULL; pgpDigParams pubp = NULL; char * d = NULL; char * enc = NULL; char * n = NULL; char * u = NULL; char * v = NULL; char * r = NULL; char * evr = NULL; int rc = -1; if ((enc = rpmPubkeyBase64(key)) == NULL) goto exit; if ((dig = rpmPubkeyDig(key)) == NULL) goto exit; if ((pubp = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY)) == NULL) goto exit; /* Build header elements. */ v = pgpHexStr(pubp->signid, sizeof(pubp->signid)); r = pgpHexStr(pubp->time, sizeof(pubp->time)); userid = pubp->userid ? pubp->userid : "none"; keytime = pgpGrab(pubp->time, sizeof(pubp->time)); rasprintf(&n, "gpg(%s)", v+8); rasprintf(&u, "gpg(%s)", userid); rasprintf(&evr, "%d:%s-%s", pubp->version, v, r); headerPutString(h, RPMTAG_PUBKEYS, enc); if ((d = headerFormat(h, afmt, NULL)) == NULL) goto exit; headerPutString(h, RPMTAG_NAME, "gpg-pubkey"); headerPutString(h, RPMTAG_VERSION, v+8); headerPutString(h, RPMTAG_RELEASE, r); headerPutString(h, RPMTAG_DESCRIPTION, d); headerPutString(h, RPMTAG_GROUP, group); headerPutString(h, RPMTAG_LICENSE, license); headerPutString(h, RPMTAG_SUMMARY, u); headerPutString(h, RPMTAG_PACKAGER, userid); headerPutUint32(h, RPMTAG_SIZE, &zero, 1); headerPutString(h, RPMTAG_PROVIDENAME, u); headerPutString(h, RPMTAG_PROVIDEVERSION, evr); headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); headerPutString(h, RPMTAG_PROVIDENAME, n); headerPutString(h, RPMTAG_PROVIDEVERSION, evr); headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION); headerPutString(h, RPMTAG_BUILDHOST, buildhost); headerPutUint32(h, RPMTAG_BUILDTIME, &keytime, 1); headerPutString(h, RPMTAG_SOURCERPM, "(none)"); /* Reload the lot to immutable region and stomp sha1 digest on it */ h = headerReload(h, RPMTAG_HEADERIMMUTABLE); if (h != NULL) { char *sha1 = NULL; unsigned int blen = 0; const void *blob = headerExport(h, &blen); /* XXX FIXME: bah, this code is repeated in way too many places */ DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestUpdate(ctx, blob, blen); rpmDigestFinal(ctx, (void **)&sha1, NULL, 1); if (sha1) { headerPutString(h, RPMTAG_SHA1HEADER, sha1); *hdrp = headerLink(h); rc = 0; } free(sha1); } exit: headerFree(h); pgpFreeDig(dig); free(n); free(u); free(v); free(r); free(evr); free(enc); free(d); return rc; }