_alpm_gpg_checksig was renamed to _alpm_gpg_checksig_memory. It checks signatures which are in memory. The packages' signatures are stored in the repository database and are kept in memory when they need to be verified. _alpm_gpg_checksig_file is very similar to _alpm_gpg_checksig_memory, but the signature is read from a file. The return values for both functions are: 0 = valid; 1 = invalid; -1 = error while verifying. Signed-off-by: Denis A. AltoƩ Falqueto <denisfalqueto@gmail.com> --- lib/libalpm/signing.c | 159 ++++++++++++++++++++++++++++++++++++------------- lib/libalpm/signing.h | 3 +- 2 files changed, 120 insertions(+), 42 deletions(-) diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index 2b15528..781a1d1 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -91,21 +91,76 @@ error: RET_ERR(PM_ERR_GPGME, 1); } +static int gpgme_checksig(gpgme_ctx_t ctx, gpgme_data_t filedata, gpgme_data_t sigdata, + char *filepath) +{ + int ret = 0; + gpgme_error_t err; + gpgme_signature_t gpgsig; + gpgme_verify_result_t result; + + /* here's where the magic happens */ + err = gpgme_op_verify(ctx, sigdata, filedata, NULL); + CHECK_ERR(); + result = gpgme_op_verify_result(ctx); + gpgsig = result->signatures; + if (!gpgsig || gpgsig->next) { + _alpm_log(PM_LOG_ERROR, _("Unexpected number of signatures\n")); + ret = -1; + goto error; + } + fprintf(stdout, "\nsummary=%x\n", gpgsig->summary); + fprintf(stdout, "fpr=%s\n", gpgsig->fpr); + fprintf(stdout, "status=%d\n", gpgsig->status); + fprintf(stdout, "timestamp=%lu\n", gpgsig->timestamp); + fprintf(stdout, "wrong_key_usage=%u\n", gpgsig->wrong_key_usage); + fprintf(stdout, "pka_trust=%u\n", gpgsig->pka_trust); + fprintf(stdout, "chain_model=%u\n", gpgsig->chain_model); + fprintf(stdout, "validity=%d\n", gpgsig->validity); + fprintf(stdout, "validity_reason=%d\n", gpgsig->validity_reason); + fprintf(stdout, "key=%d\n", gpgsig->pubkey_algo); + fprintf(stdout, "hash=%d\n", gpgsig->hash_algo); + + if(gpgsig->summary & GPGME_SIGSUM_VALID) { + /* good signature, continue */ + _alpm_log(PM_LOG_DEBUG, _("Package %s has a valid signature.\n"), + filepath); + } else if(gpgsig->summary & GPGME_SIGSUM_GREEN) { + /* 'green' signature, not sure what to do here */ + _alpm_log(PM_LOG_WARNING, _("Package %s has a green signature.\n"), + filepath); + } else if(gpgsig->summary & GPGME_SIGSUM_KEY_MISSING) { + pm_errno = PM_ERR_SIG_UNKNOWN; + _alpm_log(PM_LOG_WARNING, _("Package %s has a signature from an unknown key.\n"), + filepath); + ret = -1; + } else { + /* we'll capture everything else here */ + pm_errno = PM_ERR_SIG_INVALID; + _alpm_log(PM_LOG_ERROR, _("Package %s has an invalid signature.\n"), + filepath); + ret = 1; + } + return ret; +error: + _alpm_log(PM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); + RET_ERR(PM_ERR_GPGME, 1); +} + /** * Check the PGP package signature for the given package file. * @param pkgpath the full path to a package file * @param sig PGP signature data in raw form (already decoded) * @return a int value : 0 (valid), 1 (invalid), -1 (an error occured) */ -int _alpm_gpgme_checksig(const char *pkgpath, const pmpgpsig_t *sig) +int _alpm_gpgme_checksig_memory(const char *pkgpath, const pmpgpsig_t *sig) { int ret = 0; gpgme_error_t err; gpgme_ctx_t ctx; gpgme_data_t pkgdata, sigdata; gpgme_verify_result_t result; - gpgme_signature_t gpgsig; - FILE *pkgfile = NULL, *sigfile = NULL; + FILE *pkgfile = NULL; ALPM_LOG_FUNC; @@ -137,58 +192,80 @@ int _alpm_gpgme_checksig(const char *pkgpath, const pmpgpsig_t *sig) err = gpgme_data_new_from_mem(&sigdata, (char*)sig->rawdata, sig->rawlen, 0); CHECK_ERR(); - /* here's where the magic happens */ - err = gpgme_op_verify(ctx, sigdata, pkgdata, NULL); + ret = gpgme_checksig(ctx, pkgdata, sigdata, pkgpath); +error: + gpgme_data_release(sigdata); + gpgme_data_release(pkgdata); + gpgme_release(ctx); + if(pkgfile) { + fclose(pkgfile); + } + if(err != GPG_ERR_NO_ERROR) { + _alpm_log(PM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); + RET_ERR(PM_ERR_GPGME, -1); + } + return(ret); +} + +/** + * Check the PGP signature for the some file + * @param filepath the full path to the signed file + * @param sigpath the full path to the signature file + * @return a int value : 0 (valid), 1 (invalid), -1 (an error occured) + */ +int _alpm_gpgme_checksig_file(const char *filepath, const char *sigpath) +{ + int ret = 0; + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_data_t filedata, sigdata; + gpgme_verify_result_t result; + gpgme_signature_t gpgsig; + FILE *file = NULL, *sigfile = NULL; + + ALPM_LOG_FUNC; + + if(!filepath || access(filepath, R_OK) != 0) { + RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + } + if(gpgme_init()) { + /* pm_errno was set in gpgme_init() */ + return(-1); + } + err = gpgme_new(&ctx); CHECK_ERR(); - result = gpgme_op_verify_result(ctx); - gpgsig = result->signatures; - if (!gpgsig || gpgsig->next) { - _alpm_log(PM_LOG_ERROR, _("Unexpected number of signatures\n")); + + /* create our necessary data objects to verify the signature */ + /* first the package itself */ + file = fopen(filepath, "rb"); + if(file == NULL) { + pm_errno = PM_ERR_PKG_OPEN; ret = -1; goto error; } - fprintf(stdout, "\nsummary=%x\n", gpgsig->summary); - fprintf(stdout, "fpr=%s\n", gpgsig->fpr); - fprintf(stdout, "status=%d\n", gpgsig->status); - fprintf(stdout, "timestamp=%lu\n", gpgsig->timestamp); - fprintf(stdout, "wrong_key_usage=%u\n", gpgsig->wrong_key_usage); - fprintf(stdout, "pka_trust=%u\n", gpgsig->pka_trust); - fprintf(stdout, "chain_model=%u\n", gpgsig->chain_model); - fprintf(stdout, "validity=%d\n", gpgsig->validity); - fprintf(stdout, "validity_reason=%d\n", gpgsig->validity_reason); - fprintf(stdout, "key=%d\n", gpgsig->pubkey_algo); - fprintf(stdout, "hash=%d\n", gpgsig->hash_algo); + err = gpgme_data_new_from_stream(&filedata, file); + CHECK_ERR(); - if(gpgsig->summary & GPGME_SIGSUM_VALID) { - /* good signature, continue */ - _alpm_log(PM_LOG_DEBUG, _("Package %s has a valid signature.\n"), - pkgpath); - } else if(gpgsig->summary & GPGME_SIGSUM_GREEN) { - /* 'green' signature, not sure what to do here */ - _alpm_log(PM_LOG_WARNING, _("Package %s has a green signature.\n"), - pkgpath); - } else if(gpgsig->summary & GPGME_SIGSUM_KEY_MISSING) { + /* next create data object for the signature */ + sigfile = fopen(sigpath, "rb"); + if (sigfile == NULL) { pm_errno = PM_ERR_SIG_UNKNOWN; - _alpm_log(PM_LOG_WARNING, _("Package %s has a signature from an unknown key.\n"), - pkgpath); ret = -1; - } else { - /* we'll capture everything else here */ - pm_errno = PM_ERR_SIG_INVALID; - _alpm_log(PM_LOG_ERROR, _("Package %s has an invalid signature.\n"), - pkgpath); - ret = 1; + goto error; } + err = gpgme_data_new_from_stream(&sigdata, sigfile); + CHECK_ERR(); + ret = gpgme_checksig(ctx, filedata, sigdata, filepath); error: gpgme_data_release(sigdata); - gpgme_data_release(pkgdata); + gpgme_data_release(filedata); gpgme_release(ctx); if(sigfile) { fclose(sigfile); } - if(pkgfile) { - fclose(pkgfile); + if(file) { + fclose(file); } if(err != GPG_ERR_NO_ERROR) { _alpm_log(PM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); @@ -207,7 +284,7 @@ int SYMEXPORT alpm_pkg_check_pgp_signature(pmpkg_t *pkg) ALPM_LOG_FUNC; ASSERT(pkg != NULL, return(0)); - return(_alpm_gpgme_checksig(alpm_pkg_get_filename(pkg), + return(_alpm_gpgme_checksig_memory(alpm_pkg_get_filename(pkg), alpm_pkg_get_pgpsig(pkg))); } diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h index c004697..9ae3dc1 100644 --- a/lib/libalpm/signing.h +++ b/lib/libalpm/signing.h @@ -21,7 +21,8 @@ #include "alpm.h" -int _alpm_gpgme_checksig(const char *pkgpath, const pmpgpsig_t *sig); +int _alpm_gpgme_checksig_memory(const char *pkgpath, const pmpgpsig_t *sig); +int _alpm_gpgme_checksig_file(const char *filepath, const char *sigpath); #endif /* _ALPM_SIGNING_H */ -- 1.7.1.1