#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

source /usr/libexec/helper-scripts/get_colors.sh

check_login_security() {
   local user_list password_status_list autologin_status_list \
      users_column_width user_entry table_user_barrier_entry \
      table_user_header_entry counter table_users table_settings_gui \
      table_settings_cli table_users_entry table_settings_gui_entry \
      table_settings_cli_entry table_str_gui table_str_cli user_list_str \
      password_status_list_str qubes_default_user
   if [ "$silent" -ge "4" ]; then
      true "silent is $silent. Skipping $FUNCNAME."
      return 0
   fi

   local base_msg_gui="<p>$PROJECT_NAME <a href=\"https://www.kicksecure.com/wiki/Login\">Login</a> Security Check (<a href=\"https://www.kicksecure.com/wiki/Systemcheck#Login_Security_Check_-_Meaning_of_Colors\">Colors</a>)
:</p>
XXX_LOGIN_SEC_TABLE_XXX
<p>You can adjust these settings using \"Manage Passwords\" and \"Manage GUI Autologin\"
in the System Maintenance Panel."
   local base_msg_cli="${base_msg_gui}
See also:
https://www.kicksecure.com/wiki/Login
https://www.kicksecure.com/wiki/Systemcheck#Physical_Security_Check"

   user_list_str="$(/usr/libexec/helper-scripts/get-user-list)"
   readarray -t user_list <<< "$user_list_str"

   password_status_list_str="$(leaprun get-password-status-list)"
   readarray -t password_status_list <<< "$password_status_list_str"

   autologin_status_list=()
   if [ -f '/usr/share/qubes/marker-vm' ]; then
      qubes_default_user="$(qubesdb-read '/default-user')" \
         || qubes_default_user=''
   else
      qubes_default_user=''
   fi

   for user_entry in "${user_list[@]}"; do
      ## Autologin is always "enabled" for "sysmaint" and the account pointed
      ## to by qubesdb's '/default-user' key under Qubes OS. Note that this
      ## isn't true GUI autologin from a technical perspective, it just
      ## provides a similar experience to the end user and comes with somewhat
      ## similar security concerns, thus why this is not implemented in
      ## helper-scripts /usr/sbin/autologinchange.
      if [ -f '/usr/share/qubes/marker-vm' ]; then
         if [ "${user_entry}" = "${qubes_default_user}" ] \
            || [ "${user_entry}" = 'sysmaint' ]; then
            autologin_status_list+=( 'Enabled' )
         else
            autologin_status_list+=( 'Disabled' )
         fi

         continue
      fi

      ## Account 'sysmaint' requires special handling if sysmaint-boot is
      ## available.
      if [ "${user_entry}" = 'sysmaint' ] && [ -x /usr/libexec/user-sysmaint-split/sysmaint-boot ]; then
         if [ "$(/usr/libexec/user-sysmaint-split/sysmaint-boot query-sysmaint-autologin 2>/dev/null)" = 'yes' ]; then
            autologin_status_list+=( 'Enabled' )
         else
            autologin_status_list+=( 'Disabled' )
         fi
         continue
      fi

      if /usr/sbin/autologinchange -c "${user_entry}" ; then
         autologin_status_list+=( 'Enabled' )
      else
         autologin_status_list+=( 'Disabled' )
      fi
   done

   ## Format the retrieved info into a convenient table.
   ## The table is formatted like this:
   ##
   ## +----------+--------------------------------------+
   ## | Users    | Password               GUI Autologin |
   ## +----------+--------------------------------------+
   ## | root     | Locked (Enabled)       Disabled      |
   ## | aaron    | Present                Disabled      |
   ## | user     | Absent                 Disabled      |
   ## | bob      | Absent                 Enabled       |
   ## | sysmaint | Absent                 Enabled       |
   ## +----------+--------------------------------------+
   ##
   ## The table is generated line by line. The table is divided vertically
   ## into two halves, one for the "Users" section on the left, and one for
   ## the "Settings" section and the actual table of entries on the right. The
   ## "Settings" half is always 40 characters wide, and makes up this part of
   ## the table:
   ##
   ## +--------------------------------------+
   ## | Password               GUI Autologin |
   ## +--------------------------------------+
   ## | ...                    ...           |
   ## +--------------------------------------+
   ## The "Users" half is 3 characters wide plus the length of the longest
   ## username, with a minimum width of 8 characters. It makes up this part of the table:
   ##
   ## +-------
   ## | Users
   ## +-------
   ## | ...
   ## +-------
   ##
   ## (Note that it does NOT include the separator line on the right, as that
   ## belongs to the "Settings" half.) All text is left-justified.

   users_column_width=0
   for user_entry in "${user_list[@]}"; do
      if (( ${#user_entry} > users_column_width )); then
         users_column_width="${#user_entry}"
      fi
   done
   if (( users_column_width < 5 )); then
      users_column_width=5
   fi
   table_user_barrier_entry='+-------'
   table_user_header_entry='| Users '
   for (( counter=5; counter < users_column_width; counter++ )); do
      table_user_barrier_entry+='-'
      table_user_header_entry+=' '
   done
   table_users=(
      "${table_user_barrier_entry}"
      "${table_user_header_entry}"
      "${table_user_barrier_entry}"
   )
   table_settings_gui=(
      '+--------------------------------------+'
      '| Password               GUI Autologin |'
      '+--------------------------------------+'
   )
   table_settings_cli=( "${table_settings_gui[@]}" )
   for (( counter=0; counter < ${#user_list[@]}; counter++ )); do
      printf -v table_users_entry "| %-${users_column_width}s " "${user_list[counter]}"
      table_users+=( "${table_users_entry}" )
      printf -v table_settings_gui_entry "| %-20s   %-13s |" "${password_status_list[counter]}" "${autologin_status_list[counter]}"
      table_settings_cli_entry="${table_settings_gui_entry}"
      if [[ "${table_settings_gui_entry}" =~ 'Locked (Present)' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Locked (Present)'/'<font color="green">Locked (Present)</font>'}"
      elif [[ "${table_settings_gui_entry}" =~ 'Restricted (Present)' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Restricted (Present)'/'<font color="green">Restricted (Present)</font>'}"
      elif [[ "${table_settings_gui_entry}" =~ 'Locked (Absent)' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Locked (Absent)'/'<font color="green">Locked (Absent)</font>'}"
      elif [[ "${table_settings_gui_entry}" =~ 'Restricted (Absent)' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Restricted (Absent)'/'<font color="green">Restricted (Absent)</font>'}"
      elif [[ "${table_settings_gui_entry}" =~ 'Present' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Present'/'<font color="green">Present</font>'}"
      elif [[ "${table_settings_gui_entry}" =~ 'Absent' ]]; then
        if [ "${user_list[counter]}" = "root" ]; then
          table_settings_gui_entry="${table_settings_gui_entry//'Absent'/'<font color="red">Absent</font>'}"
        else
          table_settings_gui_entry="${table_settings_gui_entry//'Absent'/'<font color="orange">Absent</font>'}"
        fi
      fi

      if [[ "${table_settings_gui_entry}" =~ 'Disabled' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Disabled'/'<font color="green">Disabled</font>'}"
      elif [[ "${table_settings_gui_entry}" =~ 'Enabled' ]]; then
        if [ "${user_list[counter]}" = "root" ]; then
          table_settings_gui_entry="${table_settings_gui_entry//'Enabled'/'<font color="red">Enabled</font>'}"
        else
          table_settings_gui_entry="${table_settings_gui_entry//'Enabled'/'<font color="orange">Enabled</font>'}"
        fi
      elif [[ "${table_settings_gui_entry}" =~ 'Error' ]]; then
        table_settings_gui_entry="${table_settings_gui_entry//'Error'/'<font color="red">Error</font>'}"
      fi

      if [[ "${table_settings_cli_entry}" =~ 'Locked (Present)' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Locked (Present)'/"${green}Locked (Present)${nocolor}"}"
      elif [[ "${table_settings_cli_entry}" =~ 'Restricted (Present)' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Restricted (Present)'/"${green}Restricted (Present)${nocolor}"}"
      elif [[ "${table_settings_cli_entry}" =~ 'Locked (Absent)' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Locked (Absent)'/"${green}Locked (Absent)${nocolor}"}"
      elif [[ "${table_settings_cli_entry}" =~ 'Restricted (Absent)' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Restricted (Absent)'/"${green}Restricted (Absent)${nocolor}"}"
      elif [[ "${table_settings_cli_entry}" =~ 'Present' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Present'/"${green}Present${nocolor}"}"
      elif [[ "${table_settings_cli_entry}" =~ 'Absent' ]]; then
        if [ "${user_list[counter]}" = "root" ]; then
          table_settings_cli_entry="${table_settings_cli_entry//'Absent'/"${red}Absent${nocolor}"}"
        else
          table_settings_cli_entry="${table_settings_cli_entry//'Absent'/"${yellow}Absent${nocolor}"}"
        fi
      fi

      if [[ "${table_settings_cli_entry}" =~ 'Disabled' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Disabled'/"${green}Disabled${nocolor}"}"
      elif [[ "${table_settings_cli_entry}" =~ 'Enabled' ]]; then
        if [ "${user_list[counter]}" = "root" ]; then
          table_settings_cli_entry="${table_settings_cli_entry//'Enabled'/"${red}Enabled${nocolor}"}"
        else
          table_settings_cli_entry="${table_settings_cli_entry//'Enabled'/"${yellow}Enabled${nocolor}"}"
        fi
      elif [[ "${table_settings_cli_entry}" =~ 'Error' ]]; then
        table_settings_cli_entry="${table_settings_cli_entry//'Error'/"${red}Error${nocolor}"}"
      fi

      table_settings_gui+=( "${table_settings_gui_entry}" )
      table_settings_cli+=( "${table_settings_cli_entry}" )
   done
   table_users+=( "${table_user_barrier_entry}" )
   table_settings_gui+=( '+--------------------------------------+' )
   table_settings_cli+=( '+--------------------------------------+' )
   table_str_gui='<pre>'$'\n'
   table_str_cli=''
   for (( counter=0; counter < ${#table_users[@]}; counter++ )); do
      table_str_gui+="${table_users[counter]}${table_settings_gui[counter]}"$'\n'
      table_str_cli+="${table_users[counter]}${table_settings_cli[counter]}"$'\n'
   done
   table_str_gui+='</pre>'
   base_msg_gui="${base_msg_gui//XXX_LOGIN_SEC_TABLE_XXX/"${table_str_gui}"}"
   base_msg_cli="${base_msg_cli//XXX_LOGIN_SEC_TABLE_XXX/"${table_str_cli}"}"

   local MSG
   MSG="${base_msg_gui}"
   $output_x ${output_opts[@]} --messagex --typex "info" --message "$MSG"
   MSG="${base_msg_cli}"
   $output_cli ${output_opts[@]} --messagecli --typecli "info" --message "$MSG"
}
