#!/bin/sh -e

# $NetBSD: rel-hashes.sh,v 1.5 2010/11/13 18:34:26 snj Exp $

#
# Generate hashes for all sets and iso files involved in a NetBSD release.  
# Just copy the file to a directory on ftp.n.o that you have r/w access to 
# (e.g. your home directory) and run it.
#
# e.g. ./rel-hashes.sh 3.0.1
#
# will create a NetBSD-3.0.1_hashes file in the current directory which can
# then be signed and copied to /ftp/pub/NetBSD/security/hashes/ on ftp.n.o
#
# The script assumes the release will be located under
# ${RELHOME}/${RELEASE_PREFIX}${RELEASE_VER}
#

#
# Comments/bugs/abuse: adrianp@NetBSD.org or security-officer@netbsd.org
#

# directories and files we need
DIGEST="/usr/bin/cksum -a"
ADIGEST="/usr/bin/openssl dgst -"
RELHOME=/ftp/pub/NetBSD
RELEASE_PREFIX=NetBSD-

# some tools we need
AWK=/usr/bin/awk
CAT=/bin/cat
CP=/bin/cp
RM=/bin/rm
LS=/bin/ls
FIND=/usr/bin/find
SED=/usr/bin/sed
ECHO=/bin/echo
PWD=/bin/pwd

# special variables for us - these can be added to later as necessary
SPECIAL="instfs.tgz diskimage.tgz rootfs.tgz"
HASHES="sha1 sha512 rmd160 md5"
BASE=`${PWD}`

# debug currently will not execute the digest commands but just show
# what command _would_ be run.  The output is in ${FINAL_HASHES}.
#
DEBUG=NO

# verbose will print a status message as it generates the digest for 
# each of the architecture directories processed.  In addition it will 
# also do the same for each .iso processed.
#
VERBOSE=YES

# turn debugging on if necessary
if [ "x${DEBUG}" = "xYES" ]; then
	NO_CKSUM=${ECHO}
else
	NO_CKSUM=""
fi

# generate the hash and double check it
hash()
{
	FILE=$1
	OUTPUT=$2

	for o in ${HASHES}; do
		D=`${NO_CKSUM} ${DIGEST} ${o} ${FILE}`
		AD=`${NO_CKSUM} ${ADIGEST}${o} ${FILE}`

		if [ "x${DEBUG}" = "xYES" ]; then
			${ECHO} ${D} >> ${OUTPUT}
			${ECHO} ${AD} >> ${OUTPUT}
		else
			V_D=`${ECHO} ${D} | ${AWK} '{print $4}'`
			V_AD=`${ECHO} ${AD} | ${AWK} '{print $2}'`
		
			if [ "x${V_D}" != "x${V_AD}" ]; then
				${ECHO} "ERROR: Digest mismatch on: ${FILE}"
				exit 1;
			else
				${ECHO} ${D} >> ${OUTPUT}
			fi
		fi
	done
}

# check a release name was specified
if [ "x$1" = "x" ]; then
	${ECHO} "Usage: $0 <netbsd_release>"
	${ECHO} "e.g. $0 3.0.1"
	exit 1;
else
	RELEASE_VER=$1
	RELEASE=${RELEASE_PREFIX}${RELEASE_VER}
	FINAL_HASHES=${BASE}/NetBSD-${RELEASE_VER}_hashes
	TEMP_HASHES=${FINAL_HASHES}.tmp
	if [ ! -d ${RELHOME}/${RELEASE} ]; then
		${ECHO} "Release directory ${RELHOME}/${RELEASE} does not exist."
		exit 1;
	fi
fi

# kill any existing files
${ECHO} "Cleaning up any existing files."
if [ -f ${TEMP_HASHES} ]; then
	${RM} -f ${TEMP_HASHES}
fi

if [ -f ${FINAL_HASHES} ]; then
	${RM} -f ${FINAL_HASHES}
fi

# get a list of all the directories we need to walk through
cd ${RELHOME}/${RELEASE} && SUBS=`${LS}`
cd ${RELHOME}
${ECHO} "Generating checksums."

# All contents, except MD5 and SHA512 files
for s in ${SUBS}; do
	if [ "x${VERBOSE}" = "xYES" ]; then
		${ECHO} "Generating checksums for: ${s}."
	fi
	FILES=`$FIND -L ${RELEASE}/${s} -type f  \! -name ' \?\*' \! -name MD5 \! -name SHA512 -print`
	for f in ${FILES}; do
		hash ${f} ${TEMP_HASHES}
	done
done

# generate the final file hash file
cd ${BASE}
${CAT} <<HEADER > ${FINAL_HASHES}


The following is a complete list of distribution files for ${RELEASE}

This includes all binary distributions, kernels, install images,
source tarballs, release notes and related files.  Multiple hash
formats are used for each file.

Signatures will be made available for any additional install media as
they are published.

						NetBSD Security-Officer
						security-officer@NetBSD.org

HEADER

${CAT} ${TEMP_HASHES} >> ${FINAL_HASHES}
${RM} -f ${TEMP_HASHES}

# final instructions 
if [ -f ${FINAL_HASHES} ]; then
	${ECHO}
	${ECHO} "Please now sign the output as follows:"
	${ECHO} "gpg -sta -u security-officer ${FINAL_HASHES}"
fi

exit 0;
