[pacman-dev] [PATCH] Add information on how an installed package was validated
Dan McGee
dpmcgee at gmail.com
Sun Feb 19 17:49:21 EST 2012
On Sat, Feb 18, 2012 at 12:42 AM, Allan McRae <allan at archlinux.org> wrote:
> When installing a package, store information on which validation
> method was used and output this on "pacman -Qi" operations.
>
> e.g.
> Validated By : SHA256 Sum
>
> Possible values are Unknown, None, MD5 Sum, SHA256 Sum, Signature.
>
> Signed-off-by: Allan McRae <allan at archlinux.org>
> ---
>
> The only thing I am concerned about is setting the validation level for
> "pacman -U" operations. During the actual validation step we do not have
> the package struct yet so there is nowhere to store whether or not a
> signature is checked. If there is a .sig file present after loading the
> package (which occurs immediately after signature verification), it is
> just assumed that the .sig file was checked.
>
> lib/libalpm/alpm.h | 15 +++++++++++++++
> lib/libalpm/be_local.c | 14 ++++++++++++++
> lib/libalpm/be_package.c | 17 +++++++++++++++++
> lib/libalpm/package.c | 9 +++++++++
> lib/libalpm/package.h | 2 ++
> lib/libalpm/sync.c | 2 ++
> src/pacman/package.c | 24 ++++++++++++++++++++++++
> 7 files changed, 83 insertions(+), 0 deletions(-)
>
> diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
> index aeb1bb7..eafe931 100644
> --- a/lib/libalpm/alpm.h
> +++ b/lib/libalpm/alpm.h
> @@ -64,6 +64,15 @@ typedef enum _alpm_pkgfrom_t {
> PKG_FROM_SYNCDB
> } alpm_pkgfrom_t;
>
> +/** Location a package object was loaded from. */
> +typedef enum _alpm_pkgvalidation_t {
> + ALPM_PKG_VALIDATION_UNKNOWN,
> + ALPM_PKG_VALIDATION_NONE,
> + ALPM_PKG_VALIDATION_MD5SUM,
> + ALPM_PKG_VALIDATION_SHA256SUM,
> + ALPM_PKG_VALIDATION_SIGNATURE
> +} alpm_pkgvalidation_t;
It might be smart to make these bitmask values- that way, you could
store the fact that we checked both a signature and an MD5 sum, for
instance. We don't do this now but seems trivial to allow that to be
stored. (See enum _alpm_loglevel_t for an example).
> +
> /** Types of version constraints in dependency specs. */
> typedef enum _alpm_depmod_t {
> /** No version constraint */
> @@ -879,6 +888,12 @@ alpm_db_t *alpm_pkg_get_db(alpm_pkg_t *pkg);
> */
> const char *alpm_pkg_get_base64_sig(alpm_pkg_t *pkg);
>
> +/** Returns the method used to validate a package during install.
> + * @param pkg a pointer to package
> + * @return an enum member giving the validation method
> + */
> +alpm_pkgvalidation_t alpm_pkg_get_validation(alpm_pkg_t *pkg);
> +
> /* End of alpm_pkg_t accessors */
> /* @} */
>
> diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
> index 9a8c0ec..40b273d 100644
> --- a/lib/libalpm/be_local.c
> +++ b/lib/libalpm/be_local.c
> @@ -102,6 +102,12 @@ static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg)
> return pkg->reason;
> }
>
> +static alpm_pkgvalidation_t _cache_get_validation(alpm_pkg_t *pkg)
> +{
> + LAZY_LOAD(INFRQ_DESC, -1);
> + return pkg->validation;
> +}
> +
> static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg)
> {
> LAZY_LOAD(INFRQ_DESC, NULL);
> @@ -223,6 +229,7 @@ static struct pkg_operations local_pkg_ops = {
> .get_arch = _cache_get_arch,
> .get_isize = _cache_get_isize,
> .get_reason = _cache_get_reason,
> + .get_validation = _cache_get_validation,
> .has_scriptlet = _cache_has_scriptlet,
> .get_licenses = _cache_get_licenses,
> .get_groups = _cache_get_groups,
> @@ -603,6 +610,9 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
> } else if(strcmp(line, "%REASON%") == 0) {
> READ_NEXT();
> info->reason = (alpm_pkgreason_t)atoi(line);
> + } else if(strcmp(line, "%VALIDATION%") == 0) {
> + READ_NEXT();
> + info->validation = (alpm_pkgvalidation_t)atoi(line);
> } else if(strcmp(line, "%SIZE%") == 0) {
> READ_NEXT();
> info->isize = _alpm_strtoofft(line);
> @@ -817,6 +827,10 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
> fprintf(fp, "%%REASON%%\n"
> "%u\n\n", info->reason);
> }
> + if(info->validation) {
> + fprintf(fp, "%%VALIDATION%%\n"
> + "%u\n\n", info->validation);
> + }
> if(info->depends) {
> fputs("%DEPENDS%\n", fp);
> for(lp = info->depends; lp; lp = lp->next) {
> diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
> index 4b43f21..06b4037 100644
> --- a/lib/libalpm/be_package.c
> +++ b/lib/libalpm/be_package.c
> @@ -320,6 +320,10 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
> RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, -1);
> }
>
> + if (syncpkg) {
> + syncpkg->validation = ALPM_PKG_VALIDATION_NONE;
> + }
> +
> /* can we get away with skipping checksums? */
> has_sig = 0;
> if(level & ALPM_SIG_PACKAGE) {
> @@ -341,6 +345,7 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
> if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_CSUM_MD5) != 0) {
> RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1);
> }
> + syncpkg->validation = ALPM_PKG_VALIDATION_MD5SUM;
Mentioned this to you on IRC, but unifying the ALPM_CSUM_* enum and
your new one would be a great idea.
> }
>
> if(syncpkg->sha256sum) {
> @@ -349,6 +354,7 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
> if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_CSUM_SHA256) != 0) {
> RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1);
> }
> + syncpkg->validation = ALPM_PKG_VALIDATION_SHA256SUM;
> }
> }
>
> @@ -362,6 +368,9 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
> handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG;
> return -1;
> }
> + if (syncpkg) {
> + syncpkg->validation = ALPM_PKG_VALIDATION_SIGNATURE;
> + }
> }
>
> return 0;
> @@ -495,6 +504,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
> newpkg->ops = get_file_pkg_ops();
> newpkg->handle = handle;
> newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_SCRIPTLET;
> + newpkg->validation = ALPM_PKG_VALIDATION_NONE;
>
> if(full) {
> if(files) {
> @@ -539,6 +549,13 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful
> return -1;
> }
>
> + char *sigpath = _alpm_sigpath(handle, filename);
> + if(sigpath && !_alpm_access(handle, NULL, sigpath, R_OK)) {
> + /* package validation was done with a signature */
> + (*pkg)->validation = ALPM_PKG_VALIDATION_SIGNATURE;
> + }
> + free(sigpath);
> +
> return 0;
> }
>
> diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
> index 68fec16..5abfd72 100644
> --- a/lib/libalpm/package.c
> +++ b/lib/libalpm/package.c
> @@ -91,6 +91,7 @@ static const char *_pkg_get_packager(alpm_pkg_t *pkg) { return pkg->packager;
> static const char *_pkg_get_arch(alpm_pkg_t *pkg) { return pkg->arch; }
> static off_t _pkg_get_isize(alpm_pkg_t *pkg) { return pkg->isize; }
> static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; }
> +static alpm_pkgvalidation_t _pkg_get_validation(alpm_pkg_t *pkg) { return pkg->validation; }
> static int _pkg_has_scriptlet(alpm_pkg_t *pkg) { return pkg->scriptlet; }
>
> static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg) { return pkg->licenses; }
> @@ -134,6 +135,7 @@ struct pkg_operations default_pkg_ops = {
> .get_arch = _pkg_get_arch,
> .get_isize = _pkg_get_isize,
> .get_reason = _pkg_get_reason,
> + .get_validation = _pkg_get_validation,
> .has_scriptlet = _pkg_has_scriptlet,
>
> .get_licenses = _pkg_get_licenses,
> @@ -268,6 +270,13 @@ alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg)
> return pkg->ops->get_reason(pkg);
> }
>
> +alpm_pkgvalidation_t SYMEXPORT alpm_pkg_get_validation(alpm_pkg_t *pkg)
> +{
> + ASSERT(pkg != NULL, return -1);
> + pkg->handle->pm_errno = 0;
> + return pkg->ops->get_validation(pkg);
> +}
> +
> alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg)
> {
> ASSERT(pkg != NULL, return NULL);
> diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
> index 172d2f3..0c0973e 100644
> --- a/lib/libalpm/package.h
> +++ b/lib/libalpm/package.h
> @@ -47,6 +47,7 @@ struct pkg_operations {
> const char *(*get_arch) (alpm_pkg_t *);
> off_t (*get_isize) (alpm_pkg_t *);
> alpm_pkgreason_t (*get_reason) (alpm_pkg_t *);
> + alpm_pkgvalidation_t (*get_validation) (alpm_pkg_t *);
> int (*has_scriptlet) (alpm_pkg_t *);
>
> alpm_list_t *(*get_licenses) (alpm_pkg_t *);
> @@ -96,6 +97,7 @@ struct __alpm_pkg_t {
> int scriptlet;
>
> alpm_pkgreason_t reason;
> + alpm_pkgvalidation_t validation;
> alpm_dbinfrq_t infolevel;
> alpm_pkgfrom_t origin;
> /* origin == PKG_FROM_FILE, use pkg->origin_data.file
> diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
> index 468438f..68630c1 100644
> --- a/lib/libalpm/sync.c
> +++ b/lib/libalpm/sync.c
> @@ -1083,6 +1083,8 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data,
> free(filepath);
> /* copy over the install reason */
> pkgfile->reason = spkg->reason;
> + /* copy over validation method */
> + pkgfile->validation = spkg->validation;
> i->data = pkgfile;
> /* spkg has been removed from the target list, so we can free the
> * sync-specific fields */
> diff --git a/src/pacman/package.c b/src/pacman/package.c
> index ecf5745..2345d30 100644
> --- a/src/pacman/package.c
> +++ b/src/pacman/package.c
> @@ -63,6 +63,7 @@ static void deplist_display(const char *title,
> void dump_pkg_full(alpm_pkg_t *pkg, int extra)
> {
> const char *reason;
> + const char *validation = NULL;
> time_t bdate, idate;
> char bdatestr[50] = "", idatestr[50] = "";
> const char *label;
> @@ -94,6 +95,26 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra)
> break;
> }
>
> + if(from == PKG_FROM_LOCALDB) {
> + switch(alpm_pkg_get_validation(pkg)) {
What is the return code of this method for sync packages? I'm
wondering if you should leave it unprotected like the reason stuff
already is; even if we don't end up displaying it, it isn't that
expensive to do.
Additionally, it might make sense to use this same method to simplify
our -Si display. Current:
$ pacman -Si pacman
Repository : core
Name : pacman
...
Build Date : Sat 11 Feb 2012 03:36:23 PM CST
MD5 Sum : 1999200ccee8d823118ebbe61ce48c58
SHA256 Sum :
0a7d4e439ea565de41aadaaf75ea8752722fdfa3d147686f6aa080857fabdd3a
Signatures : Yes
Description : A library-based package manager with dependency support
Proposed:
$ pacman -Si pacman
Repository : core
Name : pacman
...
Build Date : Sat 11 Feb 2012 03:36:23 PM CST
Validated By : MD5 Checksum, SHA256 Checksum, PGP Signature
Description : A library-based package manager with dependency support
> + case ALPM_PKG_VALIDATION_NONE:
> + validation = _("None");
> + break;
> + case ALPM_PKG_VALIDATION_MD5SUM:
> + validation = _("MD5 Sum");
> + break;
> + case ALPM_PKG_VALIDATION_SHA256SUM:
> + validation = _("SHA256 Sum");
> + break;
> + case ALPM_PKG_VALIDATION_SIGNATURE:
> + validation = _("Signature");
> + break;
> + default:
> + validation = _("Unknown");
> + break;
> + }
> + }
> +
> if(extra || from == PKG_FROM_LOCALDB) {
> /* compute this here so we don't get a pause in the middle of output */
> requiredby = alpm_pkg_compute_requiredby(pkg);
> @@ -159,6 +180,9 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra)
> }
> alpm_siglist_cleanup(&siglist);
> }
> + if(from == PKG_FROM_LOCALDB) {
> + string_display(_("Validated By :"), validation);
> + }
> string_display(_("Description :"), alpm_pkg_get_desc(pkg));
>
> /* Print additional package info if info flag passed more than once */
> --
> 1.7.9.1
>
>
More information about the pacman-dev
mailing list