Пример #1
0
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;
}
Пример #2
0
/**
 * 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;
}
Пример #3
0
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;
}
Пример #4
0
/**
 * 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;
}