diff options
author | Dan McGee <dan@archlinux.org> | 2012-01-11 15:08:09 -0600 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2012-04-08 21:59:41 -0500 |
commit | fee55210c6e8ed9a686ea892c2d9783e6f158e18 (patch) | |
tree | aec19c0862bd9cbec7cf971c9dd519c0270a002c | |
parent | 51669a55ed854909172f3dba2f29c79ba1efb86a (diff) | |
download | pacman-fee55210c6e8ed9a686ea892c2d9783e6f158e18.tar.gz pacman-fee55210c6e8ed9a686ea892c2d9783e6f158e18.zip |
WIP: make signing take fd, not path
-rw-r--r-- | lib/libalpm/be_package.c | 18 | ||||
-rw-r--r-- | lib/libalpm/be_sync.c | 3 | ||||
-rw-r--r-- | lib/libalpm/signing.c | 66 | ||||
-rw-r--r-- | lib/libalpm/signing.h | 6 |
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, |