On Fri, Dec 21, 2001 at 01:04:41AM +0000, toad wrote:
> Errm, whoops. Release is signed, it includes MD5's of the Packages files.
> I wonder if it's ever verified at the client level...
It's not, no.
The attached script, if run after every apt-get update, should verify
all the information apt uses to do installs and upgrades, from signed
Release files, though.
It's very alpha quality and could use someone to maintain it and make it
a little less verbose when there aren't any problems. It's also not very
widely tested, and not supported atm. At the moment, Release signatures
aren't particularly supported either, although if/when people have actually
tested them on the client side a bit, they probably will be.
The keys used to sign Release.gpg files are available at:
http://ftp-master.debian.org/ziyi_key2.asc
http://ftp-master.debian.org/ziyi_key.asc
and need to be added to your ~/.gnupg/trustedkeys.gpg keyring (for
/usr/bin/gpgv). Note that one's revoked and the other's due to expire
early in the new year.
Cheers,
aj
--
Anthony Towns <aj@humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. GPG signed mail preferred.
The daffodils are coming. Are you?
linux.conf.au, February 2002, Brisbane, Australia
--- http://www.linux.org.au/conf
#!/bin/bash
# Copyright (c) 2001 Anthony Towns <ajt@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
rm -rf /tmp/apt-release-check
mkdir /tmp/apt-release-check || exit 1
cd /tmp/apt-release-check
>OK
>MISSING
>NOCHECK
>BAD
arch=`dpkg --print-installation-architecture`
am_root () {
[ `id -u` -eq 0 ]
}
get_md5sumsize () {
cat "$1" | awk '/^MD5Sum:/,/^SHA1:/' |
MYARG="$2" perl -ne '@f = split /\s+/; if ($f[3] eq $ENV{"MYARG"}) { print "$f[1] $f[2]\n"; exit(0); }'
}
checkit () {
local FILE="$1"
local LOOKUP="$2"
Y="`get_md5sumsize Release "$LOOKUP"`"
Y="`echo "$Y" | sed 's/^ *//;s/ */ /g'`"
if [ ! -e "/var/lib/apt/lists/$FILE" ]; then
if [ "$Y" = "" ]; then
# No file, but not needed anyway
echo "OK"
return
fi
echo "$FILE" >>MISSING
echo "MISSING $Y"
return
fi
if [ "$Y" = "" ]; then
echo "$FILE" >>NOCHECK
echo "NOCHECK"
return
fi
X="`md5sum < /var/lib/apt/lists/$FILE` `wc -c < /var/lib/apt/lists/$FILE`"
X="`echo "$X" | sed 's/^ *//;s/ */ /g'`"
if [ "$X" != "$Y" ]; then
echo "$FILE" >>BAD
echo "BAD"
return
fi
echo "$FILE" >>OK
echo "OK"
}
echo
echo "Checking sources in /etc/apt/sources.list:"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo
(echo "You should take care to ensure that the distributions you're downloading"
echo "are the ones you think you are downloading, and that they are as up to"
echo "date as you would expect (testing and unstable should be no more than"
echo "two or three days out of date, stable-updates no more than a few weeks"
echo "or a month)."
) | fmt
echo
cat /etc/apt/sources.list |
sed 's/^ *//' | grep '^[^#]' |
while read ty url dist comps; do
if [ "${url%%:*}" = "http" -o "${url%%:*}" = "ftp" ]; then
baseurl="${url#*://}"
else
continue
fi
echo "Source: ${ty} ${url} ${dist} ${comps}"
rm -f Release Release.gpg
wget -q -O Release "${url}/dists/${dist}/Release"
if ! grep -q '^' Release; then
echo " * NO TOP-LEVEL Release FILE"
else
origline=`sed -n 's/^Origin: *//p' Release | head -1`
lablline=`sed -n 's/^Label: *//p' Release | head -1`
suitline=`sed -n 's/^Suite: *//p' Release | head -1`
codeline=`sed -n 's/^Codename: *//p' Release | head -1`
dateline=`grep "^Date:" Release | head -1`
dscrline=`grep "^Description:" Release | head -1`
echo " o Origin: $origline/$lablline"
echo " o Suite: $suitline/$codeline"
echo " o $dateline"
echo " o $dscrline"
if [ "${dist%%/*}" != "$suitline" -a "${dist%%/*}" != "$codeline" ]; then
echo " * WARNING: asked for $dist, got $suitline/$codeline"
fi
wget -q -O Release.gpg "${url}/dists/${dist}/Release.gpg"
gpgv --status-fd 3 Release.gpg Release 3>&1 >/dev/null 2>&1 | sed -n "s/^\[GNUPG:\] //p" | (okay=0; while read gpgcode rest; do
if [ "$gpgcode" = "GOODSIG" ]; then
echo " o Signed by: ${rest#* }"
okay=1
elif [ "$gpgcode" = "BADSIG" ]; then
echo " * BAD SIGNATURE BY: ${rest#* }"
fi
done
if [ "$okay" != 1 ]; then
echo " * NO VALID SIGNATURE"
>Release
fi)
fi
okaycomps=""
for comp in $comps; do
if [ "$ty" = "deb" ]; then
X=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/binary-${arch}/Release" | sed 's,//*,_,g'`" "${comp}/binary-${arch}/Release")
Y=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/binary-${arch}/Packages" | sed 's,//*,_,g'`" "${comp}/binary-${arch}/Packages")
if [ "$X $Y" = "OK OK" ]; then
okaycomps="$okaycomps $comp"
else
echo " * PROBLEMS WITH $comp ($X, $Y)"
fi
elif [ "$ty" = "deb-src" ]; then
X=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/source/Release" | sed 's,//*,_,g'`" "${comp}/source/Release")
Y=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/source/Sources" | sed 's,//*,_,g'`" "${comp}/source/Sources")
if [ "$X $Y" = "OK OK" ]; then
okaycomps="$okaycomps $comp"
else
echo " * PROBLEMS WITH component $comp ($X, $Y)"
fi
fi
done
[ "$okaycomps" = "" ] || echo " o Okay:$okaycomps"
echo
done
echo "Results"
echo "~~~~~~~"
echo
allokay=true
cd /tmp/apt-release-check
diff <(cat BAD MISSING NOCHECK OK | sort) <(cd /var/lib/apt/lists && find . -type f -maxdepth 1 | sed 's,^\./,,g' | grep '_' | sort) | sed -n 's/^> //p' >UNVALIDATED
cd /tmp/apt-release-check
if grep -q ^ UNVALIDATED; then
allokay=false
(echo "The following files in /var/lib/apt/lists have not been validated."
echo "This could turn out to be a harmless indication that this script"
echo "is buggy or out of date, or it could let trojaned packages get onto"
echo "your system."
) | fmt
echo
sed 's/^/ /' < UNVALIDATED
echo
fi
if grep -q ^ BAD; then
allokay=false
(echo "The contents of the following files in /var/lib/apt/lists does not"
echo "match what was expected. This may mean these sources are out of date,"
echo "that the archive is having problems, or that someone is actively"
echo "using your mirror to distribute trojans."
if am_root; then
echo "The files have been renamed to have the extension .FAILED and"
echo "will be ignored by apt."
cat BAD | while read a; do
mv /var/lib/apt/lists/$a /var/lib/apt/lists/${a}.FAILED
done
fi) | fmt
echo
sed 's/^/ /' < BAD
echo
fi
if grep -q ^ MISSING; then
allokay=false
(echo "The following files from /var/lib/apt/lists were missing. This"
echo "may cause you to miss out on updates to some vulnerable packages."
) | fmt
echo
sed 's/^/ /' < MISSING
echo
fi
if grep -q ^ NOCHECK; then
allokay=false
(echo "The contents of the following files in /var/lib/apt/lists could not"
echo "be validated due to the lack of a signed Release file, or the lack"
echo "of an appropriate entry in a signed Release file. This probably"
echo "means that the maintainers of these sources are slack, but may mean"
echo "these sources are being actively used to distribute trojans."
if am_root; then
echo "The files have been renamed to have the extension .FAILED and"
echo "will be ignored by apt."
cat NOCHECK | while read a; do
mv /var/lib/apt/lists/$a /var/lib/apt/lists/${a}.FAILED
done
fi) | fmt
echo
sed 's/^/ /' < NOCHECK
echo
fi
if $allokay; then
echo 'Everything seems okay!'
echo
fi
rm -rf /tmp/apt-release-check
Attachment:
pgp9xIzjYxVJU.pgp
Description: PGP signature