Under Construction
Step 5: Set PermitRootLogin to no
Next, we’ll implement setting PermitRootLogin to “no“. Before we implement this, let’s apply the rule from custom/sshd.xml to the system:
/etc/security/aixpert # aixpert -f custom/sshd.xml
Processedrules=1 Passedrules=1 PrereqFailedrules=0 Failedrules=0 Level=TEST
Input file=custom/sshd.xml
/etc/security/aixpert #
According to the output, the rule was successfully implemented (Passedrules=1)! However, a check shows that this is obviously not the case (Failedrules=1), after all, we haven’t implemented the implementation yet:
/etc/security/aixpert # aixpert -c
Processedrules=1 Passedrules=0 Failedrules=1 Level=TEST
Input file=/etc/security/aixpert/core/appliedaixpert.xml
/etc/security/aixpert #
We extend our script and add the following loop to the end of the script:
firstOccurrence=true
while read -r line
do
case "$line" in
PermitRootLogin*)
if $firstOccurrence
then
print "PermitRootLogin no"
firstOccurrence=false
fi
;;
*)
print $line ;;
esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
$firstOccurrence && print "PermitRootLogin no" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm /etc/ssh/sshd_config.new
The loop reads /etc/ssh/sshd_config line by line. If a line begins with PermitRootLogin, it is replaced with “PermitRootLogin no” (but only the first time it occurs). All other lines are simply copied. The lines are written to the file /etc/ssh/sshd_config.new. If there was no line with PermitRootLogin, the line “PermitRootLogin no” is simply appended to the end of /etc/ssh/sshd_config.new. Finally, /etc/ssh/sshd_config.new is copied to /etc/ssh/sshd_config, and the intermediate file is deleted.
Note: This loop is a first draft and does not account for all practical scenarios. For example, there may be one or more spaces or tabs before PermitRootLogin, or match statements may have been used in sshd_config. In that case, it would be necessary to ensure that “PermitRootLogin no” precedes the match statements. And there are certainly other special cases that need to be considered.
Overall, this results in the following version of the script:
# cat /etc/security/aixpert/bin/local_chsshdconf
#! /bin/ksh
export PATH=/usr/bin:/usr/sbin:$PATH
# Initialize variables AIXPERT_FIFO, LOG, REPORT, SCPTDIR and UNDOXML
. /etc/security/aixpert/bin/initialize_variables
# Log output and errors to /etc/security/aixpert/log/aixpert.log
exec 1>>$LOG
exec 2>&1
# echo all the commands and the current time and date to the AIXpert log
set -x
date
echo $0 $@ AIXPERT_CHECK_REPORT=$AIXPERT_CHECK_REPORT BASE_REPT=$BASE_REPT DETAILED_REPT=$DETAILED_REPT
if [ $# -ne 0 ]
then
echo "Usage : local_chsshdconf\n"
exit 1
fi
# Check whether AIXPERT_CHECK_REPORT environment variable is set or not.
report=`echo $AIXPERT_CHECK_REPORT`
BrType=`echo $BASE_REPT`
DrType=`echo $DETAILED_REPT`
if [ "$report" = "1" ]
then
ret=1
permit=$( awk '$1 ~ /^PermitRootLogin$/ { print $2; }' /etc/ssh/sshd_config 2>/dev/null | tail -n 1 )
case "${permit}" in
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]) ret=0 ;;
esac
if [ $ret = 1 ]
then
if [ "$BrType" = "1" ]
then
echo "Base Compliance Report\n";
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$TMPREPT
elif [ "$DrType" = "1" ]
then
echo "Description Report\n";
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$TMPREPT
else
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$REPORT
printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$AIXPERT_FIFO
fi
fi
exit $ret
fi
firstOccurrence=true
while read -r line
do
case "$line" in
PermitRootLogin*)
if $firstOccurrence
then
print "PermitRootLogin no"
firstOccurrence=false
fi
;;
*)
print $line ;;
esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
$firstOccurrence && print "PermitRootLogin no" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm /etc/ssh/sshd_config.new
exit 0
#
A test run is again successful according to the output:
/etc/security/aixpert # aixpert -f custom/sshd.xml
Processedrules=1 Passedrules=1 PrereqFailedrules=0 Failedrules=0 Level=TEST
Input file=custom/sshd.xml
/etc/security/aixpert #
We start a check and see whether it was really successful (Passedrules=1):
/etc/security/aixpert # aixpert -c
Processedrules=1 Passedrules=1 Failedrules=0 Level=TEST
Input file=/etc/security/aixpert/core/appliedaixpert.xml
/etc/security/aixpert #
A quick check of /etc/ssh/sshd_config shows that the value of PermitRootLogin has now indeed been changed:
# grep -w PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin no
#
What’s also missing from the above loop is an error check! If an error occurs during one of the commands, a message should be written to /etc/security/aixpert/log/aixpert.log and the script should abort with an exit status other than 0. We won’t implement this for now.
What’s still missing is support for the undo functionality. We’ll address that in the next step.