#!/bin/bash

## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP <adrelanos@riseup.net>
## See the file COPYING for copying conditions.

## Exit codes of this script get interpreted by sdwdate.
## exit 0
## exit 1: wait, retry and warning icon
## exit 2: wait, retry and error icon

set -o pipefail
set -e errtrace

error_handler() {
   local exit_code="$?"
   echo "\
BASH_COMMAND: $BASH_COMMAND
exit_code: $exit_code"
}

trap "error_handler" ERR

source /usr/local/lib64/helper-scripts/tor_enabled_check
source /usr/local/lib64/helper-scripts/pkg_manager_running_check
source /usr/local/lib64/helper-scripts/tor_bootstrap_check.bsh

te_pe_tb_check() {
   if [ -f "/usr/share/anon-gw-base-files/gateway" ]; then
      VM="Gateway"
   elif [ -f "/usr/share/anon-ws-base-files/workstation" ]; then
      VM="Workstation"
   else
      VM="Could not determine if this is gateway or workstation. Please report this bug."
   fi

   clock_causes="\
<br><br>Possible causes:<br>
- The host clock is wrong -> shut down the VM, fix the clock in the host and restart the VM.<br>
- The VM clock is wrong -> manually fix the clock. Restart Tor if necessary. Then restart sdwdate.<br>
- A host clock attack succeeded.<br>
- A hardware issue (for example bios clock issues).<br>"

   ## Debugging.
   true "$FUNCNAME: CURL: $CURL"
   true "$FUNCNAME: LD_PRELOAD: $LD_PRELOAD"

   if [ -e /usr/share/timesanitycheck/shared ]; then
      ## provides: time_sanity_check
      ## sets: time_sanity_check_exit_code
      ## sets: time_sanity_check_msg_static
      source /usr/share/timesanitycheck/shared
      time_sanity_check
      if [ "$time_sanity_check_exit_code" = "0" ]; then
         echo "$time_sanity_check_msg_static" >&2
      else
         echo "$time_sanity_check_msg_static
$clock_causes"
         timesanitycheck_static_timestamp_based_failed="true"
         if [ "$VM" = "Gateway" ]; then
            exit 1
         fi
      fi
   fi

   ## Sets: TOR_ENABLED
   check_tor_enabled_do

   if [ "$TOR_ENABLED" = "1" ]; then
      ## Ok.
      true
   else
      if [ -f /usr/share/whonix/marker ]; then
         echo "<b>Tor is disabled.</b> Please enable Tor using whonixsetup.<br> \
Start Menu -> System -> Anon Connection Wizard or in Terminal: sudo whonixsetup"
      else
         echo "Tor is disabled. Please enable Tor in the Tor config."
      fi

      exit 1
   fi

   ## sets: check_apt_get_exit_code
   ## sets: package_manager_waiting_msg
   #check_package_manager_running_helper ## pkg_manager_running_check
   #if [ "$check_apt_get_exit_code" = "0" ]; then
      #true "Package manager not busy, ok."
   #else
      #echo "$package_manager_waiting_msg"

      #exit 2
   #fi

   ## sets: check_bootstrap_helper_script
   ## sets: lastpid
   ## sets: tor_bootstrap_percent
   ## sets: tor_bootstrap_status
   check_tor_circuit_established ## tor_bootstrap_check.bsh

   ## $tor_circuit_established_check_exit_code on timeout returns:
   ## - 124 if sigterm was sufficient
   ## - 137 if needed to use kill.

   for invalid_exit_code in "124" "137" "254" ; do
      if [ "$tor_circuit_established_check_exit_code" = "$invalid_exit_code" ]; then
         echo "Tor Bootstrap Result: \
   <b>ERROR ($tor_circuit_established_check_exit_code).</b><br> Please report this bug!"
         exit 1
      fi
   done

   if [ "$tor_circuit_established_check_exit_code" = "255" ]; then
      if [ "$VM" = "Gateway" ]; then
         echo "Tor Bootstrap Result: \
<b>Tor's Control Port could not be reached.</b><br>"
      elif [ "$VM" = "Workstation" ]; then
         if [ -f /usr/share/whonix/marker ]; then
            echo "Tor Bootstrap Result: \
<b>Tor's Control Port could not be reached.</b><br> \
<br>Did you start Gateway beforehand? \
<br>Please run whonixcheck on Gateway."
         else
            echo "Tor Bootstrap Result: \
<b>Tor's Control Port could not be reached.</b><br> \
<br>Did you start Gateway beforehand?"
         fi
      else
         if [ -f /usr/share/whonix/marker ]; then
            echo "Tor Bootstrap Result: \
<b>Tor's Control Port could not be reached.</b><br> \
<br>Did you start Gateway beforehand? \
<br>Please run whonixcheck on Gateway.
<br>$FUNCNAME: This is neither a gateway nor a workstation. Please report this bug!"
         else
            echo "Tor Bootstrap Result: \
<b>Tor's Control Port could not be reached.</b><br> \
<br>Did you start Gateway beforehand?
<br>$FUNCNAME: This is neither a gateway nor a workstation. Please report this bug!"
         fi
      fi

      exit 1
   fi

   if [ "$VM" = "Gateway" ]; then
      check_tor_bootstrap_status
   fi

   ## When using an old Tor consensus which might be the case when no Tor
   ## circuit has been established yet, there is no point to check Tor
   ## consensus time as it might be outdated leading to concluding that the
   ## clock is fast.
   if [ "$tor_circuit_established" = "0" ]; then
      if [ "$VM" = "Gateway" ]; then
         echo "<b>Tor is not yet fully bootstrapped.</b> $tor_bootstrap_percent % done.\
   <br>Tor reports: $tor_bootstrap_status"
      else
         echo "<b>Tor is not yet fully bootstrapped.</b> Tor circuit: $tor_circuit_established_word."
      fi
      exit "2"
   fi

   ## If the static timestamp based time sanity check failed, there is no
   ## need to run the Tor consensus based time sanity check. Avoiding
   ## duplicate output.
   if [ ! "$timesanitycheck_static_timestamp_based_failed" = "true" ]; then
      ## sets: tor_consensus_valid_after_exit_code
      ## sets: tor_consensus_valid_after_output
      ## sets: tor_consensus_valid_after_unixtime
      tor_consensus_valid-after

      ## sets: tor_consensus_valid_until_exit_code
      ## sets: tor_consensus_valid_until_output
      ## sets: tor_consensus_valid_until_unixtime
      tor_consensus_valid-until

      current_unixtime="$(date +"%s")"

      if [ "$tor_consensus_valid_after_exit_code" = "0" ] && [ "$tor_consensus_valid_until_exit_code" = "0" ]; then
         clock_tor_consensus_check_result="ok"
         if [ "$current_unixtime" -ge "$tor_consensus_valid_after_unixtime" ]; then
            true
         else
            clock_tor_consensus_check_result="slow"
            clock_tor_consensus_check_msg="The clock might be too slow. Clock is slower than consensus/valid-after $tor_consensus_valid_after_output. $clock_causes"
         fi
         if [ "$current_unixtime" -ge "$tor_consensus_valid_until_unixtime" ]; then
            clock_tor_consensus_check_result="fast"
            clock_tor_consensus_check_msg="The clock might be too fast. Clock is faster than consensus/valid-until $tor_consensus_valid_until_output. $clock_causes"
         else
            true
         fi
      elif [ "$tor_consensus_valid_after_exit_code" = "277" ] && [ "$tor_consensus_valid_until_exit_code" = "277" ]; then
         clock_tor_consensus_check_result="noneyet"
         clock_tor_consensus_check_msg="Might not have downloaded a Tor consensus yet."
      else
         clock_tor_consensus_check_result="error"
         clock_tor_consensus_check_msg="Consensus time sanity check failed. $clock_causes"
      fi

      if [ "$clock_tor_consensus_check_result" = "ok" ]; then
         clock_tor_consensus_check_result="ok"
         clock_tor_consensus_check_msg="Clock within consensus parameters consensus/valid-after $tor_consensus_valid_after_output and consensus/valid-until $tor_consensus_valid_until_output."
      fi

      if [ "$clock_tor_consensus_check_result" = "ok" ]; then
         echo "<p>$clock_tor_consensus_check_msg</p>" >&2
      else
         echo "<p>$clock_tor_consensus_check_msg</p>"
      fi

      ## TODO
      ## Would have to parse tor_bootstrap_status.
      ## In case Tor cannot fetch Tor consensus $tor_consensus_valid_after_exit_code /
      ## $tor_consensus_valid_until_exit_code may be zero but $tor_consensus_valid_until_output
      ## may be empty.
      #if [ ! "$clock_tor_consensus_check_result" = "ok" ]; then
      #   if [ "$VM" = "Gateway" ]; then
      #      exit "1"
      #   fi
      #fi
   fi

   if [ "$tor_circuit_established" = "1" ]; then
      echo "<p>Tor fully bootstrapped.</p>"
      exit "0"
   fi

   echo "Tor Bootstrap Result: \
   <b>ERROR tor_circuit_established is neither 0 nor 1. tor_circuit_established: $tor_circuit_established</b><br> Please report this bug!" >&2
   exit "0"
}

te_pe_tb_check "$@"
