diff --git a/package/pkg-download.mk b/package/pkg-download.mk index c021e92db..ba72fc1f0 100644 --- a/package/pkg-download.mk +++ b/package/pkg-download.mk @@ -60,17 +60,6 @@ domainseparator = $(if $(1),$(1),/) # github(user,package,version): returns site of GitHub repository github = https://github.com/$(1)/$(2)/archive/$(3) -# Helper for checking a tarball's checksum -# If the hash does not match, remove the incorrect file -# $(1): the path to the file with the hashes -# $(2): the full path to the file to check -define VERIFY_HASH - if ! support/download/check-hash $(1) $(2) $(if $(QUIET),>/dev/null); then \ - rm -f $(2); \ - exit 1; \ - fi -endef - ################################################################################ # The DOWNLOAD_* helpers are in charge of getting a working copy # of the source repository for their corresponding SCM, @@ -98,6 +87,7 @@ endef define DOWNLOAD_GIT $(EXTRA_ENV) $(DL_WRAPPER) -b git \ -o $(DL_DIR)/$($(PKG)_SOURCE) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ $($(PKG)_SITE) \ $($(PKG)_DL_VERSION) \ @@ -118,6 +108,7 @@ endef define DOWNLOAD_BZR $(EXTRA_ENV) $(DL_WRAPPER) -b bzr \ -o $(DL_DIR)/$($(PKG)_SOURCE) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ $($(PKG)_SITE) \ $($(PKG)_DL_VERSION) \ @@ -135,6 +126,7 @@ endef define DOWNLOAD_CVS $(EXTRA_ENV) $(DL_WRAPPER) -b cvs \ -o $(DL_DIR)/$($(PKG)_SOURCE) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ $(call stripurischeme,$(call qstrip,$($(PKG)_SITE))) \ $($(PKG)_DL_VERSION) \ @@ -154,6 +146,7 @@ endef define DOWNLOAD_SVN $(EXTRA_ENV) $(DL_WRAPPER) -b svn \ -o $(DL_DIR)/$($(PKG)_SOURCE) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ $($(PKG)_SITE) \ $($(PKG)_DL_VERSION) \ @@ -174,9 +167,9 @@ endef define DOWNLOAD_SCP $(EXTRA_ENV) $(DL_WRAPPER) -b scp \ -o $(DL_DIR)/$(2) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ - '$(call stripurischeme,$(call qstrip,$(1)))' && \ - $(call VERIFY_HASH,$(PKGDIR)/$($(PKG)_RAWNAME).hash,$(DL_DIR)/$(2)) + '$(call stripurischeme,$(call qstrip,$(1)))' endef define SOURCE_CHECK_SCP @@ -191,6 +184,7 @@ endef define DOWNLOAD_HG $(EXTRA_ENV) $(DL_WRAPPER) -b hg \ -o $(DL_DIR)/$($(PKG)_SOURCE) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ $($(PKG)_SITE) \ $($(PKG)_DL_VERSION) \ @@ -211,9 +205,9 @@ endef define DOWNLOAD_WGET $(EXTRA_ENV) $(DL_WRAPPER) -b wget \ -o $(DL_DIR)/$(2) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ - '$(call qstrip,$(1))' && \ - $(call VERIFY_HASH,$(PKGDIR)/$($(PKG)_RAWNAME).hash,$(DL_DIR)/$(2)) + '$(call qstrip,$(1))' endef define SOURCE_CHECK_WGET @@ -227,9 +221,9 @@ endef define DOWNLOAD_LOCALFILES $(EXTRA_ENV) $(DL_WRAPPER) -b cp \ -o $(DL_DIR)/$(2) \ + -H $(PKGDIR)/$($(PKG)_RAWNAME).hash \ -- \ - $(call stripurischeme,$(call qstrip,$(1))) && \ - $(call VERIFY_HASH,$(PKGDIR)/$($(PKG)_RAWNAME).hash,$(DL_DIR)/$(2)) + $(call stripurischeme,$(call qstrip,$(1))) endef define SOURCE_CHECK_LOCALFILES diff --git a/support/download/check-hash b/support/download/check-hash index 13e361afc..b59fd2a22 100755 --- a/support/download/check-hash +++ b/support/download/check-hash @@ -4,10 +4,15 @@ set -e # Helper to check a file matches its known hash # Call it with: # $1: the path of the file containing all the the expected hashes -# $2: the full path to the file to check +# $2: the full path to the temporary file that was downloaded, and +# that is to be checked +# $3: the final basename of the file, to which it will be ultimately +# saved as, to be able to match it to the corresponding hashes +# in the .hash file h_file="${1}" file="${2}" +base="${3}" # Does the hash-file exist? if [ ! -f "${h_file}" ]; then @@ -30,7 +35,7 @@ check_one_hash() { sha224|sha256|sha384|sha512) ;; *) # Unknown hash, exit with error printf "ERROR: unknown hash '%s' for '%s'\n" \ - "${_h}" "${_file##*/}" >&2 + "${_h}" "${base}" >&2 exit 1 ;; esac @@ -38,11 +43,11 @@ check_one_hash() { # Do the hashes match? _hash=$( ${_h}sum "${_file}" |cut -d ' ' -f 1 ) if [ "${_hash}" = "${_known}" ]; then - printf "%s: OK (%s: %s)\n" "${_file##*/}" "${_h}" "${_hash}" + printf "%s: OK (%s: %s)\n" "${base}" "${_h}" "${_hash}" return 0 fi - printf "ERROR: %s has wrong %s hash:\n" "${_file##*/}" "${_h}" >&2 + printf "ERROR: %s has wrong %s hash:\n" "${base}" "${_h}" >&2 printf "ERROR: expected: %s\n" "${_known}" >&2 printf "ERROR: got : %s\n" "${_hash}" >&2 printf "ERROR: Incomplete download, or man-in-the-middle (MITM) attack\n" >&2 @@ -59,7 +64,7 @@ while read t h f; do continue ;; *) - if [ "${f}" = "${file##*/}" ]; then + if [ "${f}" = "${base}" ]; then check_one_hash "${t}" "${h}" "${file}" : $((nb_checks++)) fi @@ -69,9 +74,9 @@ done <"${h_file}" if [ ${nb_checks} -eq 0 ]; then if [ -n "${BR2_ENFORCE_CHECK_HASH}" ]; then - printf "ERROR: No hash found for %s\n" "${file}" >&2 + printf "ERROR: No hash found for %s\n" "${base}" >&2 exit 1 else - printf "WARNING: No hash found for %s\n" "${file}" >&2 + printf "WARNING: No hash found for %s\n" "${base}" >&2 fi fi diff --git a/support/download/dl-wrapper b/support/download/dl-wrapper index dc5b4b08d..f0cdd735b 100755 --- a/support/download/dl-wrapper +++ b/support/download/dl-wrapper @@ -21,14 +21,15 @@ set -e main() { local OPT OPTARG - local backend output + local backend output hfile # Parse our options; anything after '--' is for the backend - while getopts :hb:o: OPT; do + while getopts :hb:o:H: OPT; do case "${OPT}" in h) help; exit 0;; b) backend="${OPTARG}";; o) output="${OPTARG}";; + H) hfile="${OPTARG}";; :) error "option '%s' expects a mandatory argument\n" "${OPTARG}";; \?) error "unknown option '%s'\n" "${OPTARG}";; esac @@ -42,6 +43,9 @@ main() { if [ -z "${output}" ]; then error "no output specified, use -o\n" fi + if [ -z "${hfile}" ]; then + error "no hash-file specified, use -H\n" + fi # If the output file already exists, do not download it again if [ -e "${output}" ]; then @@ -75,6 +79,13 @@ main() { # cd back to free the temp-dir, so we can remove it later cd "${OLDPWD}" + # Check if the downloaded file is sane, and matches the stored hashes + # for that file + if ! support/download/check-hash "${hfile}" "${tmpf}" "${output##*/}"; then + rm -rf "${tmpd}" + exit 1 + fi + # tmp_output is in the same directory as the final output, so we can # later move it atomically. tmp_output="$(mktemp "${output}.XXXXXX")" @@ -150,6 +161,10 @@ DESCRIPTION -o FILE Store the downloaded archive in FILE. + -H FILE + Use FILE to read hashes from, and check them against the downloaded + archive. + Exit status: 0 if OK !0 in case of error