NetBSD/share/examples/veriexecctl/fpgen.sh

220 lines
6.0 KiB
Bash
Executable File

#!/bin/sh
#
# $NetBSD: fpgen.sh,v 1.3 2005/09/03 10:22:21 elad Exp $
#
# Copyright 2005 Brett Lymn <blymn@netbsd.org>
# Copyright 2005 Elad Efrat <elad@netbsd.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Neither the name of The NetBSD Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#
# This script will scan FFS filesystems for files, adding digital
# fingerprints of files to a text database. It also makes sure that the
# same file will not be added twice - ie., hardlinks.
#
# Options:
# -d <dir> start scanning from <dir> (absolute path)
# -r do recursive scanning
# -a scan all files (not only executables)
# -q be quiet (no output)
#
# Usage pattern: fpgen.sh [flags] <hash> <database file>
# Examples:
# ./fpgen.sh -r md5 /etc/signatures (scan recursively from current dir)
# ./fpgen.sh -ar sha1 /etc/signatures (all files recursively from current dir)
# ./fpgen.sh -d /bin rmd160 /etc/signatures (only executables in /bin)
CKSUM="/usr/bin/cksum"
# Get inode of given file.
inode() {
local _inode=`/bin/ls -li $1 | /usr/bin/cut -d' ' -f1`
echo "$_inode"
}
# Go through the provided file, getting filenames. (first field)
# For each filename, get its inode, and compare with the inode we want
# to add.
# Returns 0 if we can add it or 1 if it's already added.
check_dup() {
local _file="$1"
local _inode="$2"
local _ret="0"
while read line; do
if [ ${line} ]; then
_ret="1"
#entry=`echo $line | /usr/bin/cut -d' ' -f1`
#entry_inode=`inode $entry`
#if [ "${_inode}" = "${entry_inode}" ]; then
# _ret="1"
# break
#fi
fi
done < $_file
echo "$_ret"
}
# End of subroutines.
# Defaults
find_pattern="-perm -0100 -or -perm -0010 -or -perm -0001"
recurse="-maxdepth 1"
rootdir="$PWD"
howdeep="non-recursive"
scanwhat="executables only"
quiet="0"
# Sanity
if [ $# -lt 2 -o $# -gt 6 ]; then
echo "Usage: $0 [-a|-r|-d <dir>] [-q] <hash_type> <fingerprint_file>"
echo "(a)ll files; (r)ecursive scan; (d)irectory root."
echo ""
echo "See the man page for cksum for the supported"
echo "hash types. Hash type names are of the form sha1, sha384,"
echo "rmd160, and so forth"
exit 2
fi
# Parse arguments: Build search pattern and set root dir.
set -- `getopt qard: $*`
for i do
case "$i" in
-a) scanwhat="all files"; find_pattern="! -perm 0000"; shift;;
-d) rootdir=$2; shift; shift;;
-r) howdeep="recursive"; recurse=; shift;;
-q) quiet="1"; shift;;
esac
done
# Set hash type and command (ghetto) and output file
hashtype=$2;
dbfile=$3;
# Make sure we have a hash type
if [ -z "${hashtype}" ]; then
echo "ERROR: No hash algorithm: Aborting."
exit;
fi
# Make sure we have a target file.
if [ -z "${dbfile}" ]; then
echo "ERROR: No DB file. Aborting."
exit
fi
if [ -e ${CKSUM} ]; then
hashcmd="${CKSUM} -a ${hashtype}"
# Make sure hash type is supported.
echo "foo foo foo" | ${hashcmd} > /dev/null 2>&1
if [ "$?" != 0 ]; then
echo "ERROR: ${CKSUM} does not support the hash ${hashtype}"
exit 1
fi
else
echo "ERROR: No ${CKSUM}! Aborting."
exit 1
fi
if [ "${quiet}" = "0" ]; then
echo "Verified Exec Fingerprint Generator, v0.1"
echo
echo "Command : \"${hashcmd}\""
echo "Root dir: \"${rootdir}\" [${howdeep}]"
echo "DB file : \"${dbfile}\""
echo "Mode : ${scanwhat}"
echo
fi
# Backup existing file (if got one)
if [ -e "${dbfile}" ]; then
if [ "${quiet}" = "0" ]; then
echo "NOTE: Backing up existing fingerprint file to \"${dbfile}.old\"."
echo
fi
mv ${dbfile} ${dbfile}.old
fi
echo "# Generated by `whoami`, `date`, for ${rootdir}" > ${dbfile}
# Create temporary file.
done="0"
tmpfile=`mktemp /tmp/vexecctl.XXXXXXXXXX`
# XXX: egrep -v ^/kern
# XXX: do we need the lib*so* thing?
find $rootdir $recurse \( \( -fstype ffs -and -type f -and \( $find_pattern \) \) \
-or -name "lib*so*" \) | egrep -v '^/proc.*' > $tmpfile
while read file; do
hash=`${hashcmd} < ${file} 2>/dev/null`
flag=""
if [ -z "${hash}" ]; then
continue
fi
# Non-executables need the "FILE" flag
if [ ! -x $file ]; then
flag=" FILE"
fi
# Check if already in database under a different name. (hardlink)
_ret="0"
_inode=`inode $file`
while read line; do
line2=`echo ${line} | awk -F# '{print $1}'`
if [ -n "${line2}" ]; then
entry=`echo ${line2} | /usr/bin/cut -d' ' -f1`
entry_inode=`inode ${entry}`
if [ X"${_inode}" = X"${entry_inode}" ]; then
_ret="1"
break
fi
fi
done < $dbfile
# Add to the database.
if [ X"${_ret}" = X"0" -a -n "${hash}" -a -n "${file}" ]; then
if [ $quiet = "0" ]; then
echo "Adding $file."
fi
echo "$file ${hashtype} ${hash}${flag}" >> $dbfile
fi
done < $tmpfile
echo >> ${dbfile}
if [ $quiet = "0" ]; then
echo
echo "###############################################################"
echo " PLEASE VERIFY CONTENTS OF $dbfile AND FINE-TUNE THE"
echo " FLAGS WHERE APPROPRIATE AFTER READING veriexecctl(8)"
echo "###############################################################"
fi
rm -f ${tmpfile}