pacman: add file checksum validation against mtree

With libarchive v3.5.0 we have API to fetch the digest from the mtree.
Use that to validate if the installed files are modified or not.

As always, a modified backup file will trigger a warning but will not
result in an actual failure.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
Emil Velikov 2021-01-05 00:56:22 +00:00 committed by Allan McRae
parent 3f5125e47c
commit 8f7415c41b

View file

@ -176,19 +176,78 @@ static int check_file_size(const char *pkgname, const char *filepath,
return 0; return 0;
} }
/* placeholders - libarchive currently does not read checksums from mtree files #if ARCHIVE_VERSION_NUMBER >= 3005000
static int check_file_md5sum(const char *pkgname, const char *filepath, static int check_file_cksum(const char *pkgname, const char *filepath,
struct stat *st, struct archive_entry *entry, int backup) int backup, const char *cksum_name, const char *cksum_calc, const char *cksum_mtree)
{ {
if(!cksum_calc) {
if(!config->quiet) {
pm_printf(ALPM_LOG_WARNING, _("%s: %s (failed to calculate %s checksum)\n"),
pkgname, filepath, cksum_name);
}
return 1;
}
if(!cksum_mtree) {
if(!config->quiet) {
pm_printf(ALPM_LOG_WARNING, _("%s: %s (%s checksum information not available)\n"),
pkgname, filepath, cksum_name);
}
return 1;
}
if(strcmp(cksum_calc, cksum_mtree) != 0) {
if(backup) {
if(!config->quiet) {
printf("%s%s%s: ", config->colstr.title, _("backup file"),
config->colstr.nocolor);
printf(_("%s: %s (%s checksum mismatch)\n"),
pkgname, filepath, cksum_name);
}
return 0;
}
if(!config->quiet) {
pm_printf(ALPM_LOG_WARNING, _("%s: %s (%s checksum mismatch)\n"),
pkgname, filepath, cksum_name);
}
return 1;
}
return 0; return 0;
} }
#endif
static int check_file_md5sum(const char *pkgname, const char *filepath,
struct archive_entry *entry, int backup)
{
int errors = 0;
#if ARCHIVE_VERSION_NUMBER >= 3005000
char *cksum_calc = alpm_compute_md5sum(filepath);
char *cksum_mtree = hex_representation(archive_entry_digest(entry,
ARCHIVE_ENTRY_DIGEST_MD5), 16);
errors = check_file_cksum(pkgname, filepath, backup, "MD5", cksum_calc,
cksum_mtree);
free(cksum_mtree);
free(cksum_calc);
#endif
return (errors != 0 ? 1 : 0);
}
static int check_file_sha256sum(const char *pkgname, const char *filepath, static int check_file_sha256sum(const char *pkgname, const char *filepath,
struct stat *st, struct archive_entry *entry, int backup) struct archive_entry *entry, int backup)
{ {
return 0; int errors = 0;
#if ARCHIVE_VERSION_NUMBER >= 3005000
char *cksum_calc = alpm_compute_sha256sum(filepath);
char *cksum_mtree = hex_representation(archive_entry_digest(entry,
ARCHIVE_ENTRY_DIGEST_SHA256), 32);
errors = check_file_cksum(pkgname, filepath, backup, "SHA256", cksum_calc,
cksum_mtree);
free(cksum_mtree);
free(cksum_calc);
#endif
return (errors != 0 ? 1 : 0);
} }
*/
/* Loop through the files of the package to check if they exist. */ /* Loop through the files of the package to check if they exist. */
int check_pkg_fast(alpm_pkg_t *pkg) int check_pkg_fast(alpm_pkg_t *pkg)
@ -369,7 +428,8 @@ int check_pkg_full(alpm_pkg_t *pkg)
if(type == AE_IFREG) { if(type == AE_IFREG) {
file_errors += check_file_size(pkgname, filepath, &st, entry, backup); file_errors += check_file_size(pkgname, filepath, &st, entry, backup);
/* file_errors += check_file_md5sum(pkgname, filepath, &st, entry, backup); */ file_errors += check_file_md5sum(pkgname, filepath, entry, backup);
file_errors += check_file_sha256sum(pkgname, filepath, entry, backup);
} }
if(config->quiet && file_errors) { if(config->quiet && file_errors) {