#!/bin/sh

#######################################################################################
#
#  $Id: selinux-allow-ntpd-refclock 1.3 2012/04/10 13:57:59Z martin REL_M $
#
#  (c) 2009 Martin Burnicki <martin.burnicki@meinberg.de>
#
#  Description:
#    This script generates a policy file for ntpd under SELinux in order
#    to grant ntpd the permissions to access hardware reference clocks,
#    e.g. /dev/mbgclock0 which is accessed by ntpd via a symbolic
#    link /dev/refclock-0.
#
#    The script has been tested under some CentOS / RHEL / Fedora versions.
#
#    Run ./selinux-allow-ntpd-refclock without arguments to see usage information.
#
#    The following RPM packages should be installed to provide 
#    the required programs:
#
#      policycoreutils
#      checkpolicy
#
# ------------------------------------------------------------------------------------
#  $Log: selinux-allow-ntpd-refclock $
#  Revision 1.3  2012/04/10 13:57:59Z  martin
#  Added a hint about changed package names providing required scripts
#  in new versions of Fedora/RedHat/CentOS.
#  Revision 1.2  2009/04/30 10:12:15  martin
#  Log file to be parsed must be specified on the command line.
#  If no log file is specified then display verbose usage information.
#  Revision 1.1  2009/01/29 15:31:14  martin
#  Initial revision.
#
#######################################################################################

# The base name of the rules file:
selinux_module=ntpd

usage()
{
  echo "This script creates and installs a SELinux policy file which"
  echo "grants the NTP daemon access to the Meinberg cards."
  echo ""
  echo "usage:";
  echo "  $0 { -h | --help }  # display this help"
  echo "  $0 AUDITLOG         # process input file AUDITLOG"
  echo ""
  echo "SELinix is a security tool which controls which programs have access"
  echo "to which files and devices. If a new device is installed in a computer"
  echo "an appropriate SELinux policy may need to be installed to let programs be"
  echo "able to access the new device."
  echo ""
  echo "This script calls some SELinux tools to create a policy file from a"
  echo "couple of lines extracted from the SELinux audit.log file."
  echo "The \"policycoreutils\" and \"checkpolicy\" packages need to be"
  echo "installed to provide the necessary SELinux tools."
  echo ""
  echo "In newer versions of Fedora/RedHat/CentOS (e.g. RHEL 6 )the policycoreutils"
  echo "package has been split, and the audit2allow program is now in the"
  echo "policycoreutils-python package which has in turn several dependencies."
  echo ""
  echo "If the ntpd-audit*.log files which come with this script are not"
  echo "appropriate for the target system then an appropriate log file has"
  echo "to be generated/extracted first from the SELinux audit.log file, e.g.:"
  echo ""
  echo "Temporarily switch SELinux to permissive mode, which allows all "
  echo "actions, but logs what would be inhibited in enforcing mode:"
  echo ""
  echo "  setenforce permissive"
  echo ""
  echo "Restart the NTP daemon in order to generate the required log entries:"
  echo ""
  echo "  service ntpd restart"
  echo ""
  echo "Wait a couple of seconds, then extract the relevant log entries:"
  echo ""
  echo "  grep ntpd /var/log/audit/audit.log > ntpd-audit.log"
  echo ""
  echo "Now run this script to generate and install the new policy file:"
  echo ""
  echo "  $0 ntpd-audit.log"
  echo ""
  echo "Finally you should set SELinux back to enforcing mode:"
  echo "  setenforce Enforcing"
  echo ""
}

err_no_parm()
{
  echo "";
  echo "No parameter given on the command line.";
  echo "";
  usage;
}

do_exit()
{
  echo "";
  echo "Command $1 failed, exiting.";
  exit 1;
}

run_cmd()
{
  cmd="$1";
  cmdline="$cmd $2";

  if ! test -z $3 && ! test -z $4 ; then
    echo "$cmdline < $3 > $4";
    $cmdline < $3 > $4 || do_exit $cmd;
  else
    echo "$cmdline";
    $cmdline || do_exit $cmd;
  fi;
}



if [ $# -lt 1 ]; then
  err_no_parm;
  exit 1;
fi

case "$1" in
  -? | -h* | --help )
    usage
    exit 0;;
  *)
    audit_log=`echo $1`;
    echo "Using file $audit_log";;
esac

if test -z $audit_log; then
  err_no_parm;
  exit 1;
fi


if ! test -f $audit_log; then
  echo "File $audit_log does not exist.";
  exit 1;
fi

# Parse the input file and generate the module file, 
# or exit if one of the commands fails:
run_cmd audit2allow "-m $selinux_module" "$audit_log" "$selinux_module.te"
run_cmd checkmodule "-M -m -o $selinux_module.mod $selinux_module.te"
run_cmd semodule_package "-o $selinux_module.pp -m $selinux_module.mod"

# Install and load the new module
run_cmd "semodule -i" "$selinux_module.pp"

echo "$selinux_module.pp" installed and loaded successfully.
