This is an automated email from the git hooks/post-receive script.
boklm pushed a commit to branch maint-11.0 in repository builders/tor-browser-build.
commit a2886d8460b00af8eae907e1e5e7c21c2a551b33 Author: Matthew Finkel sysrqb@torproject.org AuthorDate: Tue Nov 17 03:01:22 2020 +0000
Bug 40157: Add sanity check scripts --- tools/authenticode_verify_timestamp.sh | 95 +++++++++++++++++++ tools/marsigning_check.sh | 12 +++ tools/signing/check_file_counts | 168 +++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+)
diff --git a/tools/authenticode_verify_timestamp.sh b/tools/authenticode_verify_timestamp.sh new file mode 100755 index 0000000..efa8986 --- /dev/null +++ b/tools/authenticode_verify_timestamp.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +# Copyright (c) 2021, The Tor Project, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# +# * Neither the names of the copyright owners nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Usage: +# 1) Let OSSLSIGNCODE point to your osslsigncode binary +# 2) Change into the directory containing the .exe files and the sha256sums-unsigned-build.txt +# 3) Run /path/to/authenticode_verify_timestamp.sh + +if [ -z "$OSSLSIGNCODE" ] +then + echo "The path to your osslsigncode binary is missing!" + exit 1 +fi + +#set -x + +VERIFIED_PACKAGES=0 +MISSING_TIMESTAMP=0 + +for f in `ls *.exe`; do + echo -n "$f timestamped: " + + ${OSSLSIGNCODE} extract-signature -pem -in $f -out $f.sigs 1>/dev/null + ts=`openssl pkcs7 -print -in $f.sigs | grep -A 227 unauth_attr` + ts_len=`openssl pkcs7 -print -in $f.sigs | grep -A 227 unauth_attr | wc -l` + rm $f.sigs + + if [ $ts_len -ne 228 ]; then + echo "timestamp format changed. Expected 228 lines, but received $ts_len" + fi + + missing_attrs=0 + # Random selection. We can choose better ones later. + for exp in "d=1 hl=2 l= 9 prim: OBJECT :pkcs7-signedData" \ + "d=4 hl=2 l= 11 prim: OBJECT :id-smime-ct-TSTInfo" \ + "d=9 hl=2 l= 40 prim: PRINTABLESTRING :DigiCert SHA2 Assured ID Timestamping CA" \ + "d=9 hl=2 l= 23 prim: PRINTABLESTRING :DigiCert Timestamp 2021" \ + "d=7 hl=2 l= 9 prim: OBJECT :signingTime"; do + #echo "Checking '$exp'" + if ! `echo $ts | grep -q "$exp"`; then + missing_attrs=`expr $missing_attrs + 1` + echo "no: missing attribute: $exp" + fi + done + if [ $missing_attrs -ne 0 ]; then + MISSING_TIMESTAMP=`expr $MISSING_TIMESTAMP + 1` + else + echo yes + fi + + CHECKED_PACKAGES=`expr ${CHECKED_PACKAGES} + 1` +done + +if [ "${MISSING_TIMESTAMP}" -ne 0 ]; then + echo "${MISSING_TIMESTAMP} packages not timestamped." + exit 1 +fi + +if [ "${CHECKED_PACKAGES}" -ne `ls *.exe | wc -l` ]; then + echo "Some packages were not verified!." + exit 1 +fi + +echo "Successfully verified are ${CHECKED_PACKAGES} timestamped" + +exit 0 diff --git a/tools/marsigning_check.sh b/tools/marsigning_check.sh index fb5e4f6..28f149a 100755 --- a/tools/marsigning_check.sh +++ b/tools/marsigning_check.sh @@ -35,6 +35,7 @@ # 2) Let LD_LIBRARY_PATH point to the mar-tools directory # 3) Let NSS_DB_DIR point to the directory containing the database with the # signing certificate to check against. +# 4) Let CHANNEL be the expected update channel # # To create the database to use for signature checking import the # release*.der certificate of your choice found in @@ -66,6 +67,12 @@ then exit 1 fi
+if [ -z "$CHANNEL" ] +then + echo "The update channel is missing! ([nightly|alpha|release])" + exit 1 +fi + unsigned_mars=0 badsigned_mars=0 not_reproduced_mars=0 @@ -98,6 +105,11 @@ for f in *.mar; do fi fi
+ # Test 1.5: Is the MAR file correctly signed by the correct channel key? + if [ ! "$($SIGNMAR -T "$f" | grep "MAR channel name")" = " - MAR channel name: torbrowser-torproject-${CHANNEL}" ]; then + echo "$f contains wrong update channel!" + fi + # Test 2: Do we get the old SHA-256 sum after stripping the MAR signature? We # want to have a test for that to be sure we've the signed MAR files in front # of us which we actually want to ship to our users. diff --git a/tools/signing/check_file_counts b/tools/signing/check_file_counts new file mode 100755 index 0000000..beaa8e7 --- /dev/null +++ b/tools/signing/check_file_counts @@ -0,0 +1,168 @@ +#!/bin/bash + +#set -x +#set -e + +VERSION=$1 +LANG_COUNT=$2 +INCREMENTAL_VERSIONS="$3" +SIGNERS="$4" + +if [ "$#" -ne 4 ]; then + echo "<version> <lang_count> <incrementals> <signers>" + exit +fi + +INSTALL_PLATFORMS="tor-browser-linux32-${VERSION}_*.tar.xz tor-browser-linux64-${VERSION}_*.tar.xz torbrowser-install-${VERSION}_*.exe torbrowser-install-win64-${VERSION}_*.exe TorBrowser-${VERSION}-osx64_*.dmg" + +MAR_PLATFORMS="linux32 linux64 win32 win64 osx64" +MAR_TOOLS_PLATFORMS="linux32 linux64 win32 win64 mac64" + +total_count=0 +remaining_files=$(ls) + +for p in ${INSTALL_PLATFORMS}; do + expand_p=$(echo "${p}" | sed 's/\*/*/g') + test "$(ls ${expand_p} 2>/dev/null | wc -l)" = "${LANG_COUNT}" || echo "${p} not ${LANG_COUNT}" + total_count=$(( total_count + LANG_COUNT )) + for f in ${expand_p}; do + remaining_files=$(echo "${remaining_files}" | sed 's/ '"${f}"' / /') + done +done + +for p in ${INSTALL_PLATFORMS}; do + expand_p="$(echo "${p}" | sed 's/\*/*/g')" + test "$(ls ${expand_p}.asc 2>/dev/null | wc -l)" = "${LANG_COUNT}" || echo "${p}.asc not ${LANG_COUNT}" + total_count=$(( total_count + LANG_COUNT )) + for f in ${expand_p}; do + remaining_files=$(echo "${remaining_files}" | sed 's/ '"${f}.asc"' / /') + done +done + +p=tor-browser-"${VERSION}"-android-*-multi*.apk +expand_p="$(echo "${p}" | sed 's/\\*/*/g')" +test "$(ls ${expand_p} 2>/dev/null | wc -l)" = 8 || echo "${p} not 8" +total_count=$(( total_count + 8 )) +for f in ${expand_p}; do + remaining_files=$(echo "${remaining_files}" | sed 's/ '"${f}"' / /') +done +test "$(ls ${expand_p}.asc 2>/dev/null | wc -l)" = 8 || echo "${p}.asc not 8" +total_count=$(( total_count + 8 )) +for f in ${expand_p}; do + remaining_files=$(echo "${remaining_files}" | sed 's/ '"${f}.asc"' / /') +done + +for p in ${MAR_PLATFORMS}; do + count=$(ls tor-browser-"${p}"-"${VERSION}"_*.mar 2>/dev/null | wc -l) + test "${count}" -eq "${LANG_COUNT}" || echo "${p} not ${LANG_COUNT} (found $count)" + total_count=$(( total_count + count )) + for f in tor-browser-"${p}"-"${VERSION}"_*.mar; do + remaining_files=$(echo "${remaining_files}" | sed 's/ '"${f}"' / /') + done +done + +for p in ${MAR_TOOLS_PLATFORMS}; do + test -f mar-tools-"${p}".zip || echo mar-tools-"${p}".zip does not exit + total_count=$(( total_count + 1 )) + remaining_files=$(echo "${remaining_files}" | sed 's/ 'mar-tools-"${p}".zip' / /') +done + +for p in ${MAR_TOOLS_PLATFORMS}; do + test -f mar-tools-"${p}".zip.asc || echo mar-tools-"${p}".zip.asc does not exit + total_count=$(( total_count + 1 )) + remaining_files=$(echo "${remaining_files}" | sed 's/ 'mar-tools-"${p}".zip.asc' / /') +done + +for p in ${MAR_PLATFORMS}; do + for i in ${INCREMENTAL_VERSIONS}; do + count="$(ls tor-browser-"${p}"-"${i}"-"${VERSION}"_*.mar 2>/dev/null | wc -l)" + test "${count}" -eq "${LANG_COUNT}" || echo "${p} ${i} incrementals not ${LANG_COUNT} (found $count)" + total_count=$(( total_count + count )) + for f in tor-browser-"${p}"-"${i}"-"${VERSION}"_*.mar; do + remaining_files=$(echo "${remaining_files}" | sed 's/ '"${f}"' / /') + done + done +done + +for f in tor-win32-*.zip tor-win64-*.zip; do + test -f "${f}" || echo "${f} does not exist" + test -f "${f}.asc" || echo "${f}.asc does not exist" + total_count=$(( total_count + 2 )) + remaining_files=$(echo "${remaining_files}" | sed 's/[ ]*'"${f}"'[ ]*/ /') + remaining_files=$(echo "${remaining_files}" | sed 's/[ ]*'"${f}.asc"'[ ]*/ /') +done + +for f in sha256sums-unsigned-build.txt sha256sums-unsigned-build.incrementals.txt sha256sums-signed-build.txt sha256sums-signed-build.incrementals.txt; do + test -f ${f} || echo ${f} does not exist + test -f ${f}.asc || echo ${f}.asc does not exist + total_count=$(( total_count + 2 )) + #remaining_files=$(echo ${remaining_files} | sed 's/ '${f}' / /') + remaining_files=$(echo "${remaining_files}" | sed 's/ '${f}' / /') + remaining_files=$(echo "${remaining_files}" | sed 's/ '${f}.asc' / /') +done + +for s in ${SIGNERS}; do + for f in sha256sums-unsigned-build.txt sha256sums-unsigned-build.incrementals.txt; do + test -f "${f}.asc-${s}" || echo "${f}.asc-${s} does not exist" + total_count=$(( total_count + 1 )) + remaining_files="$(echo "${remaining_files}" | sed 's/ '"${f}.asc-${s}"' / /')" + done +done + +for f in sha256sums-unsigned-build.txt sha256sums-unsigned-build.incrementals.txt; do + for s in "${f}".asc-*; do + gpg2 --quiet --verify "${s}" ${f} + done +done + +for f in sha256sums-signed-build.txt sha256sums-signed-build.incrementals.txt; do + gpg2 --quiet --verify ${f}.asc ${f} +done + +for f in sha256sums-signed-build.txt sha256sums-signed-build.incrementals.txt; do + sha256sum --quiet -c $f +done + +f=geckodriver-linux64.tar.xz +test -f ${f} || echo ${f} does not exist +test -f ${f}.asc || echo ${f}.asc does not exist +total_count=$(( total_count + 2 )) +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}"'[ ]*/ /')" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}.asc"'[ ]*/ /')" + +for f in tor-browser-linux64-debug.tar.xz tor-linux32-debug.tar.xz tor-linux64-debug.tar.xz; do + test -f ${f} || echo ${f} does not exist + test -f ${f}.asc || echo ${f}.asc does not exist + total_count=$(( total_count + 2 )) + remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}"'[ ]*/ /')" + remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}.asc"'[ ]*/ /')" +done + +test "$(ls src-firefox-tor-browser-*.tar.xz 2>/dev/null | wc -l)" = 1 || echo src-firefox-tor-browser-*.tar.xz is wrong +test "$(ls src-firefox-tor-browser-*.tar.xz.asc 2>/dev/null | wc -l)" = 1 || echo src-firefox-tor-browser-*.tar.xz.asc is wrong +total_count=$(( total_count + 2 )) +f="$(ls src-firefox-tor-browser-*.tar.xz)" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}"'[ ]*/ /')" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}.asc"'[ ]*/ /')" + +test "$(ls src-tor-launcher-*.tar.xz 2>/dev/null | wc -l)" = 1 || echo src-tor-launcher-*.tar.xz is wrong +test "$(ls src-tor-launcher-*.tar.xz.asc 2>/dev/null | wc -l)" = 1 || echo src-tor-launcher-*.tar.xz.asc is wrong +total_count=$(( total_count + 2 )) +f="$(ls src-tor-launcher-*.tar.xz)" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}"'[ ]*/ /')" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}.asc"'[ ]*/ /')" + +test "$(ls langpacks-tor-browser-linux64-*.tar.xz 2>/dev/null | wc -l)" = 1 || echo langpacks-tor-browser-linux64-*.tar.xz is wrong +test "$(ls langpacks-tor-browser-linux64-*.tar.xz.asc 2>/dev/null | wc -l)" = 1 || echo langpacks-tor-browser-linux64-*.tar.xz.asc is wrong +total_count=$(( total_count + 2 )) +f="$(ls langpacks-tor-browser-linux64-*.tar.xz)" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}"'[ ]*/ /')" +remaining_files="$(echo "${remaining_files}" | sed 's/[ ]*'"${f}.asc"'[ ]*/ /')" + +# Expected file endings +file_count_by_ending="$(ls ./*.tar.xz{,.asc} ./*.zip{,.asc} ./*.exe{,.asc} ./*.mar ./*.dmg{,.asc} ./*.apk{,.asc} ./*.txt{,.asc} ./*.txt.asc-* | wc -l)" +test "${file_count_by_ending}" -eq ${total_count} || echo "Unexpected file endings: counted ${file_count_by_ending} vs ${total_count}" + +test "$(ls | wc -l)" -eq ${total_count} || echo "wrong total count: $(ls | wc -l) vs ${total_count}" +echo "${remaining_files}" +echo done.