usr/src/cmd/stunnel/test_stunnel.sh
author Cyril Plisko <cyril.plisko@grigale.com>
Tue, 06 Apr 2010 16:00:14 +0300
changeset 11 87960ed158f9
parent 0 b34509ac961f
permissions -rw-r--r--
Import sfw build 137 Bugs Fixed ---------- 6926835 Wireshark cannot open files typed into the location bar 6930214 CVE-2010-0624: Heap-based buffer overflow in GNU Tar 6933424 Various sfw manual pages need to be adjusted to use the new OpenSolaris package names. 6937764 upgrade OpenSSL to 0.9.8n (and fix CVE-2010-0740)

#!/bin/sh
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#ident	"@(#)test_stunnel.sh	1.2	08/12/11 SMI"
#
# This test script can be used to test stunnel configurations. This script
# should be run on two machines (that can communicate).
#
# The script does the following on both machines:
#
#	* Sets up apache to listen on localhost:HTTP_SERVER_PORT
#	* Sets up an OpenSSL CA
#	* Creates a x509 certificate for stunnel to use.
#	* Signs the certificate
#	* Configures the stunnel config file to:
#
#		** Listen on local addresses for incomming SSL connections
#		** Redirect these connections to the local web server
#		** Listen on localhost:LOCAL_LISTEN_PORT for TCP connections
#		** Make outbound SSL connections to the other machine
#		   for these connections.
#		** Enable the stunnel service
#		** Enable the webserver
#		** Spit out a script which can be used to test stunnel
#		** on both machines.
#
#
# Before running this script configure the two ADDRESSES variables below
# with the IP address(es) of the two machines that will be used for testing.
# The addresses below are just examples! Use ones that work. You can add
# the addresses for both systems before running the script, it works out
# if the addesses are local or not when you run it.
#
# Note that the example has multiple addresses for each machine, a single
# address will work too, but the script will accommodate hosts with multiple
# addresses, including IPv6 addresses.
ADDRESSES1=''
ADDRESSES2=''
# EG:
#ADDRESSES1='129.146.108.232 192.168.99.2 fe80::202:b3ff:febd:a5e5'
#ADDRESSES2='129.146.108.233 192.168.99.1 fe80::a00:20ff:feb8:c1fc'
#
# Now do the following:
#
#	* Run this script on the first machine (check for errors)
#	* Run this script on the second machine (check for errors)
#	* Run the "test_stunnel_script" that in generated on each system.
#	* Tidy-up afterwards by:
#		** svcadm disable stunnel
#		** rm /etc/stunnel/stunnel.conf (or rename)
#		** svcadm disable http
#		** rm the http.conf generated (or rename)
#		** rm server certificate
#
# Most of the following should not ever need changing
#
LOCAL_LISTEN_PORT=55501
HTTP_SERVER_PORT=3333
HTTPS_PORT=443
progname=`basename ${0}`
TMP1=/tmp/${progname}_scratch.$$
SCRIPT=/tmp/test_stunnel_script
CHECK_SCRIPT=/tmp/test_stunnel_check_script
STUNNEL=svc:/network/ssl/stunnel:default
#
# Web server stuff
#
DOC_ROOT=/var/tmp/test_http
HTTPD=svc:/network/http:apache2
HTTPD_CONF_DIR=/etc/apache2/
HTTP_VER=""
#
# This is only here because somebody thought it would be a good idea
# to move the default location of apache :-(
#
if [ -d /etc/apache2/2.2 ]
	then HTTPD=svc:/network/http:apache22
	HTTPD_VER="2.2"
	HTTPD_CONF_DIR=/etc/apache2/${HTTPD_VER}
fi
HTTPD_CONF=${HTTPD_CONF_DIR}/httpd.conf
HTTP_LOG=/var/apache2/${HTTPD_VER}/logs/error_log
STUNNEL_CONF=/etc/stunnel/stunnel.conf
WGET=/usr/bin/wget
GET_FILE=test_file
#
# CA stuff
#
CA_DIR=/tmp/my_CA
PEMDIR=/var/tmp/my_CA/etc/stunnel
PEMFILE=${PEMDIR}/stunnel.pem
OPENSSL=/usr/bin/openssl
OPEN_SSL_CONF="${CA_DIR}/openssl.cnf"
RAND_OPTS=''
# These variables are used to make up the DN
# of the CA signing certificate and the CRLs
# Try and use your own details here!
CA_SIG='rsa'
CA_KEY="abc123"
DEFAULT_BITS=1024
COUNTRY='US'
STATE='CA'
LOCALITY='Nowhere City'
ORG='Mycorp'
OUNIT='Test'
USER_NAME='Jon Doe'
EMAIL='[email protected]'
USE_EXISTING='no'
FIRST_CERT='01'

HOME=${CA_DIR}
export HOME

#
# Script functions see "Main" for program
#
# Source in the setup_ca() and setup_certificate() functions
# from the shell library.

SHELL_LIB=`dirname $0`/stunnel_ca_lib.sh

. ${SHELL_LIB}

# Use netstat to see if things worked

clobber_files() {

rm -rf ${CHECK_SCRIPT} ${SCRIPT} ${STUNNEL_CONF} ${CA_DIR} ${PEMDIR}
}

check_services() {

for port in ${HTTP_SERVER_PORT} ${HTTPS_PORT}
	do echo "\n\necho Checking to see if system listening on ${port}" \
		>> ${CHECK_SCRIPT}
	echo "netstat -an | grep ${port}" >> ${CHECK_SCRIPT}
done

sh ${CHECK_SCRIPT}
}

check_addresses() {

# Need to be root for this
/usr/bin/id | grep root >/dev/null 2>&1
if [ "$?" != "0" ]
	then echo "Need to be root to run this."
	exit 1
fi
# Figure out which system we are on
for address in  ${ADDRESSES1}
	do ifconfig -a | nawk '
	{
		if (substr($1,1,4) == "inet") {
			if (address == $2) {
				# Found address
				exit(2)
			}
		}
	}' address="${address}"
	if [ "$?" = "2" ]
		then echo "This system has these addresses:"
		echo "${ADDRESSES1}"
		THIS_SYSTEM_ADDRESSES=${ADDRESSES1}
		OTHER_SYSTEM_ADDRESSES=${ADDRESSES2}
		break
	fi
done

if [ "xx${THIS_SYSTEM_ADDRESSES}" = "xx" ]
	then for address in  ${ADDRESSES2}
		do ifconfig -a | nawk '
		{
			if (substr($1,1,4) == "inet") {
				if (address == $2) {
					# Found address
					exit(2)
				}
			}
		}' address="${address}"
		if [ "$?" = "2" ]
			then echo "This system has these addresses:"
			echo "${ADDRESSES2}"
			THIS_SYSTEM_ADDRESSES=${ADDRESSES2}
			OTHER_SYSTEM_ADDRESSES=${ADDRESSES1}
			break
		fi
	done
fi
		
if [ "xx${THIS_SYSTEM_ADDRESSES}" = "xx" ]
	then echo "The variables ADDRESSES1 and ADDRESSES2 need to be"
	echo "configured to match the two test systems - exiting."
	exit 1
fi
}

# Check state of smf(5) service
get_state() {

service=${1}
svcs ${service} >${TMP1} 2>&1
return=$?
check_return ${return}
num_services=`wc -l ${TMP1} | nawk '{print $1}'`
if [ ${num_services} -gt 2 ]
	then echo "${service} matches more than one service."
	exit 2
fi
service_state=`grep -v STATE ${TMP1} | nawk '{print $1}'`
}


check_service() {

service=${1}
get_state ${service}
echo "${service} state is: ${service_state}"
if [ "${service_state}" = "maintenance" ]
	then svcadm clear  ${service}
	get_state ${service}
fi
}

check_return() {

	if [ "${1}" != "0" ]
		then echo "Error code of ${1} returned."
		exit 1
	fi
}

# This generates the stunnel configuration file
setup_stunnel() {

if [ -f ${STUNNEL_CONF} ]
	then mv ${STUNNEL_CONF} ${STUNNEL_CONF}.save.$$
fi

echo "${OTHER_SYSTEM_ADDRESSES}" | nawk '
BEGIN {
	count = 1
	printf("pid = /var/run/stunnel.pid\n")
	printf("debug = 7\n")
	printf("cd /tmp\n") >> "'"${SCRIPT}"'"
}
{
	while ($count != "") {
		printf("[outbound%s]\n", count)
		printf("verify = 0\n")
		printf("accept = localhost:%d\n", out_port)
		printf("connect = %s:%d\n", $count, https_port)
		printf("client = yes\n")
		printf("ciphers = DES-CBC3-SHA:IDEA-CBC-MD5\n\n")
		# spit out test scripts
		printf("rm -rf %s\n", file)  >> "'"${SCRIPT}"'"
		printf("%s http://localhost:%d/%s\n",
			wget, out_port, file) >> "'"${SCRIPT}"'"
		printf("cat %s\n" , file)  >> "'"${SCRIPT}"'"
		printf("echo Checking for listeners on port %d\n\n",
			out_port) >> "'"${CHECK_SCRIPT}"'"
		printf("netstat -an | grep %d\n",
			out_port) >> "'"${CHECK_SCRIPT}"'"
		count++
		out_port++
	}
}' out_port="${LOCAL_LISTEN_PORT}" \
	https_port="${HTTPS_PORT}" wget="${WGET}" \
	file="${GET_FILE}" > ${STUNNEL_CONF}

echo "${THIS_SYSTEM_ADDRESSES}" | nawk '
BEGIN {
	count = 1
}
{
	while ($count != "") {
		printf("[inbound%s]\n", count)
		printf("client = no\n")
		printf("cert = %s\n", keyfile)
		printf("connect = localhost:%d\n", local_listen_port)
		printf("accept = %s:%d\n\n", $count, https_port)
		count++
	}
}' local_listen_port="${HTTP_SERVER_PORT}" \
	https_port="${HTTPS_PORT}" \
	keyfile="${PEMFILE}" >> ${STUNNEL_CONF}

}

setup_http() {

if [ -f ${HTTPD_CONF} ]
	then mv ${HTTPD_CONF} ${HTTPD_CONF}.save.$$
fi
cat <<EOF > ${HTTPD_CONF}
Listen localhost:${HTTP_SERVER_PORT}
User webservd
Group webservd
ServerName 127.0.0.1
ErrorLog ${HTTP_LOG}
DocumentRoot ${DOC_ROOT}
EOF
mkdir -p  ${DOC_ROOT}
# Write something to the file the web server will send.
banner `hostname` > ${DOC_ROOT}/${GET_FILE}

}

service_action() {

action=${1}
service=${2}

case ${action} in

	"disable")
		if [ "${service_state}" = "online" ]
			then svcadm disable ${service}
		fi
	;;

	"enable")
		svcadm enable -s ${service}
	;;
esac
}

# main
check_addresses
clobber_files
check_service ${HTTPD}
service_action disable ${HTTPD}
check_service ${STUNNEL}
service_action disable ${STUNNEL}
# just in case stunnel was started outside of smf(5)
pkill stunnel
setup_http
setup_stunnel
echo "\n\nCreating simple CA in ${CA_DIR}"
echo "Creating configuration file: ${OPEN_SSL_CONF}"
setup_ca
echo "\n\nGenerating CA certificate"
create_CA_certificate
echo "\n\nGenerating a CSR"
generate_csr
echo "\n\nSign CSR"
ca_sign_csr
echo "\n\nCreating ${PEMFILE}"
combine_pem

service_action enable ${HTTPD}
service_action enable ${STUNNEL}
check_services
chmod +x ${SCRIPT}
echo "\n\nNow run this script on the other system, when thats done run this:\n"
echo "${SCRIPT}"