#!/bin/bash
# DAMAGE REDUCTION/PREVENTION

# this may slow down processing quite alot, I believe this is a necessary precaution
# do not allow rules to directly call most/all internal tkis functions
# do not allow rules to redefine local variables used by tkis
tkis_security_check(){
  local insecure_call=

  if [[ $(echo $1 | grep -s "^[[:space:]]*tkis_source_file\>") != "" ]] ; then
    insecure_call="tkis_source_file"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_security_check\>") != "" ]] ; then
    insecure_call="tkis_security_check"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_security_check_remove\>") != "" ]] ; then
    insecure_call="tkis_security_check_remove"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_deny_private_variables\>") != "" ]] ; then
    insecure_call="tkis_deny_private_variables"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*error\>") != "" ]] ; then
    insecure_call="error"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*warning\>") != "" ]] ; then
    insecure_call="warning"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*notice\>") != "" ]] ; then
    insecure_call="notice"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*echoit\>") != "" ]] ; then
    insecure_call="echoit"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*debug\>") != "" ]] ; then
    insecure_call="debug"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_execute\>") != "" ]] ; then
    insecure_call="tkis_execute"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_handle_patches\>") != "" ]] ; then
    insecure_call="tkis_handle_patches"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_cleanup\>") != "" ]] ; then
    insecure_call="tkis_cleanup"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_load_list\>") != "" ]] ; then
    insecure_call="tkis_load_list"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_system\>") != "" ]] ; then
    insecure_call="tkis_system"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_get_patches\>") != "" ]] ; then
    insecure_call="tkis_get_patches"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_get_version\>") != "" ]] ; then
    insecure_call="tkis_get_version"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_package\>") != "" ]] ; then
    insecure_call="tkis_package"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_upgrade\>") != "" ]] ; then
    insecure_call="tkis_upgrade"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_single_execution\>") != "" ]] ; then
    insecure_call="tkis_single_execution"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_confirm_global_settings\>") != "" ]] ; then
    insecure_call="tkis_confirm_global_settings"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_main\>") != "" ]] ; then
    insecure_call="tkis_main"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_command_line\>") != "" ]] ; then
    insecure_call="tkis_command_line"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_prepare\>") != "" ]] ; then
    insecure_call="tkis_prepare"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*push_to_null\>") != "" ]] ; then
    insecure_call="push_to_null"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*pop_to_null\>") != "" ]] ; then
    insecure_call="pop_to_null"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*exit\>") != "" ]] ; then
    insecure_call="exit"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_load_distribution_list\>") != "" ]] ; then
    insecure_call="tkis_load_distribution_list"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_install_system\>") != "" ]] ; then
    insecure_call="tkis_install_system"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*tkis_install_distribution\>") != "" ]] ; then
    insecure_call="tkis_install_distribution"
  fi

  debug "Processing tkis_security_check() with insecure_call=$insecure_call"

  if [[ $insecure_call != "" ]] ; then
    error "The rule $color_reset$color_notice$rule_name$color_reset$color_error for $color_reset$color_notice$program_name$color_reset$color_error in $color_reset$color_notice$tkis_process$color_reset$color_error tried to directly call the internal function \"$color_reset$color_notice$insecure_call$color_reset$color_error\" and this is not allowed"
  fi
}

# do not allow rules to directly define their own variables so that they cannot work around the rule checks
tkis_deny_private_variables(){
  local insecure_action=

  if [[ $(echo $1 | grep -s "^[[:space:]]*set[[:space:]]") != "" ]] ; then
    insecure_action="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*let[[:space:]]") != "" ]] ; then
    insecure_action="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*export[[:space:]]") != "" ]] ; then
    insecure_action="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*[[:alnum:]_]*=") != "" ]] ; then
    insecure_action="yes"
  fi

  debug "Processing tkis_deny_private_variables() with insecure_action=$insecure_action"

  if [[ $insecure_action == "yes" ]] ; then
    error "The rule $color_reset$color_notice$rule_name$color_reset$color_error for $color_reset$color_notice$program_name$color_reset$color_error in $color_reset$color_notice$tkis_process$color_reset$color_error tried to set or define environmental variable(s) \"$color_reset$color_notice$1$color_reset$color_error\" and this is not allowed"
  fi
}

# prevent the most dangerous command to run as root
tkis_security_check_remove(){
  local oh_shit=

  # check as many possible ways to remove / as I can think of
  if [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,]*/[/,}]*$") != "" ]] ; then
    oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,]*/[/,}]*[[:space:]]") != "" ]] ; then
    oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,]*/[/,}]*$") != "" ]] ; then
    oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,]*/[/,}]*[[:space:]]") != "" ]] ; then
    oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*/{[[:alnum:]_+-,]*,[},]$") != "" ]] ; then
    oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*/{[[:alnum:]_+-,]*,[},][[:space:]]") != "" ]] ; then
    oh_shit="yes"
  fi

  debug "Processing tkis_securirty_check_remove() with oh_shit=$oh_shit"

  if [[ $oh_shit == "yes" ]] ; then
    if [[ $run_command == "complete-clean" || $run_command == "wipe" ]] ; then
      error "!!EMERGENCY!! The complete-clean or wipe tried to delete $color_reset$color_notice$1$color_reset$color_error and this is VERY DANGEROUS, make sure \$WO and \$TO are properly defined in $tkis_path/settings/global_settings!!"
    else
      error "!!EMERGENCY!! The rule $color_reset$color_notice$rule_name$color_reset$color_error for $color_reset$color_notice$program_name$color_reset$color_error in $color_reset$color_notice$tkis_process$color_reset$color_error delete \"$color_reset$color_notice$1$color_reset$color_error\" and this is VERY DANGEROUS!"
    fi
  fi
}

# prevent very dangerous commands to run as root outside of chroot
# check for removal of /bin /boot /dev /etc /home /lib /mnt /proc /sys /tmp /toolchain /var /usr (against the host system)
tkis_security_check_host_remove(){
  local oh_shit=

  for i in bin boot dev etc home lib mnt proc sys tmp toolchain var usr documentation ; do
    # check as many possible ways to remove / as I can think of
    if [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,/]*$i[/,}]*$") != "" ]] ; then
      oh_shit="yes"
    elif [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,/]*$i[/,}]*[[:space:]]") != "" ]] ; then
      oh_shit="yes"
    elif [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,/]*$i[/,}]*$") != "" ]] ; then
      oh_shit="yes"
    elif [[ $(echo $1 | grep -s "^[[:space:]]*[{ ,/]*$i[/,}]*[[:space:]]") != "" ]] ; then
      oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*/$i{[[:alnum:]_+-,]*,[},]$") != "" ]] ; then
    oh_shit="yes"
  elif [[ $(echo $1 | grep -s "^[[:space:]]*/$i{[[:alnum:]_+-,]*,[},][[:space:]]") != "" ]] ; then
    oh_shit="yes"
    fi
  done

  debug "Processing tkis_securirty_check_host_remove() with oh_shit=$oh_shit"

  if [[ $oh_shit == "yes" ]] ; then
    error "!!EMERGENCY!! The rule $color_reset$color_notice$rule_name$color_reset$color_error for $color_reset$color_notice$program_name$color_reset$color_error in $color_reset$color_notice$tkis_process$color_reset$color_error delete \"$color_reset$color_notice$1$color_reset$color_error\" on the HOST SYSTEM and this is VERY DANGEROUS!"
  fi
}

# make sure our global variables exist and are defined, otherwise generate an error so that unsafe transactions do not occur
tkis_confirm_global_settings(){
  if [[ $tkis_path == "" ]] ; then
    error "$color_reset${color_notice}tkis_path$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $tkis_global_settings == "" ]] ; then
    error "$color_reset${color_notice}tkis_global_settings$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $turtle_version == "" ]] ; then
    error "$color_reset${color_notice}turtle_version$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $archive_formats == "" ]] ; then
    error "$color_reset${color_notice}archive_formats$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $root_user_name == "" ]] ; then
    error "$color_reset${color_notice}root_user_name$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $root_user_name_length == "" ]] ; then
    error "$color_reset${color_notice}root_user_name_length$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $root_user_home_dir == "" ]] ; then
    error "$color_reset${color_notice}root_user_home_dir$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $host_system_path == "" ]] ; then
    error "$color_reset${color_notice}host_system_path$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $target_system_path == "" ]] ; then
    error "$color_reset${color_notice}target_system_path$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $target == "" ]] ; then
    error "$color_reset${color_notice}target$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $ldso == "" ]] ; then
    error "$color_reset${color_notice}ldso$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $system_version_file == "" ]] ; then
    error "$color_reset${color_notice}system_version_file$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $AR == "" ]] ; then
    error "$color_reset${color_notice}AR$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $PA == "" ]] ; then
    error "$color_reset${color_notice}PA$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $PR == "" ]] ; then
    error "$color_reset${color_notice}PR$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $RU == "" ]] ; then
    error "$color_reset${color_notice}RU$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $SC == "" ]] ; then
    error "$color_reset${color_notice}SC$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $SE == "" ]] ; then
    error "$color_reset${color_notice}SE$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $SY == "" ]] ; then
    error "$color_reset${color_notice}SY$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $TO == "" ]] ; then
    error "$color_reset${color_notice}TO$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $WO == "" ]] ; then
    error "$color_reset${color_notice}WO$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $PO == "" ]] ; then
    error "$color_reset${color_notice}PO$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $target_toolchain == "" ]] ; then
    error "$color_reset${color_notice}target_toolchain$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $target_system == "" ]] ; then
    error "$color_reset${color_notice}target_system$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $TC == "" ]] ; then
    error "$color_reset${color_notice}TC$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $TA == "" ]] ; then
    error "$color_reset${color_notice}TA$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $DI == "" ]] ; then
    error "$color_reset${color_notice}DI$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $TD == "" ]] ; then
    error "$color_reset${color_notice}TD$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $tkis_data == "" ]] ; then
    error "$color_reset${color_notice}tkis_data$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $tkis_output == "" ]] ; then
    error "$color_reset${color_notice}tkis_output$color_reset$color_error is not and should be defined by the install program"
  fi
  if [[ $host_system_lib_path == "" ]] ; then
    error "$color_reset${color_notice}host_system_lib_path$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $glibc_host != "yes" && $glibc_host != "no" ]] ; then
    error "$color_reset${color_notice}glibc_host$color_reset$color_error is not and should be define as either 'yes' or 'no' in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $documentation_directory == "" ]] ; then
    error "$color_reset${color_notice}documentation_directory$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $kernel_build_type == "" ]] ; then
    error "$color_reset${color_notice}kernel_build_type$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
  if [[ $gmp_build_type == "" ]] ; then
    error "$color_reset${color_notice}gmp_build_type$color_reset$color_error is not and should be defined in the global_settings file ($color_reset$color_notice$tkis_global_settings$color_reset$color_error)"
  fi
}
