shadow/shadow-login_defs-check.sh

287 lines
11 KiB
Bash

#!/bin/bash
# login.defs and lib/getdef.c contain support for third party variables.
# It also contains support for variables that are unusable in installations with PAM support enabled.
# This script generates a list of used and unused variables in login.defs
# with respect to the current configuration.
# Arguments: arguments of osc build
# If the shadow-login_defs-check-unused.lst is generated, you should
# update login.defs.
set -o errexit
echo "Preparing..."
# Check for required commands
which quilt >/dev/null
which osc >/dev/null
# login.defs is shared with util-linux login, su and runuser.
# Extract list of referenced variables.
if ! test -f openSUSE:Factory/util-linux/BUILD/*/configure.ac ; then
echo "Checking out util-linux..."
if test -d ../util-linux ; then
echo -n "../util-linux found. Are you preparing new version? (y/N) "
read
if test "${REPLY:0:1}" = "y" ; then
mkdir -p openSUSE:Factory
cp -a ../util-linux openSUSE:Factory/
else
osc co openSUSE:Factory util-linux
fi
else
osc co openSUSE:Factory util-linux
fi
cd openSUSE:Factory/util-linux
quilt setup -d BUILD util-linux.spec
cd BUILD/*
quilt push -a
cd ../../../..
fi
echo "Extracting variables from util-linux..."
cd openSUSE:Factory/util-linux/BUILD/*
(
grep -rh getlogindefs . |
sed -n 's/^.*getlogindefs[a-z_]*("\([A-Z0-9_]*\)".*$/\1/p'
grep -rh logindefs_setenv . |
sed -n 's/^.*logindefs_setenv*("[A-Z0-9_]*", "\([A-Z0-9_]*\)".*$/\1/p'
) |
LC_ALL=C sort -u >../../../../shadow-login_defs-check-util-linux.lst
cd ../../../..
# login.defs is shared pam_unix*.so, pam_faildelay.so and pam_umask.so.
# Extract list of referenced variables.
if ! test -f openSUSE:Factory/pam/BUILD/*/configure.ac ; then
echo "Checking out pam..."
if test -d ../pam ; then
echo -n "../pam found. Are you preparing new version? (y/N) "
read
if test "${REPLY:0:1}" = "y" ; then
mkdir -p openSUSE:Factory
cp -a ../pam openSUSE:Factory/
else
osc co openSUSE:Factory pam
fi
else
osc co openSUSE:Factory pam
fi
cd openSUSE:Factory/pam
quilt setup -d BUILD pam.spec
cd BUILD/*
quilt push -a
cd ../../../..
fi
echo "Extracting variables from pam..."
cd openSUSE:Factory/pam/BUILD/*
grep -rh LOGIN_DEFS . |
sed -n 's/CRYPTO_KEY/\"HMAC_CRYPTO_ALGO\"/g;s/^.*search_key *([A-Za-z_]*, *[A-Z_]*LOGIN_DEFS, *"\([A-Z0-9_]*\)").*$/\1/p' |
LC_ALL=C sort -u >../../../../shadow-login_defs-check-pam.lst
cd ../../../..
if ! test -f shadow-login_defs-check-build/stamp ; then
echo "Performing preprocessing of shadow by osc..."
if ! test -f shadow.spec.shadow-login_defs-check-save ; then
cp -a shadow.spec shadow.spec.shadow-login_defs-check-save
# In case of shadow, variables extraction is more complicated. The list
# depends on configure options, so we have to perform a fake build and
# extract variables from prepreocessed sources.
# sed -i '/^%make_build/i\_smp_mpflags="%{?_smp_mpflags} -k CPPFLAGS=\\"-E\\""' shadow.spec
sed -i 's/^%make_build/%make_build -k CPPFLAGS=\\"-E\\"/' shadow.spec
if cmp -s shadow.spec shadow.spec.shadow-login_defs-check-save ; then
echo "$0: Please fix sed expression modifying shadow.spec."
mv shadow.spec.shadow-login_defs-check-save shadow.spec
exit 1
fi
fi
if osc build "$@" ; then
echo "This build command was expected to fail, but it succeeded."
echo "$0: Please fix sed expression modifying shadow.spec."
mv shadow.spec.shadow-login_defs-check-save shadow.spec
exit 1
else
echo "This build command was expected to fail."
echo ""
fi
mv shadow.spec.shadow-login_defs-check-save shadow.spec
BUILD_ROOT=$(osc lbl | sed -n 's/^.*Using BUILD_ROOT=//p')
BUILD_DIR=$(osc lbl | sed -n 's/^.* cd //p' | head -n1)
rm -rf shadow-login_defs-check-build
mkdir shadow-login_defs-check-build
cp -a "$BUILD_ROOT/$BUILD_DIR"/shadow-* shadow-login_defs-check-build/
touch shadow-login_defs-check-build/stamp
fi
echo "Extracting list of deleted binaries..."
sed -n 's~rm %{buildroot}/%{_\(s\|\)bindir}/\(.*\)$~\2~p' <shadow.spec >shadow-login_defs-check-deleted.lst
# The build above is optional only for case of failure or edits in the
# code below. If any other build was performed, don't expect correct
# results.
cd shadow-login_defs-check-build/shadow-*
echo "Extracting variables from etc/login.defs..."
# Extract variables referenced in login.defs, both active and commented out.
sed -n "s/^#//;s/\([A-Z0-9_]*\)\([[:space:]].*\|\)$/\1/p" <etc/login.defs | sed '/^$/d' | uniq | sed '/^$/d' >../../shadow-login_defs-check-login_defs.lst
LC_ALL=C sort -u ../../shadow-login_defs-check-login_defs.lst >../../shadow-login_defs-check-login_defs-sorted.lst
echo "Extracting variables from lib/getdef.c..."
# Extract variables referenced in lib/getdef.c using current defines.
sed -n 's/^\(},\|\) {"\([A-Z0-9_]*\)", /\2/p' <lib/libshadow_la-getdef.o >../../shadow-login_defs-check-getdef.lst
LC_ALL=C sort -u ../../shadow-login_defs-check-getdef.lst >../../shadow-login_defs-check-getdef-sorted.lst
echo "Extracting variables from shadow..."
# Extract variables referenced in preprocessed files.
grep -r '\(getdef[a-z_]*\|call_script\|is_listed\) *( *"[A-Za-z0-9_]*"' |
grep '[^ ]*\.o:' >../../shadow-login_defs-check-shadow.log
cd ../..
export RC=0
echo ""
echo ""
echo "Performing checks..."
sed '
s/^.*\(getdef[a-z_]*\|call_script\|is_listed*\) *( *"\([A-Za-z0-9_]*\)".*$/\2/
' <shadow-login_defs-check-shadow.log | LC_ALL=C sort -u >../../shadow-login_defs-check-shadow-all.lst
sed 's%^\(.*\)%/^.*\\\/\1\.o:/d%' <shadow-login_defs-check-deleted.lst >shadow-login_defs-check-deleted.sed
sed -f shadow-login_defs-check-deleted.sed <shadow-login_defs-check-shadow.log |
sed '
s/^.*\(getdef[a-z_]*\|call_script\|is_listed*\) *( *"\([A-Za-z0-9_]*\)".*$/\2/
' | LC_ALL=C sort -u >shadow-login_defs-check-shadow-used.lst
if ! test -s shadow-login_defs-check-deleted.sed ; then
echo " BUG: Empty shadow-login_defs-check-deleted.sed Results will be unreliable!"
if test $RC -le 4 ; then export RC=4 ; fi
fi
echo ""
echo "Checking that variables in login.defs are referred only once..."
if test $(wc -l shadow-login_defs-check-login_defs.lst | sed 's/ .*//') != $(wc -l shadow-login_defs-check-login_defs-sorted.lst | sed 's/ .*//') ; then
echo " ERROR: Some variable referred at more places of login.defs!"
LC_ALL=C sort shadow-login_defs-check-login_defs.lst >shadow-login_defs-check-login_defs-sorted-nu.lst
diff shadow-login_defs-check-login_defs-sorted-nu.lst shadow-login_defs-check-login_defs-sorted.lst
if test $RC -le 3 ; then export RC=3 ; fi
fi
echo ""
echo "Checking that variables in lib/getdef.c are referred only once..."
if test $(wc -l shadow-login_defs-check-getdef.lst | sed 's/ .*//') != $(wc -l shadow-login_defs-check-getdef-sorted.lst | sed 's/ .*//') ; then
echo " ERROR: Some variable referred at more places of lib/getdef.c!"
LC_ALL=C sort shadow-login_defs-check-getdef.lst >shadow-login_defs-check-getdef-sorted-nu.lst
diff shadow-login_defs-check-getdef-sorted-nu.lst shadow-login_defs-check-getdef-sorted.lst
if test $RC -le 3 ; then export RC=3 ; fi
fi
cat shadow-login_defs-check-shadow-used.lst shadow-login_defs-check-util-linux.lst shadow-login_defs-check-pam.lst | LC_ALL=C sort -u >shadow-login_defs-check-all-used.lst
# RC inside pipe cannot be read directly. Use 3 for a real stdout inside the pipe, and use stdout for RC.
exec 3>&1
function report_packages() {
echo -n " ("
grep -l $1 shadow-login_defs-check-{shadow-used,util-linux,pam}.lst |
sed 's/shadow-login_defs-check-//;s/\.lst//;s/-used//;s/$/, /;$s/, $//' |
tr -d '\n'
echo -n ")"
}
# Extracting variables from shadow is not capable to identify compiled-but-unused library code.
# This function will identify known false matches.
function falsematch() {
case "$1" in
# MAIL_* used by library call mailcheck() used only by login.c that is deleted in the spec.
MAIL_* ) return 0 ;;
# FTMP_FILE used by library call failtmp() used only by login.c that is deleted in the spec.
FTMP_FILE ) return 0 ;;
# ISSUE_FILE used by library call login_prompt() used only by login.c that is deleted in the spec.
ISSUE_FILE ) return 0 ;;
# PREVENT_NO_AUTH us used only by login.c and su.c that are deleted in the spec.
PREVENT_NO_AUTH ) return 0 ;;
* ) return 1 ;;
esac
}
echo ""
echo "Checking that all used variables are covered by login.defs..."
RC=$(cat shadow-login_defs-check-all-used.lst | (
while read ; do
if falsematch "$REPLY" ; then
echo " FALSE MATCH: Variable $REPLY is not present in login.defs$(report_packages $REPLY)" >&3
continue
fi
if ! grep -q -x "$REPLY" shadow-login_defs-check-login_defs-sorted.lst ; then
echo " NOTICE: Variable $REPLY is not present in login.defs$(report_packages $REPLY)" >&3
if test $RC -le 2 ; then RC=2 ; fi
fi
done
echo $RC
) )
echo ""
echo "Checking that all used variables are covered by lib/getdef.c..."
RC=$(cat shadow-login_defs-check-all-used.lst | (
while read ; do
if falsematch "$REPLY" ; then continue ; fi
if ! grep -q -x "$REPLY" shadow-login_defs-check-getdef.lst ; then
echo " ERROR: Variable $REPLY is missing in the parser$(report_packages $REPLY)" >&3
if test $RC -le 3 ; then RC=3 ; fi
fi
done
echo $RC
) )
echo ""
echo "Checking that all used variables referred in login.defs are valid..."
RC=$(cat shadow-login_defs-check-login_defs.lst | (
while read ; do
if ! grep -q -x "$REPLY" shadow-login_defs-check-all-used.lst ; then
echo " ERROR: Failed to find reference for $REPLY" >&3
if test $RC -le 3 ; then RC=3 ; fi
fi
if ! grep -q -x "$REPLY" shadow-login_defs-check-getdef.lst ; then
echo " BUG: Parser does not contain reference for $REPLY" >&3
if test $RC -le 4 ; then RC=4 ; fi
fi
done
echo $RC
) )
echo ""
echo ""
echo "All checks finished."
echo -n "Result: "
case $RC in
0) echo "OK." ;;
1) echo "Notices only. Action is optional." ;;
2) echo "Warnings only. Evaluation is needed." ;;
3) echo "Errors found. Fix is recommended." ;;
4) echo "Fatal error. Fix has to be done." ;;
esac
if test $RC -ge 1 ; then
exit 1
fi
echo "
If you ported shadow-util-linux.patch to the new util-linux version,
please submit these updates:
Change in util-linux.spec:"
sed -n 's/^Version:[[:space:]]*/Requires: login_defs-support-for-util-linux >= /p' <openSUSE\:Factory/util-linux/util-linux.spec
echo "Change in shadow.spec:"
sed -n 's/^Version:[[:space:]]*/Provides: login_defs-support-for-util-linux = /p' <openSUSE\:Factory/util-linux/util-linux.spec
echo "
If you ported shadow-login_defs-unused-by-pam.patch to the new pam version,
please submit these updates:
Change in pam.spec:"
sed -n 's/^Version:[[:space:]]*/Requires: login_defs-support-for-pam >= /p' <openSUSE\:Factory/pam/pam.spec
echo "Change in shadow.spec:"
sed -n 's/^Version:[[:space:]]*/Provides: login_defs-support-for-pam = /p' <openSUSE\:Factory/pam/pam.spec