summaryrefslogtreecommitdiffstats
path: root/test/make_sni.sh
diff options
context:
space:
mode:
Diffstat (limited to 'test/make_sni.sh')
-rw-r--r--test/make_sni.sh396
1 files changed, 396 insertions, 0 deletions
diff --git a/test/make_sni.sh b/test/make_sni.sh
new file mode 100644
index 0000000..1805c4b
--- /dev/null
+++ b/test/make_sni.sh
@@ -0,0 +1,396 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# This script will populate a directory 'sni' with 3 sites, httpd.conf
+# and certificates as to facilitate testing of TLS server name
+# indication support (RFC 4366) or SNI.
+#
+#
+OPENSSL=${OPENSSL:-openssl}
+DOMAIN=${DOMAIN:-my-sni-test.org}
+DIR=${DIR:-$PWD/sni}
+
+# List of hostnames automatically created by default.
+NAMES=${NAMES:-ape nut pear apple banana}
+
+# IP address these hostnames are bound to.
+IP=${IP:-127.0.0.1}
+
+# A certificate password for the .p12 files of the client
+# authentication test. Normally not set. However some browsers
+# require a password of at least 4 characters.
+#
+PASSWD=${PASSWD:-}
+
+args=`getopt a:fd:D:p: $*`
+if [ $? != 0 ]; then
+ echo "Syntax: $0 [-f] [-a IPaddress] [-d outdir] [-D domain ] [two or more vhost names ]"
+ echo " -f Force overwriting of outdir (default is $DIR)"
+ echo " -d dir Directory to create the SNI test server in (default is $DIR)"
+ echo " -D domain Domain name to use for this test (default is $DOMAIN)"
+ echo " -a IP IP address to use for this virtual host (default is $IP)"
+ echo " -p str Password for the client certificate test (some browsers require a set password)"
+ echo " [names] List of optional vhost names (default is $NAMES)"
+ echo
+ echo "Example:"
+ echo " $0 -D SecureBlogsAreUs.com peter fred mary jane ardy"
+ echo
+ echo "Which will create peter.SecureBlogsAreUs.com, fred.SecureBlogsAreUs.com and"
+ echo "so on. Note that the _first_ FQDN is also the default for non SNI hosts. It"
+ echo "may make sense to give this host a generic name - and allow each of the real"
+ echo "SNI site as sub directories/URI's of this generic name; thus allowing the "
+ echo "few non-SNI browsers access."
+ exit 1
+fi
+set -- $args
+for i
+do
+ case "$i"
+ in
+ -f)
+ FORCE=1
+ shift;;
+ -a)
+ IP=$2; shift
+ shift;;
+ -d)
+ DIR=$2; shift
+ shift;;
+ -p)
+ PASSWD=$2; shift
+ shift;;
+ -D)
+ DOMAIN=$2; shift
+ shift;;
+ --)
+ shift; break;
+ esac
+done
+
+if [ $# = 1 ]; then
+ echo "Aborted - just specifying one vhost makes no sense for SNI testing. Go wild !"
+ exit 1
+fi
+
+if [ $# -gt 0 ]; then
+ NAMES=$*
+fi
+
+if ! openssl version | grep -q OpenSSL; then
+ echo Aborted - your openssl is very old or misconfigured.
+ exit 1
+fi
+
+set `openssl version`
+if test "0$2" \< "00.9"; then
+ echo Aborted - version of openssl too old, 0.9 or up required.
+ exit 1
+fi
+
+if test -d ${DIR} -a "x$FORCE" != "x1"; then
+ echo Aborted - already an ${DIR} directory. Use the -f flag to overwrite.
+ exit 1
+fi
+
+mkdir -p ${DIR} || exit 1
+mkdir -p ${DIR}/ssl ${DIR}/htdocs ${DIR}/logs || exit 1
+
+# Create a 'CA' - keep using different serial numbers
+# as the browsers get upset if they see an identical
+# serial with a different pub-key.
+#
+# Note that we're not relying on the 'v3_ca' section as
+# in the default openssl.conf file - so the certificate
+# will be without the basicConstraints = CA:true and
+# keyUsage = cRLSign, keyCertSign values. This is fine
+# for most browsers.
+#
+serial=$RANDOM$$
+
+openssl req -new -nodes -batch \
+ -x509 \
+ -days 10 -subj '/CN=Da Root/O=SNI testing/' -set_serial $serial \
+ -keyout ${DIR}/root.key -out ${DIR}/root.pem \
+ || exit 2
+
+CDIR=${DIR}/client-xs-control
+mkdir -p ${CDIR}
+# Create some certificate authorities for testing client controls
+#
+openssl req -new -nodes -batch \
+ -x509 \
+ -days 10 -subj '/CN=Da Second Root/O=SNI user access I/' -set_serial 2$serial$$\
+ -keyout ${CDIR}/xs-root-1.key -out ${CDIR}/xs-root-1.pem \
+ || exit 2
+
+openssl req -new -nodes -batch \
+ -x509 \
+ -days 10 -subj '/CN=Da Second Root/O=SNI user access II/' -set_serial 3$serial$$ \
+ -keyout ${CDIR}/xs-root-2.key -out ${CDIR}/xs-root-2.pem \
+ || exit 2
+
+# Create a chain of just the two access authorities:
+cat ${CDIR}/xs-root-2.pem ${CDIR}/xs-root-1.pem > ${CDIR}/xs-root-chain.pem
+
+# And likewise a directory with the same information (using the
+# required 'hash' naming format
+#
+mkdir -p ${CDIR}/xs-root-dir || exit 1
+rm -f {$CDIR}/*.0
+ln ${CDIR}/xs-root-1.pem ${CDIR}/xs-root-dir/`openssl x509 -noout -hash -in ${CDIR}/xs-root-1.pem`.0
+ln ${CDIR}/xs-root-2.pem ${CDIR}/xs-root-dir/`openssl x509 -noout -hash -in ${CDIR}/xs-root-2.pem`.0
+
+# Use the above two client certificate authorities to make a few users
+for i in 1 2
+do
+ # Create a certificate request for a test user.
+ #
+ openssl req -new -nodes -batch \
+ -days 9 -subj "/CN=User $i/O=SNI Test Crash Dummy Dept/" \
+ -keyout ${CDIR}/client-$i.key -out ${CDIR}/client-$i.req -batch \
+ || exit 3
+
+ # And get it signed by either our client cert issuing root authority.
+ #
+ openssl x509 -text -req \
+ -CA ${CDIR}/xs-root-$i.pem -CAkey ${CDIR}/xs-root-$i.key \
+ -set_serial 3$serial$$ -in ${CDIR}/client-$i.req -out ${CDIR}/client-$i.pem \
+ || exit 4
+
+ # And create a pkcs#12 version for easy browser import.
+ #
+ openssl pkcs12 -export \
+ -inkey ${CDIR}/client-$i.key -in ${CDIR}/client-$i.pem -name "Client $i" \
+ -caname "Issuing client root $i" -certfile ${CDIR}/xs-root-$i.pem \
+ -out ${CDIR}/client.p12 -passout pass:"$PASSWD" || exit 5
+
+ rm ${CDIR}/client-$i.req
+done
+
+# Create the header for the example '/etc/hosts' file.
+#
+echo '# To append to your hosts file' > ${DIR}/hosts
+
+# Create a header for the httpd.conf snipped.
+#
+cat > ${DIR}/httpd-sni.conf << EOM
+# To append to your httpd.conf file'
+Listen ${IP}:443
+NameVirtualHost ${IP}:443
+
+LoadModule ssl_module modules/mod_ssl.so
+
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+
+LogLevel debug
+TransferLog ${DIR}/logs/access_log
+ErrorLog ${DIR}/logs/error_log
+
+# You'll get a warning about this.
+#
+SSLSessionCache none
+
+# Note that this SSL configuration is far
+# from complete - you probably will want
+# to configure SSLSession Caches at the
+# very least.
+
+<Directory />
+ Options None
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory "${DIR}/htdocs">
+ allow from all
+ Require all granted
+</Directory>
+
+# This first entry is also the default for non SNI
+# supporting clients.
+#
+EOM
+
+# Create the header of a sample BIND zone file.
+#
+(
+ echo "; Configuration sample to be added to the $DOMAIN zone file of BIND."
+ echo "\$ORIGIN $DOMAIN."
+) > ${DIR}/zone-file
+
+ZADD="IN A $IP"
+INFO="and also the site you see when the browser does not support SNI."
+
+set -- ${NAMES}
+DEFAULT=$1
+
+for n in ${NAMES}
+do
+ FQDN=$n.$DOMAIN
+ serial=`expr $serial + 1`
+
+ # Create a certificate request for this host.
+ #
+ openssl req -new -nodes -batch \
+ -days 9 -subj "/CN=$FQDN/O=SNI Testing/" \
+ -keyout ${DIR}/$n.key -out ${DIR}/$n.req -batch \
+ || exit 3
+
+ # And get it signed by our root authority.
+ #
+ openssl x509 -text -req \
+ -CA ${DIR}/root.pem -CAkey ${DIR}/root.key \
+ -set_serial $serial -in ${DIR}/$n.req -out ${DIR}/$n.pem \
+ || exit 4
+
+ # Combine the key and certificate in one file.
+ #
+ cat ${DIR}/$n.pem ${DIR}/$n.key > ${DIR}/ssl/$n.crt
+ rm ${DIR}/$n.req ${DIR}/$n.key ${DIR}/$n.pem
+
+ LST="$LST
+ https://$FQDN/index.html"
+
+ # Create a /etc/host and bind-zone file example
+ #
+ echo "${IP} $FQDN $n" >> ${DIR}/hosts
+ echo "$n $ZADD" >> ${DIR}/zone-file
+ ZADD="IN CNAME $DEFAULT"
+
+ # Create and populate a docroot for this host.
+ #
+ mkdir -p ${DIR}/htdocs/$n || exit 1
+ echo We are $FQDN $INFO > ${DIR}/htdocs/$n/index.html || exit 1
+
+ # And change the info text - so that only the default/fallback site
+ # gets marked as such.
+ #
+ INFO="and you'd normally only see this site when there is proper SNI support."
+
+ # And create a configuration snipped.
+ #
+ cat >> ${DIR}/httpd-sni.conf << EOM
+<VirtualHost ${IP}:443>
+ SSLEngine On
+ ServerName $FQDN:443
+ DocumentRoot ${DIR}/htdocs/$n
+ SSLCertificateChainFile ${DIR}/root.pem
+ SSLCertificateFile ${DIR}/ssl/$n.crt
+
+ # Uncomment the following lines if you
+ # want to only allow access to clients with
+ # a certificate issued/signed by some
+ # selection of the issuing authorities
+ #
+ # SSLCACertificate ${CDIR}/xs-root-1.pem # just root 1
+ # SSLCACertificate ${CDIR}/xs-root-2.pem # just root 2
+ # SSLCACertificate ${CDIR}/xs-root-chain.pem # 1 & 2
+ # SSLCACertificateDir ${CDIR}/xs-root-dir # 1 & 2 - but as a directory.
+ #
+ # SSLVerifyClient require
+ # SSLVerifyDepth 2
+ #
+ TransferLog ${DIR}/logs/access_$n
+</VirtualHost>
+
+EOM
+
+done
+
+cat << EOM
+SNI Files generated
+===================
+
+The directory ${DIR}/sni has been populated with the following
+
+- root.key|pem Certificate authority root and key. (You could
+ import the root.pem key into your browser to
+ quell warnings about an unknown authority).
+
+- hosts /etc/hosts file with fake entries for the hosts
+
+- htdocs directory with one docroot for each domain,
+ each with a small sample file.
+
+- ssl directory with an ssl cert (signed by root)
+ for each of the domains).
+
+- logs logfiles, one for each domain and an
+ access_log for any misses.
+
+The directory ${CDIR} contains optional test files to allow client
+authentication testing:
+
+- client*pem/p12 Files for client authentication testing. These
+ need to be imported into the browser.
+
+- xs-root-1/2 Certificate authority which has issued above
+ client authentication certificates.
+
+- xs-root-dir A directory specific for the SSLCACertificateDir
+ directive.
+
+- xs-root-chain A chain of the two client xs authorities for the
+ SSLCACertificate directive.
+
+SNI Test
+========
+
+A directory ${DIR}/sni has been created. Run an apache
+server against it with
+
+ .../httpd -f ${DIR}/httpd-sni.conf
+
+and keep an eye on ${DIR}/logs/error_log. When everything
+is fine you will see entries like:
+
+ Feb 11 16:12:26 2008] [debug] Init:
+ SSL server IP/port overlap: ape.*:443 (httpd-sni.conf:24) vs. jane.*:443 (httpd-sni.conf:42)
+
+for each vhost configured and a concluding warning:
+
+ [Mon Feb 11 16:12:26 2008] [warn] Init:
+ Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)
+
+HOWEVER - If you see an entry like:
+
+ [Mon Feb 11 15:41:41 2008] [warn] Init:
+ You should not use name-based virtual hosts in conjunction with SSL!!
+
+then you are either using an OpenSSL which is too old and/or you need to ensure that the
+TLS Extensions are compiled into openssl with the 'enable-tlsext' flag. Once you have
+recompiled or reinstalled OpenSSL with TLS Extensions you will have to recompile mod_ssl
+to allow it to recognize SNI support.
+
+Meanwhile add 'hosts' to your c:\windows\system32\drivers\etc\hosts
+or /etc/hosts file as to point the various URL's to your server:
+$LST
+
+and verify that each returns its own name (and an entry in its
+own ${DIR}/logs) file).
+
+NOTE
+====
+
+Note that in the generated example the 'first' domain is special - and is the
+catch all for non-SNI browsers. Depending on your circumstances it may make
+sense to use a generic name - and have each of the SNI domains as subdirectories
+(and hence URI's under this generic name). Thus allowing non SNI browsers also
+access to those sites.
+EOM
+exit 0