#!/bin/bash


#
## Global variables
#

unset http_proxy


PARR=$1
RCON_DIR="/opt/rcon/bin"
LOG_DIR="/var/rcon"
PRIVATE_KEY_STUB="mykeyfile"
PUBLIC_KEY_STUB="$PRIVATE_KEY_STUB.pub"
PRIVATE_KEYP="$LOG_DIR/$PRIVATE_KEY_STUB"
PUBLIC_KEYP="$LOG_DIR/$PUBLIC_KEY_STUB"
KEY_CONFIG="$LOG_DIR/$PRIVATE_KEY_STUB.cfg"

SSH_CONFIGF="$RCON_DIR/ssh_config"
RECOVERY_SCRIPT="sshr-download.cgi"
RUNAS_ROOT="/opt/rcon/bin/sshr-exec"

CURL="curl"
CURL_PARAMS='-k -m 15 --tlsv1' 
GETHINFO="/opt/bin/gethinfo"
GETHAIPSETUPENTRY="/opt/webservice/scripts/gethaipsetupentry.sh"
PARAMTABLE="$RCON_DIR/paramtable.conf"
PRINTLIST="no"
TIMEOUT=-1 # default timeout is unlimited
LOG_MAXLINES=50000
TRACEFILE=$LOG_DIR/$(basename $0).trc #$LOG_DIR/$1.trc
VERBOSE="no"

ASCONFIGURECLAN=/opt/ASwebmin/bin/configure_clan.pl
CAPCONFIGURECLAN=/opt/siemens/OpenScape_4000_CSTA/bin/configure_clan

#Disable FIPS mode for openssl, this blocks execution of ssh
unset OPENSSL_FORCE_FIPS_MODE

#
## Functions
#

# Detect on which system is script currently running
#
function detectSystem {
	if [ -e /etc/fsshr.system.type ]; then
		case $(cat /etc/fsshr.system.type) in
			assistant)
				_SYSTEMTYPE="assistant_intl"
				;;
			manager)
				_SYSTEMTYPE="assistant_intl"
				;;
			host)
				_SYSTEMTYPE="host_intl"
				;;
			cap)
				_SYSTEMTYPE="cap_intl"
				;;
		esac
	fi

	#not resolved yet, use fallback mechanism on Quorum, nodeB
	if [ -z "$_SYSTEMTYPE" ]; then
		if ! /opt/webservice/scripts/is_quorum; then
			_SYSTEMTYPE="host_intl"
		elif ! /opt/webservice/scripts/is_duplex; then
			_SYSTEMTYPE="host_intl"
		elif ! /opt/webservice/scripts/is_mono; then
			_SYSTEMTYPE="host_intl"
		fi
	fi &>/dev/null

	tracef " initialization:detectSystem() current system=\"$_SYSTEMTYPE\""
	echo $_SYSTEMTYPE
	return 0
}


# Detect type of remote system
# param1 = type of current system
# param2 = type of remote system
#
# When remote system type is not specified, use old way asisstant->host, host->assistant
# Other cases produces error
#
function getRSystem {
  tracef " getRSystem() detect type of remote system (current=$1, remote=$2)"
  _CSYSTEM="$1"
  _RSYS="$2"
  # Check if param2 is defined
  if [ -z "$_RSYS" ];then
    # If system is asisstant and no remote system is defined
    if [ "$_CSYSTEM" == "assistant_intl" ];then
      _RSYS="host_intl"
    fi
    # If system is host and no remote system is defined
    if [ "$_CSYSTEM" == "host_intl" ];then
      _RSYS="assistant_intl"
    fi
  else
    # param2 is defined
    # Check if param2 contains "_intl"
    GR=$(echo $_RSYS | grep "_intl" >/dev/null)
    if [ $? -ne 0 ];then
      tracef "  extend name of remote system with \"_intl\""
      _RSYS=$_RSYS"_intl"
    fi
    _CSYSTEM="$_RSYS"
  fi

  # Check if remote system is defined in $PARAMTABLE
  _RES=$(grep "^\[$_RSYS\]" $PARAMTABLE | wc -l)
  if [ $_RES -lt 1 ];then
    # Error
    _RSYS="undefined"
    tracef "  ERROR:getRSystem() unable to identify remote system in paramtable"
    _RES2=209
  else
    _RES2=0
  fi

  tracef " getRSystem() result=\"$_RSYS\" (res=$_RES2)"
  echo "$_RSYS"
  return $_RES2 
}


# Get parameter of defined system
# param1 = name of system
# param2 = name of parameter
#
function getValue {
  tracef " getValue() get parameter from config file (system=$1, parameter=$2)"
  _FREQUEST="$1_$2"
  if [ ! -e $PARAMTABLE ];then
    _RECORD="undefined"
    tracef "  ERROR:getValue() \"$PARAMTABLE\" does not exist"
    _RES=214
  else
    _RECORD=$(grep "^$_FREQUEST" $PARAMTABLE | head -n 1 | cut -f 2 -d "=")
    _BYTES=$(echo $_RECORD | wc -c)
    if [ $_BYTES -gt 0 ];then
      _RES=0
    else
      _RES=1
    fi
  fi

  tracef " getValue() result=\"$_RECORD\" (ret=$_RES)"
  echo "$_RECORD"
  return $_RES
}

# Get IP of system with defined hostname
# param1 = name of current system
# param2 = hostname of system
function hostname2IP {
  tracef " hostname2IP() get IP of system with defined hostname - nslookup(current=$1,hostname=$2) [$(date)]"
  _SYSTEM=$1
  _HNAME=$2
  #_RECORD=$(nslookup $1 2>/dev/null | grep Add | grep -v '#' | cut -d ' ' -f 2)
  if [ "$_SYSTEM" == "host_intl" ];then
    _DNS=$(/opt/rcon/bin/getlocintIP)
    #_DNS="host_intl"
  else
    _DNS="os4kplt"
  fi

  #_RECORD=$(host $_HNAME $_DNS | grep ^$_HNAME | awk '{print $NF}')
  _RECORD=$(nslookup -querytype=A $_HNAME\. $_DNS | grep Address | tail -n 1 | awk '{print $2}')
  _LENGTH=$(echo $_RECORD  | wc -c)
  if [ $_LENGTH -gt 6 ];then
    _RES=0
  else
    tracef "  ERROR:hostname2IP() unable to get IP of system (via nslookup) [$(date)]"
    _RES=212
  fi

  tracef " hostname2IP() result=\"$_RECORD\" (ret=$_RES) [$(date)]"
  echo "$_RECORD"
  return $_RES 
}

# Get IP address from defined network interface
# param1 = name of interface
#
function getIfaceIP {
  tracef " getfaceIP() get IP address from interface (if=$1)"
  _IFACE="$1"
  _IFACEDEFINED=$(ip addr show dev $_IFACE 2>/dev/null | grep 'inet ' 2>/dev/null | wc -l)
  if [ $_IFACEDEFINED -lt 1 ]; then
    _IP="IP_unknown"
    tracef "  ERROR:getfaceIP() unable to read IP address of \"$_IFACE\" interface"
    _RES=215
  else 
    _IP=$(ip addr show dev $_IFACE 2>/dev/null | grep 'inet ' | head -n 1 | awk '{ print $2}' | awk -F '/' '{ print $1}')
    _RES=0
  fi

  tracef " getIfaceIP result=\"$_IP\" (res=$_RES)" 
  echo $_IP
  return $_RES 
}


# Get record from HA configuration file
# param1 = name on element
#
function getHaFileRecord {
  tracef " getHaFileRecord() get record from HA conf.file (element=$1)"
  if [ ! -x $GETHAIPSETUPENTRY ];then
    _RECORD="undefined"
    tracef "  ERROR:getHaFileRecord() unable to find \"$GETHAIPSETUPENTRY\" file [$(date)]"
    _RES=216
  else
    _SEARCH="$1"
	_RECORD=$($GETHAIPSETUPENTRY $_SEARCH)
    _RES=$?
  fi

  tracef " getHaFileRecord() result=\"$_RECORD\" (res=$_RES)"
  echo $_RECORD
  return $_RES
}


# Get IP address of system from /etc/hosts file
# param1 = name of system
#
function getHostRecord {
  tracef " getHostRecord() get IP address from /etc/hosts (system=$1)"
  _RES=0
  _SEARCH="$1"

  #_RECORD=$(getent hosts $_SEARCH | awk -F ' ' '{ print $1}')
  _RECORD=$(grep "\b$_SEARCH\b" /etc/hosts 2>/dev/null | tail -n 1 | awk '{print $1}')
  _BYTES=$(echo $_RECORD | wc -c)
  if [ $_BYTES -gt 1 ];then
    _RES=0
  else
    tracef "  ERROR:getHostRecord() unable to get IP of system (from /etc/hosts) [$(date)]"
    _RES=213
  fi

  tracef " getHostRecord() result=\"$_RECORD\" (res=$_RES)" 
  echo $_RECORD
  return $_RES
}


# Return home directory of defined user
#
# param1 = user name
#
function getUserHome {
  tracef " getUserHome() user=$1"
  _USER="$1"
  _RECORD=$(getent passwd $_USER | awk -F ':' '{print($6)}')
  if [ -z "$_RECORD" ];then
    #Home directory not found, use root's directory
    _RECORD="/root"
  fi
  tracef " getUserHome() result=\"$_RECORD\""
  echo $_RECORD
  return 0
}

# Returns name of program which escalate access rights to root
#
function getRootAccess {
  tracef " getRootAccess() result=\"$RUNAS_ROOT\""
  echo $RUNAS_ROOT
  return 0
}


# Check if key pair generated on current system is valid
#
function checkKeys {
_RES=0

  tracef " checkKeys() check validity key pair"
  if [ ! -e $PRIVATE_KEYP -o ! -e $PUBLIC_KEYP ];then
    tracef " keys does not exist"
    _RES=2
  elif [ ! -e $KEY_CONFIG ]; then
    tracef " key config does not exist"
    _RES=3
  else
    SSHA1=$(sha1sum $PRIVATE_KEYP 2>/dev/null | cut -f 1 -d " ")
    SSHA2=$(sha1sum $PUBLIC_KEYP 2>/dev/null | cut -f 1 -d " ")
    CSHA1=$(sed -n '1{p;q;}' $KEY_CONFIG 2>/dev/null)
    CSHA2=$(sed -n '2{p;q;}' $KEY_CONFIG 2>/dev/null)
    tracef "  sha1sum of public  key=\"$SSHA2\", config=\"$CSHA2\""
    tracef "  sha1sum of private key=\"$SSHA1\", config=\"$CSHA1\""

    if [ $SSHA1 = $CSHA1 -a $SSHA2 = $CSHA2 ]; then
      _RES=0
    else
      tracef "  WARNING:checkKeys() sha1sum are differrent [$(date)]"
      _RES=1
    fi    

  fi
  tracef " checkKeys() result=$_RES"

  echo $_RES
  return $_RES
}



#Test of connectivity to remote system
#
# param1 = IP of remote system
# param2 = user name
# param3 = shortcut of system
#
function connectivityTest {
  tracef " connectivityTest() test of connectivity [$(date)] (remote=$1,username=$2,shortcut=$3)"
  _SERVERIP=$1
  _RUSER=$2
  _RSYSTEM=$3
  _ITERATION=$4
  _LCK_RSFILE=$LOG_DIR/lock.$_RSYSTEM
  _LCK_FILE=$LOG_DIR/lock.general


  #_KEYS=$(checkKeys)
  #if [ $? -ne 0 ];then
  #  tracef "  key pair not created yet. Start generation [$(date)]"
  #  touch $_LCK_FILE
  #  flock --timeout=30 $_LCK_FILE $RCON_DIR/sshr-generate -c "$_RSYSTEM" -u "$_RUSER" </dev/null
  #fi

  tracef "sles15skip  testing command: ssh -q -l $_RUSER $_SERVERIP -i $PRIVATE_KEYP -F $SSH_CONFIGF"
  #$(ssh -q -l $_RUSER $_SERVERIP -i $PRIVATE_KEYP -F $SSH_CONFIGF </dev/null >/dev/null 2>&1)
  #_TESTRES=$?
  _TESTRES=0
  
  case "$_TESTRES" in
  0 )
      tracef "  connection test passed [$(date)]"
      _RES=0
  ;;
  * )
    #Error during connection
    tracef "  ERROR:connectivityTest() error during connection test (err=$_TESTRES)"
    #Verify if remote system is reachable, is yes, verify if local key pair is OK,
        #if yes, inform remote system to download public key
        #if no, generate new key pair
    $(ping -c 2 $_SERVERIP >>$TRACEFILE 2>>$TRACEFILE)
    _PINGRES=$?
    if [ ! $_PINGRES -eq 0 ]; then
      #Ping was not successful
      tracef "  ERROR:connectivityTest() remote system not accessible"
      _RES=202
    else
      tracef "  remote system is up, starting generation of new key pair [$(date)]"
      touch $_LCK_RSFILE
      flock --timeout=30 $_LCK_RSFILE $RCON_DIR/sshr-generate -c "$_RSYSTEM" -u "$_RUSER" </dev/null
      if [ $? -eq 0 ];then
        tracef "  new key pair was successfully generated [$(date)]"
        _RES=0
      else
	if [ -z "$_ITERATION" ]; then
	  tracef "  ERROR:connectivityTest() flock timeout, next attempt ongoing (err=$?) [$(date)]"
	  connectivityTest $_SERVERIP $_RUSER $_RSYSTEM "iteration" 
	else
	  tracef "  ERROR:connectivityTest() unable to generate/exchange new key pair (err=$?) [$(date)]"
          _RES=203
        fi
      fi
    fi
    ;;
  esac

  tracef " connectivityTest() result=$_RES [$(date)]"
  return $_RES
}

cutLog() {
  _LINES=$(cat $TRACEFILE 2>/dev/null | wc -l)
  umask 0017
  if [ $_LINES -gt $LOG_MAXLINES ]
  then
    mv $TRACEFILE $TRACEFILE.old 2>/dev/null
    tracef "=== Log is cutted here ==="
  fi
  touch $TRACEFILE >/dev/null 2>&1
  if [ `id -g` = "0" ]; then
    chgrp sshd $TRACEFILE 2>/dev/null
  fi

  #chmod 0660 $TRACEFILE >/dev/null 2>&1
}

tracef() {
  #echo "[$(date +'%x %X %N')] [$$] $1" >>$TRACEFILE 2>/dev/null
  #date comand is commented to speed up script execution
  [ -w $TRACEFILE ] && echo "[$$] $1" >>$TRACEFILE 2>/dev/null
}

trace() {
  if [ "$VERBOSE" = "yes" ];then
    echo $@
  fi
  [ -w $TRACEFILE ] && echo "[$$] log: $@" >>$TRACEFILE 2>/dev/null
}



#Detect current system
CURRENTSYSTEM=$(detectSystem)



