diff --git a/doc/TODO b/doc/TODO index fc84d1f0b30..1c042754ea2 100644 --- a/doc/TODO +++ b/doc/TODO @@ -16,10 +16,6 @@ xbps-bin: * Add support to handle conf_files and keep_dirs from package metadata. [PARTIALLY IMPLEMENTED] * Add support to install binary packages without any repository. - * Check SHA256 hash of pkg and dependencies before installing. - Currently the hash is checked before a pkg is unpacked, this is - suboptimal because if some pkg fails, previous packages will be - installed and therefore unusable. [IN PROGRESS] * Show binpkg size and installed size for all packages that are going to be installed before installation happens. * Add support to update packages. diff --git a/include/util.h b/include/util.h index 91615bdf2a4..626823d8233 100644 --- a/include/util.h +++ b/include/util.h @@ -29,6 +29,7 @@ /* From lib/util.c */ char * xbps_append_full_path(bool, const char *, const char *); int xbps_check_file_hash(const char *, const char *); +int xbps_check_pkg_file_hash(prop_dictionary_t, const char *); int xbps_check_is_installed_pkg(const char *); bool xbps_check_is_installed_pkgname(const char *); char * xbps_get_pkg_index_plist(const char *); diff --git a/lib/depends.c b/lib/depends.c index e3f586717bd..75f0f5af480 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -599,6 +599,7 @@ xbps_install_pkg_deps(const char *pkgname, const char *destdir, int flags) prop_array_t required, missing; prop_object_t obj; prop_object_iterator_t iter; + const char *repoloc; int rv = 0; /* @@ -623,11 +624,22 @@ xbps_install_pkg_deps(const char *pkgname, const char *destdir, int flags) if (required == NULL) return 0; - iter = prop_array_iterator(required); if (iter == NULL) return ENOMEM; + /* + * Check the SHA256 hash for any binary package that's going + * to be installed. + */ + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); + rv = xbps_check_pkg_file_hash(obj, repoloc); + if (rv != 0) + goto out; + } + prop_object_iterator_reset(iter); + /* * Install all required dependencies, previously sorted. */ @@ -636,6 +648,8 @@ xbps_install_pkg_deps(const char *pkgname, const char *destdir, int flags) if (rv != 0) break; } + +out: prop_object_iterator_release(iter); return rv; diff --git a/lib/install.c b/lib/install.c index 6ee6267e52e..40d62ab923b 100644 --- a/lib/install.c +++ b/lib/install.c @@ -111,6 +111,7 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) { prop_dictionary_t repod, pkgrd; struct cbargs *cb = arg; + const char *repoloc; char *plist; int rv = 0; @@ -139,6 +140,16 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) /* * Check SHA256 hash for binary package before anything else. */ + if (!prop_dictionary_get_cstring_nocopy(repod, "location-local", + &repoloc)) { + prop_object_release(repod); + return EINVAL; + } + + if ((rv = xbps_check_pkg_file_hash(pkgrd, repoloc)) != 0) { + prop_object_release(repod); + return rv; + } /* * Check if this package needs dependencies. diff --git a/lib/unpack.c b/lib/unpack.c index 6f3de82eb73..2997e224508 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -45,7 +45,6 @@ xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg, const char *destdir, int flags) { prop_string_t filename, repoloc, arch; - const char *sha256; char *binfile, *path; int rv = 0; @@ -54,7 +53,6 @@ xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg, /* Append filename to the full path for binary pkg */ filename = prop_dictionary_get(pkg, "filename"); arch = prop_dictionary_get(pkg, "architecture"); - prop_dictionary_get_cstring_nocopy(pkg, "filename-sha256", &sha256); if (repo) repoloc = prop_dictionary_get(repo, "location-local"); else @@ -74,13 +72,6 @@ xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg, } free(path); - if ((rv = xbps_check_file_hash(binfile, sha256)) == ERANGE) { - printf("ERROR: SHA256 doesn't match for %s!\n", - prop_string_cstring_nocopy(filename)); - free(binfile); - return rv; - } - rv = unpack_archive_init(pkg, destdir, binfile, flags); free(binfile); return rv; diff --git a/lib/util.c b/lib/util.c index 48d24a93610..d549a6756eb 100644 --- a/lib/util.c +++ b/lib/util.c @@ -61,6 +61,53 @@ xbps_check_file_hash(const char *path, const char *sha256) return rv; } +int +xbps_check_pkg_file_hash(prop_dictionary_t pkgd, const char *repoloc) +{ + const char *sha256, *arch, *filename; + char *binfile, *path; + int rv = 0; + + assert(repoloc != NULL); + + if (!prop_dictionary_get_cstring_nocopy(pkgd, "filename", &filename)) + return EINVAL; + + if (!prop_dictionary_get_cstring_nocopy(pkgd, "filename-sha256", + &sha256)) + return EINVAL; + + if (!prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch)) + return EINVAL; + + path = xbps_append_full_path(false, repoloc, arch); + if (path == NULL) + return EINVAL; + + binfile = xbps_append_full_path(false, path, filename); + if (binfile == NULL) { + free(path); + return EINVAL; + } + free(path); + + printf("Checking SHA256 for %s ... ", filename); + (void)fflush(stdout); + + rv = xbps_check_file_hash(binfile, sha256); + if (rv != 0 && rv != ERANGE) + printf("failed (%s)\n", strerror(rv)); + else if (rv == ERANGE) + printf("failed! aborting installation.\n"); + else if (rv == 0) + printf("ok.\n"); + + (void)fflush(stdout); + + free(binfile); + return rv; +} + int xbps_check_is_installed_pkg(const char *pkg) {