[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