X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/59f57473ab85d3fb3354d086db2df2466c1c3896..8d1cb6da6e21302c654da3f09de3975af7e4a11f:/test/integration/framework diff --git a/test/integration/framework b/test/integration/framework index ee976aff5..93e17e454 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -54,7 +54,7 @@ msgprintf() { printf "$START " "$1" shift while [ -n "$1" ]; do - printf "$MIDDLE " "$(echo "$1" | sed -e 's#^apt\([cfghs]\)#apt-\1#')" + printf "$MIDDLE " "$(echo "$1" | sed -e 's#^apt\([cfghks]\)#apt-\1#')" shift done fi @@ -95,7 +95,7 @@ msgfail() { if [ $# -gt 0 ] && [ -n "$1" ]; then printf "${CFAIL}FAIL: $*${CNORMAL}\n" >&2; else printf "${CFAIL}FAIL${CNORMAL}\n" >&2; fi if [ -n "$APT_DEBUG_TESTS" ]; then - $SHELL + runapt $SHELL fi EXIT_CODE=$((EXIT_CODE+1)); } @@ -169,12 +169,13 @@ runapt() { msgdebug "Executing: ${CCMD}$*${CDEBUG} " local CMD="$1" shift - case $CMD in + case "$CMD" in sh|aptitude|*/*|command) ;; *) CMD="${BUILDDIRECTORY}/$CMD";; esac - MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${LIBRARYPATH} $CMD "$@" + MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH="${LIBRARYPATH}:${LD_LIBRARY_PATH}" "$CMD" "$@" } +runpython3() { runapt command python3 "$@"; } aptconfig() { runapt apt-config "$@"; } aptcache() { runapt apt-cache "$@"; } aptcdrom() { runapt apt-cdrom "$@"; } @@ -190,6 +191,7 @@ aptitude() { runapt aptitude "$@"; } aptextracttemplates() { runapt apt-extracttemplates "$@"; } aptinternalsolver() { runapt "${APTINTERNALSOLVER}" "$@"; } aptdumpsolver() { runapt "${APTDUMPSOLVER}" "$@"; } +aptinternalplaner() { runapt "${APTINTERNALPLANER}" "$@"; } dpkg() { "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" "$@" @@ -216,6 +218,12 @@ gdb() { fi runapt command gdb --quiet -ex run "$CMD" --args "$CMD" "$@" } +lastmodification() { + date -u -d "@$(stat -c '%Y' "${TMPWORKINGDIRECTORY}/$1")" '+%a, %d %b %Y %H:%M:%S GMT' +} +releasefiledate() { + grep "^${2:-Date}:" "$1" | cut -d' ' -f 2- | sed -e 's#UTC#GMT#' +} exitwithstatus() { # error if we about to overflow, but ... @@ -245,13 +253,23 @@ addtrap() { trap "shellsetedetector; $CURRENTTRAP exitwithstatus;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM } +escape_shell() { + echo "$@" | sed -e "s#'#'\"'\"'#g" +} + setupenvironment() { # privilege dropping and testing doesn't work if /tmp isn't world-writeable (as e.g. with libpam-tmpdir) if [ -n "$TMPDIR" ] && [ "$(id -u)" = '0' ] && [ "$(stat --format '%a' "$TMPDIR")" != '1777' ]; then unset TMPDIR fi TMPWORKINGDIRECTORY="$(mktemp -d)" - addtrap "cd /; rm -rf \"$TMPWORKINGDIRECTORY\";" + addtrap "cd /; rm -rf '$(escape_shell "$TMPWORKINGDIRECTORY")';" + if [ -n "$TMPDIR_ADD" ]; then + TMPWORKINGDIRECTORY="${TMPWORKINGDIRECTORY}/${TMPDIR_ADD}" + mkdir -p "$TMPWORKINGDIRECTORY" + unset TMPDIR_ADD + export TMPDIR="$TMPWORKINGDIRECTORY" + fi msgninfo "Preparing environment for ${0##*/} in ${TMPWORKINGDIRECTORY}…" mkdir -m 700 "${TMPWORKINGDIRECTORY}/downloaded" @@ -272,6 +290,7 @@ setupenvironment() { APTWEBSERVERBINDIR="${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-"${BUILDDIRECTORY}"}" APTINTERNALSOLVER="${APT_INTEGRATION_TESTS_INTERNAL_SOLVER:-"${BUILDDIRECTORY}/apt-internal-solver"}" APTDUMPSOLVER="${APT_INTEGRATION_TESTS_DUMP_SOLVER:-"${BUILDDIRECTORY}/apt-dump-solver"}" + APTINTERNALPLANER="${APT_INTEGRATION_TESTS_INTERNAL_PLANER:-"${BUILDDIRECTORY}/apt-internal-planer"}" test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first" # ----- @@ -285,10 +304,13 @@ setupenvironment() { mkdir -p usr/lib/apt ln -s "${METHODSDIR}" usr/lib/apt/methods if [ "$BUILDDIRECTORY" = "$LIBRARYPATH" ]; then - mkdir -p usr/lib/apt/solvers + mkdir -p usr/lib/apt/solvers usr/lib/apt/planers ln -s "${BUILDDIRECTORY}/apt-dump-solver" usr/lib/apt/solvers/dump + ln -s "${BUILDDIRECTORY}/apt-dump-solver" usr/lib/apt/planers/dump ln -s "${BUILDDIRECTORY}/apt-internal-solver" usr/lib/apt/solvers/apt + ln -s "${BUILDDIRECTORY}/apt-internal-planer" usr/lib/apt/planers/apt echo "Dir::Bin::Solvers \"${TMPWORKINGDIRECTORY}/rootdir/usr/lib/apt/solvers\";" > etc/apt/apt.conf.d/externalsolver.conf + echo "Dir::Bin::Planers \"${TMPWORKINGDIRECTORY}/rootdir/usr/lib/apt/planers\";" > etc/apt/apt.conf.d/externalplaner.conf fi # use the autoremove from the BUILDDIRECTORY if its there, otherwise # system @@ -307,10 +329,8 @@ setupenvironment() { if [ -f "${TESTDIRECTORY}/${SOURCESSFILE}" ]; then cp "${TESTDIRECTORY}/${SOURCESSFILE}" aptarchive/Sources fi - for key in $(find "$TESTDIRECTORY" -name '*.pub' -o -name '*.sec'); do - cp "$key" keys/ - chmod 644 "$key" - done + find "$TESTDIRECTORY" \( -name '*.pub' -o -name '*.sec' \) -exec cp '{}' keys/ \; + chmod 644 keys/* ln -s "${TMPWORKINGDIRECTORY}/keys/joesixpack.pub" rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf @@ -324,17 +344,19 @@ setupenvironment() { # destroys coverage reporting though, so we disable changing user for the calling gpgv echo "Dir::Bin::apt-key \"${BUILDDIRECTORY}/apt-key\";" >> aptconfig.conf if [ "$(id -u)" = '0' ]; then - echo 'Binary::gpgv::Debug::NoDropPrivs "true";' >>aptconfig.conf + echo 'Binary::gpgv::APT::Sandbox::User "root";' >> aptconfig.conf + # same for the solver executables + echo 'APT::Solver::RunAsUser "root";' >> aptconfig.conf fi cat > "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" <> "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" <> "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/gdb-dpkg" < rootdir/etc/apt/apt.conf.d/99https echo "Apt::Cmd::Disable-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary echo 'Acquire::Connect::AddrConfig "false";' > rootdir/etc/apt/apt.conf.d/connect-addrconfig + configcompression '.' 'gz' #'bz2' 'lzma' 'xz' - confighashes 'SHA1' # these are tests, not security best-practices + confighashes 'SHA256' # these are tests, not security best-practices # create some files in /tmp and look at user/group to get what this means TEST_DEFAULT_USER="$(id -un)" @@ -399,6 +422,15 @@ EOF unset LANGUAGE APT_CONFIG unset GREP_OPTIONS DEB_BUILD_PROFILES unset http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy + + # If gpgv supports --weak-digest, pass it to make sure we can disable SHA1 + if aptkey verify --weak-digest SHA1 --help 2>/dev/null >/dev/null; then + echo 'Acquire::gpgv::Options { "--weak-digest"; "sha1"; };' > rootdir/etc/apt/apt.conf.d/no-sha1 + fi + + # most tests just need one signed Release file, not both + export APT_DONT_SIGN='Release.gpg' + msgdone "info" } @@ -478,7 +510,6 @@ configdpkgnoopchroot() { #include #include #include -#include static char * chrootdir = NULL; @@ -495,26 +526,35 @@ int execvp(const char *file, char *const argv[]) { if (chrootdir == NULL || strncmp(file, "/var/lib/dpkg/", strlen("/var/lib/dpkg/")) != 0) return func_execvp(file, argv); printf("REWRITE execvp call %s into %s\n", file, chrootdir); - char newfile[PATH_MAX]; - snprintf(newfile, sizeof(newfile), "%s/%s", chrootdir, file); + char *newfile; + if (asprintf(&newfile, "%s%s", chrootdir, file) == -1) { + perror("asprintf"); + return -1; + } char const * const baseadmindir = "/var/lib/dpkg"; - char admindir[PATH_MAX]; - snprintf(admindir, sizeof(admindir), "%s/%s", chrootdir, baseadmindir); + char *admindir; + if (asprintf(&admindir, "%s%s", chrootdir, baseadmindir) == -1) { + perror("asprintf"); + return -1; + } setenv("DPKG_ADMINDIR", admindir, 1); return func_execvp(newfile, argv); } EOF - testsuccess --nomsg gcc -fPIC -shared -o noopchroot.so noopchroot.c -ldl + testempty --nomsg gcc -Wall -Wextra -fPIC -shared -o noopchroot.so noopchroot.c -ldl } configcompression() { + if [ "$1" = 'ALL' ]; then + configcompression '.' $(aptconfig dump APT::Compressor --format '%t %v%n' | sed -n 's#^Extension \.\(.*\)$#\1#p') + return + fi + local CMD='apthelper cat-file -C' while [ -n "$1" ]; do case "$1" in '.') printf ".\t.\tcat\n";; - 'gz') printf "gzip\tgz\tgzip\n";; - 'bz2') printf "bzip2\tbz2\tbzip2\n";; - 'lzma') printf "lzma\tlzma\txz --format=lzma\n";; - 'xz') printf "xz\txz\txz\n";; - *) printf "$1\t$1\t$1\n";; + 'gz') printf "gzip\tgz\t$CMD $1\n";; + 'bz2') printf "bzip2\tbz2\t$CMD $1\n";; + *) printf "$1\t$1\t$CMD $1\n";; esac shift done > "${TMPWORKINGDIRECTORY}/rootdir/etc/testcase-compressor.conf" @@ -537,32 +577,20 @@ confighashes() { } forcecompressor() { COMPRESSOR="$1" - COMPRESSOR_CMD="$1" + COMPRESS="$1" + COMPRESSOR_CMD="apthelper cat-file -C $1" case $COMPRESSOR in gzip) COMPRESS='gz';; bzip2) COMPRESS='bz2';; - lzma) COMPRESS='lzma';; - xz) COMPRESS='xz';; - *) msgdie "Compressor $COMPRESSOR is unknown to framework, so can't be forced by forcecompressor!";; esac local CONFFILE="${TMPWORKINGDIRECTORY}/rootdir/etc/apt/apt.conf.d/00force-compressor" echo "Acquire::CompressionTypes::Order { \"${COMPRESS}\"; }; -Dir::Bin::uncompressed \"/does/not/exist\"; -Dir::Bin::gzip \"/does/not/exist\"; -Dir::Bin::bzip2 \"/does/not/exist\"; -Dir::Bin::lzma \"/does/not/exist\"; -Dir::Bin::xz \"/does/not/exist\";" > "$CONFFILE" - if [ -e "/bin/${COMPRESSOR}" ]; then - echo "Dir::Bin::${COMPRESSOR} \"/bin/${COMPRESSOR}\";" >> "$CONFFILE" - elif [ -e "/usr/bin/${COMPRESSOR}" ]; then - echo "Dir::Bin::${COMPRESSOR} \"/usr/bin/${COMPRESSOR}\";" >> "$CONFFILE" - elif [ "${COMPRESSOR}" = 'lzma' ]; then - echo 'Dir::Bin::xz "/usr/bin/xz";' >> "$CONFFILE" - COMPRESSOR_CMD='xz --format=lzma' - else - msgtest 'Test for availability of compressor' "${COMPRESSOR}" - msgfail "${COMPRESSOR} not available" - fi +Dir::Bin::uncompressed \"/does/not/exist\";" > "$CONFFILE" + for COMP in $(aptconfig dump 'APT::Compressor' --format '%f%n' | cut -d':' -f 5 | uniq); do + if [ -z "$COMP" -o "$COMP" = '.' -o "$COMP" = "$COMPRESSOR" ]; then continue; fi + echo "Dir::Bin::${COMP} \"/does/not/exist\";" >> "$CONFFILE" + echo "APT::Compressor::${COMP}::Name \"${COMP}-disabled\";" >> "$CONFFILE" + done } setupsimplenativepackage() { @@ -587,12 +615,12 @@ setupsimplenativepackage() { mkdir -p ${BUILDDIR}/debian/source cd ${BUILDDIR} echo "* most suckless software product ever" > FEATURES - test -e debian/copyright || echo "Copyleft by Joe Sixpack $(date +%Y)" > debian/copyright + test -e debian/copyright || echo "Copyleft by Joe Sixpack $(date -u +%Y)" > debian/copyright test -e debian/changelog || echo "$NAME ($VERSION) $RELEASE; urgency=low * Initial release - -- Joe Sixpack $(date -R)" > debian/changelog + -- Joe Sixpack $(date -u -R)" > debian/changelog test -e debian/control || echo "Source: $NAME Section: $SECTION Priority: optional @@ -650,12 +678,12 @@ buildsimplenativepackage() { echo "#!/bin/sh echo '$NAME says \"Hello!\"'" > "${BUILDDIR}/${NAME}" - echo "Copyleft by Joe Sixpack $(date +%Y)" > "${BUILDDIR}/debian/copyright" + echo "Copyleft by Joe Sixpack $(date -u +%Y)" > "${BUILDDIR}/debian/copyright" echo "$NAME ($VERSION) $RELEASE; urgency=low * Initial release - -- Joe Sixpack $(date -R)" > "${BUILDDIR}/debian/changelog" + -- Joe Sixpack $(date -u -R)" > "${BUILDDIR}/debian/changelog" { echo "Source: $NAME Priority: $PRIORITY @@ -854,31 +882,33 @@ Description-en: $DESCRIPTION } insertsource() { - local RELEASE="$1" + local RELEASES="$1" local NAME="$2" local ARCH="$3" local VERSION="$4" local DEPENDENCIES="$5" - local BINARY="${6:-$NAME}" + local BINARY="${6:-$NAME}" local ARCHS="" - local SPATH="aptarchive/dists/${RELEASE}/main/source" - mkdir -p $SPATH - local FILE="${SPATH}/Sources" - local DSCFILE="${NAME}_${VERSION}.dsc" - local TARFILE="${NAME}_${VERSION}.tar.gz" - echo "Package: $NAME + for RELEASE in $(printf '%s' "$RELEASES" | tr ',' '\n'); do + local SPATH="aptarchive/dists/${RELEASE}/main/source" + mkdir -p $SPATH + local FILE="${SPATH}/Sources" + local DSCFILE="${NAME}_${VERSION}.dsc" + local TARFILE="${NAME}_${VERSION}.tar.gz" + echo "Package: $NAME Binary: $BINARY Version: $VERSION Maintainer: Joe Sixpack Architecture: $ARCH" >> $FILE - test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> "$FILE" - echo "Files: + test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> "$FILE" + echo "Files: $(echo -n "$DSCFILE" | md5sum | cut -d' ' -f 1) $(echo -n "$DSCFILE" | wc -c) "$DSCFILE" $(echo -n "$TARFILE" | md5sum | cut -d' ' -f 1) $(echo -n "$TARFILE" | wc -c) "$TARFILE" Checksums-Sha256: $(echo -n "$DSCFILE" | sha256sum | cut -d' ' -f 1) $(echo -n "$DSCFILE" | wc -c) "$DSCFILE" $(echo -n "$TARFILE" | sha256sum | cut -d' ' -f 1) $(echo -n "$TARFILE" | wc -c) "$TARFILE" " >> "$FILE" + done } insertinstalledpackage() { @@ -942,7 +972,7 @@ buildaptarchivefromfiles() { } compressfile() { - cat "${TMPWORKINGDIRECTORY}/rootdir/etc/testcase-compressor.conf" | while read compressor extension command; do + while read compressor extension command; do if [ "$compressor" = '.' ]; then if [ -n "$2" ]; then touch -d "$2" "$1" @@ -953,7 +983,7 @@ compressfile() { if [ -n "$2" ]; then touch -d "$2" "${1}.${extension}" fi - done + done < "${TMPWORKINGDIRECTORY}/rootdir/etc/testcase-compressor.conf" } # can be overridden by testcases for their pleasure @@ -1004,13 +1034,13 @@ NotAutomatic: yes' "$dir/Release" fi if [ -n "$DATE" -a "$DATE" != "now" ]; then for release in $(find ./aptarchive -name 'Release'); do - sed -i "s/^Date: .*$/Date: $(date -d "$DATE" '+%a, %d %b %Y %H:%M:%S %Z')/" "$release" + sed -i "s/^Date: .*$/Date: $(date -u -d "$DATE" '+%a, %d %b %Y %H:%M:%S %Z')/" "$release" touch -d "$DATE" "$release" done fi if [ -n "$VALIDUNTIL" ]; then sed -i "/^Date: / a\ -Valid-Until: $(date -d "$VALIDUNTIL" '+%a, %d %b %Y %H:%M:%S %Z')" $(find ./aptarchive -name 'Release') +Valid-Until: $(date -u -d "$VALIDUNTIL" '+%a, %d %b %Y %H:%M:%S %Z')" $(find ./aptarchive -name 'Release') fi msgdone "info" } @@ -1066,40 +1096,73 @@ setupaptarchive() { } signreleasefiles() { - local SIGNER="${1:-Joe Sixpack}" + local SIGNERS="${1:-Joe Sixpack}" local REPODIR="${2:-aptarchive}" - local KEY="keys/$(echo "$SIGNER" | tr 'A-Z' 'a-z' | sed 's# ##g')" - local GPG="aptkey --quiet --keyring ${KEY}.pub --secret-keyring ${KEY}.sec --readonly adv --batch --yes" - msgninfo "\tSign archive with $SIGNER key $KEY… " + if [ -n "$1" ]; then shift; fi + if [ -n "$1" ]; then shift; fi + local KEY="keys/$(echo "$SIGNERS" | tr 'A-Z' 'a-z' | tr -d ' ,')" + msgninfo "\tSign archive with $SIGNERS key $KEY… " local REXKEY='keys/rexexpired' local SECEXPIREBAK="${REXKEY}.sec.bak" local PUBEXPIREBAK="${REXKEY}.pub.bak" - if [ "${SIGNER}" = 'Rex Expired' ]; then - # the key is expired, so gpg doesn't allow to sign with and the --faked-system-time - # option doesn't exist anymore (and using faketime would add a new obscure dependency) - # therefore we 'temporary' make the key not expired and restore a backup after signing - cp "${REXKEY}.sec" "$SECEXPIREBAK" - cp "${REXKEY}.pub" "$PUBEXPIREBAK" - local SECUNEXPIRED="${REXKEY}.sec.unexpired" - local PUBUNEXPIRED="${REXKEY}.pub.unexpired" - if [ -f "$SECUNEXPIRED" ] && [ -f "$PUBUNEXPIRED" ]; then - cp "$SECUNEXPIRED" "${REXKEY}.sec" - cp "$PUBUNEXPIRED" "${REXKEY}.pub" - else - if ! printf "expire\n1w\nsave\n" | $GPG --default-key "$SIGNER" --command-fd 0 --edit-key "${SIGNER}" >setexpire.gpg 2>&1; then - cat setexpire.gpg - exit 1 + local SIGUSERS="" + while [ -n "${SIGNERS%%,*}" ]; do + local SIGNER="${SIGNERS%%,*}" + if [ "${SIGNERS}" = "${SIGNER}" ]; then + SIGNERS="" + fi + SIGNERS="${SIGNERS#*,}" + # FIXME: This should be the full name, but we can't encode the space properly currently + SIGUSERS="${SIGUSERS} -u ${SIGNER#* }" + if [ "${SIGNER}" = 'Rex Expired' ]; then + # the key is expired, so gpg doesn't allow to sign with and the --faked-system-time + # option doesn't exist anymore (and using faketime would add a new obscure dependency) + # therefore we 'temporary' make the key not expired and restore a backup after signing + cp "${REXKEY}.sec" "$SECEXPIREBAK" + cp "${REXKEY}.pub" "$PUBEXPIREBAK" + local SECUNEXPIRED="${REXKEY}.sec.unexpired" + local PUBUNEXPIRED="${REXKEY}.pub.unexpired" + if [ -f "$SECUNEXPIRED" ] && [ -f "$PUBUNEXPIRED" ]; then + cp "$SECUNEXPIRED" "${REXKEY}.sec" + cp "$PUBUNEXPIRED" "${REXKEY}.pub" + else + if ! printf "expire\n1w\nsave\n" | aptkey --quiet --keyring "${REXKEY}.pub" --secret-keyring "${REXKEY}.sec" \ + --readonly adv --batch --yes --digest-algo "${APT_TESTS_DIGEST_ALGO:-SHA512}" \ + --default-key "$SIGNER" --command-fd 0 --edit-key "${SIGNER}" >setexpire.gpg 2>&1; then + cat setexpire.gpg + exit 1 + fi + cp "${REXKEY}.sec" "$SECUNEXPIRED" + cp "${REXKEY}.pub" "$PUBUNEXPIRED" fi - cp "${REXKEY}.sec" "$SECUNEXPIRED" - cp "${REXKEY}.pub" "$PUBUNEXPIRED" fi + if [ ! -e "${KEY}.pub" ]; then + local K="keys/$(echo "$SIGNER" | tr 'A-Z' 'a-z' | tr -d ' ,')" + cat "${K}.pub" >> "${KEY}.new.pub" + cat "${K}.sec" >> "${KEY}.new.sec" + fi + done + if [ ! -e "${KEY}.pub" ]; then + mv "${KEY}.new.pub" "${KEY}.pub" + mv "${KEY}.new.sec" "${KEY}.sec" fi + local GPG="aptkey --quiet --keyring ${KEY}.pub --secret-keyring ${KEY}.sec --readonly adv --batch --yes --digest-algo ${APT_TESTS_DIGEST_ALGO:-SHA512}" for RELEASE in $(find "${REPODIR}/" -name Release); do - $GPG --default-key "$SIGNER" --armor --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" - local INRELEASE="$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" - $GPG --default-key "$SIGNER" --clearsign --output "$INRELEASE" "$RELEASE" # we might have set a specific date for the Release file, so copy it - touch -d "$(stat --format "%y" ${RELEASE})" "${RELEASE}.gpg" "${INRELEASE}" + local DATE="$(stat --format "%y" "${RELEASE}")" + if [ "$APT_DONT_SIGN" = 'Release.gpg' ]; then + rm -f "${RELEASE}.gpg" + else + testsuccess $GPG "$@" $SIGUSERS --armor --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" + touch -d "$DATE" "${RELEASE}.gpg" + fi + local INRELEASE="${RELEASE%/*}/InRelease" + if [ "$APT_DONT_SIGN" = 'InRelease' ]; then + rm -f "$INRELEASE" + else + testsuccess $GPG "$@" $SIGUSERS --clearsign --output "$INRELEASE" "$RELEASE" + touch -d "$DATE" "${INRELEASE}" + fi done if [ -f "$SECEXPIREBAK" ] && [ -f "$PUBEXPIREBAK" ]; then mv -f "$SECEXPIREBAK" "${REXKEY}.sec" @@ -1109,7 +1172,7 @@ signreleasefiles() { } redatereleasefiles() { - local DATE="$(date -d "$1" '+%a, %d %b %Y %H:%M:%S %Z')" + local DATE="$(date -u -d "$1" '+%a, %d %b %Y %H:%M:%S %Z')" for release in $(find aptarchive/ -name 'Release'); do sed -i "s/^Date: .*$/Date: ${DATE}/" "$release" touch -d "$DATE" "$release" @@ -1151,8 +1214,8 @@ rewritesourceslist() { local APTARCHIVE2="copy://$(readlink -f "${TMPWORKINGDIRECTORY}/aptarchive" | sed 's# #%20#g')" for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do sed -i $LIST -e "s#$APTARCHIVE#${1}#" -e "s#$APTARCHIVE2#${1}#" \ - -e "s#http://localhost:${APTHTTPPORT}/#${1}#" \ - -e "s#https://localhost:${APTHTTPSPORT}/#${1}#" + -e "s#http://[^@]*@\?localhost:${APTHTTPPORT}/\?#${1}#" \ + -e "s#https://[^@]*@\?localhost:${APTHTTPSPORT}/\?#${1}#" done } @@ -1181,7 +1244,7 @@ changetowebserver() { cd aptarchive local LOG="webserver.log" if ! aptwebserver --port 0 -o aptwebserver::fork=1 -o aptwebserver::portfile='aptwebserver.port' "$@" >$LOG 2>&1 ; then - cat $LOG + cat "$LOG" false fi waitforpidfile aptwebserver.pid @@ -1226,7 +1289,7 @@ connect = $APTHTTPPORT msgdie 'Could not fork stunnel4 successfully' fi addtrap 'prefix' "kill ${PID};" - APTHTTPSPORT="$(lsof -i | awk "/^stunnel4 / && \$2 == \"${PID}\" {print \$9; exit; }" | cut -d':' -f 2)" + APTHTTPSPORT="$(lsof -i -n | awk "/^stunnel4 / && \$2 == \"${PID}\" {print \$9; exit; }" | cut -d':' -f 2)" webserverconfig 'aptwebserver::port::https' "$APTHTTPSPORT" "https://localhost:${APTHTTPSPORT}" rewritesourceslist "https://localhost:${APTHTTPSPORT}/" } @@ -1251,7 +1314,7 @@ EOF # start with an unmounted disk mv "${CD}" "${CD}-unmounted" # we don't want the disk to be modifiable - addtrap 'prefix' "chmod -f -R +w \"$PWD/rootdir/media/cdrom/dists/\" \"$PWD/rootdir/media/cdrom-unmounted/dists/\" || true;" + addtrap 'prefix' "chmod -f -R +w '$(escape_shell "$PWD/rootdir/media/cdrom/dists/")' '$(escape_shell "$PWD/rootdir/media/cdrom-unmounted/dists/")' || true;" chmod -R 555 rootdir/media/cdrom-unmounted/dists } @@ -1316,9 +1379,13 @@ testfileequal() { testempty() { msggroup 'testempty' - msgtest "Test for no output of" "$*" + if [ "$1" = '--nomsg' ]; then + shift + else + msgtest "Test for no output of" "$*" + fi local COMPAREFILE="${TMPWORKINGDIRECTORY}/rootdir/tmp/testempty.comparefile" - if ("$@" >"$COMPAREFILE" 2>&1 || true) && test ! -s "$COMPAREFILE"; then + if "$@" >"$COMPAREFILE" 2>&1 && test ! -s "$COMPAREFILE"; then msgpass else msgfailoutput '' "$COMPAREFILE" "$@" @@ -1491,6 +1558,14 @@ testmarkedmanual() { msggroup } +catfile() { + if [ "${1##*.}" = 'deb' ]; then + stat >&2 "$1" || true + file >&2 "$1" || true + else + cat >&2 "$1" || true + fi +} msgfailoutput() { msgreportheader 'msgfailoutput' local MSG="$1" @@ -1500,7 +1575,7 @@ msgfailoutput() { echo >&2 while [ -n "$2" ]; do shift; done echo "#### Complete file: $1 ####" - cat >&2 "$1" || true + catfile "$1" echo '#### grep output ####' elif [ "$1" = 'test' ]; then echo >&2 @@ -1515,7 +1590,7 @@ msgfailoutput() { ls >&2 "$2" || true elif test -e "$2"; then echo "#### Complete file: $2 ####" - cat >&2 "$2" || true + catfile "$2" fi fi } @@ -1525,8 +1600,16 @@ msgfailoutput() { msgfailoutputstatfile "$2" "$3" done echo '#### test output ####' + elif [ "$1" = 'cmp' ]; then + echo >&2 + while [ -n "$2" ]; do + echo "#### Complete file: $2 ####" + catfile "$2" + shift + done + echo '#### cmp output ####' fi - cat >&2 "$OUTPUT" + catfile "$OUTPUT" msgfail "$MSG" } @@ -1625,8 +1708,9 @@ testfailure() { local EXITCODE=$? if expr match "$1" '^apt.*' >/dev/null; then if [ "$1" = 'aptkey' ]; then - if grep -q -E " Can't check signature: " "$OUTPUT" || \ - grep -q -E " BAD signature from " "$OUTPUT"; then + if grep -q " Can't check signature: + BAD signature from + signature could not be verified" "$OUTPUT"; then msgpass else msgfailoutput "run failed with exitcode ${EXITCODE}, but no signature error" "$OUTPUT" "$@" @@ -1764,6 +1848,51 @@ testwebserverlaststatuscode() { msggroup } +createlistofkeys() { + local OUTPUT="$1" + shift + while [ -n "$1" ]; do + # gpg 2.1.something starts printing [SC] at some point + if grep -q ' rsa2048/' "$OUTPUT" && grep -qF '[SC]' "$OUTPUT"; then + case "$1" in + *Joe*|*Sixpack*) echo 'pub rsa2048/DBAC8DAE 2010-08-18 [SC]';; + *Rex*|*Expired*) echo 'pub rsa2048/27CE74F9 2013-07-12 [SC] [expired: 2013-07-13]';; + *Marvin*|*Paranoid*) echo 'pub rsa2048/528144E2 2011-01-16 [SC]';; + oldarchive) echo 'pub rsa1024/F68C85A3 2013-12-19 [SC]';; + newarchive) echo 'pub rsa2048/DBAC8DAE 2010-08-18 [SC]';; + *) echo 'UNKNOWN KEY';; + esac + # gpg 2.1 has a slightly different output format + elif grep -q ' rsa2048/' "$OUTPUT"; then + case "$1" in + *Joe*|*Sixpack*) echo 'pub rsa2048/DBAC8DAE 2010-08-18';; + *Rex*|*Expired*) echo 'pub rsa2048/27CE74F9 2013-07-12 [expired: 2013-07-13]';; + *Marvin*|*Paranoid*) echo 'pub rsa2048/528144E2 2011-01-16';; + oldarchive) echo 'pub rsa1024/F68C85A3 2013-12-19';; + newarchive) echo 'pub rsa2048/DBAC8DAE 2010-08-18';; + *) echo 'UNKNOWN KEY';; + esac + else + case "$1" in + *Joe*|*Sixpack*) echo 'pub 2048R/DBAC8DAE 2010-08-18';; + *Rex*|*Expired*) echo 'pub 2048R/27CE74F9 2013-07-12 [expired: 2013-07-13]';; + *Marvin*|*Paranoid*) echo 'pub 2048R/528144E2 2011-01-16';; + oldarchive) echo 'pub 1024R/F68C85A3 2013-12-19';; + newarchive) echo 'pub 2048R/DBAC8DAE 2010-08-18';; + *) echo 'UNKNOWN KEY';; + esac + fi + shift + done +} +testaptkeys() { + local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/aptkeylist.output" + if ! aptkey list | grep '^pub' > "$OUTPUT"; then + echo -n > "$OUTPUT" + fi + testfileequal "$OUTPUT" "$(createlistofkeys "$OUTPUT" "$@")" +} + pause() { echo "STOPPED execution. Press enter to continue" local IGNORE @@ -1780,6 +1909,13 @@ listcurrentlistsdirectory() { done } | sort } +forallsupportedcompressors() { + rm -f "${TMPWORKINGDIRECTORY}/rootdir/etc/apt/apt.conf.d/00force-compressor" + for COMP in $(aptconfig dump 'APT::Compressor' --format '%f%n' | cut -d':' -f 5 | uniq); do + if [ -z "$COMP" -o "$COMP" = '.' ]; then continue; fi + "$@" "$COMP" + done +} ### convenience hacks ### mkdir() { @@ -1806,7 +1942,7 @@ aptautotest() { local TESTCALL="$1" local CMD="$2" local FIRSTOPT="$3" - local AUTOTEST="aptautotest_$(echo "${CMD##*/}_${FIRSTOPT}" | tr -d '-')" + local AUTOTEST="aptautotest_$(echo "${CMD##*/}_${FIRSTOPT}" | tr -d -c 'A-za-z0-9')" if command -v $AUTOTEST >/dev/null; then shift 3 # save and restore the *.output files from other tests