aboutsummaryrefslogtreecommitdiff
path: root/security/portaudit/files/portaudit-cmd.sh
diff options
context:
space:
mode:
Diffstat (limited to 'security/portaudit/files/portaudit-cmd.sh')
-rw-r--r--security/portaudit/files/portaudit-cmd.sh390
1 files changed, 330 insertions, 60 deletions
diff --git a/security/portaudit/files/portaudit-cmd.sh b/security/portaudit/files/portaudit-cmd.sh
index 99fdcbde8bbd..1f90e921f9d2 100644
--- a/security/portaudit/files/portaudit-cmd.sh
+++ b/security/portaudit/files/portaudit-cmd.sh
@@ -1,4 +1,4 @@
-#!/bin/sh -e
+#!/bin/sh -efu
#
# Copyright (c) 2004 Oliver Eikemeier. All rights reserved.
#
@@ -6,8 +6,8 @@
# 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.
+# 1. Redistributions of source code must retain the above copyright notice
+# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
@@ -31,35 +31,325 @@
# $FreeBSD$
#
-. %%DATADIR%%/portaudit.functions
+portaudit_confs()
+{
+ portaudit_dir=${portaudit_dir:-"%%DATABASEDIR%%"}
+ portaudit_filename=${portaudit_filename:-"auditfile.tbz"}
+
+ portaudit_fetch_env=${portaudit_fetch_env:-}
+ portaudit_fetch_cmd=${portaudit_fetch_cmd:-"fetch -1amp"}
+
+ portaudit_sites=${portaudit_sites:-"http://www.FreeBSD.org/ports/"}
+
+ if [ -r %%PREFIX%%/etc/portaudit.conf ]; then
+ . %%PREFIX%%/etc/portaudit.conf
+ fi
+}
+
+extract_auditfile()
+{
+ %%BZIP2_CMD%% -dc -- "$portaudit_dir/$portaudit_filename" | \
+ tar -xOf - auditfile
+}
+
+checksum_auditfile()
+{
+ chksum1=`extract_auditfile |
+ sed -nE -e '$s/^#CHECKSUM: *MD5 *([0-9a-f]{32})$/\1/p'`
+ chksum2=`extract_auditfile | sed -e '$d' | md5`
+ [ "$chksum1" = "$chksum2" ];
+}
+
+getcreated_auditfile()
+{
+ extract_auditfile |
+ sed -nE -e '1s/^#CREATED: *([0-9]{4})-?([0-9]{2})-?([0-9]{2}) *([0-9]{2}):?([0-9]{2}):?([0-9]{2}).*$/\1-\2-\3 \4:\5:\6/p'
+}
+
+gettimestamp_auditfile()
+{
+ extract_auditfile |
+ sed -nE -e '1s/^#CREATED: *([0-9]{4})-?([0-9]{2})-?([0-9]{2}).*$/\1\2\3/p'
+}
+
+checkexpiry_auditfile()
+{
+ created=`gettimestamp_auditfile`
+ expiry=`date -u -v-$1d '+%Y%m%d'`
+ [ "$created" -gt "$expiry" ];
+}
+
+portaudit_prerequisites()
+{
+ if $prerequisites_checked; then
+ return 0
+ fi
+
+ if [ -z "${pkg_info:-}" ]; then
+ if [ -x "%%LOCALBASE%%/sbin/pkg_info" ]; then
+ pkg_info="%%LOCALBASE%%/sbin/pkg_info"
+ else
+ pkg_info="/usr/sbin/pkg_info"
+ fi
+ fi
+
+ if [ -z "${pkg_version:-}"]; then
+ case "$pkg_info" in
+ */*)
+ pkg_version="${pkg_info%/*}/pkg_version";;
+ *)
+ pkg_version="pkg_version";;
+ esac
+ fi
+
+ PKG_INSTALL_VER=`$pkg_info -qP 2>/dev/null`
+ if [ -z "$PKG_INSTALL_VER" -o "$PKG_INSTALL_VER" -lt %%REQPKGVER%% ]; then
+ echo "$pkg_info is too old, please update port sysutils/pkg_install-devel"
+ return 1
+ fi
+
+ if [ ! -r "$portaudit_dir/$portaudit_filename" ]; then
+ echo "portaudit: Database missing, run \`portaudit -F' to update." >&2
+ return 2
+ elif ! checksum_auditfile; then
+ echo "portaudit: Corrupt database." >&2
+ return 2
+ elif ! checkexpiry_auditfile 14; then
+ echo "portaudit: Database too old." >&2
+ return 2
+ fi
+
+ prerequisites_checked=true
+ return 0
+}
+
+audit_installed()
+{
+ local rc=0
+
+ extract_auditfile | awk -F\| '
+ BEGIN { vul=0 }
+ /^(#|\$)/ { next }
+ {
+ cmd="'"$pkg_info"' -E \"" $1 "\""
+ while((cmd | getline pkg) > 0) {
+ vul++
+ split($2, ref, / /)
+ print "Affected package: " pkg
+ print "Type of problem: " $3 "."
+ for (r in ref)
+ print "Reference: <" ref[r] ">"
+ print ""
+ }
+ close(cmd)
+ }
+ END {
+ print vul " problem(s) in your installed packages found."
+ if (vul > 0) {
+ print "\nYou are advised to update or deinstall" \
+ " the affected package(s) immediately."
+ exit(1)
+ }
+ }
+ ' || rc=$?
+
+ return $rc
+}
+
+audit_file()
+{
+ local rc=0
+ local TMPFILE=
+
+ case "$1" in
+ -)
+ TMPFILE=`mktemp -t portaudit`
+ cat > "$TMPFILE"
+ FILE="$TMPFILE"
+ ;;
+ http://*|ftp://*|https://*|file://*)
+ echo "portaudit: Can't audit remote file $1" >&2
+ return 2
+ ;;
+ *)
+ if [ -r "$1" ]; then
+ FILE="$1"
+ else
+ echo "portaudit: Can't read $1" >&2
+ return 2
+ fi
+ ;;
+ esac
+
+ extract_auditfile | awk -F\| '
+ BEGIN { vul=0 }
+ /^(#|\$)/ { next }
+ {
+ cmd="'"$pkg_version"' -T - \"" $1 "\" <\"'"$FILE"'\""
+ while((cmd | getline pkg) > 0) {
+ vul++
+ split($2, ref, / /)
+ split(pkg, p)
+ print "Affected package: " p[1]
+ print "Type of problem: " $3 "."
+ for (r in ref)
+ print "Reference: <" ref[r] ">"
+ print ""
+ }
+ close(cmd)
+ }
+ END {
+ print vul " problem(s) found."
+ if (vul > 0) {
+ exit(1)
+ }
+ }
+ ' || rc=$?
+
+ if [ -n "$TMPFILE" ]; then
+ rm "$TMPFILE"
+ fi
+ return $rc
+}
+
+audit_args()
+{
+ local VULCNT=0
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ /*|-)
+ echo "portaudit: $1 is a file, please use the -f option" >&2
+ ;;
+ http://*|ftp://*|https://*|file://*)
+ echo "portaudit: Can't audit remote file $1" >&2
+ ;;
+ *)
+ if VLIST=`extract_auditfile | grep -v '^#' | $pkg_version -T "$1" -`; then
+ VULCNT=$(($VULCNT+1))
+ echo "$VLIST" | awk -F\| '{
+ print "Affected package: '$1' (matched by " $1 ")"
+ print "Type of problem: " $3 "."
+ split($2, ref, / /)
+ for (r in ref)
+ print "Reference: <" ref[r] ">"
+ print ""
+ }'
+ fi
+ ;;
+ esac
+ shift
+ done
+ $opt_quiet || echo "$VULCNT problem(s) found."
+ if [ $VULCNT -gt 0 ]; then
+ return 1
+ fi
+}
+
+audit_cwd()
+{
+ if [ ! -r "Makefile" ]; then
+ echo "portaudit: No Makefile here" >&2
+ return 2
+ fi
+
+ PKGNAME=`make -VPKGNAME 2>/dev/null || true"`
+
+ if [ -z "$PKGNAME" ]; then
+ echo "portaudit: Can't determine the package name" >&2
+ return 2
+ fi
+
+ if VLIST=`extract_auditfile | grep -v '^#' | $pkg_version -T "$PKGNAME" -`; then
+ echo "$VLIST" | awk -F\| '{
+ print "Affected package: '$PKGNAME' (matched by " $1 ")"
+ print "Type of problem: " $3 "."
+ split($2, ref, / /)
+ for (r in ref)
+ print "Reference: <" ref[r] ">"
+ print ""
+ }'
+ return 1
+ fi
+}
+
+fetch_auditfile()
+{
+ local rc=2
+
+ if [ ! -d "$portaudit_dir" ]; then
+ if ! mkdir -p "$portaudit_dir"; then
+ echo "Couldn't create $portaudit_dir, try running \`portaudit -F' as root" >&2
+ return 2
+ fi
+ fi
+ if [ ! -w "$portaudit_dir" ]; then
+ echo "Couldn't write to $portaudit_dir, try running \`portaudit -F' as root" >&2
+ return 2
+
+ fi
+ cd "$portaudit_dir"
+ if [ -r "$portaudit_filename" ]; then
+ cp -f "$portaudit_filename" "$portaudit_filename.old"
+ fi
+
+ $opt_verbose && echo "Attempting to fetch from $portaudit_site."
+ urls=`echo "$portaudit_sites" | tr -s ' \t' '\n' | sed -E -e "s/?\$/$portaudit_filename"`
+
+ if ! env $portaudit_fetch_env $portaudit_fetch_cmd $urls; then
+ echo "Couldn't fetch database." >&2
+ elif [ ! -f "$portaudit_dir/$portaudit_filename" ] ; then
+ echo "portaudit: No database." >&2
+ elif ! checksum_auditfile; then
+ echo "portaudit: Database corrupt." >&2
+ elif ! checkexpiry_auditfile 7; then
+ echo "portaudit: Database too old." >&2
+ else
+ $opt_quiet || echo "New database installed."
+ rc=0
+ break
+ fi
+
+ if [ -f "$portaudit_filename.old" ]; then
+ if [ $rc -eq 0 ]; then
+ rm -f "$portaudit_filename.old"
+ else
+ mv -f "$portaudit_filename.old" "$portaudit_filename"
+ $opt_quiet || echo "Old database restored."
+ fi
+ fi
+ if [ -f "$portaudit_filename" ]; then
+ chmod a=r "$portaudit_filename"
+ fi
+
+ return $rc
+}
+
portaudit_confs
opt_audit=false
opt_auditcwd=false
-opt_audittree=false
opt_dbversion=false
opt_fetch=false
opt_file=
opt_quiet=false
opt_verbose=false
opt_version=false
+opt_expiry=
if [ $# -eq 0 ] ; then
opt_audit=true
fi
-while getopts aACdf:FqvV opt; do
+while getopts aCdf:FqvVX: opt; do
case "$opt" in
a)
opt_audit=true;;
- A)
- opt_audittree=true;;
C)
opt_auditcwd=true;;
d)
opt_dbversion=true;;
f)
- opt_file=$OPTARG;;
+ opt_file="$OPTARG";;
F)
opt_fetch=true;;
q)
@@ -68,91 +358,71 @@ while getopts aACdf:FqvV opt; do
opt_verbose=true;;
V)
opt_version=true;;
+ X)
+ opt_expiry="$OPTARG";;
?)
- echo "Usage: $0 -aACvVdFq [-f file]"
+ echo "Usage: $0 -aCdF [-f file] [pkg-name ...]"
exit 2;;
esac
done
-shift $((${OPTIND}-1))
+shift $(($OPTIND-1))
+
+ret=0
if $opt_version; then
echo "portaudit version %%PORTVERSION%%"
fi
if $opt_fetch; then
- fetch_auditfile || echo "failed."
+ if ! fetch_auditfile; then
+ echo "portaudit: Download failed." >&2
+ exit 2
+ fi
+elif [ -n "$opt_expiry" ]; then
+ if [ ! -r "$portaudit_dir/$portaudit_filename" ] || ! checkexpiry_auditfile "$opt_expiry"; then
+ $opt_quiet || echo "Downloading fresh database."
+ if ! fetch_auditfile; then
+ echo "portaudit: Download failed." >&2
+ exit 2
+ fi
+ ret=1
+ fi
fi
if $opt_dbversion; then
- if [ ! -f "${portaudit_dir}/${portaudit_filename}" ]; then
- echo "portaudit: database missing. run \`portaudit -F' to update."
+ if [ ! -f "$portaudit_dir/$portaudit_filename" ]; then
+ echo "portaudit: Database missing, run \`portaudit -F' to update." >&2
exit 2
fi
if ! checksum_auditfile; then
- echo "portaudit: database corrupt."
+ echo "portaudit: Database corrupt." >&2
exit 2
fi
created=`getcreated_auditfile`
- echo "database created: `/bin/date -j -f '%Y-%m-%d %H:%M:%S %Z' \"${created} GMT\"`"
+ echo "Database created: `date -j -f '%Y-%m-%d %H:%M:%S %Z' \"$created GMT\"`"
fi
+prerequisites_checked=false
+
if $opt_audit; then
portaudit_prerequisites
- audit_installed || true
+ audit_installed || ret=$?
fi
if $opt_auditcwd; then
portaudit_prerequisites
- audit_cwd
-fi
-
-if $opt_audittree; then
- echo "auditing ports tree for known vulnerabilities"
- VULCNT=0
-
- portaudit_prerequisites
-
- cd "${PORTSDIR:=/usr/ports}"
- CATEGORIES=`echo [a-z]*`
-
- for category in ${CATEGORIES}; do
- if [ ! -d "${PORTSDIR}/${category}" ]; then continue; fi
- case "${category}" in
- CVS) continue ;;
- Mk) continue ;;
- Templates) continue ;;
- Tools) continue ;;
- distfiles) continue ;;
- packages) continue ;;
- esac
-
- $opt_quiet || echo "==> ${category}"
-
- cd "${PORTSDIR}/${category}"
- PORTS=`echo *`
-
- for port in ${PORTS}; do
- if [ ! -d "${PORTSDIR}/${category}/${port}" ]; then continue; fi
- case "${port}" in
- pkg) continue ;;
- CVS) continue ;;
- esac
-
- cd "${PORTSDIR}/${category}/${port}"
- audit_cwd;
- done
- done
-
- echo "${VULCNT} ports with unmarked vulnerabilities."
+ audit_cwd || ret=$?
fi
if [ -n "$opt_file" ]; then
portaudit_prerequisites
- audit_file "$opt_file"
+ audit_file "$opt_file" || ret=$?
fi
if [ $# -gt 0 ]; then
portaudit_prerequisites
- audit_args "$@"
+ audit_args "$@" || ret=$?
fi
+
+exit $ret