Commit fb5e2b1a authored by Thomas Johansen's avatar Thomas Johansen Committed by Mislav Marohnić
Browse files

Replace MD5 commands with SHA2 equivalents

A more secure hashing algorithm makes it less feasible to serve up a
modified tarball that matches the same checksum.

See the discussion in #548
parent 846cad88
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -166,14 +166,31 @@ make_package() {
  popd >&4
}

compute_sha2() {
  local output
  if type shasum &>/dev/null; then
    output="$(shasum -a 256 -b)" || return 1
    echo "${output% *}"
  elif type openssl &>/dev/null; then
    output="$(openssl dgst -sha256)" || return 1
    echo "${output##* }"
  elif type sha256sum &>/dev/null; then
    output="$(sha256sum --quiet)" || return 1
    echo "${output% *}"
  else
    return 1
  fi
}

compute_md5() {
  local output
  if type md5 &>/dev/null; then
    md5 -q
  elif type openssl &>/dev/null; then
    local output="$(openssl md5)"
    output="$(openssl md5)" || return 1
    echo "${output##* }"
  elif type md5sum &>/dev/null; then
    local output="$(md5sum -b)"
    output="$(md5sum -b)" || return 1
    echo "${output% *}"
  else
    return 1
@@ -181,8 +198,8 @@ compute_md5() {
}

verify_checksum() {
  # If there's no MD5 support, return success
  [ -n "$HAS_MD5_SUPPORT" ] || return 0
  # If there's no SHA2 support, return success
  [ -n "$HAS_SHA2_SUPPORT" ] || return 0

  # If the specified filename doesn't exist, return success
  local filename="$1"
@@ -193,7 +210,7 @@ verify_checksum() {
  [ -n "$expected_checksum" ] || return 0

  # If the computed checksum is empty, return failure
  local computed_checksum=`echo "$(compute_md5 < "$filename")" | tr [A-Z] [a-z]`
  local computed_checksum=`echo "$(compute_sha2 < "$filename")" | tr [A-Z] [a-z]`
  [ -n "$computed_checksum" ] || return 1

  if [ "$expected_checksum" != "$computed_checksum" ]; then
@@ -983,10 +1000,10 @@ if [ -n "$RUBY_BUILD_SKIP_MIRROR" ]; then
  unset RUBY_BUILD_MIRROR_URL
fi

if echo test | compute_md5 >/dev/null; then
  HAS_MD5_SUPPORT=1
if echo test | compute_sha2 >/dev/null; then
  HAS_SHA2_SUPPORT=1
else
  unset HAS_MD5_SUPPORT
  unset HAS_SHA2_SUPPORT
  unset RUBY_BUILD_MIRROR_URL
fi

+3 −3
Original line number Diff line number Diff line
@@ -11,8 +11,8 @@ test_mirrored() {
  curl -qsSfIL "$RUBY_BUILD_MIRROR_URL/$1" >/dev/null 2>&1
}

compute_md5() {
  local output="$(openssl md5)"
compute_sha2() {
  local output="$(openssl dgst -sha256)"
  echo "${output##* }" | tr '[A-Z]' '[a-z]'
}

@@ -26,7 +26,7 @@ download_and_verify() {
  local file="$2"
  local expected="$3"
  download_package "$url" "$file"
  checksum="$(compute_md5 < "$file")"
  checksum="$(compute_sha2 < "$file")"
  if [ "$checksum" != "$expected" ]; then
    echo "Error: $url doesn't match its checksum $expected" >&2
    return 1
+11 −11
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ setup() {


@test "packages are saved to download cache" {
  stub md5 true
  stub shasum true
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  install_fixture definitions/without-checksum
@@ -18,12 +18,12 @@ setup() {
  [ -e "${RUBY_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "cached package without checksum" {
  stub md5 true
  stub shasum true
  stub curl

  cp "${FIXTURE_ROOT}/package-1.0.0.tar.gz" "$RUBY_BUILD_CACHE_PATH"
@@ -33,12 +33,12 @@ setup() {
  [ -e "${RUBY_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "cached package with valid checksum" {
  stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
  stub shasum true "echo ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5"
  stub curl

  cp "${FIXTURE_ROOT}/package-1.0.0.tar.gz" "$RUBY_BUILD_CACHE_PATH"
@@ -49,15 +49,15 @@ setup() {
  [ -e "${RUBY_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "cached package with invalid checksum falls back to mirror and updates cache" {
  export RUBY_BUILD_SKIP_MIRROR=
  local checksum="83e6d7725e20166024a1eb74cde80677"
  local checksum="ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5"

  stub md5 true "echo invalid" "echo $checksum"
  stub shasum true "echo invalid" "echo $checksum"
  stub curl "-*I* : true" \
    "-q -o * -*S* http://?*/$checksum : cp $FIXTURE_ROOT/package-1.0.0.tar.gz \$3"

@@ -70,12 +70,12 @@ setup() {
  diff -q "${RUBY_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" "${FIXTURE_ROOT}/package-1.0.0.tar.gz"

  unstub curl
  unstub md5
  unstub shasum
}


@test "nonexistent cache directory is ignored" {
  stub md5 true
  stub shasum true
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  export RUBY_BUILD_CACHE_PATH="${TMP}/nonexistent"
@@ -86,5 +86,5 @@ setup() {
  [ ! -d "$RUBY_BUILD_CACHE_PATH" ]

  unstub curl
  unstub md5
  unstub shasum
}
+18 −18
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ export RUBY_BUILD_CACHE_PATH=


@test "package URL without checksum" {
  stub md5 true
  stub shasum true
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  install_fixture definitions/without-checksum
@@ -14,12 +14,12 @@ export RUBY_BUILD_CACHE_PATH=
  [ -x "${INSTALL_ROOT}/bin/package" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "package URL with valid checksum" {
  stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
  stub shasum true "echo ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5"
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  install_fixture definitions/with-checksum
@@ -27,12 +27,12 @@ export RUBY_BUILD_CACHE_PATH=
  [ -x "${INSTALL_ROOT}/bin/package" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "package URL with invalid checksum" {
  stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
  stub shasum true "echo ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5"
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  install_fixture definitions/with-invalid-checksum
@@ -40,12 +40,12 @@ export RUBY_BUILD_CACHE_PATH=
  [ ! -f "${INSTALL_ROOT}/bin/package" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "package URL with checksum but no MD5 support" {
  stub md5 false
@test "package URL with checksum but no shasum support" {
  stub shasum false
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  install_fixture definitions/with-checksum
@@ -53,12 +53,12 @@ export RUBY_BUILD_CACHE_PATH=
  [ -x "${INSTALL_ROOT}/bin/package" ]

  unstub curl
  unstub md5
  unstub shasum
}


@test "package with invalid checksum" {
  stub md5 true "echo invalid"
  stub shasum true "echo invalid"
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  install_fixture definitions/with-checksum
@@ -66,11 +66,11 @@ export RUBY_BUILD_CACHE_PATH=
  [ ! -f "${INSTALL_ROOT}/bin/package" ]

  unstub curl
  unstub md5
  unstub shasum
}

@test "existing tarball in build location is reused" {
  stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
  stub shasum true "echo ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5"
  stub curl false
  stub wget false

@@ -81,19 +81,19 @@ export RUBY_BUILD_CACHE_PATH=
  ln -s "${FIXTURE_ROOT}/package-1.0.0.tar.gz" "$RUBY_BUILD_BUILD_PATH"

  run_inline_definition <<DEF
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#83e6d7725e20166024a1eb74cde80677" copy
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5" copy
DEF

  assert_success
  [ -x "${INSTALL_ROOT}/bin/package" ]

  unstub md5
  unstub shasum
}

@test "existing tarball in build location is discarded if not matching checksum" {
  stub md5 true \
  stub shasum true \
    "echo invalid" \
    "echo 83e6d7725e20166024a1eb74cde80677"
    "echo ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5"
  stub curl "-q -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${5##*/} \$3"

  export -n RUBY_BUILD_CACHE_PATH
@@ -103,11 +103,11 @@ DEF
  touch "${RUBY_BUILD_BUILD_PATH}/package-1.0.0.tar.gz"

  run_inline_definition <<DEF
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#83e6d7725e20166024a1eb74cde80677" copy
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5" copy
DEF

  assert_success
  [ -x "${INSTALL_ROOT}/bin/package" ]

  unstub md5
  unstub shasum
}
+1 −1
Original line number Diff line number Diff line
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#83e6d7725e20166024a1eb74cde80677" copy
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#ba988b1bb4250dee0b9dd3d4d722f9c64b2bacfc805d1b6eba7426bda72dd3c5" copy
Loading