[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