#!/bin/sh
# Filename: kinit-host
# Location: 
# Author: bgstack15@gmail.com
# Startdate: 2018-08-28 10:12:53
# Title: Script That Requests Kerberos Ticket Using Host Keytab
# Purpose: 
# Package: bgscripts-core
# History: 
#    2018-09-12 fix binary location
#    2019-05-28 fix #29 add KH_ATDOMAIN
#    2020-04-19 remove trap 17 (breaks dash)
# Usage: 
# Reference: ftemplate.sh 2018-08-28a; framework.sh 2018-08-28a
# Improve:
# Dependencies:
#    dep-raw: kinit
#    rec-devuan: krb5-user
fiversion="2018-08-28a"
kinithostversion="2019-05-28a"

usage() {
   ${PAGER:-/usr/bin/less -F} >&2 <<ENDUSAGE
usage: kinit-host.sh [-duV] [-c conffile] [-u --upper|-l --lower] [-D --dollar|-n --no-dollar] [-f --fqdn|-s --short] [--hostname <HOSTNAME>] [--domain <DOMAIN>] [--atdomain <DOMAIN>] [-q --silent] [--kinit </opt/bin/kinit>] [-N --dry-run]
version ${kinithostversion}
 -d debug   Show debugging info, including parsed variables.
 -u usage   Show this usage block.
 -V version Show script version number.
 -c conf    Read in this config file.
Environment variables:
KH_UPPER [0|1]  Use (0) lowercase or (1) uppercase name in request. Default is 1
KH_FQDN [0|1]   Use (0) shortname or (1) fqdn (hostname.example.com). Default is 0
KH_DOLLAR [0|1] Append $ dollar sign to end. Default is 1
KH_HOSTNAME     If left blank, will use \$( hostname -s )
KH_KRB5_CONF    Use this krb5.conf file. Default is /etc/krb5.conf
KH_KINIT        Use this binary for kinit request. Default is /usr/bin/kinit
KH_DOMAIN       Use this domain for the fqdn action. Default is derived from KH_KRB5_CONF file.
KH_ATDOMAIN     Use this domain in the request after the at symbol. Defaults to \$KH_DOMAIN.
KH_SILENT [0|1] Suppress kinit errors. Default is 0
KH_DRYRUN [0|1] Suppress action. Default is 0
Debug levels:
 1 kinit request
 5 all KH_ environment parameters
Return values:
 0 Normal
 1 Help or version info displayed
 2 Count or type of flaglessvals is incorrect
 3 Incorrect OS type
 4 Unable to find dependency
 5 Not run as root or sudo
Or alternatively will return the value from the kinit execution
ENDUSAGE
}

# DEFINE FUNCTIONS

kinit_host() {
   # call: kinit_host "${KH_UPPER}" "${KH_DOLLAR}" "${KH_HOSTNAME}" "${KH_FQDN}" "${KH_DOMAIN}" "${KH_KINIT}" "${KH_DRYRUN}" "${KH_SILENT}" "${KH_ATDOMAIN}"
   ___kh_upper="${1}"
   ___kh_dollar="${2}"
   ___kh_hostname="${3}"
   ___kh_fqdn="${4}"
   ___kh_domain="${5}"
   ___kh_kinit="${6}"
   ___kh_dryrun="${7}"
   ___kh_silent="${8}"
   ___kh_atdomain="${9}"

   # start assembling values
   ___kh_string="${___kh_hostname}"

   # add domain to hostname
   fistruthy "${___kh_fqdn}" && ___kh_string="${___kh_string}.${___kh_domain}"

   # convert to uppercase
   if fistruthy "${___kh_upper}" ;
   then
      ___kh_string="$( echo "${___kh_string}" | tr '[[:lower:]]' '[[:upper:]]' )"
   else
      ___kh_string="$( echo "${___kh_string}" | tr '[[:upper:]]' '[[:lower:]]' )"
   fi

   # add dollar sign
   fistruthy "${___kh_dollar}" && ___kh_string="${___kh_string}\$"

   # add at domain
   ___kh_string="${___kh_string}@${___kh_atdomain}"

   # execute
   debuglev 1 && ferror "${___kh_kinit}" -k "${___kh_string}"
   if ! fistruthy "${___kh_dryrun}" ;
   then
      { "${___kh_kinit}" -k "${___kh_string}" 2>&1 ; ___return_code=$? ; echo "${___return_code}" > "${KH_tmpfile1}" ; } | {
         fistruthy "${___kh_silent}" && cat 1>/dev/null 2>&1 || cat ;
      }
   fi
   ___return_code="$( cat "${KH_tmpfile1}" 2>/dev/null )"
   return_code ${___return_code:-0}
}

# DEFINE TRAPS

clean_kinithost() {
   # use at end of entire script if you need to clean up tmpfiles
   # rm -f "${tmpfile1}" "${tmpfile2}" 2>/dev/null

   # Delayed cleanup
   if test -z "${FETCH_NO_CLEAN}" ;
   then
      nohup /bin/bash <<EOF 1>/dev/null 2>&1 &
sleep "${KH_CLEANUP_SEC:-2}" ; /bin/rm -r "${KH_TMPDIR:-NOTHINGTODELETE}" 1>/dev/null 2>&1 ;
EOF
   fi
}

CTRLC() {
   # use with: trap "CTRLC" 2
   # useful for controlling the ctrl+c keystroke
   :
}

CTRLZ() {
   # use with: trap "CTRLZ" 18
   # useful for controlling the ctrl+z keystroke
   :
}

parseFlag() {
   flag="$1"
   hasval=0
   case ${flag} in
      # INSERT FLAGS HERE
      "d" | "debug" | "DEBUG" | "dd" ) setdebug; ferror "debug level ${debug}"; __debug_set_by_param=1;;
      "u" | "usage" | "help" | "h" ) usage; exit 1;;
      "V" | "fcheck" | "version" ) ferror "${scriptfile} version ${kinithostversion}"; exit 1;;
      #"i" | "infile" | "inputfile" ) getval; infile1=${tempval};;
      "c" | "conf" | "conffile" | "config" ) getval; conffile="${tempval}";;
      "u" | "upper" ) KH_UPPER=1 ;;
      "l" | "lower" ) KH_UPPER=0 ;;
      "D" | "dollar" | "with-dollar" | "with-dollar-sign" ) KH_DOLLAR=1 ;;
      "n" | "nodollar" | "no-dollar" | "no-with-dollar" | "not-dollar" | "not-with-dollar" | "no-with-dollar-sign" ) KH_DOLLAR=0 ;;
      "f" | "fqdn" | "full" ) KH_FQDN=1 ;;
      "s" | "short" ) KH_FQDN=0 ;;
      "hostname" ) getval ; KH_HOSTNAME="${tempval}" ;;
      "domain" ) getval ; KH_DOMAIN="${tempval}" ;;
      "atdomain" ) getval ; KH_ATDOMAIN="${tempval}" ;;
      "q" | "silent" ) KH_SILENT=1 ;; # really just for suppressing warnings
      "kinit" ) getval ; KH_KINIT="${tempval}" ;;
      "N" | "dryrun" | "dry-run" ) KH_DRYRUN=1 ;;
   esac
   
   debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}"; }
}

# DETERMINE LOCATION OF FRAMEWORK
f_needed=20171111 # WORKEHERE set back to 20180828
while read flocation ; do if test -e ${flocation} ; then __thisfver="$( sh ${flocation} --fcheck 2>/dev/null )" ; if test ${__thisfver} -ge ${f_needed} ; then frameworkscript="${flocation}" ; break; else printf "Obsolete: %s %s\n" "${flocation}" "${__this_fver}" 1>&2 ; fi ; fi ; done <<EOFLOCATIONS
./framework.sh
${scriptdir}/framework.sh
$HOME/bin/bgscripts/framework.sh
$HOME/bin/framework.sh
$HOME/bgscripts/framework.sh
$HOME/framework.sh
/usr/local/bin/bgscripts/framework.sh
/usr/local/bin/framework.sh
/usr/bin/bgscripts/framework.sh
/usr/bin/framework.sh
/bin/bgscripts/framework.sh
/usr/local/share/bgscripts/framework.sh
/usr/share/bgscripts/framework.sh
/usr/libexec/bgscripts/framework.sh
EOFLOCATIONS
test -z "${frameworkscript}" && echo "$0: framework not found. Aborted." 1>&2 && exit 4

# INITIALIZE VARIABLES
# variables set in framework:
# today server thistty scriptdir scriptfile scripttrim
# is_cronjob stdin_piped stdout_piped stderr_piped sendsh sendopts
. ${frameworkscript} || echo "$0: framework did not run properly. Continuing..." 1>&2
infile1=
outfile1=
logfile=${scriptdir}/${scripttrim}.${today}.out
define_if_new interestedparties "bgstack15@gmail.com"
# SIMPLECONF
define_if_new default_conffile "/etc/default/kinit-host"
define_if_new defuser_conffile ~/.config/kinit-host
test -z "${KH_TMPDIR}" && KH_TMPDIR="$( mktemp -d )"
KH_tmpfile1="$( TMPDIR="${KH_TMPDIR}" mktemp )"
#tmpfile2="$( TMPDIR="${KH_TMPDIR}" mktemp )"
define_if_new KH_UPPER 1
define_if_new KH_FQDN 0
define_if_new KH_DOLLAR 1
define_if_new KH_HOSTNAME "${server}"
define_if_new KH_KRB5_CONF /etc/krb5.conf
define_if_new KH_SILENT 0
define_if_new KH_KINIT /usr/bin/kinit
define_if_new KH_DRYRUN 0

# REACT TO OPERATING SYSTEM TYPE
case $( uname -s ) in
   Linux) : ;;
   FreeBSD) : ;;
   *) echo "${scriptfile}: 3. Indeterminate OS: $( uname -s )" 1>&2 && exit 3;;
esac

## REACT TO ROOT STATUS
#case ${is_root} in
#   1) # proper root
#      : ;;
#   sudo) # sudo to root
#      : ;;
#   "") # not root at all
#      #ferror "${scriptfile}: 5. Please run as root or sudo. Aborted."
#      #exit 5
#      :
#      ;;
#esac

# SET CUSTOM SCRIPT AND VALUES
#setval 1 sendsh sendopts<<EOFSENDSH     # if $1="1" then setvalout="critical-fail" on failure
#/usr/local/share/bgscripts/send.sh -hs  # setvalout maybe be "fail" otherwise
#/usr/share/bgscripts/send.sh -hs        # on success, setvalout="valid-sendsh"
#/usr/local/bin/send.sh -hs
#/usr/bin/mail -s
#EOFSENDSH
#test "${setvalout}" = "critical-fail" && ferror "${scriptfile}: 4. mailer not found. Aborted." && exit 4

# VALIDATE PARAMETERS
# objects before the dash are options, which get filled with the optvals
# to debug flags, use option DEBUG. Variables set in framework: fallopts
validateparams - "$@"

# LEARN KH_DEBUG
test -z "${__debug_set_by_param}" && fisnum "${KH_DEBUG}" && debug="${KH_DEBUG}"

# CONFIRM TOTAL NUMBER OF FLAGLESSVALS IS CORRECT
#if test ${thiscount} -lt 2;
#then
#   ferror "${scriptfile}: 2. Fewer than 2 flaglessvals. Aborted."
#   exit 2
#fi

# LOAD CONFIG FROM SIMPLECONF
# This section follows a simple hierarchy of precedence, with first being used:
#    1. parameters and flags
#    2. environment
#    3. config file
#    4. default user config: ~/.config/script/script.conf
#    5. default config: /etc/script/script.conf
if test -f "${conffile}";
then
   get_conf "${conffile}"
else
   if test "${conffile}" = "${default_conffile}" || test "${conffile}" = "${defuser_conffile}"; then :; else test -n "${conffile}" && ferror "${scriptfile}: Ignoring conf file which is not found: ${conffile}."; fi
fi
test -f "${defuser_conffile}" && get_conf "${defuser_conffile}"
test -f "${default_conffile}" && get_conf "${default_conffile}"

# CONFIGURE VARIABLES AFTER PARAMETERS
define_if_new KH_DOMAIN "$( awk -F'=' '/^.*[#]/ { next } /default_realm/{print $2}' "${KH_KRB5_CONF}" | xargs )"
define_if_new KH_ATDOMAIN "${KH_DOMAIN}"

## REACT TO BEING A CRONJOB
#if test ${is_cronjob} -eq 1;
#then
#   :
#else
#   :
#fi

# SET TRAPS
#trap "CTRLC" 2
#trap "CTRLZ" 18
trap "__ec=$? ; clean_kinithost ; trap '' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 ; exit ${__ec} ;" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20

# DEBUG SIMPLECONF
debuglev 5 && {
   ferror "Using values"
   # used values: KH_(OPT1|OPT2|VERBOSE)
   set | grep -iE "^KH_" 1>&2
}

# MAIN LOOP
#{
   kinit_host "${KH_UPPER}" "${KH_DOLLAR}" "${KH_HOSTNAME}" "${KH_FQDN}" "${KH_DOMAIN}" "${KH_KINIT}" "${KH_DRYRUN}" "${KH_SILENT}" "${KH_ATDOMAIN}"
#} | tee -a ${logfile}

# EMAIL LOGFILE
#${sendsh} ${sendopts} "${server} ${scriptfile} out" ${logfile} ${interestedparties}

return_code 0
