Ctrl K
ComunidadGuías…

hshq-dev.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/bin/bash
HSHQ_WRAPPER_SCRIPT_VERSION=26

# Copyright (C) 2023 HomeServerHQ <drdoug@homeserverhq.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

set -e

function main()
{
  IS_DISABLE_UPDATE_CHECKS=false
  MENU_WIDTH=69
  MENU_HEIGHT=24
  MENU_INT_HEIGHT=10
  export NEWT_COLORS='
  root=,black
  window=white,blue
  title=white,blue
  border=white,blue
  textbox=white,blue
  acttextbox=black,yellow
  listbox=white,blue
  sellistbox=black,yellow
  actlistbox=black,yellow
  actsellistbox=black,yellow
  button=black,yellow
  actbutton=black,yellow
  compactbutton=white,blue
  checkbox=white,blue
  actcheckbox=black,yellow
  '
  USERNAME=$(id -u -n)
  HSHQ_APP_TYPE=home
  if [ -f $HOME/hshq/hshq.dev ]; then
    HSHQ_WRAP_URL=https://homeserverhq.com/hshq-dev.sh
    HSHQ_WRAP_VER_URL=https://homeserverhq.com/ver/getwrapversion-dev
    HSHQ_LIB_URL=https://homeserverhq.com/hshqlib-dev.sh
    HSHQ_LIB_VER_URL=https://homeserverhq.com/ver/getversion-dev
  elif [ -f $HOME/hshq/hshq.test ]; then
    HSHQ_WRAP_URL=https://homeserverhq.com/hshq-test.sh
    HSHQ_WRAP_VER_URL=https://homeserverhq.com/ver/getwrapversion-test
    HSHQ_LIB_URL=https://homeserverhq.com/hshqlib-test.sh
    HSHQ_LIB_VER_URL=https://homeserverhq.com/ver/getversion-test
  else
    HSHQ_WRAP_URL=https://homeserverhq.com/hshq.sh
    HSHQ_WRAP_VER_URL=https://homeserverhq.com/ver/getwrapversion
    HSHQ_LIB_URL=https://homeserverhq.com/hshqlib.sh
    HSHQ_LIB_VER_URL=https://homeserverhq.com/ver/getversion
  fi
  HSHQ_RELEASES_URL=https://homeserverhq.com/releases
  HSHQ_SIG_BASE_URL=https://homeserverhq.com/signatures/
  HSHQ_SIGN_PUB_KEY=https://homeserverhq.com/misc/hshq.asc
  HSHQ_GPG_FINGERPRINT=5B9C33067C71ABCFCE1ACF8A7F46128ABB7C1E42
  HSHQ_GPG_FINGERPRINT_SHORT=7F46128ABB7C1E42
  HSHQ_BASE_DIR=$HOME/hshq
  HSHQ_DATA_DIR=$HSHQ_BASE_DIR/data
  HSHQ_LIB_DIR=$HSHQ_DATA_DIR/lib
  HSHQ_LIB_SCRIPT=$HSHQ_LIB_DIR/hshqlib.sh
  HSHQ_NEW_LIB_SCRIPT=$HSHQ_LIB_DIR/hshqlib.new
  HSHQ_LIB_TMP=$HOME/hshqlib.tmp
  HSHQ_WRAP_SCRIPT=$0
  HSHQ_WRAP_TMP=$HOME/hshqwrap.tmp
  MIN_REQUIRED_LIB_VERSION=28

  logo=$(cat << EOF
#===============================================================#
# ▀█  █  ▄▄  ▄▄ ▄▄ ▄▄▄ █▀▀▀█ ▄▄▄ ▄▄▄  ▄   ▄ ▄▄▄ ▄▄▄  █  █ █▀▀█  #
#  █▀▀█ █  █ █ █ █ ▄▄  ▀▀▀▄▄ ▄▄  ▄▄▄▀ ▀▄ ▄▀ ▄▄  ▄▄▄▀ █▀▀█ █  █  #
#  █  █ ▀▄▄▀ █   █ ▄▄▄ █▄▄▄█ ▄▄▄ ▄▄▄▄  ▀█▀  ▄▄▄ ▄▄▄▄ █  █ █▄▄█▄ #
#===============================================================#
        HomeServerHQ Installation and Management Utility
    Copyright (C) 2023 HomeServerHQ <drdoug@homeserverhq.com>    
       Licensed under GNU General Public License Version 3      
-----------------------------------------------------------------\n
EOF
  )
  isPromptPW=false
  while getopts ':a:ps' opt; do
    case "$opt" in
      a)
        CONNECTING_IP="$OPTARG" ;;
      p)
        isPromptPW=true ;;
      s)
        is_skip_confirm=true ;;
      ?|h)
        echo "Usage: $(basename $0) [-a arg]"
        exit 1 ;;
    esac
  done
  shift "$(($OPTIND -1))"

  set +e
  if [ "$isPromptPW" = "true" ]; then
    read -s -p "" USER_SUDO_PW
  fi
  is_dpkg_config=false
  if [[ "$(isProgramInstalled sudo)" = "false" ]]; then
    if ! [ "$USERNAME" = "root" ]; then
      echo -e "\n\n================================================================================"
      echo -e "The command, sudo, is not installed, and you are currently logged in"
      echo -e "as a non-root user. You must perform the following steps to continue:\n"
      echo -e "  1) Switch to the root user: 'su -'"
      echo -e "  2) Install sudo: 'apt update && apt install sudo -y'"
      echo -e "  3) Add your user to the sudoers group: 'usermod -aG sudo $USERNAME'"
      echo -e "  4) Exit the terminal session entirely: 'exit', then 'exit' again"
      echo -e "  5) Log back in and re-run this script: 'bash hshq.sh'"
      echo -e "\nTo copy these instructions, simply select the text with your mouse,"
      echo -e "and it will automatically be copied to the clipboard."
      echo -e "================================================================================"
      exit 2
    fi
    echo "Installing sudo, please wait..."
    DEBIAN_FRONTEND=noninteractive apt update
    sudo dpkg --configure -a
    is_dpkg_config=true
    DEBIAN_FRONTEND=noninteractive apt install -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' sudo > /dev/null 2>&1
  fi
  # Underscores in hostname have shown to be problematic...
  hostname | grep "_" > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    cur_hostname=$(hostname)
    new_hostname=$(echo $cur_hostname | sed 's|_|-|g')
    sudo hostnamectl set-hostname $new_hostname
  fi
  if [ "$(cat /etc/hosts | grep $(cat /etc/hostname))" = "" ]; then
    echo "127.0.1.1 $(hostname)" | sudo tee -a /etc/hosts
  fi
  rm -f $HOME/dead.letter
  # Also check if config directory exists, so that we don't perpetually remove needrestart. The user may have added it back.
  if [[ "$(isProgramInstalled needrestart)" = "true" ]] && ! [ -d $HSHQ_DATA_DIR/config ]; then
    checkPromptUserPW false
    echo "Removing needrestart, please wait..."
    sudo sed -i "s/#\$nrconf{kernelhints} = -1;/\$nrconf{kernelhints} = -1;/g" /etc/needrestart/needrestart.conf
    sudo DEBIAN_FRONTEND=noninteractive apt remove -y needrestart > /dev/null 2>&1
  fi
  if [[ "$(isProgramInstalled wget)" = "false" ]]; then
    checkPromptUserPW false
    echo "Installing wget, please wait..."
    sudo DEBIAN_FRONTEND=noninteractive apt update
    if [ "$is_dpkg_config" = "false" ]; then
      sudo dpkg --configure -a
      is_dpkg_config=true
    fi
    performAptInstall wget > /dev/null 2>&1
  fi
  if [[ "$(isProgramInstalled curl)" = "false" ]]; then
    checkPromptUserPW false
    echo "Installing curl, please wait..."
    sudo DEBIAN_FRONTEND=noninteractive apt update
    if [ "$is_dpkg_config" = "false" ]; then
      sudo dpkg --configure -a
      is_dpkg_config=true
    fi
    performAptInstall curl > /dev/null 2>&1
  fi
  if [[ "$(isProgramInstalled whiptail)" = "false" ]]; then
    checkPromptUserPW false
    echo "Installing whiptail, please wait..."
    sudo DEBIAN_FRONTEND=noninteractive apt update
    if [ "$is_dpkg_config" = "false" ]; then
      sudo dpkg --configure -a
      is_dpkg_config=true
    fi
    performAptInstall whiptail > /dev/null 2>&1
  fi
  if [[ "$(isProgramInstalled gpg)" = "false" ]]; then
    checkPromptUserPW false
    echo "Installing gnupg, please wait..."
    sudo DEBIAN_FRONTEND=noninteractive apt update
    if [ "$is_dpkg_config" = "false" ]; then
      sudo dpkg --configure -a
      is_dpkg_config=true
    fi
    performAptInstall gnupg > /dev/null 2>&1
  fi
  set -e
  initMenu=$(cat << EOF
$logo

                   Do you wish to continue?

EOF
  )
  if [ -z $is_skip_confirm ]; then
    if ! (whiptail --title "HomeServerHQ" --yesno "$initMenu" $MENU_HEIGHT $MENU_WIDTH); then
      exit 1
    fi
  fi
  if [ -z $CONNECTING_IP ]; then
    CONNECTING_IP=$(getConnectingIPAddress)
  fi
  ciparg=""
  if ! [ -z $CONNECTING_IP ]; then
    ciparg="-a $CONNECTING_IP"
  fi
  if [ "$USERNAME" = "root" ]; then
    showYesNoMessageBox "Non-Root" "You are running this script as root. You must run this from a non-root user account. Do you wish to create one now?"
    mbres=$?
    if [ $mbres -eq 0 ]; then
      LINUX_USERNAME=""
      is_use_existing=false
      while [ -z "$LINUX_USERNAME" ]
      do
        LINUX_USERNAME=$(promptUserInputMenu "" "Enter Username" "Enter your desired username: ")
        if [ $(checkValidUsername "$LINUX_USERNAME") = "false" ]; then
          showMessageBox "Invalid Character(s)" "The username contains invalid character(s). It must consist of a-z (lowercase) and/or 0-9"
          LINUX_USERNAME=""
        fi
        set +e
        getent passwd | grep $LINUX_USERNAME
        if [ $? -eq 0 ]; then
          showYesNoMessageBox "User Exists" "The username already exists, do you want to switch to this user rather than creating a new user?"
          if [ $? -eq 0 ]; then
            is_use_existing=true
          else
            LINUX_USERNAME=""
          fi
        fi
        set -e
      done
      tmp_pw1=""
      if [ "$is_use_existing" = "false" ]; then
        tmp_pw1=1
        tmp_pw2=2
        while ! [ "$tmp_pw1" = "$tmp_pw2" ]
        do
          tmp_pw1=$(promptPasswordMenu "Enter Password" "Enter the password for your user ($LINUX_USERNAME) account: ")
          tmp_pw2=$(promptPasswordMenu "Confirm Password" "Enter the password again to confirm: ")
          if ! [ "$tmp_pw1" = "$tmp_pw2" ]; then
            showMessageBox "Password Mismatch" "The passwords do not match, please try again."
            continue
          fi
          if [ $(checkValidPassword "$tmp_pw1" 8) = "false" ]; then
            showMessageBox "Weak Password" "The password is invalid or is too weak. It must contain at least 8 characters and consist of uppercase letters, lowercase letters, and numbers. No spaces or dollar sign ($)."
            tmp_pw1=1
            tmp_pw2=2
            continue
          fi
        done
        # Capture and pass the user password to the self-referenced function call below.
        # This change was implemented on version 10 of the wrapper (hshq.sh), and 
        # version 68 of the lib (hshqlib.sh), in order to speed up the installation
        # process and eliminate duplicate prompting.
        USER_SUDO_PW="$tmp_pw1"
        pw_hash=$(openssl passwd -6 $tmp_pw1)
        tmp_pw1=""
        tmp_pw2=""
        useradd -m -G sudo -p $pw_hash -s /bin/bash $LINUX_USERNAME
        set +e
        getent group docker >/dev/null || sudo groupadd docker
        set -e
        usermod -aG docker $LINUX_USERNAME
        showMessageBox "New User Created" "New user ($LINUX_USERNAME) has been created. This script will be moved into this user's home directory, i.e. /home/$LINUX_USERNAME. You will now be switched to this new user. Please restart this utility by entering 'bash hshq.sh'."
      else
        showMessageBox "User Selected" "This script will be moved into this user's home directory, i.e. /home/$LINUX_USERNAME. You will now be switched to this new user. Please restart this utility by entering 'bash hshq.sh'."
      fi
      if ! [ -z $CONNECTING_IP ]; then
        mkdir -p /home/$LINUX_USERNAME/hshq
        chown $LINUX_USERNAME:$LINUX_USERNAME /home/$LINUX_USERNAME/hshq
        echo "$CONNECTING_IP" > /home/$LINUX_USERNAME/hshq/cip.txt
        chown $LINUX_USERNAME:$LINUX_USERNAME /home/$LINUX_USERNAME/hshq/cip.txt
      fi
      chown ${LINUX_USERNAME}:${LINUX_USERNAME} $0
      mv $0 /home/$LINUX_USERNAME/
      su - $LINUX_USERNAME
      exit
    fi
    exit 1
  fi
  set +e
  id -nG | grep docker > /dev/null 2>&1
  if [ $? -ne 0 ]; then
    checkPromptUserPW false
    getent group docker >/dev/null || sudo groupadd docker
    sudo usermod -aG docker $USERNAME
    # This can cause infinite recursion given certain circumstances
    #sudo -u $USERNAME bash $0 -s -p $ciparg <<< "$USER_SUDO_PW"
    showMessageBox "Docker User" "The user ($USERNAME) has been added to the docker group. Please restart the installation utility. If you continue to see this message, you may have to reboot your system."
    newgrp
    exit 0
  fi
  if ! [ -d $HSHQ_LIB_DIR ]; then
    mkdir -p $HSHQ_BASE_DIR $HSHQ_DATA_DIR $HSHQ_LIB_DIR
  fi
  is_pending_avail=false
  if [ -f $HSHQ_NEW_LIB_SCRIPT ]; then
    is_pending_avail=true
  fi
  checkDownloadGPGKey
  is_download_lib=false
  checkAnyUpdates
  if [ $? -eq 0 ]; then
    checkDownloadWrapper
    returnVal=$?
    if [ $returnVal -eq 0 ]; then
      checkDownloadLib
    else
      echo "Error updating wrapper ($returnVal)"
    fi
  fi
  if [ -f $HSHQ_LIB_SCRIPT ]; then
    hshq_lib_local_version=$(sed -n 2p $HSHQ_LIB_SCRIPT | cut -d"=" -f2)
    if [ $hshq_lib_local_version -lt $MIN_REQUIRED_LIB_VERSION ]; then
      showMessageBox "Min Version Required" "You must have at least Version $MIN_REQUIRED_LIB_VERSION of the lib script to continue. Please update to the most recent version. Exiting..."
      exit 1
    fi
  fi
  is_apply_pending=false
  if ! [ "$is_download_lib" = "true" ] && [ "$is_pending_avail" = "true" ]; then
    showYesNoMessageBox "Pending Update" "There is a pending update. Do you wish to apply it now?"
    if [ $? -eq 0 ]; then
      is_apply_pending=true
    fi
  fi
  if ! [ -f $HSHQ_LIB_SCRIPT ] && ! [ -f $HSHQ_NEW_LIB_SCRIPT ]; then
    # This should never happen
    showMessageBox "ERROR" "You are missing the required files, exiting..."
    exit 1
  fi
  if ! [ -f $HSHQ_LIB_SCRIPT ]; then
    sudo mv $HSHQ_NEW_LIB_SCRIPT $HSHQ_LIB_SCRIPT
  elif [ "$is_download_lib" = "true" ] || [ "$is_apply_pending" = "true" ]; then
    source $HSHQ_NEW_LIB_SCRIPT lib
    for curSource in $HSHQ_SCRIPTS_DIR/source/*; do
      if [ -f "$curSource" ]; then
        source "$curSource"
      fi
    done
    set +e
    if [[ $(type -t performPreUpdateCheck) = function ]]; then
      # Aquire all locks
      isGotAllLocks=false
      checkRes="$(acquireAllLocks)"
      if ! [ -z "$checkRes" ]; then
        # Could not get all locks
        showYesNoMessageBox "ERROR" "The necessary locks could not be obtained ($checkRes). They can be forcefully reset if you are certain that there are no other running HSHQ processes either in another console window or Script-server. Do you want to forcefully reset them?"
        if [ $? -eq 0 ]; then
          sudo -k
          checkPromptUserPW false
          releaseAllLocks true
          checkRes="$(acquireAllLocks)"
          if ! [ -z "$checkRes" ]; then
            exit 6
          fi
          isGotAllLocks=true
        else
          exit 1
        fi
      else
        isGotAllLocks=true
      fi
      if [ "$isGotAllLocks" = "true" ]; then
        # Get sudo and decrypt config
        checkPromptUserPW true
        if [ $? -ne 0 ]; then
          releaseAllLocks false
          exit 3
        fi
        promptTestDecryptConfigFile
        if [ $? -ne 0 ]; then
          releaseAllLocks false
          exit 3
        fi
        PRIOR_HSHQ_VERSION=$hshq_lib_local_version
        if [ "$PRIMARY_VPN_SETUP_TYPE" = "host" ] && [ $PRIOR_HSHQ_VERSION -lt $LAST_RELAYSERVER_VERSION_UPDATE ]; then
          promptTestRelayServerPassword
        fi
        performPreUpdateCheck
        if [ $? -eq 0 ]; then
          sudo mv $HSHQ_NEW_LIB_SCRIPT $HSHQ_LIB_SCRIPT
          source $HSHQ_LIB_SCRIPT update
          showMessageBox "Update Complete" "All updates have been successfully applied."
          releaseAllLocks false
          is_download_lib=false
        else
          performExitFunctions false
          releaseAllLocks false
          return 0
        fi
      fi
    else
      sudo mv $HSHQ_NEW_LIB_SCRIPT $HSHQ_LIB_SCRIPT
    fi
  fi
  if ! [ -f $HSHQ_LIB_SCRIPT ]; then
    # This should never happen
    showMessageBox "ERROR" "You are missing the required files, exiting..."
    exit 1
  fi
  source $HSHQ_LIB_SCRIPT run "$is_download_lib" "$CONNECTING_IP"
}

function checkDownloadGPGKey()
{
  gpg --list-keys $HSHQ_GPG_FINGERPRINT > /dev/null 2>&1
  if [ $? -ne 0 ]; then
    echo "Obtaining HomeServerHQ Public GPG Key..."
    curl -L -s $HSHQ_SIGN_PUB_KEY | gpg --import > /dev/null 2>&1
  fi
  gpg --list-keys $HSHQ_GPG_FINGERPRINT > /dev/null 2>&1
  if [ $? -ne 0 ]; then
    showMessageBox "GPG Key Error" "There was an error obtaining HomeServerHQ's Public GPG Key, exiting..."
    exit 1
  fi
}

function checkAnyUpdates()
{
  isAny=false
  if [ "$IS_DISABLE_UPDATE_CHECKS" = "true" ]; then
    return 2
  fi
  hshq_wrap_latest_version=$(curl -L --connect-timeout 5 --silent $HSHQ_WRAP_VER_URL)
  if [ $? -ne 0 ] || [ -z "$hshq_wrap_latest_version" ] || ! [ "$(checkValidVersionNumber "$hshq_wrap_latest_version")" = "true" ]; then
    return 3
  fi
  hshq_wrap_local_version=$(sed -n 2p $HSHQ_WRAP_SCRIPT | cut -d"=" -f2)
  if [ $hshq_wrap_local_version -lt $hshq_wrap_latest_version ]; then
    isAny=true
  fi
  if ! [ -f $HSHQ_LIB_SCRIPT ]; then
    return 0
  fi
  hshq_lib_latest_version=$(curl -L --connect-timeout 5 --silent $HSHQ_LIB_VER_URL)
  if [ $? -ne 0 ] || [ -z "$hshq_wrap_latest_version" ] || ! [ "$(checkValidVersionNumber "$hshq_lib_latest_version")" = "true" ]; then
    return 4
  fi
  hshq_lib_local_version=$(sed -n 2p $HSHQ_LIB_SCRIPT  | cut -d"=" -f2)
  if [ $hshq_lib_local_version -lt $hshq_lib_latest_version ]; then
    isAny=true
  fi
  if [ "$isAny" = "true" ]; then
    updateMenu=$(cat << EOF
$logo
There is a more updated version of this software (Version $hshq_lib_latest_version).
See release info at $HSHQ_RELEASES_URL for more details.

         Do you want to obtain this latest version?

EOF
    )
    if (whiptail --title "HomeServerHQ" --yesno "$updateMenu" $MENU_HEIGHT $MENU_WIDTH); then
      return 0
    fi
  fi
  return 1
}

function checkDownloadWrapper()
{
  if [ $hshq_wrap_local_version -lt $hshq_wrap_latest_version ]; then
    echo "Getting new wrapper.."
    wget -q4 -O $HSHQ_WRAP_TMP $HSHQ_WRAP_URL
    if [ $? -ne 0 ]; then
      rm -f $HSHQ_WRAP_TMP
      rm -f $HSHQ_LIB_TMP
      if [ -f $HSHQ_WRAP_SCRIPT ]; then
        showMessageBox "Download Error" "There was an error obtaining the latest wrapper version, proceeding with local version..."
      else
        showMessageBox "Download Error" "There was an error obtaining the required wrapper. Please try again later."
        exit 1
      fi
      return 1
    fi
  else
    # No update needed
    return 0
  fi
  echo "Checking new wrapper..."
  hshq_wrap_dl_version=$(sed -n 2p $HSHQ_WRAP_TMP | cut -d"=" -f2)
  if ! [ "$(checkValidVersionNumber "$hshq_wrap_dl_version")" = "true" ]; then
    rm -f $HSHQ_WRAP_TMP
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Download Error" "There was an error obtaining the latest wrapper version (not a number), proceeding with local version..."
    else
      showMessageBox "Download Error" "There was an error with the indicated wrapper version - not a number. Please try again later."
      exit 5
    fi
    return 0
  fi
  echo "Obtained Wrapper Version $hshq_wrap_dl_version"
  wget -q4 -O $HOME/wrap-${hshq_wrap_dl_version}.sig $HSHQ_SIG_BASE_URL/wrap-${hshq_wrap_dl_version}.sig
  if [ $? -eq 0 ]; then
    echo "Signature downloaded (wrap-${hshq_wrap_dl_version}.sig)..."
  else
    rm -f $HOME/wrap-${hshq_wrap_dl_version}.sig
    rm -f $HSHQ_WRAP_TMP
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Download Error" "There was an error obtaining the wrapper signature, proceeding with local version..."
    else
      showMessageBox "Download Error" "There was an error obtaining the wrapper signature. Please try again later."
      exit 1
    fi
    return 0
  fi
  echo "Verifying wrap with signature..."
  verifyFile $HSHQ_WRAP_TMP $HOME/wrap-${hshq_wrap_dl_version}.sig
  ver_res=$?
  rm -f $HOME/wrap-${hshq_wrap_dl_version}.sig
  if [ $ver_res -ne 0 ]; then
   # Not verified, raise the red flag
    rm -f $HSHQ_WRAP_TMP
    rm -f $HSHQ_LIB_TMP
    echo "@@@@@@@@@@@@@@@@@@@@@@@  SECURITY ALERT  @@@@@@@@@@@@@@@@@@@@@@@"
    echo " There was a verification error on the latest wrapper version (${hshq_wrap_dl_version}). "
    echo " Please email security@homeserverhq.com as soon as possible.  "
    echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Security Alert" "@@@@@@@@@@@@@@@@@@@@@@@  SECURITY ALERT  @@@@@@@@@@@@@@@@@@@@@@@\n There was a verification error on the latest wrapper version (${hshq_wrap_dl_version}). \n Please email security@homeserverhq.com as soon as possible.\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n Proceeding safely with local version..."
    else
      showMessageBox "Security Alert" "@@@@@@@@@@@@@@@@@@@@@@@  SECURITY ALERT  @@@@@@@@@@@@@@@@@@@@@@@\n There was a verification error on the downloaded script.\n Please email security@homeserverhq.com as soon as possible.\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\nExiting..."
      exit 1
    fi
    return 0
  fi
  # Verified
  chmod 544 $HSHQ_WRAP_TMP
  mv -f $HSHQ_WRAP_TMP $HSHQ_WRAP_SCRIPT
  # Show message box
  showMessageBox "Wrapper Script Updated" "The wrapper script was updated. You will have to restart the script (bash hshq.sh). Exiting..."
  exit
}

function checkDownloadLib()
{
  if [ -f $HSHQ_LIB_SCRIPT ]; then
    if [ -z "$hshq_lib_latest_version" ]; then
      hshq_lib_latest_version=$(curl -L --connect-timeout 5 --silent $HSHQ_LIB_VER_URL)
      if [ $? -ne 0 ] || [ -z "$hshq_lib_latest_version" ] || ! [ "$(checkValidVersionNumber "$hshq_lib_latest_version")" = "true" ]; then
        return 0
      fi
    fi
    if [ $hshq_lib_local_version -ge $hshq_lib_latest_version ]; then
      # No updated needed
      return 0
    fi
  fi
  echo "Downloading latest version..."
  wget -q4 -O $HSHQ_LIB_TMP $HSHQ_LIB_URL
  if [ $? -ne 0 ]; then
    rm -f $HSHQ_LIB_TMP
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Download Error" "There was an error obtaining the latest lib version, proceeding with local version..."
    else
      showMessageBox "Download Error" "There was an error obtaining the required lib. Please try again later."
      exit 1
    fi
    return 0
  fi
  hshq_lib_dl_version=$(sed -n 2p $HSHQ_LIB_TMP | cut -d"=" -f2)
  if ! [ "$(checkValidVersionNumber "$hshq_lib_dl_version")" = "true" ]; then
    rm -f $HSHQ_LIB_TMP
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Download Error" "There was an error obtaining the latest lib version (not a number), proceeding with local version..."
    else
      showMessageBox "Download Error" "There was an error with the indicated lib version - not a number. Please try again later."
      exit 5
    fi
    return 0
  fi
  echo "Obtained Library Version $hshq_lib_dl_version"
  wget -q4 -O $HOME/lib-${hshq_lib_dl_version}.sig $HSHQ_SIG_BASE_URL/lib-${hshq_lib_dl_version}.sig
  if [ $? -ne 0 ]; then
    rm -f $HOME/lib-${hshq_lib_dl_version}.sig
    rm -f $HSHQ_LIB_TMP
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Download Error" "There was an error obtaining the lib signature, proceeding with local version..."
    else
      showMessageBox "Download Error" "There was an error obtaining the lib signature. Please try again later."
      exit 1
    fi
    return 0
  fi
  echo "Signature downloaded (lib-${hshq_lib_dl_version}.sig)..."
  echo "Verifying lib with signature..."
  verifyFile $HSHQ_LIB_TMP $HOME/lib-${hshq_lib_dl_version}.sig
  ver_res=$?
  rm -f $HOME/lib-${hshq_lib_dl_version}.sig
  if [ $ver_res -ne 0 ]; then
    # Not verified, raise the red flag
    is_download_wrap=false
    rm -f $HSHQ_WRAP_TMP
    rm -f $HOME/wrap-${hshq_wrap_dl_version}.sig
    rm -f $HSHQ_LIB_TMP
    echo "@@@@@@@@@@@@@@@@@@@@@@@  SECURITY ALERT  @@@@@@@@@@@@@@@@@@@@@@@"
    echo " There was a verification error on the latest lib version(${hshq_lib_dl_version})."
    echo "   Please email security@homeserverhq.com as soon as possible.  "
    echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
    if [ -f $HSHQ_LIB_SCRIPT ]; then
      showMessageBox "Security Alert" "@@@@@@@@@@@@@@@@@@@@@@@  SECURITY ALERT  @@@@@@@@@@@@@@@@@@@@@@@\n There was a verification error on the latest lib version(${hshq_lib_dl_version}).\n Please email security@homeserverhq.com as soon as possible.\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n Proceeding safely with local version..."
    else
      showMessageBox "Security Alert" "@@@@@@@@@@@@@@@@@@@@@@@  SECURITY ALERT  @@@@@@@@@@@@@@@@@@@@@@@\n There was a verification error on the downloaded script.\n Please email security@homeserverhq.com as soon as possible.\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n Exiting..."
      exit 1
    fi
    return 0
  fi
  # Verified
  echo "Source code verified!"
  rm -f $HSHQ_NEW_LIB_SCRIPT
  chmod 644 $HSHQ_LIB_TMP
  sudo mv $HSHQ_LIB_TMP $HSHQ_NEW_LIB_SCRIPT
  is_download_lib=true
}

function verifyFile()
{
  # Perform 4 checks:
  # 1 - Ensure both src and sig files exist
  # 2 - Verify the file
  # 3 - Ensure the verification process used the correct key
  # 4 - Ensure the output contains "Good signature" (This step is likely redundant, but thats fine)
  src_file=$1
  sig_file=$2
  if ! [ -f "$src_file" ] || ! [ -f "$sig_file" ]; then
    return 4
  fi
  gpg --verify $sig_file $src_file >/dev/null 2>/tmp/verify
  ver_res=$?
  if [ $ver_res -ne 0 ]; then
    rm -f /tmp/verify
    return $ver_res
  fi
  grep $HSHQ_GPG_FINGERPRINT /tmp/verify > /dev/null 2>&1
  ver_res=$?
  if [ $ver_res -ne 0 ]; then
    rm -f /tmp/verify
    return $ver_res
  fi
  grep "Good signature" /tmp/verify > /dev/null 2>&1
  ver_res=$ver_res
  if [ $? -ne 0 ]; then
    rm -f /tmp/verify
    return $ver_res
  fi
  rm -f /tmp/verify
}

function performAptInstall()
{
  sudo DEBIAN_FRONTEND=noninteractive apt install -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' $1
}

function isProgramInstalled()
{
  bin_name=$(echo $1 | cut -d"|" -f1)
  lib_name=$(echo $1 | cut -d"|" -f2)
  if [[ -z $(which ${bin_name}) ]]; then
    echo "false"
  else
    echo "true"
  fi
}

function getConnectingIPAddress()
{
  echo $(echo $SSH_CLIENT | xargs | cut -d" " -f1)
}

function showMessageBox()
{
  msgmenu=$(cat << EOF
$logo
$2

EOF
  )
  whiptail --title "$1" --msgbox "$msgmenu" $MENU_HEIGHT $MENU_WIDTH
}

function showYesNoMessageBox()
{
  msgmenu=$(cat << EOF
$logo
$2

EOF
  )
  whiptail --title "$1" --yesno "$msgmenu" $MENU_HEIGHT $MENU_WIDTH
}

function promptUserInputMenu()
{
  usermenu=$(cat << EOF
$logo
$3

EOF
  )
  menures=$(whiptail --title "$2" --inputbox "$usermenu" $MENU_HEIGHT $MENU_WIDTH "$1" 3>&1 1>&2 2>&3)
  if [ $? -ne 0 ]; then
    exit 1
  fi
  echo "$menures"
}

function promptPasswordMenu()
{
  usermenu=$(cat << EOF
$logo
$2

EOF
  )
  menures=$(whiptail --title "$1" --passwordbox "$usermenu" $MENU_HEIGHT $MENU_WIDTH 3>&1 1>&2 2>&3)
  if [ $? -ne 0 ]; then
    exit 1
  fi
  echo "$menures"
}

function checkPromptUserPW()
{
  isReturnOnFail="$1"
  if ! [ "$USERNAME" = "root" ]; then
    sudo -k
    if ! [ -z "$USER_SUDO_PW" ]; then
      echo "$USER_SUDO_PW" | sudo -S -v -p "" > /dev/null 2>&1
      if [ $? -ne 0 ]; then
        USER_SUDO_PW=""
      fi
    fi
    while [ -z "$USER_SUDO_PW" ]
    do
      USER_SUDO_PW=$(promptPasswordMenu "Enter Password" "Enter your sudo password for $USERNAME: ")
      retVal=$?
      if [ $retVal -ne 0 ]; then
        if [ "$isReturnOnFail" = "true" ]; then
          return 3
        else
          exit 3
        fi
      fi
      echo "$USER_SUDO_PW" | sudo -S -v -p "" > /dev/null 2>&1
      if [ $? -ne 0 ]; then
        showMessageBox "Incorrect Password" "The password is incorrect, please re-enter it."
        USER_SUDO_PW=""
        continue
      fi
    done
  fi
}

function checkValidString()
{
  check_string=$1
  addchars=$2
  if [[ $check_string =~ ^[0-9a-z$addchars]+$ ]]; then
    echo "true"
  else
    echo "false"
  fi
}

function checkValidUsername()
{
  chkName="$1"
  if echo "$chkName" | grep -Eq '^[a-z0-9]+$' && echo "$chkName" | cut -c1 | grep -Eq '[a-z]' && [ ${#chkName} -le 32 ] && [ ${#chkName} -ge 4 ]; then
    echo "true"
  else
    echo "false"
  fi
}

function checkValidPassword()
{
  pw_in="$1"
  min_length=$2
  pw_length=${#pw_in}
  if ! [[ "$pw_in" =~ [[:upper:]] ]]; then
    # Does not contain upper case.
    echo "false"
  elif ! [[ "$pw_in" =~ [[:lower:]] ]]; then
    # Does not contain lower case.
    echo "false"
  elif ! [[ "$pw_in" =~ [0-9] ]]; then
    # Does not contain number.
    echo "false"
  elif [[ "$pw_in" =~ [[:space:]] ]]; then
    # Contains a space.
    echo "false"
  elif [[ "$pw_in" =~ '$' ]]; then
    # Contains a dollar sign.
    echo "false"
  elif [ $pw_length -lt $min_length ]; then
    # Less than min characters
    echo "false"
  else
    echo "true"
  fi
}

function checkValidNumber()
{
  check_string=$1
  if [[ $check_string =~ ^[0-9]+$ ]]; then
    echo "true"
  else
    echo "false"
  fi
}

function checkValidVersionNumber()
{
  check_number="$1"
  if [ "$(checkValidNumber "$check_number")" = "false" ]; then
    echo "false"
  elif [ $check_number -lt 1 ] || [ $check_number -gt 10000 ]; then
    echo "false"
  else
    echo "true"
  fi
}
main "$@"