#!/bin/bash
#
# kernel.sh v1.1 2005/05
#
# download and digital signature verification tool
#
# Copyright (C) 2005 by Pedro Venda < pjvenda (at) pjvenda org >
#
# Distributed under the terms of the GNU Public License Agreement (GPLv2)
# http://www.fsf.org/licensing/licenses/gpl.html or
# http://www.fsf.org/licensing/licenses/gpl.txt
#
# Changelog
# =========
#
# v1.2 - 2007/03/22
# - small cleanup
# - support for destination directory
#
# v1.1 - 2005/06/13
# - added helptext and dependency info
# - minor bug corrections
#
# v1.0 - 2005/05/06
# - first version
#

GPG_BIN="/usr/bin/gpg"
KERNEL_URL_MIRROR="http://www.kernel.org"
KERNEL_URL_PATH="/pub/linux/kernel/v2.6/"
SRC_DIR="/usr/src/kernel_src"
PATCH_EXTENSION="bz2"
KERNEL_EXTENSION="bz2"
KEYSERVER_URL="wwwkeys.pgp.net"
GPG_KERNEL_KEYID="0x517D0F0E"
WGET_BIN="/usr/bin/wget"
MKDIR_BIN="/usr/bin/mkdir"

show_help() {
	echo "usage: kernel.sh {kernel|patch} version"
}

show_dependencies() {
	echo ""
	echo "this script requires the following binaries:"
	echo "  wget - multiprotocol internet file fetching program"
	echo "  gpg - implementation of assymetric key manager"
	echo "  tar - tape archiver"
	echo "  gzip/bzip2 - common compressors/uncompressors"
	echo ""
	echo "if any of those are reported missing, you can't use this script as is"
}

check_gpg_binary() {
${GPG_BIN} --version > /dev/null 2>&1
if [ ! $? = 0 ]; then
        echo "gpg binary not found or not in ${GPG_BIN}"
	GPG=0
else
	GPG=1
fi
}

check_wget_binary() {
${WGET_BIN} --version > /dev/null 2>&1
if [ ! $? = 0 ]; then
        echo "wget binary not found or not in ${WGET_BIN}"
	WGET=0
else
	WGET=1
fi
}

check_gpg_key() {

	if [ ${GPG} = "0" ]; then
		return;
	fi
	${GPG_BIN} -q --list-keys ${GPG_KERNEL_KEYID} > /dev/null 2>&1
	if [ ! $? = 0 ]; then
		echo -n "kernel public key not found: fetching key ${GPG_KERNEL_KEYID} ... "
		${GPG_BIN} -q --keyserver ${KEYSERVER_URL} --recv-keys ${GPG_KERNEL_KEYID} > /dev/null 2>&1
		if [ ! $? = 0 ]; then
			echo "failed"
			GPG=0
		fi
		echo "done"
		GPG=1
	else
		GPG=1
	fi
}

get_file() {
	if [ ! -f ${SRC_DIR}/${1} ]; then
		echo -n "	getting ${1} ... "
		${WGET_BIN} -q -c -P ${SRC_DIR} ${KERNEL_URL_MIRROR}/${KERNEL_URL_PATH}/${1}	
		if [ $? = "0" ]; then
			echo "done"
		else
			echo "failed"
		fi
		return 0;
	else
		echo "	${1} already exists: not downloading"
	fi
}

check_file() {
	echo "	checking with ${1}"
	if [ ! -f ${1} ]; then
		echo "	no signature found: trying to fetch ... "
		get_file ${1}
	fi
	${GPG_BIN} -q --verify ${1} > /dev/null 2>&1
	if [ $? = "0" ]; then
		echo "	signature OK"
	else
		echo "	WARNING: signature not valid!!"
	fi
}

get_kernel_patch() {
	echo "requested kernel patch version ${1} "
	PATCH_FILE=patch-${1}.${PATCH_EXTENSION}
	PATCH_SIGNATURE=${PATCH_FILE}.sign
	get_file ${PATCH_FILE}
	get_file ${PATCH_SIGNATURE}
}

check_kernel_patch() {
	if [ ${GPG} = "0" ]; then
		echo "unable to check digital signature"
		return;
	fi
	echo "checking signature for kernel patch version ${1}"
	check_file ${SRC_DIR}/patch-${1}.${PATCH_EXTENSION}.sign
}

get_kernel() {
	echo "requested kernel version ${1} "
	KERNEL_FILE=linux-${1}.tar.${KERNEL_EXTENSION}
	KERNEL_SIGNATURE=${KERNEL_FILE}.sign
	get_file ${KERNEL_FILE}
	get_file ${KERNEL_SIGNATURE}
}

check_kernel() {
	if [ ${GPG} = "0" ]; then
		echo "unable to check digital signature"
		return;
	fi
	echo "checking signature for kernel version ${1}"
	check_file ${SRC_DIR}/linux-${1}.tar.${KERNEL_EXTENSION}.sign
}

# STEP 0: check arguments
if ((${#} < 2)); then
	echo "not enough arguments"
	show_help
	exit 1;
fi

# STEP 1: validate arguments
if [ ! ${1} = "patch" ] && [ ! ${1} = "kernel" ] && [ ! ${1} = "check" ]; then
	echo "invalid arguments"
	show_help
	exit 1;
fi
# STEP 1.1: verify existing destination directory
if [ ! -d ${SRC_DIR} ]; then
	${MKDIR_BIN} -p ${SRC_DIR}
fi

check_wget_binary
if [ ${WGET} = "0" ]; then
	show_dependencies
	exit 1;
fi
# STEP 2: check for gpg binary
check_gpg_binary
# STEP 3: check for gpg public key
check_gpg_key

# STEP 3.1: patch request?
if [ ${1} = "patch" ]; then
	get_kernel_patch ${2}
	check_kernel_patch ${2}
fi

# STEP 3.2: kernel request?
if [ ${1} = "kernel" ]; then
	get_kernel ${2}
	check_kernel ${2}
fi
