0541807809
postinstall, so remove it; sshd functions fine without the entries. This type of functionality is performed as part of etcupdate(8) (et al).
1054 lines
24 KiB
Bash
Executable File
1054 lines
24 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# $NetBSD: postinstall,v 1.72 2004/02/03 08:02:41 lukem Exp $
|
|
#
|
|
# Copyright (c) 2002-2004 The NetBSD Foundation, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This code is derived from software contributed to The NetBSD Foundation
|
|
# by Luke Mewburn.
|
|
#
|
|
# 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. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# 3. All advertising materials mentioning features or use of this software
|
|
# must display the following acknowledgement:
|
|
# This product includes software developed by the NetBSD
|
|
# Foundation, Inc. and its contributors.
|
|
# 4. 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.
|
|
#
|
|
# postinstall
|
|
# check for or fix configuration changes that occur
|
|
# over time as NetBSD evolves.
|
|
#
|
|
|
|
#
|
|
# checks to add:
|
|
# - obsolete minor/teeny shared libraries in /lib
|
|
# - sysctl(8) renames
|
|
# - de* -> tlp* migration (/etc/ifconfig.de*, $ifconfig_de*,
|
|
# dhclient.conf, ...) ?
|
|
# - support quiet/verbose mode ?
|
|
# - differentiate between failures caused by missing source
|
|
# and real failures
|
|
# - install moduli into usr/share/examples/ssh and use from there?
|
|
#
|
|
|
|
#
|
|
# helper functions
|
|
#
|
|
|
|
err()
|
|
{
|
|
exitval=$1
|
|
shift
|
|
echo 1>&2 "${PROGNAME}: $@"
|
|
exit ${exitval}
|
|
}
|
|
|
|
warn()
|
|
{
|
|
echo 1>&2 "${PROGNAME}: $@"
|
|
}
|
|
|
|
msg()
|
|
{
|
|
echo " $@"
|
|
}
|
|
|
|
# additem item description
|
|
# add item to list of supported items to check/fix
|
|
#
|
|
additem()
|
|
{
|
|
[ $# -eq 2 ] || err 2 "USAGE: additem item description"
|
|
items="${items}${items:+ }$1"
|
|
eval desc_$1=\"$2\"
|
|
}
|
|
|
|
# checkdir op dir mode
|
|
# ensure dir exists, and if not, create it with the appropriate mode.
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
check_dir()
|
|
{
|
|
[ $# -eq 3 ] || err 2 "USAGE: check_dir op dir mode"
|
|
_cdop=$1
|
|
_cddir=$2
|
|
_cdmode=$3
|
|
[ -d "${_cddir}" ] && return 0
|
|
if [ "${_cdop}" = "check" ]; then
|
|
msg "${_cddir} is not a directory"
|
|
return 1
|
|
elif ! mkdir -m "${_cdmode}" "${_cddir}" ; then
|
|
msg "Can't create missing ${_cddir}"
|
|
return 1
|
|
else
|
|
msg "Missing ${_cddir} created"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# check_ids op type file id [...]
|
|
# check if file of type "users" or "groups" contains the relevant ids
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
check_ids()
|
|
{
|
|
[ $# -ge 4 ] || err 2 "USAGE: checks_ids op type file id [...]"
|
|
_op=$1
|
|
_type=$2
|
|
_file=$3
|
|
shift 3
|
|
_ids="$@"
|
|
|
|
if [ ! -f "${_file}" ]; then
|
|
msg "${_file} doesn't exist; can't check for missing ${_type}"
|
|
return 1
|
|
fi
|
|
if [ ! -r "${_file}" ]; then
|
|
msg "${_file} is not readable; can't check for missing ${_type}"
|
|
return 1
|
|
fi
|
|
_notfixed=""
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
fi
|
|
_missing=$(awk -F: '
|
|
BEGIN {
|
|
for (x = 1; x < ARGC; x++)
|
|
idlist[ARGV[x]]++
|
|
ARGC=1
|
|
}
|
|
{
|
|
found[$1]++
|
|
}
|
|
END {
|
|
for (id in idlist) {
|
|
if (! (id in found))
|
|
print id
|
|
}
|
|
}
|
|
' ${_ids} < ${_file}) || return 1
|
|
if [ -n "${_missing}" ]; then
|
|
msg "Missing ${_type}${_notfixed}:" $(echo ${_missing})
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# compare_dir op src dest mode file [file ...]
|
|
# perform op ("check" or "fix") on files in src/ against dest/
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
compare_dir()
|
|
{
|
|
[ $# -ge 5 ] || err 2 "USAGE: compare_dir op src dest mode file [...]"
|
|
_op=$1
|
|
_src=$2
|
|
_dest=$3
|
|
_mode=$4
|
|
shift 4
|
|
_files="$@"
|
|
|
|
if [ ! -d "${_src}" ]; then
|
|
msg "${_src} is not a directory; skipping check"
|
|
return 1
|
|
fi
|
|
check_dir ${_op} ${_dest} 755 || return 1
|
|
|
|
_cmpdir_rv=0
|
|
for f in ${_files}; do
|
|
fs=${_src}/${f}
|
|
fd=${_dest}/${f}
|
|
_error=""
|
|
if [ ! -f "${fd}" ]; then
|
|
_error="${fd} does not exist"
|
|
elif ! cmp -s ${fs} ${fd} ; then
|
|
_error="${fs} != ${fd}"
|
|
else
|
|
continue
|
|
fi
|
|
if [ "${_op}" = "check" ]; then
|
|
msg ${_error}
|
|
_cmpdir_rv=1
|
|
elif ! rm -f ${fd} ||
|
|
! cp -f ${fs} ${fd}; then
|
|
msg "Can't copy ${fs} to ${fd}"
|
|
_cmpdir_rv=1
|
|
elif ! chmod ${_mode} ${fd}; then
|
|
msg "Can't change mode of ${fd} to ${_mode}"
|
|
_cmpdir_rv=1
|
|
else
|
|
msg "Copied ${fs} to ${fd}"
|
|
fi
|
|
done
|
|
return ${_cmpdir_rv}
|
|
}
|
|
|
|
# move_file op src dest --
|
|
# check (op == "check") or move (op != "check") from src to dest.
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
move_file()
|
|
{
|
|
[ $# -eq 3 ] || err 2 "USAGE: move_file op src dest"
|
|
_fm_op=$1
|
|
_fm_src=$2
|
|
_fm_dest=$3
|
|
|
|
if [ -f "${_fm_src}" -a ! -f "${_fm_dest}" ]; then
|
|
if [ "${_fm_op}" = "check" ]; then
|
|
msg "Move ${_fm_src} to ${_fm_dest}"
|
|
return 1
|
|
fi
|
|
if ! mv ${_fm_src} ${_fm_dest}; then
|
|
msg "Can't move ${_fm_src} to ${_fm_dest}"
|
|
return 1
|
|
fi
|
|
msg "Moved ${_fm_src} to ${_fm_dest}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# rcconf_is_set op name var [verbose] --
|
|
# load the rcconf for name, and check if obsolete rc.conf(5) variable
|
|
# var is defined or not.
|
|
# returns 0 if defined (even to ""), otherwise 1.
|
|
# if verbose != "", print an obsolete warning if the var is defined.
|
|
#
|
|
rcconf_is_set()
|
|
{
|
|
[ $# -ge 3 ] || err 2 "USAGE: rcconf_is_set op name var [verbose]"
|
|
_rcis_op=$1
|
|
_rcis_name=$2
|
|
_rcis_var=$3
|
|
_rcis_verbose=$4
|
|
_rcis_notfixed=""
|
|
if [ "${_rcis_op}" = "fix" ]; then
|
|
_rcis_notfixed=${NOT_FIXED}
|
|
fi
|
|
(
|
|
for f in \
|
|
${DEST_DIR}/etc/rc.conf \
|
|
${DEST_DIR}/etc/rc.conf.d/${_rcis_name}; do
|
|
[ -f "${f}" ] && . "${f}";
|
|
done
|
|
eval echo -n \"\${${_rcis_var}}\" 1>&3
|
|
if eval "[ -n \"\${${_rcis_var}}\" \
|
|
-o \"\${${_rcis_var}-UNSET}\" != \"UNSET\" ]"; then
|
|
if [ -n "${_rcis_verbose}" ]; then
|
|
msg \
|
|
"Obsolete rc.conf(5) variable '\$${_rcis_var}' found.${_rcis_notfixed}"
|
|
fi
|
|
exit 0
|
|
else
|
|
exit 1
|
|
fi
|
|
)
|
|
}
|
|
|
|
# find_file_in_dirlist() file message dir1 [...] --
|
|
# find which directory file is in, and sets ${dir} to match
|
|
# returns 0 if matched, otherwise 1 (and sets ${dir} to "").
|
|
#
|
|
# generally, check the directory for the "checking from source" case,
|
|
# and then the directory for the "checking from extracted etc.tgz" case.
|
|
#
|
|
find_file_in_dirlist()
|
|
{
|
|
[ $# -ge 3 ] || err 2 "USAGE: find_file_in_dirlist file msg dir1 [...]"
|
|
|
|
_file=$1 ; shift
|
|
_msg=$1 ; shift
|
|
_dir1st=
|
|
for dir in $*; do
|
|
: ${_dir1st:=${dir}}
|
|
if [ -f "${dir}/${_file}" ]; then
|
|
if [ "${_dir1st}" != "${dir}" ]; then
|
|
msg \
|
|
"(Checking for ${_msg} from ${dir} instead of ${_dir1st})"
|
|
fi
|
|
return 0
|
|
fi
|
|
done
|
|
msg "Can't find source directory for ${_msg}"
|
|
return 1
|
|
}
|
|
|
|
# stat op format target value
|
|
# call stat on the given target according to the given format, if
|
|
# stat(1) is available (it is presumed to live in /usr/bin). if
|
|
# it is not available, this routine will always succeed, otherwise
|
|
# it returns 0 or 1, depending on whether or not the output from
|
|
# stat(1) matches the expected value.
|
|
#
|
|
stat()
|
|
{
|
|
_stop=$1
|
|
_stfmt=$2
|
|
_sttgt=$3
|
|
_stval=$4
|
|
|
|
if [ ! -x /usr/bin/stat ]; then
|
|
msg "(/usr/bin/stat not available; skipping ${_stop} on ${_sttgt})"
|
|
return 0
|
|
fi
|
|
|
|
_stres=$(/usr/bin/stat -q -f "${_stfmt}" "${_sttgt}")
|
|
[ "${_stres}" = "${_stval}" ]
|
|
return $?
|
|
}
|
|
|
|
|
|
#
|
|
# items
|
|
# -----
|
|
#
|
|
|
|
#
|
|
# postinstall
|
|
#
|
|
additem postinstall "/etc/postinstall being up to date"
|
|
do_postinstall()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_postinstall fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc ${DEST_DIR}/etc 555 \
|
|
postinstall
|
|
}
|
|
|
|
#
|
|
# release
|
|
#
|
|
additem etc_release "/etc/release being up to date"
|
|
do_etc_release()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_etc_release fix|check"
|
|
|
|
if [ -f "${SRC_DIR}/etc/Makefile" -a \
|
|
! -f "${SRC_DIR}/etc/release" ] ; then
|
|
msg "etc/release is built by ${SRC_DIR}/etc/Makefile; skipping ${op}"
|
|
return 0
|
|
fi
|
|
compare_dir $1 ${SRC_DIR}/etc ${DEST_DIR}/etc 555 \
|
|
release
|
|
}
|
|
|
|
#
|
|
# defaults
|
|
#
|
|
additem defaults "/etc/defaults/ being up to date"
|
|
do_defaults()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_defaults fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc/defaults ${DEST_DIR}/etc/defaults 444 \
|
|
daily.conf monthly.conf rc.conf security.conf weekly.conf
|
|
}
|
|
|
|
#
|
|
# mtree
|
|
#
|
|
additem mtree "/etc/mtree/ being up to date"
|
|
do_mtree()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_mtree fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc/mtree ${DEST_DIR}/etc/mtree 444 \
|
|
NetBSD.dist special
|
|
}
|
|
|
|
#
|
|
# gid
|
|
#
|
|
additem gid "required GIDs"
|
|
do_gid()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_gid fix|check"
|
|
|
|
check_ids $1 groups "${DEST_DIR}/etc/group" \
|
|
named ntpd sshd smmsp
|
|
}
|
|
|
|
#
|
|
# uid
|
|
#
|
|
additem uid "required UIDs"
|
|
do_uid()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_uid fix|check"
|
|
|
|
check_ids $1 users "${DEST_DIR}/etc/master.passwd" \
|
|
named ntpd sshd smmsp
|
|
}
|
|
|
|
|
|
#
|
|
# periodic
|
|
#
|
|
additem periodic "/etc/{daily,weekly,monthly,security} being up to date"
|
|
do_periodic()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_periodic fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc ${DEST_DIR}/etc 644 \
|
|
daily weekly monthly security
|
|
}
|
|
|
|
#
|
|
# rc
|
|
#
|
|
additem rc "/etc/rc* and /etc/rc.d/ being up to date"
|
|
do_rc()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_rc fix|check"
|
|
op=$1
|
|
failed=0
|
|
|
|
compare_dir ${op} ${SRC_DIR}/etc ${DEST_DIR}/etc 644 \
|
|
rc rc.subr rc.shutdown
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
compare_dir ${op} ${SRC_DIR}/etc/rc.d ${DEST_DIR}/etc/rc.d 555 \
|
|
DAEMON LOGIN NETWORKING SERVERS accounting altqd amd \
|
|
apmd bootparams bootconf.sh ccd cgd cleartmp cron \
|
|
dhclient dhcpd dhcrelay dmesg downinterfaces fsck \
|
|
identd ifwatchd inetd ipfilter ipfs ipmon ipnat ipsec isdnd \
|
|
kdc ldconfig lkm1 lkm2 lkm3 local lpd mopd motd \
|
|
mountall mountcritlocal mountcritremote mountd moused \
|
|
mrouted mixerctl named ndbootd network newsyslog nfsd \
|
|
nfslocking ntpd ntpdate poffd postfix powerd ppp pwcheck \
|
|
quota racoon rpcbind raidframe raidframeparity rarpd rbootd \
|
|
root route6d routed rtadvd rtclocaltime rtsold rwho savecore \
|
|
screenblank sendmail securelevel smmsp sshd staticroute \
|
|
swap1 swap2 sysdb sysctl syslogd timed ttys veriexec virecover \
|
|
wdogctl wscons wsmoused \
|
|
xdm xfs ypbind yppasswdd ypserv
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
# check for obsolete rc.d files
|
|
for f in NETWORK fsck.sh kerberos nfsiod servers systemfs \
|
|
daemon gated login portmap sunndd xntpd; do
|
|
fd=${DEST_DIR}/etc/rc.d/${f}
|
|
[ ! -e "${fd}" ] && continue
|
|
if [ "${op}" = "check" ]; then
|
|
msg "Remove obsolete ${fd}"
|
|
failed=1
|
|
elif ! rm ${fd}; then
|
|
msg "Can't remove obsolete ${fd}"
|
|
failed=1
|
|
else
|
|
msg "Removed obsolete ${fd}"
|
|
fi
|
|
done
|
|
|
|
# check for obsolete rc.conf(5) variables
|
|
set -- amd amd_master \
|
|
mountcritlocal critical_filesystems_beforenet \
|
|
mountcritremote critical_filesystems \
|
|
network ip6forwarding \
|
|
sysctl defcorename \
|
|
sysctl nfsiod_flags
|
|
while [ $# -gt 1 ]; do
|
|
if rcconf_is_set ${op} $1 $2 1; then
|
|
failed=1
|
|
fi
|
|
shift 2
|
|
done
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# ssh
|
|
#
|
|
additem ssh "ssh configuration update"
|
|
do_ssh()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_ssh fix|check"
|
|
op=$1
|
|
|
|
failed=0
|
|
_etcssh=${DEST_DIR}/etc/ssh
|
|
if ! check_dir ${op} ${_etcssh} 755; then
|
|
failed=1
|
|
fi
|
|
|
|
if [ ${failed} -eq 0 ]; then
|
|
for f in \
|
|
ssh_known_hosts ssh_known_hosts2 \
|
|
ssh_host_dsa_key ssh_host_dsa_key.pub \
|
|
ssh_host_rsa_key ssh_host_rsa_key.pub \
|
|
ssh_host_key ssh_host_key.pub \
|
|
; do
|
|
if ! move_file ${op} \
|
|
${DEST_DIR}/etc/${f} ${_etcssh}/${f} ;
|
|
then
|
|
failed=1
|
|
fi
|
|
done
|
|
for f in sshd.conf ssh.conf ; do
|
|
# /etc/ssh/ssh{,d}.conf -> ssh{,d}_config
|
|
#
|
|
if ! move_file ${op} \
|
|
${_etcssh}/${f} ${_etcssh}/${f%.conf}_config ;
|
|
then
|
|
failed=1
|
|
fi
|
|
# /etc/ssh{,d}.conf -> /etc/ssh/ssh{,d}_config
|
|
#
|
|
if ! move_file ${op} \
|
|
${DEST_DIR}/etc/${f} ${_etcssh}/${f%.conf}_config ;
|
|
then
|
|
failed=1
|
|
fi
|
|
done
|
|
fi
|
|
|
|
sshdconf=""
|
|
for f in \
|
|
${_etcssh}/sshd_config \
|
|
${_etcssh}/sshd.conf \
|
|
${DEST_DIR}/etc/sshd.conf ; do
|
|
if [ -f "${f}" ]; then
|
|
sshdconf=${f}
|
|
break;
|
|
fi
|
|
done
|
|
if [ -n "${sshdconf}" ]; then
|
|
awk '
|
|
$1 ~ /^[Hh][Oo][Ss][Tt][Kk][Ee][Yy]$/ &&
|
|
$2 ~ /^\/etc\/+ssh_host(_[dr]sa)?_key$/ {
|
|
sub(/\/etc\/+/, "/etc/ssh/");
|
|
}
|
|
{ print }
|
|
' < ${sshdconf} > ${SCRATCHDIR}/sshd_config
|
|
if ! cmp -s ${sshdconf} ${SCRATCHDIR}/sshd_config; then
|
|
diff ${sshdconf} ${SCRATCHDIR}/sshd_config > \
|
|
${SCRATCHDIR}/sshd_config.diffs
|
|
if [ "${op}" = "check" ]; then
|
|
msg "${sshdconf} needs the following changes:"
|
|
failed=1
|
|
elif ! rm -f ${sshdconf} ||
|
|
! cp -f ${SCRATCHDIR}/sshd_config ${sshdconf}; then
|
|
msg "${sshdconf} changes not applied:"
|
|
failed=1
|
|
else
|
|
msg "${sshdconf} changes applied:"
|
|
fi
|
|
while read _line; do
|
|
msg " ${_line}"
|
|
done < ${SCRATCHDIR}/sshd_config.diffs
|
|
fi
|
|
fi
|
|
|
|
if ! find_file_in_dirlist moduli "moduli" \
|
|
${SRC_DIR}/crypto/dist/ssh ${SRC_DIR}/etc ; then
|
|
failed=1
|
|
elif ! compare_dir ${op} ${dir} ${DEST_DIR}/etc 444 moduli; then
|
|
failed=1
|
|
fi
|
|
|
|
if ! check_dir "${op}" "${DEST_DIR}/var/chroot/sshd" 755 ; then
|
|
failed=1
|
|
fi
|
|
|
|
if rcconf_is_set ${op} sshd sshd_conf_dir 1; then
|
|
failed=1
|
|
fi
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# wscons
|
|
#
|
|
additem wscons "wscons configuration file update"
|
|
do_wscons()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_wscons fix|check"
|
|
op=$1
|
|
|
|
[ -f ${DEST_DIR}/etc/wscons.conf ] || return 0
|
|
|
|
failed=0
|
|
notfixed=""
|
|
if [ "${op}" = "fix" ]; then
|
|
notfixed=${NOT_FIXED}
|
|
fi
|
|
while read _type _arg1 _rest; do
|
|
if [ "${_type}" = "mux" -a "${_arg1}" = "1" ]; then
|
|
msg \
|
|
"Obsolete wscons.conf(5) entry \""${_type} ${_arg1}"\" found.${notfixed}"
|
|
failed=1
|
|
fi
|
|
done < ${DEST_DIR}/etc/wscons.conf
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# makedev
|
|
#
|
|
additem makedev "/dev/MAKEDEV being up to date"
|
|
do_makedev()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_makedev fix|check"
|
|
|
|
if [ -f "${SRC_DIR}/etc/MAKEDEV.tmpl" ]; then
|
|
# generate MAKEDEV from source if source is available
|
|
env MACHINE=${MACHINE} \
|
|
MACHINE_ARCH=${MACHINE_ARCH} \
|
|
NETBSDSRCDIR="${SRC_DIR}" \
|
|
awk -f ${SRC_DIR}/etc/MAKEDEV.awk \
|
|
${SRC_DIR}/etc/MAKEDEV.tmpl > ${SCRATCHDIR}/MAKEDEV
|
|
fi
|
|
|
|
find_file_in_dirlist MAKEDEV "MAKEDEV" \
|
|
${SCRATCHDIR} ${SRC_DIR}/dev \
|
|
|| return 1
|
|
|
|
compare_dir $1 ${dir} ${DEST_DIR}/dev 555 MAKEDEV
|
|
}
|
|
|
|
#
|
|
# postfix
|
|
#
|
|
additem postfix "/etc/postfix/ being up to date"
|
|
do_postfix()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_postfix fix|check"
|
|
op=$1
|
|
failed=0
|
|
|
|
find_file_in_dirlist postfix-script "postfix scripts" \
|
|
${SRC_DIR}/gnu/dist/postfix/conf \
|
|
${DEST_DIR}/usr/share/examples/postfix \
|
|
|| return 1
|
|
|
|
compare_dir ${op} ${dir} ${DEST_DIR}/etc/postfix 555 postfix-script
|
|
failed=$(( ${failed} + $? ))
|
|
compare_dir ${op} ${dir} \
|
|
${DEST_DIR}/etc/postfix 444 post-install postfix-files
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# obsolete
|
|
#
|
|
additem obsolete "obsolete file sets"
|
|
do_obsolete()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_obsolete fix|check"
|
|
op=$1
|
|
|
|
sort -ru ${DEST_DIR}/var/db/obsolete/* | (
|
|
failed=0
|
|
while read ofile; do
|
|
ofile=${DEST_DIR}${ofile#.}
|
|
cmd="rm"
|
|
ftype="file"
|
|
if [ -h "${ofile}" ]; then
|
|
ftype="link"
|
|
elif [ -d "${ofile}" ]; then
|
|
ftype="directory"
|
|
cmd="rmdir"
|
|
elif [ ! -e "${ofile}" ]; then
|
|
continue
|
|
fi
|
|
if [ "${op}" = "check" ]; then
|
|
msg "Remove obsolete ${ftype} ${ofile}"
|
|
failed=1
|
|
elif ! eval ${cmd} ${ofile}; then
|
|
msg "Can't remove obsolete ${ftype} ${ofile}"
|
|
failed=1
|
|
else
|
|
msg "Removed obsolete ${ftype} ${ofile}"
|
|
fi
|
|
done
|
|
exit ${failed}
|
|
)
|
|
|
|
return $?
|
|
}
|
|
|
|
#
|
|
# sendmail
|
|
#
|
|
additem sendmail "sendmail configuration being up to date"
|
|
do_sendmail()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_sendmail fix|check"
|
|
_op=$1
|
|
|
|
#
|
|
# check owner and mode of sendmail (and "root" setting)
|
|
# check .cf file version
|
|
# check submit.cf existence (and version)
|
|
# uid and gid are checked elsewhere
|
|
# look at clientmqueue's owner, group, and mode
|
|
#
|
|
failed=0
|
|
_etcmail="${DEST_DIR}/etc/mail"
|
|
_sendmailcf="${_etcmail}/sendmail.cf"
|
|
_submitcf="${_etcmail}/submit.cf"
|
|
_sample_sendmailcf="${DEST_DIR}/usr/share/sendmail/cf/netbsd-proto.cf"
|
|
_sample_submitcf="${DEST_DIR}/usr/share/sendmail/cf/netbsd-msp.cf"
|
|
_sendmail=${DEST_DIR}/usr/libexec/sendmail/sendmail
|
|
|
|
#
|
|
# check for "root" setting first, so that checks can be
|
|
# adjusted accordingly
|
|
#
|
|
_notfixed=""
|
|
_root=$(rcconf_is_set ${_op} sendmail sendmail_suidroot 3>&1 1>&4) 4>&1
|
|
if [ $? != 0 ]; then
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
fi
|
|
msg "sendmail_suidroot variable not set (assuming \`\`no'')${_notfixed}"
|
|
_root=NO
|
|
failed=1
|
|
fi
|
|
|
|
# normalize the "root" setting
|
|
_root=$(. ${DEST_DIR}/etc/rc.subr
|
|
warn() {} # eliminate complaints
|
|
if checkyesno _root; then
|
|
echo true
|
|
else
|
|
echo false
|
|
fi)
|
|
|
|
if "${_root}"; then
|
|
_smownerfmt="%p %Su"
|
|
_smownermode="4555"
|
|
_smownerreq="root"
|
|
else
|
|
_smownerfmt="%p %Su:%Sg"
|
|
_smownermode="2555"
|
|
_smownerreq="root:smmsp"
|
|
fi
|
|
|
|
# check that owner and mode match what it required
|
|
_notfixed=""
|
|
if ! stat "${_op}" "${_smownerfmt}" "${_sendmail}" \
|
|
"10${_smownermode} ${_smownerreq}"; then
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
if chown "${_smownerreq}" "${_sendmail}" 2>/dev/null &&
|
|
chmod "${_smownermode}" "${_sendmail}" 2>/dev/null
|
|
then
|
|
_notfixed=" [ FIXED ]"
|
|
else
|
|
failed=1
|
|
fi
|
|
else
|
|
_notfixed=""
|
|
failed=1
|
|
fi
|
|
msg "${_sendmail} binary has wrong owner/mode${_notfixed}"
|
|
fi
|
|
|
|
_notfixed=""
|
|
if [ ! -f "${_sendmailcf}" ]; then
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
if cp "${_sample_sendmailcf}" \
|
|
"${_sendmailcf}" 2>/dev/null; then
|
|
_notfixed=" [ FIXED ]"
|
|
else
|
|
failed=1
|
|
fi
|
|
fi
|
|
msg "${_sendmailcf} is missing${_notfixed}"
|
|
fi
|
|
if [ ! -f "${_sendmailcf}" ]; then
|
|
_cfversion="10" # pretend it's okay
|
|
else
|
|
_cfversion=$(sed -n 's/^V *\([0-9]*\).*/\1/p' "${_sendmailcf}")
|
|
fi
|
|
|
|
_notfixed=""
|
|
if [ "${_cfversion}" -lt 10 ]; then
|
|
# XXX no fix here
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
fi
|
|
msg "Version of ${_sendmailcf} is ${_cfversion}," \
|
|
"should be 10${_notfixed}"
|
|
failed=1
|
|
fi
|
|
|
|
_notfixed=""
|
|
if $_root; then
|
|
if [ -f "${_submitcf}" ]; then
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
if rm -f "${_submitcf}" 2>/dev/null; then
|
|
_notfixed=" [ FIXED ]"
|
|
else
|
|
failed=1
|
|
fi
|
|
else
|
|
_notfixed=""
|
|
failed=1
|
|
fi
|
|
msg "${_submitcf} exists${_notfixed}"
|
|
fi
|
|
_checkcq=false
|
|
else
|
|
if [ ! -f "${_submitcf}" ]; then
|
|
_notfixed=""
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
if cp "${_sample_submitcf}" \
|
|
"${_submitcf}" 2>/dev/null; then
|
|
_notfixed=" [ FIXED ]"
|
|
else
|
|
failed=1
|
|
fi
|
|
fi
|
|
msg "${_submitcf} is missing${_notfixed}"
|
|
fi
|
|
_checkcq=true
|
|
fi
|
|
|
|
_cqueuemode="770"
|
|
_cqueueowner="smmsp:smmsp"
|
|
if "${_checkcq}"; then
|
|
if [ -f "${_submitcf}" ]; then
|
|
_cqueuepath=$(awk 'match($0,"^O *QueueDirectory=") {
|
|
print(substr($0, RSTART+RLENGTH))
|
|
}' "${_submitcf}")
|
|
else
|
|
_cqueuepath="/var/spool/clientmqueue"
|
|
fi
|
|
_cqueuefmt="%.1Sp %Lp %Su:%Sg"
|
|
else
|
|
_cqueuepath="/"
|
|
_cqueuefmt="d ${_cqueuemode} ${_cqueueowner}"
|
|
fi
|
|
|
|
_notfixed=""
|
|
if ! stat "${_op}" "${_cqueuefmt}" "${_cqueuepath}" \
|
|
"d ${_cqueuemode} ${_cqueueowner}"; then
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
mkdir -p "${_cqueuepath}" &&
|
|
chown "${_cqueueowner}" "${_cqueuepath}" &&
|
|
chmod "${_cqueuemode}" "${_cqueuepath}" &&
|
|
_notfixed=" [ FIXED ]" ||
|
|
failed=1
|
|
else
|
|
failed=1
|
|
fi
|
|
msg "Client queue ${_cqueuepath} has wrong owner/mode${_notfixed}"
|
|
fi
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
|
|
#
|
|
# end of items
|
|
# ------------
|
|
#
|
|
|
|
|
|
usage()
|
|
{
|
|
cat 1>&2 << _USAGE_
|
|
Usage: ${PROGNAME} [-s srcdir] [-d destdir] [-m machine] operation [item [...]]
|
|
Perform post-installation checks and/or fixes on a system's
|
|
configuration files.
|
|
If no items are provided, all checks or fixes are applied.
|
|
|
|
Options:
|
|
-s srcdir Source directory to compare from.
|
|
This can either be src/etc or
|
|
an extracted copy of "etc.tgz". [${SRC_DIR:-/}]
|
|
-d destdir Destination directory to check. [${DEST_DIR:-/}]
|
|
-m machine Machine architecture. [${MACHINE}]
|
|
-a arch Machine architecture. [${MACHINE_ARCH}]
|
|
|
|
Operation may be one of:
|
|
help display this help
|
|
list list available items
|
|
check perform post-installation checks on items
|
|
fix apply fixes that 'check' determines need to be applied
|
|
usage display this usage
|
|
_USAGE_
|
|
exit 1
|
|
}
|
|
|
|
|
|
list()
|
|
{
|
|
echo "Supported items:"
|
|
echo " Item Description"
|
|
echo " ---- -----------"
|
|
for i in ${items}; do
|
|
eval desc="\${desc_${i}}"
|
|
printf " %-12s %s\n" "${i}" "${desc}"
|
|
done
|
|
}
|
|
|
|
|
|
main()
|
|
{
|
|
while getopts s:d:m: ch; do
|
|
case ${ch} in
|
|
s)
|
|
SRC_DIR=${OPTARG} ;;
|
|
d)
|
|
DEST_DIR=${OPTARG} ;;
|
|
m)
|
|
MACHINE=${OPTARG} ;;
|
|
a)
|
|
MACHINE_ARCH=${OPTARG} ;;
|
|
*)
|
|
usage ;;
|
|
esac
|
|
done
|
|
shift $((${OPTIND} - 1))
|
|
[ $# -gt 0 ] || usage
|
|
|
|
[ -d "${SRC_DIR}" ] || err 1 "${SRC_DIR} is not a directory"
|
|
[ -d "${DEST_DIR}" ] || err 1 "${DEST_DIR} is not a directory"
|
|
[ -n "${MACHINE}" ] || err 1 "\${MACHINE} is not defined"
|
|
[ -n "${MACHINE_ARCH}" ] || err 1 "\${MACHINE_ARCH} is not defined"
|
|
|
|
# If directories are /, clear them, so various messages
|
|
# don't have leading "//". However, this requires
|
|
# the use of ${foo:-/} to display the variables.
|
|
#
|
|
[ "${SRC_DIR}" = "/" ] && SRC_DIR=""
|
|
[ "${DEST_DIR}" = "/" ] && DEST_DIR=""
|
|
|
|
op=$1
|
|
shift
|
|
|
|
case "${op}" in
|
|
|
|
usage|help)
|
|
usage
|
|
;;
|
|
|
|
list)
|
|
echo "Source directory: ${SRC_DIR:-/}"
|
|
echo "Target directory: ${DEST_DIR:-/}"
|
|
list
|
|
;;
|
|
|
|
check|fix)
|
|
todo="$@"
|
|
: ${todo:=${items}}
|
|
|
|
# ensure that all supplied items are valid
|
|
#
|
|
for i in ${todo}; do
|
|
eval desc=\"\${desc_${i}}\"
|
|
[ -n "${desc}" ] || err 1 "Unsupported ${op} '"${i}"'"
|
|
done
|
|
|
|
# perform each check/fix
|
|
#
|
|
echo "Source directory: ${SRC_DIR:-/}"
|
|
echo "Target directory: ${DEST_DIR:-/}"
|
|
items_passed=
|
|
items_failed=
|
|
for i in ${todo}; do
|
|
echo "${i} ${op}:"
|
|
( eval do_${i} ${op} )
|
|
if [ $? -eq 0 ]; then
|
|
items_passed="${items_passed} ${i}"
|
|
else
|
|
items_failed="${items_failed} ${i}"
|
|
fi
|
|
done
|
|
|
|
if [ "${op}" = "check" ]; then
|
|
plural="checks"
|
|
else
|
|
plural="fixes"
|
|
fi
|
|
|
|
echo "${PROGNAME} ${plural} passed:${items_passed}"
|
|
echo "${PROGNAME} ${plural} failed:${items_failed}"
|
|
if [ -n "${items_failed}" -a "${op}" = "check" ]; then
|
|
[ "$MACHINE" = "$(uname -m)" ] && m= || m=" -m $MACHINE"
|
|
cat <<_Fix_me_
|
|
To fix, run:
|
|
${0} -s ${SRC_DIR} -d ${DEST_DIR:-/}$m fix${items_failed}
|
|
_Fix_me_
|
|
fi
|
|
|
|
;;
|
|
|
|
*)
|
|
warn "Unknown operation '"${op}"'"
|
|
usage
|
|
;;
|
|
|
|
esac
|
|
}
|
|
|
|
mkdtemp ()
|
|
{
|
|
# Make sure we don't loop forever if mkdir will always fail.
|
|
[ -d /tmp ] || err 1 /tmp is not a directory
|
|
[ -w /tmp ] || err 1 /tmp is not writable
|
|
|
|
_base=/tmp/_postinstall.$$
|
|
_serial=0
|
|
|
|
while true; do
|
|
_dir=${_base}.${_serial}
|
|
mkdir -m 0700 ${_dir} && break
|
|
_serial=$((${_serial} + 1))
|
|
done
|
|
echo ${_dir}
|
|
}
|
|
|
|
# defaults
|
|
#
|
|
PROGNAME=${0##*/}
|
|
SRC_DIR="/usr/src"
|
|
DEST_DIR="/"
|
|
: ${MACHINE:=$( uname -m )} # assume native build if $MACHINE is not set
|
|
: ${MACHINE_ARCH:=$( uname -p )}# assume native build if not set
|
|
|
|
NOT_FIXED=" [NOT FIXED]"
|
|
SCRATCHDIR=$( mkdtemp ) || err 1 "Can't create scratch directory"
|
|
trap "/bin/rm -rf ${SCRATCHDIR} ; exit 0" 0 1 2 3 15 # EXIT HUP INT QUIT TERM
|
|
|
|
umask 022
|
|
exec 3>/dev/null
|
|
exec 4>/dev/null
|
|
|
|
main "$@"
|
|
exit 0
|