uint32_t VerifyRpmSig( rpmKeyring pKeyring, const char* pszPkgFile ) { uint32_t dwError = 0; FD_t pFD_t = NULL; rpmts pTS = NULL; rpmtd pTD = NULL; Header pPkgHeader = NULL; pgpDig pDigest = NULL; if(!pKeyring || IsNullOrEmptyString(pszPkgFile)) { dwError = ERROR_TDNF_INVALID_PARAMETER; BAIL_ON_TDNF_ERROR(dwError); } pFD_t = Fopen(pszPkgFile, "r.fdio"); if(!pFD_t) { dwError = errno; BAIL_ON_TDNF_SYSTEM_ERROR(dwError); } pTS = rpmtsCreate(); if(!pTS) { dwError = ERROR_TDNF_RPMTS_CREATE_FAILED; BAIL_ON_TDNF_RPM_ERROR(dwError); } rpmtsSetVSFlags (pTS, _RPMVSF_NOSIGNATURES); pTD = rpmtdNew(); if(!pTD) { dwError = ERROR_TDNF_RPMTD_CREATE_FAILED; BAIL_ON_TDNF_RPM_ERROR(dwError); } dwError = rpmReadPackageFile(pTS, pFD_t, pszPkgFile, &pPkgHeader); BAIL_ON_TDNF_RPM_ERROR(dwError); if(!headerConvert(pPkgHeader, HEADERCONV_RETROFIT_V3)) { dwError = ERROR_TDNF_RPM_HEADER_CONVERT_FAILED; BAIL_ON_TDNF_RPM_ERROR(dwError); } if(!headerGet(pPkgHeader, RPMTAG_RSAHEADER, pTD, HEADERGET_MINMEM)) { dwError = ERROR_TDNF_RPM_GET_RSAHEADER_FAILED; BAIL_ON_TDNF_ERROR(dwError); } pDigest = pgpNewDig(); if(pgpPrtPkts(pTD->data, pTD->count, pDigest, 0)) { dwError = ERROR_TDNF_RPM_GPG_PARSE_FAILED; BAIL_ON_TDNF_ERROR(dwError); } if(rpmKeyringLookup(pKeyring, pDigest) != RPMRC_OK) { dwError = ERROR_TDNF_RPM_GPG_NO_MATCH; BAIL_ON_TDNF_ERROR(dwError); } cleanup: if(pFD_t) { Fclose(pFD_t); } if(pDigest) { pgpFreeDig(pDigest); } if(pPkgHeader) { headerFree(pPkgHeader); } if(pTD) { rpmtdFree(pTD); } if(pTS) { rpmtsFree(pTS); } return dwError; error: goto cleanup; }
/** * 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; }
/** * dnf_keyring_check_untrusted_file: */ gboolean dnf_keyring_check_untrusted_file(rpmKeyring keyring, const gchar *filename, GError **error) { FD_t fd = NULL; gboolean ret = FALSE; Header hdr = NULL; pgpDig dig = NULL; rpmRC rc; rpmtd td = NULL; rpmts ts = NULL; /* open the file for reading */ fd = Fopen(filename, "r.fdio"); if (fd == NULL) { g_set_error(error, DNF_ERROR, DNF_ERROR_FILE_INVALID, "failed to open %s", filename); goto out; } if (Ferror(fd)) { g_set_error(error, DNF_ERROR, DNF_ERROR_FILE_INVALID, "failed to open %s: %s", filename, Fstrerror(fd)); goto out; } /* we don't want to abort on missing keys */ ts = rpmtsCreate(); rpmtsSetVSFlags(ts, _RPMVSF_NOSIGNATURES); /* read in the file */ rc = rpmReadPackageFile(ts, fd, filename, &hdr); if (rc != RPMRC_OK) { /* we only return SHA1 and MD5 failures, as we're not * checking signatures at this stage */ g_set_error(error, DNF_ERROR, DNF_ERROR_FILE_INVALID, "%s could not be verified", filename); goto out; } /* convert and upscale */ headerConvert(hdr, HEADERCONV_RETROFIT_V3); /* get RSA key */ td = rpmtdNew(); rc = headerGet(hdr, RPMTAG_RSAHEADER, td, HEADERGET_MINMEM); if (rc != 1) { /* try to read DSA key as a fallback */ rc = headerGet(hdr, RPMTAG_DSAHEADER, td, HEADERGET_MINMEM); } /* the package has no signing key */ if (rc != 1) { g_autofree char *package_filename = g_path_get_basename(filename); ret = FALSE; g_set_error(error, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID, "package not signed: %s", package_filename); goto out; } /* make it into a digest */ dig = pgpNewDig(); rc = pgpPrtPkts(td->data, td->count, dig, 0); if (rc != 0) { g_set_error(error, DNF_ERROR, DNF_ERROR_FILE_INVALID, "failed to parse digest header for %s", filename); goto out; } /* does the key exist in the keyring */ rc = rpmKeyringLookup(keyring, dig); if (rc != RPMRC_OK) { g_set_error(error, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID, "failed to lookup digest in keyring for %s", filename); goto out; } /* the package is signed by a key we trust */ g_debug("%s has been verified as trusted", filename); ret = TRUE; out: if (dig != NULL) pgpFreeDig(dig); if (td != NULL) { rpmtdFreeData(td); rpmtdFree(td); } if (ts != NULL) rpmtsFree(ts); if (hdr != NULL) headerFree(hdr); if (fd != NULL) Fclose(fd); return ret; }