#!/bin/sh

# ClonePanel - Manages duplicate accounts on two or more webservers,
# including snapshot backups, monitoring and failover dns.
# Copyright (C)2006 Chris Cheers, Internet Lynx.
# Contact chris[at]clonepanel[dot]com.
# Internet Lynx, PO Box 7117, Mannering Park, NSW 2259, Australia
#
# Credits:
# Remote key setup is based mainly on Troy Johnson's excellent tutorial here:
# http://www.jdmz.net/ssh/

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Version=0.33
# setup_remote_key -h for built-in documentation

set -u
# Be strict about variable declaration

unset PATH
#avoid use of $PATH - limit script to system commands we choose

PROGRAM_DIR=$(/bin/echo $0 |/bin/sed -e "s/\/[a-zA-Z0-9_]*$//")
# Extract the working directory from command line
# NB - if your system doesn't have echo and sed in these locations
# then this line will need to be changed in all shell scripts

# Standard include files:
. $PROGRAM_DIR/includes

# Built-in documentation:
function showdocs {
	$CAT <<-EODOC
		Setup remote access to CPanel account by ssh keys.
		ssh (secure shell) access MUST ALREADY BE ENABLED on remote account!
		
		This script sets up the private and public keys enabling this server
		(the one that runs this script) to access a remote server (specified on
		command line parameters or interactively).
		
		In effect this program sets up a 'back door' on the remote server, 
		with the key to that door kept here. If you lose the key this could have
		very nasty consequences!
		
		Command line options: 
		-h		Print these instructions and exit
		-H host		Nickname of the server hosting the account
		-u user		CPanel username of the account
		-p secret	Password for this username (not yet implemented)
		
EODOC
	exit $DOC_REQUEST
}
		

# Initialise own input variables:
host=''
user=''
password=''

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":hH:u:p:" opt
do
	case $opt in
		h)	showdocs
			;;
		H)	host=$OPTARG
			;;
		u)	user=$OPTARG
			;;
		p)	password=$OPTARG
			;;
		*)	$ECHO "Unknown option. Use -h for instructions"; exit $E_UNKNOWN_OPT
			;;
	esac
done
shift $(($OPTIND - 1))

OPTIND=1
# reset getopts for next time


if [ ! $host ]; then
	cecho -n -c $prompt "Enter host name (nickname): "
	read host
fi

if [ ! $user ]; then
	cecho -n -c $prompt "Enter account username: "
	read user
fi

if [ ! $user -o ! $host ]; then
	cecho -c $error "Host name and username must be specified"
	exit $E_BLANK_INPUTS
fi

# User-specific and host-specific config (only after defining $user and $host):
config -u $user -H $host

if [ ! $REMOTEHOST_HOME ]; then
        cecho -c $error "Host $host has no remote dir"
        exit $E_NO_REMOTE_DIR
fi

if [ ! -f $AUTH_DIR/$host ]; then
	$TOUCH $AUTH_DIR/$host
fi
$CHMOD 0600 $AUTH_DIR/$host

if [ -f $TEMP_DIR/cpc_dsa* ]; then
	cecho -c $error "key file(s) exist - clear temp dir"
	exit $E_EXISTING_KEYFILE
fi

$SSH_KEYGEN -f $TEMP_DIR/cpc_dsa -P "" -t dsa
if [ "$?" -ne 0 ]; then
        cecho -c $error "Failed to do ssh-keygen - clear temp dir"
        exit $E_KEYGEN_FAILED
fi

$MV $TEMP_DIR/cpc_dsa $AUTH_DIR/$host
# Save private key as host name

publickey=$($CAT $TEMP_DIR/cpc_dsa.pub)
# Save public key as variable to pass to remote server shortly

$RM $TEMP_DIR/cpc_dsa*
# Clean up remaining key file(s)

$CP $REMOTE_SETUP_DIR/$SYNC_R_TEMPLATE $TEMP_DIR/$SYNC_R
# Make a temporary copy of the remote script template

for var in $SYNC_R_SUBS
do
	eval val=\$$var
# Indirect reference to variable named in SYNC_R_SUBS
	regexp="s|_${var}_|$val|"
	$SED -ie $regexp $TEMP_DIR/$SYNC_R
# In sync_r program, replace _variablename_ with current value of that variable
done
remoteshell=$($CAT $TEMP_DIR/$SYNC_R)
# After substitutions, save remote shell script as variable
# to pass to remote server shortly




$RM $TEMP_DIR/$SYNC_R*
# Clean up temp script files

cecho -c $ok "Keys created."
cecho -c $info "Now connecting to remote server at $A."
cecho -c $info "You should be prompted for a password to the $REMOTEHOST_USERNAME account." 

# Now what we really want to do here is this:
# $CAT |$SSH -p $SSH_PORT $REMOTEHOST_USERNAME@$A <<-EOFREMOTESCRIPT
# ie. cat the heredoc directly into the ssh shell
# Unfortunately while this works interactively, it screws up
# when the script is called through expect (required to set
# the password non-interactively).
# So we will create a temporary file instead...

$CAT >$TEMP_DIR/setup_remote_key.tmp <<-EOFREMOTESCRIPT
set -eu
if [ ! -d $REMOTEHOST_HOME/.ssh ]; then
	mkdir $REMOTEHOST_HOME/.ssh
	if [ "\$?" -ne 0 ]; then
		echo "Failed to create remote directory .ssh"
		exit $E_MKDIR_SSH_FAILED
	fi
	chmod 700 $REMOTEHOST_HOME/.ssh
fi
if [ ! -d $REMOTEHOST_HOME/$DATABASE_STORENAME ]; then
	mkdir $REMOTEHOST_HOME/$DATABASE_STORENAME
	if [ "\$?" -ne 0 ]; then
		echo "Failed to create remote directory $DATABASE_STORENAME"
		exit $E_MKDIR_DB_FAILED
	fi
	chmod 700 $REMOTEHOST_HOME/$DATABASE_STORENAME
fi
if [ ! -d $REMOTEHOST_SYNC_DIR ]; then
	mkdir $REMOTEHOST_SYNC_DIR
	if [ "\$?" -ne 0 ]; then
		echo "Failed to create remote directory $REMOTEHOST_SYNC_DIR"
		exit $E_MKDIR_SYNC_FAILED
	fi
fi
if [ ! -d $REMOTEHOST_PROGRAM_DIR ]; then
	mkdir $REMOTEHOST_PROGRAM_DIR
	if [ "\$?" -ne 0 ]; then
		echo "Failed to create remote directory $REMOTEHOST_PROGRAM_DIR"
		exit $E_MKDIR_PROGRAM_FAILED
	fi
fi
if [ ! -f $REMOTEHOST_HOME/.ssh/authorized_keys ]; then
	touch $REMOTEHOST_HOME/.ssh/authorized_keys
	chmod 0600 $REMOTEHOST_HOME/.ssh/authorized_keys
fi

echo "from=\"$MY_IP\",command=\"$REMOTEHOST_PROGRAM_DIR/$SYNC_R\" $publickey" >>$REMOTEHOST_HOME/.ssh/authorized_keys

cat >$REMOTEHOST_PROGRAM_DIR/$SYNC_R << 'EOF'
$remoteshell
EOF
# Create the (slightly) limited access remote script to be used with key access
chmod 0700 $REMOTEHOST_PROGRAM_DIR/$SYNC_R
# and make it executable

EOFREMOTESCRIPT

# Now since we have saved this to a file, we still need to push it
# into the remote shell...

$CAT $TEMP_DIR/setup_remote_key.tmp |$SSH -p $SSH_PORT $REMOTEHOST_USERNAME@$A /bin/sh
if [ "$?" -ne 0 ]; then
	cecho -c $error "Remote ssh setup returned error $?"
	exit $E_SSH_SETUP_FAILED
fi
# and delete the temporary file
$RM $TEMP_DIR/setup_remote_key.tmp

cecho -c $ok "Remote setup done!"
cecho -c $info "Now to test the remote access key..."

response=$($SSH -p $SSH_PORT -o PasswordAuthentication=no -i $AUTH_DIR/$host $REMOTEHOST_USERNAME@$A ls)
# We want a response "Refused" - indicating that the remote shell
# has run and correctly decided that this is not an allowed command

if [ "$response" == "Refused" ]; then
	cecho -c $ok "Remote access tested OK"
else
	cecho -c $error "Remote access failed - response was $response"
	exit $E_CONNECT_FAILED
fi
 


