#!/bin/bash
#  $Id:
#  Copyright (c) 2016, 2020, Oracle and/or its affiliates.
#  This software code contains proprietary information
#  and should be treated as confidential.
#
#  Search for a local Gateway and configure for co-location if found.

source common.sh
source common-env.sh

# This is a generic product script used to establish an environment
# before starting/stopping a product or component.
# This script was built from shell library
#   $Id$
# This script has to run on every platform we support.  Any suggestions
# for improvement are welcome (but must be portable!)

# Version numbers
PRODUCT_VERSION="5.60.514"
PRODUCT_VERSION_FULL="5.60.514"
PRODUCT_VERSION_MAJOR=5
PRODUCT_VERSION_FEATURE=6
PRODUCT_VERSION_BUG=0
PRODUCT_VERSION_BUILD=514
PRODUCT_VERSION_BUILD_DECIMAL=514
PRODUCT_VERSION_AS_NUMBER=560514
PRODUCT_VERSION_CAB=5,6,0,514
PRODUCT_VERSION_RPM=5.60-514

# Product names
PRODUCT_FULL_NAME="Oracle Secure Global Desktop"
PRODUCT_SHORT_NAME="Secure Global Desktop"
PRODUCT_IDENT="SSGD"
PRODUCT_SHORT_FILENAME="Tarantella"
PRODUCT_LSBSCRIPTNAME="sun.com-sgd-base"
PRODUCT_LSBSCRIPT_RUN_LEVEL="90"
TSP_FULL_NAME="Oracle Secure Global Desktop Security Pack"
TSP_SHORT_NAME="Security Pack"
WCP_FULL_NAME="Oracle Secure Global Desktop Windows Connectivity Pack"
WCP_SHORT_NAME="Windows Connectivity Pack"
TN3270_FULL_NAME="Oracle Secure Global Desktop Mainframe Connectivity Pack"
TN3270_SHORT_NAME="Mainframe Connectivity Pack"
AS400_FULL_NAME="Oracle Secure Global Desktop AS/400 Connectivity Pack"
AS400_SHORT_NAME="AS/400 Connectivity Pack"
S1PSTK_FULL_NAME="Oracle Secure Global Desktop Channel for Sun ONE Portal Server"
S1PSIP_FULL_NAME="Oracle Secure Global Desktop Integration Pack for Sun ONE Portal Server"
S1PSTK_SHORT_NAME="Secure Global Desktop Channel for Sun ONE Portal Server"
S1PSIP_SHORT_NAME="Secure Global Desktop Integration Pack for Sun ONE Portal Server"

OBJECT_MGR_NAME="Object Manager"
ARRAY_MGR_NAME="Array Manager"
NATIVE_WIN16_FULL_NAME="Oracle Secure Global Desktop Native Client for Windows 3.1"
NATIVE_WIN16_SHORT_NAME="Native Client for Windows 3.1"
NATIVE_WIN32_FULL_NAME="Oracle Secure Global Desktop Native Client for Windows 95, 98 and NT"
NATIVE_WIN32_SHORT_NAME="Native Client for Windows 95, 98 and NT"
NATIVE_WYSE_FULL_NAME="Oracle Secure Global Desktop Native Client for Wyse"
NATIVE_WYSE_SHORT_NAME="Native Client for Wyse"
NATIVE_FULL_NAME="Oracle Secure Global Desktop Native Client"
NATIVE_SHORT_NAME="Native Client"
NATIVE_REGISTRY_NAME="Tarantella Native Client"
INTCLI_FULL_NAME="Oracle Secure Global Desktop Client"
INTCLI_SHORT_NAME="Client"
TCC_FULL_NAME="Oracle Secure Global Desktop Client"
TCC_HELPER_NAME="Oracle Secure Global Desktop Client Helper"
TCC_ACTIVEX_NAME="Oracle Secure Global Desktop ActiveX Control"
TCC_PLUGIN_NAME="Oracle Secure Global Desktop Netscape Plug-in"
T3COMPONENT_WIN_NAME="Oracle Secure Global Desktop Enhancement Module for Windows"
T3COMPONENT_UNIX_NAME="Oracle Secure Global Desktop Enhancement Module for UNIX(TM) and Linux Platforms"
T3COMPONENT_SHORT_UNIX_NAME="tem"
T3COMPONENT_NAME="Oracle Secure Global Desktop Enhancement Module"
T3COMPONENT_LSBSCRIPTNAME="sun.com-sgd-em"
T3COMPONENT_LSBSCRIPT_RUN_LEVEL="90"
GWCOMPONENT_UNIX_NAME="Oracle Secure Global Desktop Gateway for UNIX(TM) and Linux Platforms"
GWCOMPONENT_NAME="Oracle Secure Global Desktop Gateway"
GWCOMPONENT_SHORTNAME="SGD Gateway"
GWCOMPONENT_LSBSCRIPTNAME="sun.com-sgd-gw"
GWCOMPONENT_LSBSCRIPT_RUN_LEVEL="91"

# Watch the length of these names: IE refuses to remove packages if
# the name is too long.
ARCHIVE_NAME_ttalw="TCC Helper, version"
ARCHIVE_NAME_asad="3.x Framework Java Archive"
#ARCHIVE_NAME_tta="3.x Java Archive"
#ARCHIVE_NAME_tta="3.x Combined Java Archive"
ARCHIVE_NAME_tta="Client, "
ARCHIVE_NAME_tsp="3.x Security Java Archive"
ARCHIVE_NAME_proxy="3.x Proxy Java Archive"
WEBSTART_JAR_NAME="sgdwscs"
ARCHIVE_SUFFIX="K"

NS_REGKEY="java/download/com/tarantella/tta"

PRODUCT_VENDOR="Oracle Corporation, Inc."
PRODUCT_SHORT_VENDOR="Oracle"

# Capabilities:
# The format for the capabilities required by the client end of a
# connection is: CAPABILITIES_protocol_type_REQUIRED="expression"

# The format for the capabilities provided by the server end of a
# connection is: CAPABILITIES_protocol_type_PROVIDED="c1 c2 ... c3"

# Asad between a webtop client and server:
CAPABILITIES_ASAD_WEBTOPCLIENT_REQUIRED="(1.1 || 1.2)"
CAPABILITIES_ASAD_WEBTOPCLIENT_PROVIDED="1.1 1.2"

# Asad between two peer servers, or an admin tool and a server:
# 1.1 is core E3 array functionality.
# 1.2 is 3.01 array interoperability functionality.
# 2.1 is core Pisa client device mapping functionality (not a requirement)
CAPABILITIES_ASAD_PEER_REQUIRED="(1.1 || 1.2)"
CAPABILITIES_ASAD_PEER_PROVIDED="1.1 1.2 2.1"

# Client versions of server strings; same format, name prefixed by CLIENT
# Asad between a webtop client and server:
CLIENTCAPABILITIES_ASAD_WEBTOPCLIENT_REQUIRED="(1.1 || 1.2)"
CLIENTCAPABILITIES_ASAD_WEBTOPCLIENT_PROVIDED="1.1 1.2"

# Top-level item names in ENS datastore
DEFAULT_ROOT_ENS="organization"
SYSTEM_ROOT_ENS="Tarantella System Objects"
APP_ROOT_ENS="applications"
APPSERVER_ROOT_ENS="appservers"

WEB_SERVICES_VERSION=1.9


# be paranoid about the current path
if [ -d /bin ]; then
  PATH=/bin:$PATH
fi
if [ -d /sbin ]; then
  PATH=/sbin:$PATH
fi
if [ -d /usr/bin ]; then
  PATH=/usr/bin:$PATH
fi
if [ -d /usr/sbin ]; then
  PATH=/usr/sbin:$PATH
fi
if [ -d /etc ]; then
  PATH=/etc:$PATH
fi
export PATH

N=""
C=""
if echo -n | grep n > /dev/null
then
  C="\c"
else
  N="-n"
fi
case "$MACHINEARCH" in
i3li*|ppli*) N="$N -e" ;;
esac
_ss_headlines="--------------------------------------------------------------------------"

if [ -f ${TTAMSG}/common -a -f ${TTAMSG}/discover_gateway.msg ]; then
  . ${TTAMSG}/common
  . ${TTAMSG}/discover_gateway.msg
else
  echo "Unable to open message file: ${TTAMSG}/discover_gateway.msg"
  exit 1
fi

if [ -f ${TTAMSG}/common -a -f ${TTAMSG}/gateway_common.msg ]; then
  . ${TTAMSG}/common
  . ${TTAMSG}/gateway_common.msg
else
  echo "Unable to open message file: ${TTAMSG}/gateway_common.msg"
  exit 1
fi

GetPrivUsrGrp()
{
    cat $TTAINSTDIR/var/serverconfig/global/array.properties 2>/dev/null | awk -F= \
	'BEGIN { u="ttasys"; wu="ttaserv"; g="ttaserv" }
	$1 == "tarantella.config.array.privilegeduser" { u = $2 }
	$1 == "tarantella.config.array.webserveruser" { wu = $2 }
	$1 == "tarantella.config.array.privilegedgroup" { g = $2 }
	END { print u " " wu " " g }'
}
_privusrgrp=`GetPrivUsrGrp`
privusr=`expr "$_privusrgrp" : '\([^ ]*\) .*'`
webservusr=`expr "$_privusrgrp" : '.* \([^ ]*\) .*'`
privgrp=`expr "$_privusrgrp" : '.* \([^ ]*\)$'`

gwprivusr="sgdgsys"
gwprivgrp="sgdgserv"


TTAHOSTNAME_PATH="bin/bin/ttahostname"

# Discover and configure a locally installed gateway server
#
# Args: $1 installation directory of the SGD server
#       $2 installation directory of the SGD GW
#       $3 http port that is currently being used by the SGD server
#       $4 https port that is currently beng used by the SGD server
#       $5 http port that SGD should listen on once the gateway is installed
#       $6 https port that SGD should listen on once the gateway is installed
#
# Return:
discoverLocal()
{
    sgd_install_path="$1"
    gw_install_path="$2"
    http_port=$3
    https_port=$4
    sgd_colocated_http_port=$5
    sgd_colocated_https_port=$6

    # Get the SGD server peer/external hostname info first
    sgd_peer_dns="$("${sgd_install_path}/bin/scripts/getconfig" --peerdns)"
    if [ -z "${sgd_peer_dns}" ]
    then
        warn_on_error "${error_peer_dns_not_set}"
        return ${COMMON_RETURN_ERROR}
    fi
    sgd_external_dns="$("${sgd_install_path}/bin/scripts/getconfig" --extdns)"
    if [ -z "${sgd_external_dns}" ]
    then
        warn_on_error "${error_external_dns_not_set}"
        return ${COMMON_RETURN_ERROR}
    fi

    # Detect if there is a local gateway that can be added
    echo "${msg_local_detecting_gw}"
    detectLocalGateway "${sgd_install_path}" "${gw_install_path}" \
        "${sgd_peer_dns}"

    # Retrieve all SGD and gateway certificates needed to add the local gateway
    echo "${msg_local_gathering_certs}"
    exportSGDCertificates "${sgd_install_path}" "${gw_install_path}"
    if [ $? -ne ${COMMON_RETURN_TRUE} ]
    then
        exit_on_error "${error_failed_to_export_sgd_certs}"
    fi

    exportGWCertificates "${sgd_install_path}" "${gw_install_path}"
    if [ $? -ne ${COMMON_RETURN_TRUE} ]
    then
        exit_on_error "${error_failed_to_export_gw_certs}"
    fi

    echo "${msg_local_config_sgd}"

    # Switch SGD webserver to listen on co-located ported as the local gateway
    # will be listening on the standard http/https ports
    changeWebserverPorts "${sgd_install_path}" ${http_port} ${https_port} \
        ${sgd_colocated_http_port} ${sgd_colocated_https_port}

    # Move SGD webservice to use sgd_colocated_http_port instead of http_port
    # as http_port will be the gateway
    changeWebservicePorts "${sgd_install_path}" ${http_port} \
        ${sgd_colocated_http_port}

    # Add the local gateway to be used with the local SGD server
    echo "${msg_local_adding_gw}"
    local gw_https_port="`getGatewayHTTPSPort "${gw_install_path}"`"
    if [ -z "${gw_https_port}" ]
    then
        gw_https_port="${HTTPS_PORT}"
    fi
    joinGW "${sgd_install_path}" "${gw_install_path}" \
        "${sgd_peer_dns}" "${sgd_external_dns}" "${gw_https_port}"
    if [ $? -ne ${COMMON_RETURN_TRUE} ]
    then
        exit_on_error "${error_could_not_add_gw}"
    fi

    # Updates the alias file used to determine the current certificate
    # alias used by the gateway.
    updateGWAliasFile "${gw_install_path}" \
        "$("${gw_install_path}/${TTAHOSTNAME_PATH}")"

    echo ""
    echo "${msg_local_complete}"
}

# Verifies that the server can be used with a co-located Gateway,
# exiting with an appropriate error message if it cannot.
# Args: $1 installation directory of the SGD server
# Return:
verifyServerStatus()
{
    sgd_install_path="$1"

    haveColocatedConstraint "${sgd_install_path}"
    if [ $? -eq ${COMMON_RETURN_TRUE} ]
    then
        # The server is already co-located
        exit_on_error "${error_local_colocated}"
    fi

    secondaries="$(cat "${sgd_install_path}/var/info/secondaries")"
    if [ -n "${secondaries}" ]
    then
        # The server is in an array
        exit_on_error "${error_local_in_array}"
    fi

    # Does the server already have a gateway configured ?
    gw_list="$("${sgd_install_path}/bin/tarantella" gateway list | grep "Installed gateway:")"
    if [ -n "${gw_list}" ]
    then
        # The server has one or Gateways already
        exit_on_error "${error_local_has_gw}"
    fi
}

# Handle what happens when command `tarantella discover gateway --local` is run
handleDiscoverLocal()
{
    # this command takes no further arguments so
    if [ -n "$1" ]; then
       echo "${bad_argument} $1"
       exit_usage_error "${short_usage}"
    fi

    verifyServerStatus "${TTAINSTDIR}"

    discoverLocal "${TTAINSTDIR}" "${GW_INSTALL_PATH}" \
            ${HTTP_PORT} ${HTTPS_PORT} \
            ${SGD_COLOCATED_HTTP_PORT} ${SGD_COLOCATED_HTTPS_PORT}

    addColocatedConstraint "${TTAINSTDIR}"
}

# Handle what happens when command `tarantella discover gateway --host ...` is run
handleDiscoverHost()
{
    arg_host="" arg_file="" arg_noprompt=""

    processDiscoverHostArgs "$@"

    # parse the credentials file -----------------------------------------------

    key_sshuser="sshuser"
    key_sshkey="sshkey"

    # grep for the first line matching the key
    # cut on = and return from second field to the end of the line
    # remove all leading whitespace
    sshuser=$( grep -m 1 "^$key_sshuser"  $arg_file | cut -d'=' -f2- | sed 's/^ *//g')
    sshkey=$(  grep -m 1 "^$key_sshkey"   $arg_file | cut -d'=' -f2- | sed 's/^ *//g')

    # ssh credentials must be provided with --noprompt
    if [ -n "${arg_noprompt}" ] && [ -z "${sshuser}" -o -z "${sshkey}" ]
    then
        exit_on_error "${error_host_ssh_credentials_must_be_provided}"
    fi
    
    # if a key is provided check it is valid
    if [ -n "$sshkey" ] && [ ! -f "$sshkey" ]
    then
        exit_on_error "${error_host_invalid_ssh_key}"
    fi

    # both user and key must be provided if either is provided in the credentials file
    if [ -n "${sshkey}" -a -z "${sshuser}" ] || [ -z "${sshkey}"  -a -n "${sshuser}" ]
    then
        exit_on_error "${error_host_mismatch_ssh_credentials}"
    fi


    # use the SOAPClient to acquire a token ------------------------------------
    JAVA_BIN="${SGD_JAVA_DIR}/java"
    CLASS_PATH="-classpath ${TTAINSTDIR}/bin/java/jserver.jar:${TTAINSTDIR}/webserver/tomcat/default/shared/classes"
    SOAP_CLIENT="com.oracle.sgd.client.SOAPClient"
    SOAP_CLIENT_COMMAND="${JAVA_BIN} ${CLASS_PATH} ${SOAP_CLIENT}"
    
    CREATE_SESSION_COMMAND="${SOAP_CLIENT_COMMAND} ${arg_file} create"
    END_SESSION_COMMAND="${SOAP_CLIENT_COMMAND} ${arg_file} end"
    GET_TOKEN_COMMAND="${SOAP_CLIENT_COMMAND} ${arg_file} token"

    # create the session
    session_cookie=$($CREATE_SESSION_COMMAND 2> /dev/null )
    if [ $? -ne 0 ] || [ -z "${session_cookie}" ]
    then
        exit_on_error "${error_host_create_session}"
    fi

    # get a token from the session
    token=$($GET_TOKEN_COMMAND "${session_cookie}" 2> /dev/null)
    if [ $? -ne 0 ] || [ -z "${token}" ]
    then
        # attempt to end the session
        $END_SESSION_COMMAND "${session_cookie}" 2> /dev/null
        exit_on_error "${error_host_token_session}"
    fi

    # prepare the arguments for ssh
    sshArguments=()
    sudoCommand="sudo"
    if [ -n "${arg_noprompt}" ]
    then
        # set to non-interactive mode
        sshArguments+=( -o BatchMode=yes )
        sudoCommand="sudo -n"
    fi

    sgdHostName=$("${TTAINSTDIR}/${TTAHOSTNAME_PATH}")

    if [ -n "${sshkey}" ] && [ -n "${sshuser}" ]
    then
        sshArguments+=( -i "$sshkey" )
        sshArguments+=( -o IdentitiesOnly=yes )
        sshArguments+=( "$sshuser@$arg_host" )
    else
        # don't specify a user will default to user running the script (root)
        sshArguments+=( "$USER@$arg_host" )
    fi
    
    # run the command on the gateway using ssh
    protocol="http"
    isSGDSSLEnabled "${TTAINSTDIR}"
    if [ $? -eq ${COMMON_RETURN_TRUE} ]
    then
        protocol="https"
    fi

    gatewayArrayAddCommand=("$sudoCommand" \
                            "$GW_INSTALL_PATH/bin/gateway server add-array" \
                            --name "$sgdHostName"-array \
                            --serverurl "$protocol://$sgdHostName" \
                            --token "$token")

    ssh "${sshArguments[@]}" "${gatewayArrayAddCommand[@]}"
    
    if [ $? -ne 0 ]
    then
        echo "${error_host_failed_command_remote_gateway}"
    fi

    # end the session
    $END_SESSION_COMMAND "${session_cookie}" 2> /dev/null
    if [ $? -ne 0 ]
    then
        exit_on_error "${error_host_end_session}"
    fi
}


processDiscoverHostArgs()
{
    
    if [[ -z "$1" ]]; then
        exit_on_error "${error_host_missing_hostname}"
    fi

    # check if begins with "--" , may be a flag
    if [[ "$1" == --* ]]
    then
        exit_on_error "${error_host_invalid_hostname} $1"
    fi

    arg_host="$1"
    shift

    while [ -n "$1" ]
    do
    case "$1" in
        --file)
            if [[ $# -lt 2 ]]
            then
                exit_on_error "${error_host_missing_credentials_file}"
            fi

            # check begins with "--" , may be a flag
            if [[ "$2" == --* ]]
            then
                exit_on_error "${error_host_missing_credentials_file}"
            fi
            
            if [ -f "$2" ]
            then
                arg_file="$2"
            else
                exit_on_error "${error_host_invalid_credentials_file}"
            fi

            shift
            shift
        ;;

        --noprompt)
            arg_noprompt="1"
            shift
        ;;

        *)
            echo "${bad_argument} $1"
            exit_usage_error "${short_usage}"
        ;;
    esac
    done

    # credentials file must be provided
    if [ -z "${arg_file}" ]
    then
        exit_on_error "${error_host_missing_credentials_file}"
    fi
}

# Check the arguments
if [ $# -eq 0 ]
then
    exit_usage_error "${short_usage}"
fi

case "$1" in
--help)
    exit_usage_error "${long_usage}"
    ;;
--local)
    shift
    handleDiscoverLocal "$@"
    ;;
--host)
    shift
    handleDiscoverHost "$@"
    ;;
*)
    echo "${bad_argument} $1"
    exit_usage_error "${short_usage}"
    ;;
esac
