From 5c404268d965d9ca012e4819ac0c2f289a4c768c Mon Sep 17 00:00:00 2001 From: Allan McRae Date: Sat, 18 Feb 2012 16:31:37 +1000 Subject: Add information on how an installed package was validated 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. Dan: just a few very minor tweaks. Signed-off-by: Allan McRae Signed-off-by: Dan McGee --- lib/libalpm/alpm.h | 15 +++++++++++++++ lib/libalpm/be_local.c | 43 +++++++++++++++++++++++++++++++++++++++++++ lib/libalpm/be_package.c | 23 +++++++++++++++++++++-- lib/libalpm/package.c | 9 +++++++++ lib/libalpm/package.h | 4 +++- lib/libalpm/sync.c | 8 ++++++-- src/pacman/package.c | 26 ++++++++++++++++++++++++++ 7 files changed, 123 insertions(+), 5 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index a6b7c789..2e666294 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 = 0, + ALPM_PKG_VALIDATION_NONE = (1 << 0), + ALPM_PKG_VALIDATION_MD5SUM = (1 << 1), + ALPM_PKG_VALIDATION_SHA256SUM = (1 << 2), + ALPM_PKG_VALIDATION_SIGNATURE = (1 << 3) +} alpm_pkgvalidation_t; + /** Types of version constraints in dependency specs. */ typedef enum _alpm_depmod_t { /** No version constraint */ @@ -880,6 +889,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 0d423fa7..51721d1f 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,26 @@ 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) { + alpm_list_t *i, *v = NULL; + READ_AND_STORE_ALL(v); + for(i = v; i; i = alpm_list_next(i)) + { + if(strcmp(i->data, "none") == 0) { + info->validation |= ALPM_PKG_VALIDATION_NONE; + } else if(strcmp(i->data, "md5") == 0) { + info->validation |= ALPM_PKG_VALIDATION_MD5SUM; + } else if(strcmp(i->data, "sha256") == 0) { + info->validation |= ALPM_PKG_VALIDATION_SHA256SUM; + } else if(strcmp(i->data, "pgp") == 0) { + info->validation |= ALPM_PKG_VALIDATION_SIGNATURE; + } else { + _alpm_log(db->handle, ALPM_LOG_WARNING, + _("unknown validation type for package %s: %s\n"), + info->name, (const char *)i->data); + } + } + FREELIST(v); } else if(strcmp(line, "%SIZE%") == 0) { READ_NEXT(); info->isize = _alpm_strtoofft(line); @@ -817,6 +844,22 @@ 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) { + fputs("%VALIDATION%\n", fp); + if(info->validation & ALPM_PKG_VALIDATION_NONE) { + fputs("none\n", fp); + } + if(info->validation & ALPM_PKG_VALIDATION_MD5SUM) { + fputs("md5\n", fp); + } + if(info->validation & ALPM_PKG_VALIDATION_SHA256SUM) { + fputs("sha256\n", fp); + } + if(info->validation & ALPM_PKG_VALIDATION_SIGNATURE) { + fputs("pgp\n", fp); + } + fprintf(fp, "\n"); + } 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 c076f610..e4469600 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -303,11 +303,12 @@ static alpm_file_t *files_msort(alpm_file_t *files, size_t n) * sha256sum, and/or base64 signature) * @param level the required level of signature verification * @param sigdata signature data from the package to pass back + * @param validation successful validations performed on the package file * @return 0 if package is fully valid, -1 and pm_errno otherwise */ 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_siglist_t **sigdata, alpm_pkgvalidation_t *validation) { int has_sig; handle->pm_errno = 0; @@ -342,6 +343,9 @@ 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); } + if(validation) { + *validation |= ALPM_PKG_VALIDATION_MD5SUM; + } } if(syncpkg->sha256sum) { @@ -350,6 +354,9 @@ 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); } + if(validation) { + *validation |= ALPM_PKG_VALIDATION_SHA256SUM; + } } } @@ -363,6 +370,13 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle, handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG; return -1; } + if(validation && has_sig) { + *validation |= ALPM_PKG_VALIDATION_SIGNATURE; + } + } + + if (validation && !*validation) { + *validation = ALPM_PKG_VALIDATION_NONE; } return 0; @@ -496,6 +510,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) { @@ -527,10 +542,13 @@ error: int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full, alpm_siglevel_t level, alpm_pkg_t **pkg) { + alpm_pkgvalidation_t validation = 0; + CHECK_HANDLE(handle, return -1); ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL) == -1) { + if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL, + &validation) == -1) { /* pm_errno is set by pkg_validate */ return -1; } @@ -539,6 +557,7 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful /* pm_errno is set by pkg_load */ return -1; } + (*pkg)->validation = validation; return 0; } diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 5b075634..dbf0d928 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 ba0779a3..be779b46 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 @@ -133,7 +135,7 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg); 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_siglist_t **sigdata, alpm_pkgvalidation_t *validation); alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, int full); diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 7f4ef055..5f698008 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -972,6 +972,7 @@ static int check_validity(alpm_handle_t *handle, char *path; alpm_siglist_t *siglist; alpm_siglevel_t level; + alpm_pkgvalidation_t validation; alpm_errno_t error; }; size_t current = 0, current_bytes = 0; @@ -981,7 +982,7 @@ static int check_validity(alpm_handle_t *handle, EVENT(handle, ALPM_EVENT_INTEGRITY_START, NULL, NULL); for(i = handle->trans->add; i; i = i->next, current++) { - struct validity v = { i->data, NULL, NULL, 0, 0 }; + struct validity v = { i->data, NULL, NULL, 0, 0, 0 }; int percent = (int)(((double)current_bytes / total_bytes) * 100); PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", percent, @@ -995,7 +996,7 @@ static int check_validity(alpm_handle_t *handle, v.level = alpm_db_get_siglevel(alpm_pkg_get_db(v.pkg)); if(_alpm_pkg_validate_internal(handle, v.path, v.pkg, - v.level, &v.siglist) == -1) { + v.level, &v.siglist, &v.validation) == -1) { v.error = handle->pm_errno; struct validity *invalid = malloc(sizeof(struct validity)); memcpy(invalid, &v, sizeof(struct validity)); @@ -1004,6 +1005,7 @@ static int check_validity(alpm_handle_t *handle, alpm_siglist_cleanup(v.siglist); free(v.siglist); free(v.path); + v.pkg->validation = v.validation; } } @@ -1083,6 +1085,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 54c035c3..6e4901d1 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -77,6 +77,7 @@ static void optdeplist_display(const char *title, void dump_pkg_full(alpm_pkg_t *pkg, int extra) { const char *reason; + alpm_list_t *validation = NULL; time_t bdate, idate; char bdatestr[50] = "", idatestr[50] = ""; const char *label; @@ -108,6 +109,27 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) break; } + if(from == PKG_FROM_LOCALDB) { + alpm_pkgvalidation_t v = alpm_pkg_get_validation(pkg); + if(v) { + if(v & ALPM_PKG_VALIDATION_NONE) { + validation = alpm_list_add(validation, _("None")); + } else { + if(v & ALPM_PKG_VALIDATION_MD5SUM) { + validation = alpm_list_add(validation, _("MD5 Sum")); + } + if(v & ALPM_PKG_VALIDATION_SHA256SUM) { + validation = alpm_list_add(validation, _("SHA256 Sum")); + } + if(v & ALPM_PKG_VALIDATION_SIGNATURE) { + validation = alpm_list_add(validation, _("Signature")); + } + } + } else { + validation = alpm_list_add(validation, _("Unknown")); + } + } + 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); @@ -173,6 +195,9 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) } alpm_siglist_cleanup(&siglist); } + if(from == PKG_FROM_LOCALDB) { + list_display(_("Validated By :"), validation); + } string_display(_("Description :"), alpm_pkg_get_desc(pkg)); /* Print additional package info if info flag passed more than once */ @@ -184,6 +209,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) printf("\n"); FREELIST(requiredby); + alpm_list_free(validation); } static const char *get_backup_file_status(const char *root, -- cgit v1.2.3-70-g09d2