123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- #!/usr/bin/env bash
- set -e
- # Helper to check a file matches its known hash
- # Call it with:
- # $1: the path of the file containing all the expected hashes
- # $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
- #
- # Exit codes:
- # 0: the hash file exists and the file to check matches all its hashes,
- # or the hash file does not exist
- # 1: unknown command-line option
- # 2: the hash file exists and the file to check does not match at least
- # one of its hashes
- # 3: the hash file exists and there was no hash to check the file against
- # 4: the hash file exists and at least one hash type is unknown
- while getopts :q OPT; do
- case "${OPT}" in
- q) exec >/dev/null;;
- \?) exit 1;;
- esac
- done
- shift $((OPTIND-1))
- h_file="${1}"
- file="${2}"
- base="${3}"
- # Bail early if no hash to check
- if [ -z "${h_file}" ]; then
- exit 0
- fi
- # Does the hash-file exist?
- if [ ! -f "${h_file}" ]; then
- printf "WARNING: no hash file for %s\n" "${base}" >&2
- exit 0
- fi
- # Check one hash for a file
- # $1: algo hash
- # $2: known hash
- # $3: file (full path)
- check_one_hash() {
- _h="${1}"
- _known="${2}"
- _file="${3}"
- # Note: md5 is supported, but undocumented on purpose.
- # Note: sha3 is not supported, since there is currently no implementation
- # (the NIST has yet to publish the parameters).
- # Note: 'none' means there is explicitly no hash for that file.
- case "${_h}" in
- none)
- return 0
- ;;
- md5|sha1) ;;
- sha224|sha256|sha384|sha512) ;;
- *) # Unknown hash, exit with error
- printf "ERROR: unknown hash '%s' for '%s'\n" \
- "${_h}" "${base}" >&2
- exit 4
- ;;
- esac
- # Do the hashes match?
- _hash=$( ${_h}sum "${_file}" |cut -d ' ' -f 1 )
- if [ "${_hash}" = "${_known}" ]; then
- printf "%s: OK (%s: %s)\n" "${base}" "${_h}" "${_hash}"
- return 0
- fi
- 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
- exit 2
- }
- # Do we know one or more hashes for that file?
- nb_checks=0
- while read t h f; do
- case "${t}" in
- ''|'#'*)
- # Skip comments and empty lines
- continue
- ;;
- *)
- if [ "${f}" = "${base}" ]; then
- check_one_hash "${t}" "${h}" "${file}"
- : $((nb_checks++))
- fi
- ;;
- esac
- done <"${h_file}"
- if [ ${nb_checks} -eq 0 ]; then
- case " ${BR_NO_CHECK_HASH_FOR} " in
- *" ${base} "*)
- # File explicitly has no hash
- exit 0
- ;;
- esac
- printf "ERROR: No hash found for %s\n" "${base}" >&2
- exit 3
- fi
|