/ scripts / periodic / 405.pkg-base-audit.in
405.pkg-base-audit.in
  1  #!/bin/sh -f
  2  #
  3  # Copyright (c) 2004 Oliver Eikemeier. All rights reserved.
  4  # Copyright (c) 2014 Matthew Seaman <matthew@FreeBSD.org>
  5  # Copyright (c) 2016 Miroslav Lachman <000.fbsd@quip.cz>
  6  #
  7  # Redistribution and use in source and binary forms, with or without
  8  # modification, are permitted provided that the following conditions are
  9  # met:
 10  #
 11  # 1. Redistributions of source code must retain the above copyright notice
 12  #    this list of conditions and the following disclaimer.
 13  #
 14  # 2. Redistributions in binary form must reproduce the above copyright
 15  #    notice, this list of conditions and the following disclaimer in the
 16  #    documentation and/or other materials provided with the distribution.
 17  #
 18  # 3. Neither the name of the author nor the names of its contributors may be
 19  #    used to endorse or promote products derived from this software without
 20  #    specific prior written permission.
 21  #
 22  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 23  # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 24  # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 25  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 26  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 27  # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 28  # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 29  # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 30  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 31  # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32  #
 33  # $FreeBSD$
 34  #
 35  
 36  if [ -r /etc/defaults/periodic.conf ]; then
 37  	. /etc/defaults/periodic.conf
 38  	source_periodic_confs
 39  fi
 40  
 41  : ${security_status_baseaudit_enable:=YES}
 42  : ${security_status_baseaudit_period:=daily}
 43  : ${security_status_baseaudit_quiet:=NO}
 44  : ${security_status_baseaudit_chroots=$pkg_chroots}
 45  : ${security_status_baseaudit_jails=$pkg_jails}
 46  : ${security_status_baseaudit_jails_ignore+=""}
 47  : ${security_status_baseaudit_expiry:=2}
 48  
 49  # Compute PKG_DBDIR from the config file.
 50  pkgcmd=%prefix%/sbin/pkg
 51  PKG_DBDIR=`${pkgcmd} config PKG_DBDIR`
 52  auditfile="${PKG_DBDIR}/vuln.xml"
 53  
 54  audit_base() {
 55  	local pkgargs="$1"
 56  	local basedir="$2"
 57  	local rc=0
 58  	local then
 59  	local now
 60  	local usrlv
 61  	local krnlv
 62  	local strlen
 63  	local chrootv
 64  	local jailv
 65  	local jid
 66  
 67  	# get version from chroot
 68  	if [ -n "`echo "$pkgargs" | egrep '^-c'`" ]; then
 69  		if [ -x "$basedir/bin/freebsd-version" ]; then
 70  			chrootv=$($basedir/bin/freebsd-version -u)
 71  			## safety check - strlen
 72  			strlen=$(echo "$chrootv" | wc -c)
 73  			if [ $strlen -gt 17 -o $strlen -lt 11 ]; then
 74  				echo "Wrong version string, cannot run audit"
 75  				return 3
 76  			fi
 77  			usrlv=$(echo $chrootv | sed 's,^,FreeBSD-,;s,-RELEASE-p,_,;s,-RELEASE$,,')
 78  		else
 79  			echo "Cannot guess chroot version"
 80  			return 3
 81  		fi
 82  	# get version from jail
 83  	elif [ -n "`echo "$pkgargs" | egrep '^-j'`" ]; then
 84  		jid=$(echo "$pkgargs" | awk '$1 ~ /^-[j]/ { print $2 }')
 85  		jailv=$(jexec $jid freebsd-version -u)
 86  		## safety check - strlen
 87  		strlen=$(echo "$jailv" | wc -c)
 88  		if [ $strlen -gt 17 -o $strlen -lt 11 ]; then
 89  			echo "Wrong version string, cannot run audit"
 90  			return 3
 91  		fi
 92  		usrlv=$(echo $jailv | sed 's,^,FreeBSD-,;s,-RELEASE-p,_,;s,-RELEASE$,,')
 93  	# get version from host
 94  	else
 95  		usrlv=$(freebsd-version -u | sed 's,^,FreeBSD-,;s,-RELEASE-p,_,;s,-RELEASE$,,')
 96  	fi
 97  
 98  	then=`stat -f '%m' "${basedir}${auditfile}" 2> /dev/null` || rc=3
 99  	now=`date +%s` || rc=3
100  	# Add 10 minutes of padding since the check is in seconds.
101  	if [ $rc -ne 0 -o \
102  		$(( 86400 \* "${security_status_baseaudit_expiry}" )) \
103  		-le $(( ${now} - ${then} + 600 )) ]; then
104  		# When non-interactive, sleep to reduce congestion on mirrors
105  		anticongestion
106  		f="-F"
107  	else
108  		echo -n 'Database fetched: '
109  		date -r "${then}" -Iminutes || rc=3
110  	fi
111  
112  	# Reset rc: the stat/date block above only informs the fetch
113  	# decision; the actual return code should come from pkg audit.
114  	rc=0
115  
116  	# cannot check kernel in jail or chroot
117  	if [ -z "`echo "$pkgargs" | egrep '^-[cj]'`" -a `sysctl -n security.jail.jailed` = 0 ]; then
118  		krnlv=$(freebsd-version -k | sed 's,^,FreeBSD-kernel-,;s,-RELEASE-p,_,;s,-RELEASE$,,')
119  		${pkgcmd} audit $f $q $krnlv || { rc=$?; [ $rc -lt 3 ] && rc=3; }
120  	fi
121  
122  	${pkgcmd} audit $f $q $usrlv || { rc=$?; [ $rc -lt 3 ] && rc=3; }
123  
124  	return $rc
125  }
126  
127  # Use $pkg_chroots to provide a default list of chroots, and
128  # $pkg_jails to provide a default list of jails (or '*' for all jails)
129  # for all pkg periodic scripts, or set
130  # $security_status_baseaudit_chroots and
131  # $security_status_baseaudit_jails for this script only.
132  
133  audit_base_all() {
134  	local rc
135  	local last_rc
136  	local jails
137  
138  	# We always show audit results for the base system, but only print
139  	# a banner line if we're also showing audit results for any
140  	# chroots or jails.
141  
142  	if [ -n "${security_status_baseaudit_chroots}" -o \
143  		-n "${security_status_baseaudit_jails}" ]; then
144  		echo "Host system:"
145  	fi
146  
147  	audit_base '' ''
148  	last_rc=$?
149  	[ $last_rc -gt 1 ] && rc=$last_rc
150  
151  	for c in $security_status_baseaudit_chroots ; do
152  		echo
153  		echo "chroot: $c"
154  		audit_base "-c $c" $c
155  		last_rc=$?
156  		[ $last_rc -gt 1 ] && rc=$last_rc
157  	done
158  
159  	case $security_status_baseaudit_jails in
160  	\*)
161  		jails=$(jls -q -h name path | sed -e 1d -e 's/ /|/')
162  		;;
163  	'')
164  		jails=
165  		;;
166  	*)
167  		# Given the jail name or jid, find the jail path
168  		jails=
169  		for j in $security_status_baseaudit_jails ; do
170  			p=$(jls -j $j -h name path | sed -e 1d -e 's/ /|/')
171  			jails="${jails} ${p}"
172  		done
173  		;;
174  	esac
175  
176  	for j in ${jails} ; do
177  		# ignore some jails
178  		# we iterate to get exact matches because we want substring matches
179  		# foo should not match foo.bar
180  		for ignore in ${security_status_baseaudit_jails_ignore} ; do
181  			if [ "${j%|*}" = "${ignore}" ]; then
182  				echo
183  				echo "ignoring jail: ${j%|*}"
184  				# continue with the main loop
185  				continue 2
186  			fi
187  		done
188  
189  		# ignore some jails
190  		# we iterate to get prefix matches because we foo to match foo.bar
191  		for ignore in ${security_status_baseaudit_jails_ignore_wild} ; do
192  			if [ $(expr "${j%|*}" : "${ignore}") -ne 0 ] ; then
193  				echo
194  				echo "ignoring jail: ${j%|*}"
195  				# continue with the main loop
196  				continue 2
197  			fi
198  		done
199  
200  		echo
201  		echo "jail: ${j%|*}"
202  		audit_base "-j ${j%|*}" ${j##*|}
203  		last_rc=$?
204  		[ $last_rc -gt 1 ] && rc=$last_rc
205  	done
206  
207  	return $rc
208  }
209  
210  rc=0
211  
212  if check_yesno_period security_status_baseaudit_enable
213  then
214  	echo
215  	echo 'Checking for security vulnerabilities in base (userland & kernel):'
216  
217  	if ! ${pkgcmd} -N >/dev/null 2>&1 ; then
218  		echo 'pkg-audit is enabled but pkg is not used'
219  		rc=2
220  	else
221  		case "${security_status_baseaudit_quiet}" in
222  		[Yy][Ee][Ss])
223  			q='-q'
224  			;;
225  		*)
226  			q=
227  			;;
228  		esac
229  
230  		audit_base_all ; rc=$?
231  	fi
232  fi
233  
234  exit "$rc"