#!/bin/sh
# Pluto control daemon
# Copyright (C) 1998, 1999, 2001  Henry Spencer.
# 
# 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.  See <http://www.fsf.org/copyleft/gpl.txt>.
# 
# 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.
#
# RCSID $Id: _plutorun.in,v 1.26 2003/12/24 19:47:13 mcr Exp $

me='ipsec _plutorun'		# for messages

info=/var/run/pluto/ipsec.info

popts=
stderrlog=
plutorestartoncrash=true

wherelog=daemon.error
pidfile=/var/run/pluto/pluto.pid
verb=$"Starting"

syslog ()
{
    /sbin/initlog -s "$*" -f ${LOG_FACILITY:-daemon} -p ${LOG_PRIORITY:-error} -n ipsec_setup
}
[ `tty` != '/dev/console' ] && TTY=1;
log ()
{
    if [ "$1" = "-n" ]; then 
       nonl="-n";
       shift;
    fi;
    [ -n "$TTY" ] && echo $nonl $0: "$*";
    syslog $1;
}

for dummy
do
	case "$1" in
	--re)	verb="Restarting"	;;
	--plutorestartoncrash) plutorestartoncrash="$2"; shift ;;
	--debug)	plutodebug="$2" ; shift	;;
	--uniqueids)	uniqueids="$2" ; shift	;;
	--nat_traversal)    nat_traversal="$2" ; shift  ;;
	--keep_alive)   keep_alive="$2" ; shift ;;
	--force_keepalive)   force_keepalive="$2" ; shift ;;
	--disable_port_floating)    disable_port_floating="$2" ; shift  ;;
	--virtual_private)  virtual_private="$2" ; shift ;; 	
	--nocrsend)	nocrsend="$2" ; shift	;;
	--strictcrlpolicy)	strictcrlpolicy="$2" ; shift	;;
	--crlcheckinterval)	crlcheckinterval="$2"; shift	;;
	--dump)	dumpdir="$2" ; shift	;;
	--opts)	popts="$2" ; shift	;;
	--stderrlog) stderrlog="$2" ; shift	;;
	--wait)	plutowait="$2" ; shift	;;
	--pre)	prepluto="$2" ; shift	;;
	--post)	postpluto="$2" ; shift	;;
	--log)	wherelog="$2" ; shift	;;
	--pid)	pidfile="$2" ; shift	;;
	--)	shift ; break	;;
	-*)	echo $me': '$"unknown option"' `'$1"'" >&2 ; exit 2	;;
	*)	break	;;
	esac
	shift
done

export LOG_FACILITY=${wherelog%.*}
export LOG_PRIORITY=${wherelog#*.}

# initially we are in the foreground, with parent looking after logging

# precautions
if test -f $pidfile
then
	echo $"pluto appears to be running already"' (`'$pidfile"' "$"exists"'), '$"will not start another"
	exit 1
fi
if test ! -e /dev/urandom
then
	echo $"cannot start Pluto, system lacks"' `/dev/urandom'"'!?!"
	exit 1
fi

# sort out options
for d in $plutodebug
do
	popts="$popts --debug-$d"
done
case "$uniqueids" in
yes)	popts="$popts --uniqueids"	;;
no|'')				;;
*)	echo $"unknown"' uniqueids '$"value"' ('$"not"' yes/no) `'$IPSECuniqueids"'"	;;
esac
case "$nocrsend" in
yes)  popts="$popts --nocrsend"       ;;
no|'')                                ;;
*)    echo $"unknown"' nocrsend '$"value"' ('$"not"' yes/no") `'$IPSECnocrsend"'"    ;;
esac
case "$strictcrlpolicy" in
yes)  popts="$popts --strictcrlpolicy"        ;;
no|'')                                ;;
*)    echo $"unknown"' strictcrlpolicy '$"value"' ('$"not"' yes/no") `'$IPSECstrictcrlpolicy"'"      ;;
esac
case "$nat_traversal" in
yes)  popts="$popts --nat_traversal"  ;;
no|'')                ;;
*)    echo $"unknown"' nat_traversal '$"value"' ('$"not"' yes/no) `'$IPSECnat_traversal"'" ;;
esac
[ -n "$keep_alive" ] && popts="$popts --keep_alive $keep_alive"
case "$force_keepalive" in
yes)  popts="$popts --force_keepalive"  ;;
no|'')                ;;
*)    echo $"unknown"' force_keepalive '$"value"' ('$"not"' yes/no) `'$IPSECforce_keepalive"'" ;;
esac
case "$disable_port_floating" in
yes)  popts="$popts --disable_port_floating"  ;;
no|'')                ;;
*)    echo $"unknown"' disable_port_floating '$"value"' ('$"not"' yes/no) `'$disable_port_floating"'" ;;
esac
[ -n "$virtual_private" ] && popts="$popts --virtual_private $virtual_private"

# add crl check interval
if test ${crlcheckinterval:-0} -gt 0
then
	popts="$popts --crlcheckinterval $crlcheckinterval"
fi

if test -n "$stderrlog"
then
	popts="$popts --stderrlog 2>>$stderrlog"

	if test -f $stderrlog
	then
		if test ! -w $stderrlog
		then
			echo $"Cannot write to" \"$stderrlog\".
			exit 1
		fi
	else
		if test ! -w "`dirname $stderrlog`"
		then
			echo $"Cannot write to directory to create" \"$stderrlog\".
			exit 1
		fi
	fi

	echo Plutorun $"started on" `date` >$stderrlog
fi

# set up dump directory
if test " $dumpdir" = " "
then
	ulimit -c 0			# preclude core dumps
elif test ! -d "$dumpdir"
then
	echo "dumpdir \`$dumpdir' "$"does not exist"', '$"ignored"
	ulimit -c 0			# preclude core dumps
elif cd $dumpdir			# put them where desired
then
	ulimit -c unlimited		# permit them
else
	echo $"cannot cd to"' dumpdir \`$dumpdir'"', "$"ignored"
	ulimit -c 0			# preclude them
fi

# execute any preliminaries
if test " $prepluto" != " "
then
	$prepluto
	st=$?
	if test " $st" -ne 0
	then
		echo "...prepluto "$"command exited with status" $st
	fi
fi

IPSEC_SECRETS=${IPSEC_CONFS}/ipsec.secrets
if test ! -f "${IPSEC_SECRETS}"
then
    ( log $"No file"' '${IPSEC_SECRETS}', '$"generating key"'.'
      ipsec newhostkey --quiet 
      
      # tell pluto to go re-read the file
      ipsec auto --rereadsecrets
      # XXX publish the key somehow?
    ) &
fi

# 
# make sure that the isakmp port is open!
#
if test -f /etc/sysconfig/ipchains
then
    if egrep -q 500:500 /etc/sysconfig/ipchains
    then
	:
    else
	ipchains -I input 1 -p udp -s 0.0.0.0/0.0.0.0 -d 0.0.0.0/0.0.0.0 500:500 -j ACCEPT
	# if it redhat, then save the rules again.
	if [ -f /etc/redhat-release ]
	then
	    sh /etc/rc.d/init.d/ipchains save
	fi
    fi
fi

# spin off into the background, with our own logging
log $verb' Pluto '$"subsystem"'...'
execdir=${IPSEC_EXECDIR-/usr/libexec/ipsec}
libdir=${IPSEC_LIBDIR-/usr/lib/ipsec}
until (
	if test -s $info
	then
		. $info
		export defaultroutephys defaultroutevirt defaultrouteaddr defaultroutenexthop
	fi
	# eval allows $popts to contain redirection and other magic
	eval $execdir/pluto --nofork --secretsfile "$IPSEC_SECRETS" --ipsecdir "${IPSEC_CONFS}/ipsec.d" $popts
	status=$?
	echo "exit"
	echo $status
	) | $libdir/_plutoload --wait "$plutowait" --post "$postpluto"
do
	status=$?
	case "$status" in
	13)	echo $"internal failure in"' pluto '$"scripts"', '$"impossible to carry on"
		exit 1
		;;
	10)	echo 'pluto '$"apparently already running"' (?!?), '$"giving up"
		exit 1
		;;
	137)	echo 'pluto '$"killed by"' SIGKILL, '$"terminating without restart or unlock"
		exit 0
		;;
	143)	echo 'pluto '$"killed by"' SIGTERM, '$"terminating without restart"
		# pluto now does its own unlock for this
		exit 0
		;;
	*)	st=$status
	        if $plutorestartoncrash
		then
		    :
		else
		    exit 0
		fi

		if test $st -gt 128
		then
			st="$st (signal `expr $st - 128`)"
		fi
		echo "!pluto "$"failure"'!:  '$"exited with error status" $st
		echo $"restarting"' IPsec '$"after pause"'...'
		(
			sleep 10
			ipsec setup _autorestart
		) </dev/null >/dev/null 2>&1 &
		exit 1
		###sleep 10
		###rm -rf $pidfile
		#### and go around the loop again
		;;
	esac
done </dev/null 2>&1 |
/bin/sh -c 'while read line; do /sbin/initlog -s $line -f ${LOG_FACILITY:-daemon} -p ${LOG_PRIORITY:-error} -t ipsec__plutorun; done' &
exit 0
