[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bulk signing



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


Reply to: