#!/bin/sh /etc/rc.common # IPsec startup and shutdown script # Copyright (C) 1998, 1999, 2001 Henry Spencer. # Copyright (C) 2002 Michael Richardson # # 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 . # # 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. # # # ipsec init.d script for starting and stopping # the IPsec security subsystem (KLIPS and Pluto). # # This script becomes /etc/rc.d/init.d/ipsec (or possibly /etc/init.d/ipsec) # and is also accessible as "ipsec setup" (the preferred route for human # invocation). # # The startup and shutdown times are a difficult compromise (in particular, # it is almost impossible to reconcile them with the insanely early/late # times of NFS filesystem startup/shutdown). Startup is after startup of # syslog and pcmcia support; shutdown is just before shutdown of syslog. # # chkconfig: 2345 47 76 # description: IPsec provides encrypted and authenticated communications; \ # KLIPS is the kernel half of it, Pluto is the user-level management daemon. START=60 EXTRA_COMMANDS=status EXTRA_HELP=" status Show the status of the service" # Format a list into a delimited string and print it config_list_delimit() { local SECTION="$1" local OPTION="$2" local DELIMITER="${3:- }" config_list_foreach "$SECTION" "$OPTION" "printf \"%s%s\"" "$DELIMITER" | sed "s/.\{${#DELIMITER}\}$//" } # Callback for each ipsec configuration section # Converts list options from UCI to ipsec format and writes ipsec section headers CUR_SECTION_NAME= CUR_SECTION_TYPE= config_cb() { local TYPE="$1" local NAME="$2" # Handle list options from previous section if [ "$CUR_SECTION_TYPE" = "ipsec_conn" ] ; then local IKE="$(config_list_delimit "$CUR_SECTION_NAME" "ike" ", ")" if [ -n "$IKE" ] ; then printf "\tike=\"%s\"\n" "$IKE" >> "$IPSEC_UCI_CONF" fi local SUBNETS local SPACE_PAT="* *" config_get "SUBNETS" "$CUR_SECTION_NAME" "leftsubnets" case "$SUBNETS" in $SPACE_PAT) printf "\tleftsubnets={ %s }\n" "$SUBNETS" >> "$IPSEC_UCI_CONF" ;; ?*) printf "\tleftsubnet=%s\n" "$SUBNETS" >> "$IPSEC_UCI_CONF" ;; esac config_get "SUBNETS" "$CUR_SECTION_NAME" "rightsubnets" case "$SUBNETS" in $SPACE_PAT) printf "\trightsubnets={ %s }\n" "$SUBNETS" >> "$IPSEC_UCI_CONF" ;; ?*) printf "\trightsubnet=%s\n" "$SUBNETS" >> "$IPSEC_UCI_CONF" ;; esac elif [ "$CUR_SECTION_TYPE" = "ipsec_config" ] ; then local VPRIV="$(config_list_delimit "$CUR_SECTION_NAME" "virtual_private" ",")" if [ -n "$VPRIV" ] ; then printf "\tvirtual_private=%s\n" "$VPRIV" >> "$IPSEC_UCI_CONF" fi fi CUR_SECTION_NAME="$NAME" CUR_SECTION_TYPE="$TYPE" case "$CUR_SECTION_TYPE" in ipsec_config|ipsec_conn) # Handled in option_cb echo >> "$IPSEC_UCI_CONF" echo "${TYPE#ipsec_} $NAME" >> "$IPSEC_UCI_CONF" ;; *) # Not handled in option_cb ;; esac return 0 } # Callback for each ipsec configuration option # Prints each UCI option to $IPSEC_UCI_CONF in ipsec.conf format option_cb() { local NAME="$1" local VALUE="$2" case "$CUR_SECTION_TYPE" in ipsec_config|ipsec_conn) # Handle option in these sections ;; *) # Ignore options in all other sections return 0 ;; esac case "$NAME" in modecfgdns_ITEM[0-9]*) printf "\tmodecfgdns%d=%s\n" "${NAME##modecfgdns_ITEM}" "$VALUE" >> "$IPSEC_UCI_CONF" ;; modecfgwins_ITEM[0-9]*) printf "\tmodecfgwins%d=%s\n" "${NAME##modecfgwins_ITEM}" "$VALUE" >> "$IPSEC_UCI_CONF" ;; *_ITEM[0-9]*|*_LENGTH) # Ignore list items and length updates ;; [!a-zA-Z]*) # Ignore non-ipsec.conf parameters ;; *) # Quote values with characers which require quoting if echo "$VALUE" | grep -q '^[[:alnum:]_%.]*$' ; then printf "\t%s=%s\n" "$NAME" "$VALUE" >> "$IPSEC_UCI_CONF" else printf "\t%s=\"%s\"\n" "$NAME" "$VALUE" >> "$IPSEC_UCI_CONF" fi ;; esac return 0 } ipsec_config_convert() { IPSEC_UCI_CONF="${IPSEC_UCI_CONF:-${IPSEC_CONFS:-/etc}/ipsec.uci.conf}" ipsec_config_print_header config_load "ipsec" # Conversion for $IPSEC_UCI_CONF handled in section_cb and option_cb IPSEC_SEC_UCI_CONF="${IPSEC_SEC_UCI_CONF:-${IPSEC_CONFS:-/etc}/ipsec.uci.secrets}" ipsec_config_print_header_secret echo >> "$IPSEC_SEC_UCI_CONF" echo "# Certificate Secrets" >> "$IPSEC_SEC_UCI_CONF" config_foreach "ipsec_config_add_secret_cs" "ipsec_secret_cs" echo >> "$IPSEC_SEC_UCI_CONF" echo "# Shared Secrets" >> "$IPSEC_SEC_UCI_CONF" config_foreach "ipsec_config_add_secret_ss" "ipsec_secret_ss" echo >> "$IPSEC_SEC_UCI_CONF" echo "# XAUTH Secrets" >> "$IPSEC_SEC_UCI_CONF" config_foreach "ipsec_config_add_secret_xs" "ipsec_secret_xs" } ipsec_config_print_header() { cat > "$IPSEC_UCI_CONF" < "$IPSEC_SEC_UCI_CONF" <> "$IPSEC_SEC_UCI_CONF" } ipsec_config_add_secret_ss() { local SECTNAME="$1" config_get "INDICES" "$SECTNAME" "indices" config_get "SECRET" "$SECTNAME" "secret" echo "$INDICES : PSK \"$SECRET\"" >> "$IPSEC_SEC_UCI_CONF" } ipsec_config_add_secret_xs() { local SECTNAME="$1" config_get "USERNAME" "$SECTNAME" "username" config_get "SECRET" "$SECTNAME" "secret" echo "@$USERNAME : XAUTH \"$SECRET\"" >> "$IPSEC_SEC_UCI_CONF" } script_init() { me='ipsec setup' # for messages # where the private directory and the config files are IPSEC_EXECDIR="${IPSEC_EXECDIR-/usr/libexec/ipsec}" IPSEC_LIBDIR="${IPSEC_LIBDIR-/usr/lib/ipsec}" IPSEC_SBINDIR="${IPSEC_SBINDIR-/usr/sbin}" IPSEC_CONFS="${IPSEC_CONFS-/etc}" if test " $IPSEC_DIR" = " " # if we were not called by the ipsec command then # we must establish a suitable PATH ourselves PATH="${IPSEC_SBINDIR}":/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin export PATH IPSEC_DIR="$IPSEC_LIBDIR" export IPSEC_DIR IPSEC_CONFS IPSEC_LIBDIR IPSEC_EXECDIR fi # Check that the ipsec command is available. found= for dir in `echo $PATH | tr ':' ' '` do if test -f $dir/ipsec -a -x $dir/ipsec then found=yes break # NOTE BREAK OUT fi done if ! test "$found" then echo "cannot find ipsec command -- \`$1' aborted" | logger -s -p daemon.error -t ipsec_setup exit 1 fi # accept a few flags export IPSEC_setupflags IPSEC_setupflags="" config="" for dummy do case "$1" in --showonly|--show) IPSEC_setupflags="$1" ;; --config) config="--config $2" ; shift ;; *) break ;; esac shift done # Pick up IPsec configuration (until we have done this, successfully, we # do not know where errors should go, hence the explicit "daemon.error"s.) # Note the "--export", which exports the variables created. variables=`ipsec addconn $config --varprefix IPSEC --configsetup` if [ $? != 0 ] then echo "Failed to parse config setup portion of ipsec.conf" exit $? fi eval $variables if test " $IPSEC_confreadstatus" != " " then case $1 in stop|--stop|_autostop) echo "$IPSEC_confreadstatus -- \`$1' may not work" | logger -s -p daemon.error -t ipsec_setup;; *) echo "$IPSEC_confreadstatus -- \`$1' aborted" | logger -s -p daemon.error -t ipsec_setup; exit 1;; esac fi IPSEC_confreadsection=${IPSEC_confreadsection:-setup} export IPSEC_confreadsection IPSECsyslog=${IPSECsyslog-daemon.error} export IPSECsyslog # misc setup umask 022 mkdir -p /var/run/pluto } script_command() { # do it case "$1" in start|--start|stop|--stop|_autostop|_autostart) # remove for: @cygwin_START@ # portable way for checking for root if [ ! -w / ] then echo "permission denied (must be superuser)" | logger -s -p $IPSECsyslog -t ipsec_setup 2>&1 exit 1 fi # remove for: @cygwin_END@ tmp=/var/run/pluto/ipsec_setup.st outtmp=/var/run/pluto/ipsec_setup.out ( ipsec _realsetup $1 echo "$?" >$tmp ) > ${outtmp} 2>&1 st=$? if test -f $tmp then st=`cat $tmp` rm -f $tmp fi if [ -f ${outtmp} ]; then cat ${outtmp} | logger -s -p $IPSECsyslog -t ipsec_setup 2>&1 rm -f ${outtmp} fi ;; restart|--restart|force-reload) $0 $IPSEC_setupflags stop $0 $IPSEC_setupflags start ;; _autorestart) # for internal use only $0 $IPSEC_setupflags _autostop $0 $IPSEC_setupflags _autostart ;; status|--status) ipsec _realsetup $1 exit ;; --version) echo "$me $IPSEC_VERSION" exit 0 ;; --help) echo "Usage: $me [ --showonly ] {--start|--stop|--restart}" echo " $me --status" exit 0 ;; *) echo "Usage: $me [ --showonly ] {--start|--stop|--restart}" echo " $me --status" exit 2 esac } start() { ipsec_config_convert script_init start "$@" script_command start "$@" } stop() { script_init stop "$@" script_command stop "$@" } restart() { ipsec_config_convert script_init stop "$@" script_command stop "$@" script_command start "$@" } status() { script_init status "$@" ipsec _realsetup status }