#!/bin/sh
#  $Id: security_enable.sh 144933 2017-02-08 09:50:25Z justin.carveley@oracle.com $
#  Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
#  This software code contains proprietary information
#  and should be treated as confidential.
#
#  Author: Bill Weir
#
#  Carries out a variety of operations to secure an SGD installation.

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/security_enable ]; then
  . $TTAMSG/common
  . $TTAMSG/security_enable
else
  echo "Unable to open message file: $TTAMSG/security_enable"
  exit 1
fi


case "$trace" in x|X) set -x;; esac

tmp="${TMPDIR:-/tmp}/ttasecure$$"
rm -rf "${tmp}" 2>/dev/null
trap 'rm -f ${tmp} 2>/dev/null; exit' 1 2 3 15

cleanexit() {
    rm -f ${tmp} 2>/dev/null
    exit $1
}

usage() {
    echo "${lf_enable_usage}" >&2
}

short_usage() {
    echo "$1
${sf_enable_usage}" >&2
}

certfile='' keyfile='' rootfile='' keylength='' fwf='f' alreadysecure='' quiet=''

# Parse command-line parameters
while [ -n "$1" ]; do
    case "$1" in
    --certfile) certfile="${2:-<NULL>}"; shift;;
    --keyfile) keyfile="${2:-<NULL>}"; shift;;
    --rootfile) rootfile="${2:-<NULL>}"; shift;;
    --firewalltraversal) 
	case "$2" in
	1|[yY]|[yY][eE][sS]|[oO][nN]) fwf='t';;
	0|[nN]|[nN][oO]|[oO][fF][fF]) fwf='f';;
	*) short_usage "${l_invalid_arg1}$1${l_invalid_arg2}" ; cleanexit 1
	esac
	shift;;
    --keylength) 
	kl=`echo "$2" | tr -cd 0123456789`
	[ "${kl}" != "$2" ] && { short_usage "${l_invalid_arg1}$1${l_invalid_arg2}"; cleanexit 1; }
	keylength="--keylength ${kl}"
	shift;;
    --quiet) quiet='t';;
    --norestart) norestart='t';;
    --help) usage; cleanexit 0;;
    *) short_usage "${l_invalid_arg1}$1${l_invalid_arg2}" ; cleanexit 1
    esac
    [ -n "$1" ] && shift
done

[ -z "$norestart" ] && {
u="`LANG=C LC_ALL=C id | sed 's/.*uid=\([0-9][0-9]*\).*/\1/'`"
if [ "$u" = "0" ]
then
  : # all is okay
else
  echo "You must be root to run this program"
  exit 15
fi

}

# Make sure all the parameters that need arguments have in fact got them
[ "${certfile}" = "<NULL>" -o "${keyfile}" = "<NULL>" -o "${rootfile}" = "<NULL>" ] && {
    short_usage ''; cleanexit 1
}

# Do parameter consistency checks (eg can't have --keyfile without --certfile)
[ -n "${keyfile}" ] && {
    [ -z "${certfile}" ] && {
	echo "${lf_lonely_keyfile}" >&2; cleanexit 1
    }
    [ -s "${keyfile}" -a -f "${keyfile}" -a -r "${keyfile}" -a \
      -n "`egrep -e '-----BEGIN .*KEY-----' ${keyfile} 2>/dev/null`" -a \
      -n "`egrep -e '-----END .*KEY-----' ${keyfile} 2>/dev/null`" ] || {
	echo "${lf_bad_keyfile}" >&2; cleanexit 1
    }
}
[ -n "${rootfile}" ] && {
    [ -z "${certfile}" ] && {
	echo "${lf_lonely_rootca}" >&2; cleanexit 1
    }
    [ -s "${rootfile}" -a -f "${rootfile}" -a -r "${rootfile}" -a \
      -n "`egrep -e '-----BEGIN .*CERTIFICATE-----' ${rootfile} 2>/dev/null`" -a \
      -n "`egrep -e '-----END .*CERTIFICATE-----' ${rootfile} 2>/dev/null`" ] || {
	echo "${lf_bad_rootca}" >&2; cleanexit 1
    }
}
[ -n "${certfile}" ] && {
    [ -s "${certfile}" -a -f "${certfile}" -a -r "${certfile}" -a \
      -n "`egrep -e '-----BEGIN .*CERTIFICATE-----' ${certfile} 2>/dev/null`" -a \
      -n "`egrep -e '-----END .*CERTIFICATE-----' ${certfile} 2>/dev/null`" ] || {
	echo "${lf_bad_certfile}" >&2; cleanexit 1
    }
}

T="${TTADIR}/bin/tarantella"
TRACE="${TTADIR}/var/tmp/security_enable.trace"
TSPDIR="${TTADIR}/var/tsp"
CERTDIR="${TTADIR}/var/info/tspcerts"
HOSTNAME=`${TTADIR}/bin/bin/ttahostname 2>/dev/null`
A_VER=`cat ${TTADIR}/var/info/apacheversion 2>/dev/null`; A_DIR="${TTADIR}/webserver/apache/${A_VER}"
T_VER=`cat ${TTADIR}/var/info/tomcatversion 2>/dev/null`; T_DIR="${TTADIR}/webserver/tomcat/${T_VER}"
OLDPEERDNS=`trace='' ${TTADIR}/bin/scripts/getconfig --peerdns`

# Sanity check: make sure we can find everything we need
[ -x "$T" -a -n "${HOSTNAME}" -a -n "${A_VER}" -a -n "${T_VER}" ] || {
    printf "${pf1_cant_find}" ${TTADIR} >&2; cleanexit 1
}

[ -z "${quiet}" ] && [ "${fwf}" = 't' ] && {
    # Warn about firewall traversal mode
    echo "${lf_warnfwf}"
}

# Tell them that we'll be doing a restart
[ -z "${quiet}" ] && {
    echo "${lf_warnrestart}"
    while :; do
	echo $N "${lf_confirm}$C"
	read reply
	case "${reply}" in
	[yY]*) break;;
	[nN]*) echo "${lf_nochanges}"; cleanexit 0;;
	esac
    done
}

# Make sure we're not already in secure mode, and we're not in an array
trace='' $T status >${tmp}
cat ${tmp}
echo
errMsg=''
[ -z "`egrep \" members \(1\)\" <${tmp}`" -o -n "`egrep \" \(secondary\)\" <${tmp}`" ] && {
    errMsg="${errMsg}
${lf_detach}"
}
[ -n "`egrep -i \" ${OLDPEERDNS} .*: *Accepting.*secure\" <${tmp}`" ] && {
    alreadysecure='t'
}
[ -n "${errMsg}" ] && {
    echo "${lf_before}${errMsg}"
    cleanexit 3
}

    HTTP_PORT=`awk '/^Listen[ 	][ 	]*[0-9]/{print $2;exit}' ${A_DIR}/conf/httpd.conf`

    HTTPS_PORT=`awk '/^Listen[ 	][ 	]*[0-9]/{print $2}' ${A_DIR}/conf/httpd.conf | sed -n 2p`

GetPrivUsrGrp()
{
    cat ${TTADIR}/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" : '.* \([^ ]*\)$'`

[ -z "${privusr}" ] && privusr="ttasys"
[ -z "${privgrp}" ] && privgrp="ttaserv"

# Make sure the relevant config files are in a clean state
dirtyfiles='' dirtyother=''
case "${HTTPS_PORT}" in
*:*) F=${A_DIR}/conf/httpd.conf
    dirtyfiles="${dirtyfiles}
   ${F}"
esac

# Make sure the config is clean in respect of the attributes we're going to change
alreadyff=''
ArrayPortEncrypted=`trace='' $T config list --array-port-encrypted`
case "${ArrayPortEncrypted}" in
*:*${HTTPS_PORT}) alreadyff='t' ArrayPortEncrypted=''
esac
case `trace='' $T config list --security-firewallurl` in
*:*https://*) alreadyff='t'
esac
[ -n "${alreadyff}" ] && {
    dirtyother="${dirtyother}
   ${lf_alreadyff}"
}

# If anything isn't as we expect, bail out
[ -n "${dirtyfiles}" -o -n "${dirtyother}" ] && {
    echo "${lf_alreadyenabled}" >&2
    [  -n "${dirtyfiles}" ] && echo "${lf_dirtyfiles}${dirtyfiles}" >&2
    [  -n "${dirtyother}" ] && echo "${lf_dirtyother}${dirtyother}" >&2
    cleanexit 1
}

rm -rf ${TRACE}
:>${TRACE}

ShowTrace() {
    [ -n "$2" ] && HideHead="" HideFoot="" || HideHead="; next" HideFoot="#"
    awk '/^\+ '"$1"'/ {
	doecho = 1'"${HideHead}"'
    }
    doecho == 1 {
	print
    }
    END {
	'"${HideFoot}"'printf "\nThe file %s\nmay contain additional diagnostic information.\n\n", "'"${TRACE}"'"
    }' ${TRACE}
    return 0
}

[ -z "${alreadysecure}" ] && {
    # Make the server secure
    for pem in ca.pem cert.pem csr.pem key.pem key.pending.pem; do
	[ -s ${TSPDIR}/${pem} ] && cmp -s ${TSPDIR}/${pem} ${CERTDIR}/${pem}.ss && rm -f ${TSPDIR}/${pem} ${CERTDIR}/${pem}.ss 2>/dev/null
    done
    if [ -z "${certfile}" ]; then
	# Self-signed certificate ##########################################
	[ -s ${TSPDIR}/csr.pem -o -s ${TSPDIR}/cert.pem -o -s ${TSPDIR}/key.pem -o -s ${TSPDIR}/key.pending.pem ] && {
	    # Don't allow real certificate to be overwritten
	    echo "${lf_alreadycerts1}${TSPDIR}${lf_alreadycerts2}" >&2
	    cleanexit 1
	}
	rm -f ${TSPDIR}/csr.pem ${TSPDIR}/cert.pem ${TSPDIR}/key.pem ${TSPDIR}/key.pending.pem
	echo "+ certrequest --orgname \"${PRODUCT_VENDOR}\" --country US --state CA" >>${TRACE}
	trace='' $T security certrequest ${keylength} \
	    --orgname "${PRODUCT_VENDOR}" --country US --state CA </dev/null >>${TRACE} 2>&1
	ret=$?
	[ ${ret} -ne 0 ] && { ShowTrace certrequest t; echo "security certrequest failed: status=${ret}"; cleanexit 1; }

	echo "+ selfsign" >>${TRACE}
	trace='' TTA_SECURITY_ENABLE='t' $T security selfsign >>${TRACE} 2>&1
	ret=$?
	[ ${ret} -ne 0 ] && { ShowTrace selfsign t; echo "security selfsign failed: status=${ret}"; cleanexit 1; }
	ShowTrace selfsign	# display the health warning about selfsigned certs

	echo "+ customca --rootfile ${TSPDIR}/cert.pem" >>${TRACE}
	trace='' $T security customca --rootfile ${TSPDIR}/cert.pem >>${TRACE} 2>&1
	ret=$?
	[ ${ret} -ne 0 ] && { ShowTrace customca t; echo "security customca failed: status=${ret}"; cleanexit 1; }

	for pem in ca.pem cert.pem csr.pem key.pem key.pending.pem; do
	    [ -s ${TSPDIR}/${pem} ] && cp -p ${TSPDIR}/${pem} ${CERTDIR}/${pem}.ss
	done
    else
	# Proper certificate ###############################################
	UndoList=""
	[ "${certfile}" = "${TSPDIR}/cert.pem" ] && mv ${certfile} ${certfile}.bak && UndoList="${UndoList} certfile"
	[ "${keyfile}" = "${TSPDIR}/key.pem" ] && mv ${keyfile} ${keyfile}.bak && UndoList="${UndoList} keyfile"
	[ "${rootfile}" = "${TSPDIR}/ca.pem" ] && mv ${rootfile} ${rootfile}.bak && UndoList="${UndoList} rootfile"
	[ -s "${TSPDIR}/key.pem" -a ! -s "${TSPDIR}/key.pending.pem" ] && mv "${TSPDIR}/key.pem" "${TSPDIR}/key.pending.pem"
	rm -f "${TSPDIR}/cert.pem" "${TSPDIR}/key.pem" 2>/dev/null
	if [ -z "${keyfile}" ]; then
	    echo "+ certuse <${certfile}" >>${TRACE}
	    trace='' $T security certuse <${certfile} >>${TRACE} 2>&1
	else
	    echo "+ certuse --certfile ${certfile} --keyfile ${keyfile}" >>${TRACE}
	    trace='' $T security certuse --certfile ${certfile} --keyfile ${keyfile} </dev/null >>${TRACE} 2>&1
	fi
	ret=$?
	[ ${ret} -ne 0 ] && {
	    for f in ${UndoList}; do
		case "$f" in
		certfile) [ -s "${certfile}" ] || mv ${certfile}.bak ${certfile};;
		keyfile)  [ -s "${keyfile}"  ] || mv ${keyfile}.bak ${keyfile};;
		rootfile) [ -s "${rootfile}" ] || mv ${rootfile}.bak ${rootfile};;
		esac
	    done
	    ShowTrace certuse t; echo "${lf_bad_certfile_failed}"; cleanexit 1
	}
	[ -n "${rootfile}" ] && {
	    rm -f "${TSPDIR}/ca.pem" 2>/dev/null
	    echo "+ customca <${rootfile}" >>${TRACE}
	    trace='' $T security customca <${rootfile} >>${TRACE} 2>&1
	    ret=$?
	    [ ${ret} -ne 0 ] && { ShowTrace customca t; echo "security customca failed: status=${ret}"; cleanexit 1; }
	}
    fi
    trace='' $T security start
}

# create h5c configuration profiles and related folders
profile_dir="${TTADIR}/var/docroot/certs"

if [ ! -d "${profile_dir}" ]; then
  mkdir -p ${profile_dir}
  chgrp ${privgrp} ${profile_dir}
  chmod 750 ${profile_dir}
fi

cert_dir="${TSPDIR}/certs"
gw_cert_dir="${cert_dir}/gateway"
sgd_cert_dir="${cert_dir}/array"
hostname_with_dashes="`echo ${HOSTNAME} | sed 's|\.|-|g'`"

if [ ! -d "${sgd_cert_dir}" ]; then
  mkdir -p ${sgd_cert_dir}
fi
if [ ! -d "${gw_cert_dir}" ]; then
  mkdir -p ${gw_cert_dir}
fi

chmod -R 751 ${cert_dir}

if [ -f "${TSPDIR}/cert.pem" ]; then
  [ -f "${sgd_cert_dir}/${hostname_with_dashes}.pem" ] && {
    rm -f ${sgd_cert_dir}/${hostname_with_dashes}.pem
  }
  ln -s ${TSPDIR}/cert.pem ${sgd_cert_dir}/${hostname_with_dashes}.pem
fi

chown -R ${privusr} ${cert_dir}
chgrp -R ${privgrp} ${cert_dir}

${TTADIR}/bin/scripts/mobile_profile_create.sh --quiet

[ -n "${ArrayPortEncrypted}" ] && {
    echo "${ArrayPortEncrypted}" | sed 's/^array-port-encrypted: *//' >${TTADIR}/var/info/array-port-encrypted.orig
    chmod 600 ${TTADIR}/var/info/array-port-encrypted.orig
}
[ "${fwf}" = 't' ] && {
    # Set various config bits and pieces
    trace='' $T config edit --array-port-encrypted ${HTTPS_PORT}
    trace='' $T config edit --array --security-firewallurl https://127.0.0.1:${HTTPS_PORT}
}

[ -z "${norestart}" ] && {
    # Restart the webserver and SGD server
    echo y | trace='' $T restart --quiet --https --servlet
}

cleanexit 0
