[pacman-dev] [PATCH 2/5] Signature verification functions
Denis A. Altoé Falqueto
denisfalqueto at gmail.com
Mon Jul 26 16:26:02 EDT 2010
_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 at 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
More information about the pacman-dev
mailing list