summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2012-01-11 15:08:09 -0600
committerDan McGee <dan@archlinux.org>2012-04-08 21:59:41 -0500
commitfee55210c6e8ed9a686ea892c2d9783e6f158e18 (patch)
treeaec19c0862bd9cbec7cf971c9dd519c0270a002c
parent51669a55ed854909172f3dba2f29c79ba1efb86a (diff)
downloadpacman-fee55210c6e8ed9a686ea892c2d9783e6f158e18.tar.gz
pacman-fee55210c6e8ed9a686ea892c2d9783e6f158e18.zip
WIP: make signing take fd, not path
-rw-r--r--lib/libalpm/be_package.c18
-rw-r--r--lib/libalpm/be_sync.c3
-rw-r--r--lib/libalpm/signing.c66
-rw-r--r--lib/libalpm/signing.h6
4 files changed, 54 insertions, 39 deletions
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index bcb884f4..9b26964c 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -310,7 +310,7 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level,
alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation)
{
- int has_sig;
+ int has_sig, ret;
handle->pm_errno = 0;
if(pkgfile == NULL || strlen(pkgfile) == 0) {
@@ -367,16 +367,26 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
}
}
+ ret = 0;
+
/* even if we don't have a sig, run the check code if level tells us to */
if(has_sig || level & ALPM_SIG_PACKAGE) {
+ int fd;
const char *sig = syncpkg ? syncpkg->base64_sig : NULL;
_alpm_log(handle, ALPM_LOG_DEBUG, "sig data: %s\n", sig ? sig : "<from .sig>");
- if(_alpm_check_pgp_helper(handle, pkgfile, sig,
+ OPEN(fd, pkgfile, O_RDONLY);
+ if(fd < 0) {
+ RET_ERR(handle, ALPM_ERR_PKG_OPEN, -1);
+ }
+ if(_alpm_check_pgp_helper(handle, fd, _alpm_sigpath(handle, pkgfile), sig,
level & ALPM_SIG_PACKAGE_OPTIONAL, level & ALPM_SIG_PACKAGE_MARGINAL_OK,
level & ALPM_SIG_PACKAGE_UNKNOWN_OK, sigdata)) {
handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG;
- return -1;
+ ret = -1;
+ } else {
+ ret = 0;
}
+ CLOSE(fd);
if(validation && has_sig) {
*validation |= ALPM_PKG_VALIDATION_SIGNATURE;
}
@@ -386,7 +396,7 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
*validation = ALPM_PKG_VALIDATION_NONE;
}
- return 0;
+ return ret;
}
/**
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 1a9cc892..7ddda745 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -98,7 +98,8 @@ static int sync_db_validate(alpm_db_t *db)
do {
retry = 0;
alpm_siglist_t *siglist;
- ret = _alpm_check_pgp_helper(db->handle, db->path, NULL,
+ ret = _alpm_check_pgp_helper(db->handle, db->fd,
+ _alpm_sigpath(db->handle, db->path), NULL,
level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK,
level & ALPM_SIG_DATABASE_UNKNOWN_OK, &siglist);
if(ret) {
diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index ccd0ebbd..204ed9c1 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -20,6 +20,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
#if HAVE_LIBGPGME
#include <locale.h> /* setlocale() */
@@ -401,8 +405,8 @@ error:
/**
* Check the PGP signature for the given file path.
* If base64_sig is provided, it will be used as the signature data after
- * decoding. If base64_sig is NULL, expect a signature file next to path
- * (e.g. "%s.sig").
+ * decoding. If base64_sig is NULL, sigpath is used if not NULL and is expected
+ * to be a full path to a detached signature (e.g. "%s.sig").
*
* The return value will be 0 if nothing abnormal happened during the signature
* check, and -1 if an error occurred while checking signatures or if a
@@ -410,12 +414,13 @@ error:
* does not include a failed signature; the value in siglist should be checked
* to determine if the signature(s) are good.
* @param handle the context handle
- * @param path the full path to a file
+ * @param fd an open file descriptor to the data to check
+ * @param sigpath optional full path to a detached signature file
* @param base64_sig optional PGP signature data in base64 encoding
* @param siglist a pointer to storage for signature results
* @return 0 in normal cases, -1 if the something failed in the check process
*/
-int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
+int _alpm_gpgme_checksig(alpm_handle_t *handle, int fd, const char *sigpath,
const char *base64_sig, alpm_siglist_t *siglist)
{
int ret = -1, sigcount;
@@ -424,21 +429,19 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
gpgme_data_t filedata, sigdata;
gpgme_verify_result_t verify_result;
gpgme_signature_t gpgsig;
- char *sigpath = NULL;
unsigned char *decoded_sigdata = NULL;
- FILE *file = NULL, *sigfile = NULL;
+ FILE *sigfile = NULL;
- if(!path || _alpm_access(handle, NULL, path, R_OK) != 0) {
+ if(fd < 0) {
RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1);
}
- if(!siglist) {
+ if(!siglist || (!base64_sig && !sigpath)) {
RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
}
siglist->count = 0;
if(!base64_sig) {
- sigpath = _alpm_sigpath(handle, path);
if(_alpm_access(handle, NULL, sigpath, R_OK) != 0
|| (sigfile = fopen(sigpath, "rb")) == NULL) {
_alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n",
@@ -448,19 +451,12 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
}
}
- /* does the file we are verifying exist? */
- file = fopen(path, "rb");
- if(file == NULL) {
- handle->pm_errno = ALPM_ERR_NOT_A_FILE;
- goto error;
- }
-
if(init_gpgme(handle)) {
/* pm_errno was set in gpgme_init() */
goto error;
}
- _alpm_log(handle, ALPM_LOG_DEBUG, "checking signature for %s\n", path);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "checking signature\n");
memset(&ctx, 0, sizeof(ctx));
memset(&sigdata, 0, sizeof(sigdata));
@@ -470,7 +466,8 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
CHECK_ERR();
/* create our necessary data objects to verify the signature */
- err = gpgme_data_new_from_stream(&filedata, file);
+ lseek(fd, 0, SEEK_SET);
+ err = gpgme_data_new_from_fd(&filedata, fd);
CHECK_ERR();
/* next create data object for the signature */
@@ -613,10 +610,6 @@ error:
if(sigfile) {
fclose(sigfile);
}
- if(file) {
- fclose(file);
- }
- FREE(sigpath);
FREE(decoded_sigdata);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR) {
_alpm_log(handle, ALPM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err));
@@ -630,8 +623,9 @@ static int key_in_keychain(alpm_handle_t UNUSED *handle, const char UNUSED *fpr)
{
return -1;
}
-int _alpm_gpgme_checksig(alpm_handle_t UNUSED *handle, const char UNUSED *path,
- const char UNUSED *base64_sig, alpm_siglist_t UNUSED *siglist)
+int _alpm_gpgme_checksig(alpm_handle_t UNUSED *handle, int UNUSED fd,
+ const char UNUSED *sigpath, const char UNUSED *base64_sig,
+ alpm_siglist_t UNUSED *siglist)
{
return -1;
}
@@ -659,12 +653,13 @@ char *_alpm_sigpath(alpm_handle_t *handle, const char *path)
}
/**
- * Helper for checking the PGP signature for the given file path.
+ * Helper for checking the PGP signature for the given file.
* This wraps #_alpm_gpgme_checksig in a slightly friendlier manner to simplify
* handling of optional signatures and marginal/unknown trust levels and
* handling the correct error code return values.
* @param handle the context handle
- * @param path the full path to a file
+ * @param fd an open file descriptor to the data to check
+ * @param sigpath optional full path to a detached signature file
* @param base64_sig optional PGP signature data in base64 encoding
* @param optional whether signatures are optional (e.g., missing OK)
* @param marginal whether signatures with marginal trust are acceptable
@@ -672,7 +667,7 @@ char *_alpm_sigpath(alpm_handle_t *handle, const char *path)
* @param sigdata a pointer to storage for signature results
* @return 0 on success, -1 on error (consult pm_errno or sigdata)
*/
-int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path,
+int _alpm_check_pgp_helper(alpm_handle_t *handle, int fd, const char *sigpath,
const char *base64_sig, int optional, int marginal, int unknown,
alpm_siglist_t **sigdata)
{
@@ -682,7 +677,7 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path,
CALLOC(siglist, 1, sizeof(alpm_siglist_t),
RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- ret = _alpm_gpgme_checksig(handle, path, base64_sig, siglist);
+ ret = _alpm_gpgme_checksig(handle, fd, sigpath, base64_sig, siglist);
if(ret && handle->pm_errno == ALPM_ERR_SIG_MISSING) {
if(optional) {
_alpm_log(handle, ALPM_LOG_DEBUG, "missing optional signature\n");
@@ -872,12 +867,20 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg,
alpm_siglist_t *siglist)
{
+ int fd, ret;
+
ASSERT(pkg != NULL, return -1);
ASSERT(siglist != NULL, RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
pkg->handle->pm_errno = 0;
- return _alpm_gpgme_checksig(pkg->handle, pkg->filename,
- pkg->base64_sig, siglist);
+ OPEN(fd, pkg->filename, O_RDONLY);
+ if(fd < 0) {
+ RET_ERR(pkg->handle, ALPM_ERR_PKG_OPEN, -1);
+ }
+ ret = _alpm_gpgme_checksig(pkg->handle, fd,
+ _alpm_sigpath(pkg->handle, pkg->filename), pkg->base64_sig, siglist);
+ CLOSE(fd);
+ return ret;
}
/**
@@ -893,7 +896,8 @@ int SYMEXPORT alpm_db_check_pgp_signature(alpm_db_t *db,
ASSERT(siglist != NULL, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1));
db->handle->pm_errno = 0;
- return _alpm_gpgme_checksig(db->handle, db->path, NULL, siglist);
+ return _alpm_gpgme_checksig(db->handle, db->fd,
+ _alpm_sigpath(db->handle, db->path), NULL, siglist);
}
/**
diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h
index 19ffef27..36ff0b25 100644
--- a/lib/libalpm/signing.h
+++ b/lib/libalpm/signing.h
@@ -22,10 +22,10 @@
#include "alpm.h"
char *_alpm_sigpath(alpm_handle_t *handle, const char *path);
-int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
- const char *base64_sig, alpm_siglist_t *result);
+int _alpm_gpgme_checksig(alpm_handle_t *handle, int fd, const char *sigpath,
+ const char *base64_sig, alpm_siglist_t *siglist);
-int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path,
+int _alpm_check_pgp_helper(alpm_handle_t *handle, int fd, const char *sigpath,
const char *base64_sig, int optional, int marginal, int unknown,
alpm_siglist_t **sigdata);
int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,