diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8f724f29..3e00a08ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -311,6 +311,11 @@ jobs: # still fails loudly on the last attempt. A binary restored by the # step above skips the compile. # + # --ssl-revoke-best-effort: Windows curl (schannel) otherwise fails + # the TLS handshake with CRYPT_E_REVOCATION_OFFLINE whenever the + # CA's revocation server is unreachable. A revoked certificate still + # fails, and the sha256 check follows. A no-op on other OSes. + # # Either way the binary's directory goes on PATH so # `Command::new("vexctl")` in the tests resolves. shell: bash @@ -328,7 +333,7 @@ jobs: *) asset='' ;; esac if [ -n "$asset" ]; then - curl -fsSL --retry 5 --retry-all-errors -o "$dir/$bin" \ + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort -o "$dir/$bin" \ "https://github.com/openvex/vexctl/releases/download/$VEXCTL_VERSION/$asset" echo "$sha $dir/$bin" | sha256sum -c - chmod +x "$dir/$bin" @@ -1429,14 +1434,15 @@ jobs: if: steps.jvm.outputs.maven == 'true' # Straight from the Apache archive (sha512-verified), so a leg gets # exactly the release it names rather than the runner's Maven. + # --ssl-revoke-best-effort: see the `test` job's vexctl step. shell: bash env: MAVEN_VERSION: ${{ matrix.maven || '3.9.16' }} run: | major="${MAVEN_VERSION%%.*}" url="https://archive.apache.org/dist/maven/maven-${major}/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" - curl -fsSL --retry 5 --retry-all-errors "$url" -o "$RUNNER_TEMP/maven.tgz" - curl -fsSL --retry 5 --retry-all-errors "$url.sha512" -o "$RUNNER_TEMP/maven.sha512" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url" -o "$RUNNER_TEMP/maven.tgz" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url.sha512" -o "$RUNNER_TEMP/maven.sha512" python -c 'import hashlib, pathlib, os; p=pathlib.Path(os.environ["RUNNER_TEMP"]); assert hashlib.sha512((p/"maven.tgz").read_bytes()).hexdigest() == (p/"maven.sha512").read_text().split()[0]' # Python accepts native Windows paths for both archive and destination. python -m tarfile -e "$RUNNER_TEMP/maven.tgz" "$RUNNER_TEMP" @@ -1451,8 +1457,8 @@ jobs: GRADLE_VERSION: ${{ matrix.gradle }} run: | url="https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" - curl -fsSL --retry 5 --retry-all-errors "$url" -o "$RUNNER_TEMP/gradle.zip" - curl -fsSL --retry 5 --retry-all-errors "$url.sha256" -o "$RUNNER_TEMP/gradle.sha256" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url" -o "$RUNNER_TEMP/gradle.zip" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url.sha256" -o "$RUNNER_TEMP/gradle.sha256" python -c 'import hashlib, pathlib, os; p=pathlib.Path(os.environ["RUNNER_TEMP"]); assert hashlib.sha256((p/"gradle.zip").read_bytes()).hexdigest() == (p/"gradle.sha256").read_text().strip()' unzip -q "$RUNNER_TEMP/gradle.zip" -d "$RUNNER_TEMP" launcher="$RUNNER_TEMP/gradle-${GRADLE_VERSION}/bin/gradle" diff --git a/.github/workflows/composer-compatibility.yml b/.github/workflows/composer-compatibility.yml index a7f52a09d..e19c35340 100644 --- a/.github/workflows/composer-compatibility.yml +++ b/.github/workflows/composer-compatibility.yml @@ -133,8 +133,12 @@ jobs: fi phar="$dir/composer-$COMPOSER_RELEASE.phar" base="https://getcomposer.org/download/$COMPOSER_RELEASE/composer.phar" - curl -fsSL --retry 5 --retry-all-errors -o "$phar" "$base" - published="$(curl -fsSL --retry 5 --retry-all-errors "$base.sha256sum" | cut -d' ' -f1)" + # --ssl-revoke-best-effort: Windows curl (schannel) otherwise fails the + # TLS handshake with CRYPT_E_REVOCATION_OFFLINE whenever the CA's + # revocation server is unreachable. A revoked certificate still fails; + # the body is checked against a digest right after. A no-op elsewhere. + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort -o "$phar" "$base" + published="$(curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$base.sha256sum" | cut -d' ' -f1)" # shellcheck disable=SC2016 # $argv is PHP, not shell actual="$(php -r 'echo hash_file("sha256", $argv[1]);' "$phar")" if [ "$actual" != "$COMPOSER_PHAR_SHA256" ] || [ "$actual" != "$published" ]; then diff --git a/.github/workflows/gradle-compatibility.yml b/.github/workflows/gradle-compatibility.yml index ec462116d..9b17fe9b1 100644 --- a/.github/workflows/gradle-compatibility.yml +++ b/.github/workflows/gradle-compatibility.yml @@ -241,9 +241,15 @@ jobs: env: MAVEN_VERSION: '3.9.16' run: | + # --retry-all-errors: plain --retry skips refused connections and TLS + # handshake errors (curl exit 7/35), as in ci.yml's copy of this step. + # --ssl-revoke-best-effort: Windows curl (schannel) otherwise fails the + # TLS handshake with CRYPT_E_REVOCATION_OFFLINE whenever the CA's + # revocation server is unreachable. A revoked certificate still fails; + # the body is checked against a digest right after. A no-op elsewhere. url="https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" - curl -fsSL --retry 3 "$url" -o "$RUNNER_TEMP/maven.tgz" - curl -fsSL --retry 3 "$url.sha512" -o "$RUNNER_TEMP/maven.sha512" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url" -o "$RUNNER_TEMP/maven.tgz" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url.sha512" -o "$RUNNER_TEMP/maven.sha512" python -c 'import hashlib, pathlib, os; p=pathlib.Path(os.environ["RUNNER_TEMP"]); assert hashlib.sha512((p/"maven.tgz").read_bytes()).hexdigest() == (p/"maven.sha512").read_text().split()[0]' python -m tarfile -e "$RUNNER_TEMP/maven.tgz" "$RUNNER_TEMP" launcher="$RUNNER_TEMP/apache-maven-${MAVEN_VERSION}/bin/mvn" @@ -259,9 +265,10 @@ jobs: env: GRADLE_VERSION: ${{ matrix.gradle }} run: | + # Download flags: see the Maven step above. url="https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" - curl -fsSL --retry 3 "$url" -o "$RUNNER_TEMP/gradle.zip" - curl -fsSL --retry 3 "$url.sha256" -o "$RUNNER_TEMP/gradle.sha256" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url" -o "$RUNNER_TEMP/gradle.zip" + curl -fsSL --retry 5 --retry-all-errors --ssl-revoke-best-effort "$url.sha256" -o "$RUNNER_TEMP/gradle.sha256" python -c 'import hashlib, pathlib, os; p=pathlib.Path(os.environ["RUNNER_TEMP"]); assert hashlib.sha256((p/"gradle.zip").read_bytes()).hexdigest() == (p/"gradle.sha256").read_text().strip()' unzip -q "$RUNNER_TEMP/gradle.zip" -d "$RUNNER_TEMP" launcher="$RUNNER_TEMP/gradle-${GRADLE_VERSION}/bin/gradle" diff --git a/crates/socket-patch-core/src/crawlers/gradle_cache.rs b/crates/socket-patch-core/src/crawlers/gradle_cache.rs index ef295ee27..afd7c4fba 100644 --- a/crates/socket-patch-core/src/crawlers/gradle_cache.rs +++ b/crates/socket-patch-core/src/crawlers/gradle_cache.rs @@ -70,8 +70,7 @@ pub fn hash_eq(dir_name: &str, sha1_hex: &str) -> bool { /// Whether `bytes` are the pristine download Gradle stored in the hash /// directory `dir_name` (their sha1 names it). pub fn pristine(dir_name: &str, bytes: &[u8]) -> bool { - use sha1::{Digest, Sha1}; - hash_eq(dir_name, &hex::encode(Sha1::digest(bytes))) + hash_eq(dir_name, &crate::utils::digest::sha1_hex_of(bytes)) } /// Whether `path` is a version directory of a `files-2.1` tree @@ -432,8 +431,6 @@ impl DerivedIndex { /// The [`DerivedCopies`] of the jar `jar_leaf` whose pristine bytes /// hash to `pristine_sha1`. pub fn query(&self, jar_leaf: &str, pristine_sha1: &str) -> DerivedCopies { - use sha1::{Digest, Sha1}; - let instrumented = format!("instrumented-{jar_leaf}"); let mut out = DerivedCopies { incomplete: self.incomplete, @@ -460,7 +457,9 @@ impl DerivedIndex { out.stale.push(path.clone()); } else if name == jar_leaf || name == instrumented { match crate::utils::fs::read_regular_to_bytes_sync(path) { - Ok(bytes) if hash_eq(&hex::encode(Sha1::digest(&bytes)), pristine_sha1) => { + Ok(bytes) + if hash_eq(&crate::utils::digest::sha1_hex_of(&bytes), pristine_sha1) => + { out.stale.push(path.clone()) } Ok(_) => out.unknown.push(path.clone()), diff --git a/crates/socket-patch-core/src/patch/jvm_jar.rs b/crates/socket-patch-core/src/patch/jvm_jar.rs index 82d679406..f38a84403 100644 --- a/crates/socket-patch-core/src/patch/jvm_jar.rs +++ b/crates/socket-patch-core/src/patch/jvm_jar.rs @@ -25,8 +25,6 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use sha1::Digest as _; - use crate::crawlers::gradle_cache; use crate::hash::git_sha256::compute_git_sha256_from_bytes; use crate::manifest::schema::PatchFileInfo; @@ -353,12 +351,11 @@ fn unpatched_members( } fn sha256_hex(bytes: &[u8]) -> String { - use sha2::Digest as _; - hex::encode(sha2::Sha256::digest(bytes)) + crate::utils::digest::sha256_hex_of(bytes) } fn sha1_hex(bytes: &[u8]) -> String { - hex::encode(sha1::Sha1::digest(bytes)) + crate::utils::digest::sha1_hex_of(bytes) } /// `/jvm-originals/.jar`. diff --git a/crates/socket-patch-core/src/patch/sidecars/maven.rs b/crates/socket-patch-core/src/patch/sidecars/maven.rs index f2f5a2466..8798bfce6 100644 --- a/crates/socket-patch-core/src/patch/sidecars/maven.rs +++ b/crates/socket-patch-core/src/patch/sidecars/maven.rs @@ -17,8 +17,6 @@ use std::path::{Path, PathBuf}; -use sha1::Digest as _; - use super::{ SidecarAdvisory, SidecarAdvisoryCode, SidecarError, SidecarFile, SidecarFileAction, SidecarPayload, SidecarSeverity, @@ -44,7 +42,7 @@ impl Algo { fn digest(self, bytes: &[u8]) -> String { match self { - Algo::Sha1 => hex::encode(sha1::Sha1::digest(bytes)), + Algo::Sha1 => crate::utils::digest::sha1_hex_of(bytes), Algo::Md5 => hex::encode(md5(bytes)), } }