From 98add170bbc52fc3828ea74beabab08656bb4179 Mon Sep 17 00:00:00 2001 From: Andrew Leonard <31470007+andrew-m-leonard@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:24:01 +0000 Subject: [PATCH] Prevent multiple Windows exe/dll signing and verify (#1157) * Update verify_signing.groovy to check Windows exes only have one signature Signed-off-by: Andrew Leonard * Update verify_signing.groovy to check Windows exes only have one signature Signed-off-by: Andrew Leonard * Update verify_signing.groovy to check Windows exes only have one signature Signed-off-by: Andrew Leonard * Update verify_signing.groovy to check Windows exes only have one signature Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard * Prevent jdk11+ from running external sign.sh as already signed during build Signed-off-by: Andrew Leonard --------- Signed-off-by: Andrew Leonard --- .../common/openjdk_build_pipeline.groovy | 96 ++++++++++--------- pipelines/build/common/verify_signing.groovy | 27 +++++- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/pipelines/build/common/openjdk_build_pipeline.groovy b/pipelines/build/common/openjdk_build_pipeline.groovy index 80da212e8..488eb908e 100644 --- a/pipelines/build/common/openjdk_build_pipeline.groovy +++ b/pipelines/build/common/openjdk_build_pipeline.groovy @@ -1557,57 +1557,67 @@ class Build { fi for f in $FILES do - echo "Signing $f using Eclipse Foundation codesign service" dir=$(dirname "$f") file=$(basename "$f") - mv "$f" "${dir}/unsigned_${file}" - success=false - if [ "${base_os}" == "mac" ]; then - if ! curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" -F entitlements="@$ENTITLEMENTS" https://cbi.eclipse.org/macos/codesign/sign; then - echo "curl command failed, sign of $f failed" - else - success=true - fi - else - if ! curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" https://cbi.eclipse.org/authenticode/sign; then - echo "curl command failed, sign of $f failed" - else - success=true + ms_file_skipped=false + if [ "${base_os}" == "windows" ]; then + # Check if file is a Microsoft supplied file that is already signed + if [[ "$file" =~ api-ms-win.* ]] || [[ "$file" =~ msvcp.* ]] || [[ "$file" =~ ucrtbase.* ]] || [[ "$file" =~ vcruntime.* ]]; then + echo "Skipping Microsoft file $file" + ms_file_skipped=true fi fi - if [ $success == false ]; then - # Retry up to 20 times - max_iterations=20 - iteration=1 - echo "Code Not Signed For File $f" - while [ $iteration -le $max_iterations ] && [ $success = false ]; do - echo $iteration Of $max_iterations - sleep 1 - if [ "${base_os}" == "mac" ]; then - if curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" -F entitlements="@$ENTITLEMENTS" https://cbi.eclipse.org/macos/codesign/sign; then - success=true - fi + if [ $ms_file_skipped == false ]; then + echo "Signing $f using Eclipse Foundation codesign service" + mv "$f" "${dir}/unsigned_${file}" + success=false + if [ "${base_os}" == "mac" ]; then + if ! curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" -F entitlements="@$ENTITLEMENTS" https://cbi.eclipse.org/macos/codesign/sign; then + echo "curl command failed, sign of $f failed" else - if curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" https://cbi.eclipse.org/authenticode/sign; then - success=true - fi + success=true fi - - if [ $success = false ]; then - echo "curl command failed, $f Failed Signing On Attempt $iteration" - iteration=$((iteration+1)) - if [ $iteration -gt $max_iterations ] - then - echo "Errors Encountered During Signing" - exit 1 - fi + else + if ! curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" https://cbi.eclipse.org/authenticode/sign; then + echo "curl command failed, sign of $f failed" else - echo "$f Signed OK On Attempt $iteration" + success=true fi - done - fi - chmod --reference="${dir}/unsigned_${file}" "$f" - rm -rf "${dir}/unsigned_${file}" + fi + if [ $success == false ]; then + # Retry up to 20 times + max_iterations=20 + iteration=1 + echo "Code Not Signed For File $f" + while [ $iteration -le $max_iterations ] && [ $success = false ]; do + echo $iteration Of $max_iterations + sleep 1 + if [ "${base_os}" == "mac" ]; then + if curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" -F entitlements="@$ENTITLEMENTS" https://cbi.eclipse.org/macos/codesign/sign; then + success=true + fi + else + if curl --fail --silent --show-error -o "$f" -F file="@${dir}/unsigned_${file}" https://cbi.eclipse.org/authenticode/sign; then + success=true + fi + fi + + if [ $success = false ]; then + echo "curl command failed, $f Failed Signing On Attempt $iteration" + iteration=$((iteration+1)) + if [ $iteration -gt $max_iterations ] + then + echo "Errors Encountered During Signing" + exit 1 + fi + else + echo "$f Signed OK On Attempt $iteration" + fi + done + fi + chmod --reference="${dir}/unsigned_${file}" "$f" + rm -rf "${dir}/unsigned_${file}" + fi # ms_file_skipped == false done ''' // groovylint-enable diff --git a/pipelines/build/common/verify_signing.groovy b/pipelines/build/common/verify_signing.groovy index 25e7bebbc..f28bd4264 100644 --- a/pipelines/build/common/verify_signing.groovy +++ b/pipelines/build/common/verify_signing.groovy @@ -22,6 +22,7 @@ Parameters: - TARGET_OS : "mac" or "windows" - TARGET_ARCH : "aarch64 or "x64" or "x86-32" - NODE_LABEL : Jenkins label for where to run + - CERT_ISSUED_TO : Issued to org name to verify Windows Signatures */ @@ -112,7 +113,7 @@ void unpackArchives(String unpack_dir, String[] archives) { } // Verify executables for Signatures -void verifyExecutables(String unpack_dir) { +void verifyExecutables(String unpack_dir, String issueToOrg) { if (params.TARGET_OS == "mac") { // On Mac find all dylib's and "executable" binaries // Ignore "legal" text folder to reduce the number of non-extension files it finds... @@ -167,7 +168,7 @@ void verifyExecutables(String unpack_dir) { // Find all exe/dll's that must be Signed - withEnv(['unpack_dir='+unpack_dir, 'signtool='+signtool]) { + withEnv(['unpack_dir='+unpack_dir, 'signtool='+signtool, 'issueToOrg='+issueToOrg]) { // groovylint-disable sh ''' #!/bin/bash @@ -185,8 +186,24 @@ void verifyExecutables(String unpack_dir) { unsigned="$unsigned $f" cc_unsigned=$((cc_unsigned+1)) else - echo "Signed correctly: ${f}" - cc_signed=$((cc_signed+1)) + num_microsoft_sigs=$("${signtool}" verify /v /all /pa ${f} | grep "Issued to:" | grep "Microsoft" | wc -l) + num_org_sigs=$("${signtool}" verify /v /all /pa ${f} | grep "Issued to:" | grep "${issueToOrg}" | wc -l) + if [[ "$num_microsoft_sigs" -ne 0 ]] && [[ "$num_org_sigs" -ne 0 ]]; then + echo "Error: ${f} should not be signed by ${issueToOrg} as it is already signed by Microsoft." + unsigned="$unsigned $f" + cc_unsigned=$((cc_unsigned+1)) + elif [[ "$num_microsoft_sigs" -eq 0 ]] && [[ "$num_org_sigs" -gt 1 ]]; then + echo "Error: ${f} is signed by ${issueToOrg} ${num_org_sigs} times, it must only be signed once." + unsigned="$unsigned $f" + cc_unsigned=$((cc_unsigned+1)) + elif [[ "$num_microsoft_sigs" -eq 0 ]] && [[ "$num_org_sigs" -eq 0 ]]; then + echo "Error: ${f} is NOT signed by ${issueToOrg}." + unsigned="$unsigned $f" + cc_unsigned=$((cc_unsigned+1)) + else + echo "Signed correctly: ${f}" + cc_signed=$((cc_signed+1)) + fi fi done @@ -355,7 +372,7 @@ if (params.TARGET_OS != "mac" && params.TARGET_OS != "windows") { unpackArchives(unpack_dir, archives) // Verify all executables for Signatures - verifyExecutables(unpack_dir) + verifyExecutables(unpack_dir, "${params.CERT_ISSUED_TO}") // Verify installers (if built) are Signed and Notarized(mac only) verifyInstallers()