#!/bin/bash
# NAME:
#  util_alarm OPTIONS
#  
# OPTIONS (failed_login)(failed_access)
#     failed_login - To set or get failed login count or duration
#         -s -c - set count of minimum failed login attempts made by a user
#         -s -d - set duration in seconds which failed login attempts are made by user
#       
#         example util_alarm failed_login -s -c 3 -d 60
#         
#         -g - get count of minimum failed login attempts made by a user
#     failed_access  - To set or get unauthorized access delay in alarm.
#         -s -d - set duration in seconds for which next unauthorized access to a sudo command is delayed[30:900]
#         -g - get count of minimum failed login attempts made by a user and duration in seconds
#     start - To start System Monitor service for alarm generation.
#     stop - To stop System Monitor service for alarm generation.
#     restart - To restart System Monitor service for alarm generation.
#
# version 1: AVPUTIL-886
#

#define common values 
CONFIG_FILE="/etc/opt/avpualarm.conf"
FAIL_COUNT_STR="failed_attempt_count"
FAIL_DURATION_STR="failed_attempt_duration"
FAIL_ACCESS_STR="failed_access_duration"
SERVICE_NAMES_STR="service_names"

function usage()
{
 echo " "
 echo 'Usage:  util_alarm
           [ failed_login -s -c [integer value: 2-300] -d [integer value: 30-900] ]
           [ failed_access -s -d [integer value: 30-900] ] 
           [ start|stop|status|restart]
    failed_login  - To set or get failed login count or duration. 
         -s -c - set count of minimum failed login attempts made by a user, value [2:300] 
         -s -d - set duration in seconds for which failed login attempts are made by user, value [30:900] 
         -g - get count of minimum failed login attempts made by a user and duration in seconds
    failed_access  - To set or get, delay in alarm generation for consecutive unauthorized access attempts.
         -s -d - set duration in seconds by which next alarm for unauthorized access to a sudo command is delayed, value [30:900]
         -g - get count of minimum failed login attempts made by a user and duration in seconds
    test_alarm  - To generate test alarm.
         -s <id> - To generate alarm with Alarm Id as id
         -c <id> - To clear alarm with Alarm Id as id
         -l [setlist|clearlist] - To list all available Alarm Ids, setlist to generate alarm, clearlist to clear alarm

    start - To start System Monitor service for alarm generation.
    stop - To stop System Monitor service for alarm generation.
    status - to check status of System Monitor service for alarm generation.
    restart - To restart System Monitor service for alarm generation. 
';
 echo " "
 exit 1
}

# check if user is root - do a sudo if not
[ $UID -eq 0 ] || exec sudo $0 $@

# define functions
# initalize config value if file is not present
function init_conf_file()
{
   if [ ! -e "${CONFIG_FILE}" ] ; then
      auth_section="[failed_login]"
      fail_log1="${FAIL_COUNT_STR}=6"
      fail_log2="${FAIL_DURATION_STR}=600"
      acc_section="[failed_access]"
      acc_fail_log1="${FAIL_ACCESS_STR}=900"
      service_section="[monitor_service]"
      serv_mon_log1="${SERVICE_NAMES_STR}=auditd"
      echo "$auth_section"|tee -a "${CONFIG_FILE}" > /dev/null
      echo "$fail_log1"|tee -a "${CONFIG_FILE}" > /dev/null
      echo "$fail_log2"|tee -a "${CONFIG_FILE}" > /dev/null
      echo "$acc_section"|tee -a "${CONFIG_FILE}" > /dev/null
      echo "$acc_fail_log1"|tee -a "${CONFIG_FILE}" > /dev/null
      echo "$service_section"|tee -a "${CONFIG_FILE}" > /dev/null
      echo "$serv_mon_log1"|tee -a "${CONFIG_FILE}" > /dev/null
   fi
}

# check if config file exists and it has fields for failed_login
function sanity_check()
{
    if [ ! -e "${CONFIG_FILE}" ] ; then
       init_conf_file
    fi

    failed_count_val=$(sed -nr "/^\[failed_login\]/ { :l /^"${FAIL_COUNT_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")
    failed_duration_val=$(sed -nr "/^\[failed_login\]/ { :l /^"${FAIL_DURATION_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")
    failed_acc_val=$(sed -nr "/^\[failed_access\]/ { :l /^"${FAIL_ACCESS_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")
    service_monitor_val=$(sed -nr "/^\[monitor_service\]/ { :l /^"${SERVICE_NAMES_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")

    if [ -z "${failed_count_val}" ];then
        echo "Config file do not have failed_attempt_count set"
        return 2
    fi

    if [ -z "${failed_duration_val}" ];then
        echo "Config file do not have failed_attempt_duration set"
        return 2
    fi

    if [ -z "${failed_acc_val}" ];then
        echo "Config file do not have failed_attempt_duration set"
        return 2
    fi

    if [ -z "${service_monitor_val}" ];then
        echo "Config file do not have service_names set"
        return 2
    fi


    return 0
}

# update config file failed_attempt_count for failed_login
function update_login_count()
{
    COUNT_VALUE="$1"
    sed -i "/^\[failed_login\]$/,/^\[/ s/^\(failed_attempt_count*=*\).*/\1$COUNT_VALUE/" "${CONFIG_FILE}"
}

# update config file failed_attempt_duration for failed_login
function update_login_duration()
{
    INTERVAL_VALUE="$1"
    sed -i "/^\[failed_login\]$/,/^\[/ s/^\(failed_attempt_duration*=*\).*/\1$INTERVAL_VALUE/" "${CONFIG_FILE}"
}

# update config file failed_access_duration for failed_access
function update_access_delay()
{
    INTERVAL_VALUE="$1"
    sed -i "/^\[failed_access\]$/,/^\[/ s/^\(failed_access_duration*=*\).*/\1$INTERVAL_VALUE/" "${CONFIG_FILE}"
}


#get failed_attempt_count for failed_login
function get_login_count()
{
    failed_count_val=$(sed -nr "/^\[failed_login\]/ { :l /^"${FAIL_COUNT_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")
    echo "${FAIL_COUNT_STR} = $failed_count_val"
}

#get failed_attempt_duration for failed_login
function get_login_duration()
{
    failed_duration_val=$(sed -nr "/^\[failed_login\]/ { :l /^"${FAIL_DURATION_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")
    echo "${FAIL_DURATION_STR} = $failed_duration_val"
}

#get failed_attempt_duration for failed_access
function get_access_duration()
{
    failed_duration_val=$(sed -nr "/^\[failed_access\]/ { :l /^"${FAIL_ACCESS_STR}"[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "${CONFIG_FILE}")
    echo "${FAIL_ACCESS_STR} = $failed_duration_val"
}

#set command option for fail_login
function set_cmd()
{
   set_arg_count="$#"
   if [ $set_arg_count -eq 4 ];then
      if [[ "$2" =~ $re ]] || [[ "$4" =~ $re ]];then
         if [ "$1" == "-c" ] && [ "$3" == "-d" ];then
            shift
            rc=1
            if [ $1 -ge 2 ] && [ $1 -le 300 ] && [ $3 -ge 30 ] && [ $3 -le 900 ];then
               update_login_count "$1"
               update_login_duration "$3"
               echo "Failed login count and duration is set, System Monitor service will be automatically restarted"
               python /opt/avaya/common_services/system_monitor.py restart
            else
               usage
            fi
         elif [ "$1" == "-d" ] && [ "$3" == "-c" ];then
            shift
            if [ $1 -ge 30 ] && [ $1 -le 900 ] && [ $3 -ge 2 ] && [ $3 -le 300 ];then
               update_login_duration "$1"
               update_login_count "$3"
               echo "Failed login duration and count is set, System Monitor service will be automatically restarted"
               python /opt/avaya/common_services/system_monitor.py restart
            else
               usage
            fi
         else
            usage
         fi
      else
         echo "Please enter integer value for failure count and failure duration"
      fi
   elif [ $set_arg_count -eq 2 ];then
      if [ "$1" == "-c" ];then
         shift
         if [[ "$1" =~ $re ]];then
            if [ $1 -ge 2 ] && [ $1 -le 300 ];then
               update_login_count "$1"
               echo "Failed login count is set, System Monitor service will be automatically restarted"
               python /opt/avaya/common_services/system_monitor.py restart
            else
               usage
            fi
         else
            echo "Please enter an integer value for failure count"
         fi
      elif [ "$1" == "-d" ];then
         shift
         if [[ "$1" =~ $re ]];then
            if [ $1 -ge 30 ] && [ $1 -le 900 ];then
               update_login_duration "$1"
               echo "Failed login duration is set, System Monitor service will be automatically restarted"    
               python /opt/avaya/common_services/system_monitor.py restart
            else
               usage
            fi
         else
            echo "Please enter an integer value for failure duration"
         fi

      else
         usage
      fi
   else
      usage
   fi
}

#get command option for fail_login
function get_cmd()
{
   get_login_count
   get_login_duration
}

# set failed access delay 
function set_acc_cmd()
{
   arg_count="$#"
   if [ $arg_count -eq 2 ];then
      if [ "$1" == "-d" ];then
         shift
         if [[ "$1" =~ $re ]];then
            if [ $1 -ge 30 ] && [ $1 -le 900 ];then
               update_access_delay "$1"
               echo "Failed access delay is set, System Monitor service will be automatically restarted"
               python /opt/avaya/common_services/system_monitor.py restart
            else
               usage
            fi
         else
            echo "Please enter an integer value for failure access delay"
         fi
      else
         usage
      fi
   else
      usage   
   fi
}

# -----------------------------------------------------------------------------
# main
#

input_cmd="$1"
if [[ "$input_cmd" == "failed_login" ]];then
   re='^[0-9]+$'
   shift
   arg_count="$#"
   if [ $arg_count -lt 1 ] || [ $arg_count -gt 5 ];then
     usage
     exit 1
   fi 
   sanity_check
   sanity_check_rc=$?
   if [ "$sanity_check_rc" -eq 2 ];then
      exit 1
   fi
   
   input_cmd_option="$1"
   shift
   if [[ "$input_cmd_option" == "-s" ]];then
      set_cmd "$@"
   elif [[ "$input_cmd_option" == "-g" ]];then
      get_cmd
   else
      usage
   fi
elif [[ "$input_cmd" == "failed_access" ]];then
   re='^[0-9]+$'
   shift
   arg_count="$#"
   if [ $arg_count -lt 1 ] || [ $arg_count -gt 3 ];then
     usage
     exit 1
   fi

   sanity_check
   sanity_check_rc=$?
   if [ "$sanity_check_rc" -eq 2 ];then
      exit 1
   fi

   input_cmd_option="$1"
   shift
   if [[ "$input_cmd_option" == "-s" ]];then
      set_acc_cmd "$@"
   elif [[ "$input_cmd_option" == "-g" ]];then
      get_access_duration
   else
      usage
   fi

elif [[ "$input_cmd" == "status" ]];then
   python /opt/avaya/common_services/system_monitor.py status
elif [[ "$input_cmd" == "start" ]];then
   python /opt/avaya/common_services/system_monitor.py start
elif [[ "$input_cmd" == "stop" ]];then
   python /opt/avaya/common_services/system_monitor.py stop
elif [[ "$input_cmd" == "restart" ]];then
   python /opt/avaya/common_services/system_monitor.py restart
elif [[ "$input_cmd" == "enable" ]];then
    if [ ! -e "${CONFIG_FILE}" ] ; then 
        init_conf_file
    fi
    echo "Enabling local system monitor"
elif [[ "$input_cmd" == "test_alarm" ]];then
    shift
    python /opt/avaya/common_services/generateUtilTestAlarm.py "$@"
else
    usage
fi

exit 0
