#!/bin/bash

###############################################################################
# Help choosing a category
###############################################################################

echo "Hello! This tool helps you choose and set the appropriate SELinux context
for an application."
read -p "Do you want to use a guided version? y/n: " flag

while [ "$flag" != "y" ] && [ "$flag" != "n" ];
do
	read -p "Do you want to use a guided version? y/n: " flag
done

if [ "$flag" == "n" ]; then

  echo "------------------------------------------------------------------------"
  echo "Choose application category"
  echo "------------------------------------------------------------------------"

  echo " 1 - Simple local applications"
  echo " 2 - File viewers"
  echo " 3 - File editors"
  echo " 4 - Trusted file viewers"
  echo " 5 - Trusted file editors"
  echo " 6 - Device recorders"
  echo " 7 - General web browsers"
  echo " 8 - Restricted web browsers"
  echo " 9 - Trusted web browsers"
  echo "10 - Unlimited web browsers"
  echo "11 - General mail clients"
  echo "12 - Restricted mail clients"
  echo "13 - Trusted mail clients"
  echo "14 - General network applications"
  echo "15 - Teleconferencing applications"
  echo "16 - Unconfined applications (not recommended)"

  read -p "Enter the number of the category (1-16): " num

  while [[ -n ${num//[0-9]/} ]] || [ $num -lt 1 ] || [ $num -gt 16 ]; do
  	read -p "Enter the number of the category (1-16): " num
  done

  case $num in

    1)
      exec_type="local_restricted_exec_t"
      type="local_restricted_t"
      ;;

    2)
      exec_type="local_readonly_exec_t"
      type="local_readonly_t"
      ;;

    3)
      exec_type="local_general_exec_t"
      type="local_general_t"
      ;;

    4)
      exec_type="local_trusted_readonly_exec_t"
      type="local_trusted_readonly_t"
      ;;

    5)
      exec_type="local_trusted_rw_exec_t"
      type="local_trusted_rw_t"
      ;;

    6)
      exec_type="local_with_devices_exec_t"
      type="local_with_devices_t"
      ;;

    7)
      exec_type="browser_general_exec_t"
      type="browser_t"
      ;;

    8)
      exec_type="browser_restricted_exec_t"
      type="browser_t"
      ;;

    9)
      exec_type="browser_trusted_exec_t"
      type="browser_t"
      ;;

    10)
      exec_type="browser_with_devices_exec_t"
      type="browser_t"
      ;;

    11)
      exec_type="mail_general_exec_t"
      type="mail_t"
      ;;

    12)
      exec_type="mail_restricted_exec_t"
      type="mail_t"
      ;;

    13)
      exec_type="mail_trusted_exec_t"
      type="mail_t"
      ;;

    14)
      exec_type="network_general_exec_t"
      type="network_general_t"
      ;;

    15)
      exec_type="network_with_devices_exec_t"
      type="network_with_devices_t"
      ;;

    16)
      exec_type="unconfined_exec_t"
      type="unconfined_t"
      ;;
  esac

  echo "OK"

#-----------------------
# Tutorial mode

else
  echo "Answer the following questions to determine the appropriate category
  of applications."

  echo "Should the application have access to network?"
  read -p "Enter y/n: " flag

  while [ "$flag" != "y" ] && [ "$flag" != "n" ];
  do
    read -p "Enter y/n: " flag
  done

  if [ "$flag" == "y" ];
  then
    # Web browsers    
    echo "Is access to web protocols sufficient (i.e. is it a web browser)?"
    read -p "Enter y/n: " flag

    while [ "$flag" != "y" ] && [ "$flag" != "n" ];
    do
      read -p "Enter y/n: " flag
    done

    if [ $flag == "y" ];
    then
      echo "There are four possible modes for the web browser. One of them
      should be set as a default mode, but the same web browser can be
      temporarily executed in other modes using the runcon command.
      Which of the following modes do you want to set as default?"
      echo "1 - Restricted web browsers
      - can only access data in download/upload folders (downloads_t)
      - no access to webcam/microphone"
      echo "2 - General web browsers
      - full access to non-sensitive user data
      - no access to webcam/microphone"
      echo "3 - Unlimited web browsers
      - full access to non-sensitive user data
      - access to webcam/microphone"
      echo "4 - Trusted web browsers
      - read access to sensitive user data, full access to non-sensitive data
      - no access to webcam/microphone"

      read -p "Enter 1/2/3/4: " flag
      while [ $flag != 1 ] && [ $flag != 2 ] && [ $flag != 3 ] && [ $flag != 4 ];
      do
        read -p "Enter 1/2/3/4: " flag
      done

      case $flag in

      1)
        exec_type="browser_restricted_exec_t"
        type="browser_t"
        echo "Chosen category: Restricted web browsers" 
        ;;

      2)
        exec_type="browser_general_exec_t"
        type="browser_t"
        echo "Chosen category: General web browsers" 
        ;;

      3)
        exec_type="browser_with_devices_exec_t"
        type="browser_t"
        echo "Chosen category: Unlimited web browsers" 
        ;;

      4)
        exec_type="browser_trusted_exec_t"
        type="browser_t"
        echo "Chosen category: Trusted web browsers" 
        ;;
      esac

    else
      # Mail clients
      echo "Is access to mail protocols sufficient (i.e. is it a mail client)?"
      read -p "Enter y/n: " flag

      while [ "$flag" != "y" ] && [ "$flag" != "n" ];
      do
        read -p "Enter y/n: " flag
      done

      if [ "$flag" == "y" ];
      then
        echo "There are three possible modes for the mail client. One of them
        should be set as a default mode, but the same mail client can be
        temporarily executed in other modes using the runcon command.
        Which of the following modes do you want to set as default?"
        echo "1 - Restricted mail clients
        - can only access data in download/upload folders (downloads_t)
        - can only use mail protocols"
        echo "2 - General mail clients
        - full access to non-sensitive user data
        - can use mail and web protocols"
        echo "3 - Trusted mail clients
        - read access to sensitive user data, full access to non-sensitive data
        - can use mail and web protocols"

        read -p "Enter 1/2/3: " flag
        while [ $flag != 1 ] && [ $flag != 2 ] && [ $flag != 3 ];
        do
          read -p "Enter 1/2/3: " flag
        done

        case $flag in

        1)
          exec_type="mail_restricted_exec_t"
          type="mail_t"
          echo "Chosen category: Restricted mail clients" 
          ;;

        2)
          exec_type="mail_general_exec_t"
          type="mail_t"
          echo "Chosen category: General mail clients" 
          ;;

        3)
          exec_type="mail_trusted_exec_t"
          type="mail_t"
          echo "Chosen category: Trusted mail clients" 
          ;;
        esac

      else  
        # Other networking applications
        echo "Is access via TCP/UDP sufficient (i.e. no access to raw sockets)?"
        read -p "Enter y/n: " flag

        while [ "$flag" != "y" ] && [ "$flag" != "n" ];
        do
          read -p "Enter y/n: " flag
        done

        if [ "$flag" == "y" ];
        then
          echo "Is access to webcam/microphone required (i.e. for teleconferencing)?"
          read -p "Enter y/n: " flag

          while [ "$flag" != "y" ] && [ "$flag" != "n" ];
          do
            read -p "Enter y/n: " flag
          done

          if [ "$flag" == "y" ];
          then
            exec_type="network_with_devices_exec_t"
            type="network_with_devices_t"
            echo "Chosen category: Teleconferencing network applications"            
          else
            exec_type="network_general_exec_t"
            type="network_general_t"
            echo "Chosen category: General network applications"  
          fi
        else
          exec_type="network_unlimited_exec_t"
          type="network_unlimited_t"
          echo "Chosen category: Unlimited network applications" 
        fi
      fi
    fi

  else
   # Trusted applications   
    echo "Is access sensitive user data (passwords, encryption keys) required?"
    read -p "Enter y/n: " flag

    while [ "$flag" != "y" ] && [ "$flag" != "n" ];
    do
      read -p "Enter y/n: " flag
    done

    if [ "$flag" == "y" ];
    then
      echo "Is read access sufficient?"
      read -p "Enter y/n: " flag

      while [ "$flag" != "y" ] && [ "$flag" != "n" ];
      do
        read -p "Enter y/n: " flag
      done

      if [ "$flag" == "y" ];
      then
        exec_type="local_trusted_readonly_exec_t"
        type="local_trusted_readonly_t"
        echo "Chosen category: Trusted file viewers" 
      else
        exec_type="local_trusted_rw_exec_t"
        type="local_trusted_rw_t"
        echo "Chosen category: Trusted file editors"
      fi
    else
      echo "Is access to non-sensitive user data required?"
      read -p "Enter y/n: " flag

      while [ "$flag" != "y" ] && [ "$flag" != "n" ];
      do
        read -p "Enter y/n: " flag
      done

      if [ "$flag" == "y" ];
      then
        echo "Is read access sufficient?"
        read -p "Enter y/n: " flag

        while [ "$flag" != "y" ] && [ "$flag" != "n" ];
        do
          read -p "Enter y/n: " flag
        done

        if [ "$flag" == "y" ];
        then
          exec_type="local_readonly_exec_t"
          type="local_readonly_t"
          echo "Chosen category: File viewers" 
        else

          echo "Is access to raw devices required?"
          read -p "Enter y/n: " flag

          while [ "$flag" != "y" ] && [ "$flag" != "n" ];
          do
            read -p "Enter y/n: " flag
          done
          
          if [ "$flag" == "y" ];
          then
            exec_type="local_with_devices_exec_t"
            type="local_with_devices_t"
            echo "Chosen category: Device recorders"
          else
            exec_type="local_general_exec_t"
            type="local_general_t"
            echo "Chosen category: File editors"
          fi
        fi
      else
        exec_type="local_restricted_exec_t"
        type="local_restricted_t"
        echo "Chosen category: Simple local applications"
      fi
    fi
  fi

  echo "Please confirm the selected category. If it does not fit the concerned
  application, you may fallback to the unconfined category which is virtually
  unlimited. Hovewer, beware there are no security guarantees for this category."
  echo "Do you wish to proceed with the selected category?"

  read -p "Enter y/n: " flag

  while [ "$flag" != "y" ] && [ "$flag" != "n" ];
  do
    read -p "Enter y/n: " flag
  done

  if [ "$flag" == "n" ];
  then
    exec_type="unconfined_exec_t"
    type="unconfined_t"
  fi
fi

###############################################################################
# Choose operation
###############################################################################

echo "------------------------------------------------------------------------"
echo "Choose operation"
echo "------------------------------------------------------------------------"

echo "Do you want to add, modify or delete a security context?"
read -p "Enter a/m/d: " mod

while [ "$mod" != "a" ] && [ "$mod" != "m" ] && [ "$mod" != "r" ];
do
	read -p "Enter a/m/r: " mod
done

mod="-"$mod
echo "OK"

###############################################################################
# Set contexts
###############################################################################

echo "------------------------------------------------------------------------"
echo "Specify file path"
echo "------------------------------------------------------------------------"

echo "Enter full path to the application executable file (not a symbolic link).
Examples:
  /usr/bin/evolution
  /usr/lib/firefox-esr/firefox-esr
  /opt/sublime_text/sublime_text"

read -p "Executable file path: " fileName

while [ ! -e $fileName ];
do
	read -p "The specified file does not exist. Try again: " fileName
done

echo "OK"

semanage fcontext $mod -t $exec_type "$fileName"
restorecon -v $fileName

echo "------------------------------------------------------------------------"
echo "Specify directory path"
echo "------------------------------------------------------------------------"

echo "Enter full path to the application directory (in case the application
comes with some libraries, configuration files etc). This should not be a path
to the configuration files in the user home directory.
Examples:
  - (none)
  /usr/lib/firefox-esr
  /opt/sublime_text"

read -p "Application directory (or -): " folderName

while [ $folderName != "-" ];
do
  while [ ! -d $folderName ] && [ $folderName != "-" ];
  do
  	read -p "The specified folder does not exist. Try again: " folderName
  done

  if [ $folderName != "-" ]; then
    folderName=${folderName%/}
    semanage fcontext $mod -t $type "$folderName(/.*)?"
    restorecon -Rv $folderName
    read -p "Enter next directory (or -): " folderName
  fi
done

echo "OK. Bye."