#!/bin/sh

CADIR=""
CAFILE="`pwd`/ucspi.ca"
CERTFILE="`pwd`/127.0.0.1.cert"
KEYFILE="`pwd`/127.0.0.1.key"
CCAFILE="`pwd`/localhost.cert"
CCERTFILE="`pwd`/localhost.cert"
CKEYFILE="`pwd`/localhost.key"
DHFILE="`pwd`/dh1024.pem"
export CAFILE CCAFILE CERTFILE KEYFILE CCERTFILE CKEYFILE CADIR DHFILE

rm -rf rts-tmp
mkdir rts-tmp
cd rts-tmp

echo '#!/bin/sh
  trap "" 13
  echo ""
  echo PROTO="$PROTO"
  echo SSLLOCALHOST="${SSLLOCALHOST-unset}"
  echo SSLLOCALIP="${SSLLOCALIP-unset}"
  echo SSLLOCALPORT="${SSLLOCALPORT-unset}"
  echo SSLREMOTEHOST="${SSLREMOTEHOST-unset}"
  echo SSLREMOTEIP="${SSLREMOTEIP-unset}"
  echo SSLREMOTEPORT="${SSLREMOTEPORT-unset}"
  echo SSLREMOTEINFO="${SSLREMOTEINFO-unset}"

  echo TCPLOCALHOST="${TCPLOCALHOST-unset}"
  echo TCPLOCALIP="${TCPLOCALIP-unset}"
  echo TCPLOCALPORT="${TCPLOCALPORT-unset}"
  echo TCPREMOTEHOST="${TCPREMOTEHOST-unset}"
  echo TCPREMOTEIP="${TCPREMOTEIP-unset}"
  echo TCPREMOTEPORT="${TCPREMOTEPORT-unset}"
  echo TCPREMOTEINFO="${TCPREMOTEINFO-unset}"

  echo SSL_PROTOCOL="${SSL_PROTOCOL-unset}"
  echo SSL_SESSION_ID="${SSL_SESSION_ID-unset}"
  echo SSL_CIPHER="${SSL_CIPHER-unset}"
  echo SSL_CIPHER_EXPORT="${SSL_CIPHER_EXPORT-unset}"
  echo SSL_CIPHER_USEKEYSIZE="${SSL_CIPHER_USEKEYSIZE-unset}"
  echo SSL_CIPHER_ALGKEYSIZE="${SSL_CIPHER_ALGKEYSIZE-unset}"
  echo SSL_VERSION_INTERFACE="${SSL_VERSION_INTERFACE-unset}"
  echo SSL_VERSION_LIBRARY="${SSL_VERSION_LIBRARY-unset}"

  echo SSL_SERVER_M_VERSION="${SSL_SERVER_M_VERSION-unset}"
  echo SSL_SERVER_M_SERIAL="${SSL_SERVER_M_SERIAL-unset}"
  echo SSL_SERVER_S_DN="${SSL_SERVER_S_DN-unset}"
  echo SSL_SERVER_S_DN_C="${SSL_SERVER_S_DN_C-unset}"
  echo SSL_SERVER_S_DN_ST="${SSL_SERVER_S_DN_ST-unset}"
  echo SSL_SERVER_S_DN_L="${SSL_SERVER_S_DN_L-unset}"
  echo SSL_SERVER_S_DN_O="${SSL_SERVER_S_DN_O-unset}"
  echo SSL_SERVER_S_DN_OU="${SSL_SERVER_S_DN_OU-unset}"
  echo SSL_SERVER_S_DN_CN="${SSL_SERVER_S_DN_CN-unset}"
  echo SSL_SERVER_S_DN_T="${SSL_SERVER_S_DN_T-unset}"
  echo SSL_SERVER_S_DN_I="${SSL_SERVER_S_DN_I-unset}"
  echo SSL_SERVER_S_DN_G="${SSL_SERVER_S_DN_G-unset}"
  echo SSL_SERVER_S_DN_S="${SSL_SERVER_S_DN_S-unset}"
  echo SSL_SERVER_S_DN_D="${SSL_SERVER_S_DN_D-unset}"
  echo SSL_SERVER_S_DN_UID="${SSL_SERVER_S_DN_UID-unset}"
  echo SSL_SERVER_S_DN_Email="${SSL_SERVER_S_DN_Email-unset}"
  echo SSL_SERVER_I_DN="${SSL_SERVER_I_DN-unset}"
  echo SSL_SERVER_I_DN_C="${SSL_SERVER_I_DN_C-unset}"
  echo SSL_SERVER_I_DN_ST="${SSL_SERVER_I_DN_ST-unset}"
  echo SSL_SERVER_I_DN_L="${SSL_SERVER_I_DN_L-unset}"
  echo SSL_SERVER_I_DN_O="${SSL_SERVER_I_DN_O-unset}"
  echo SSL_SERVER_I_DN_OU="${SSL_SERVER_I_DN_OU-unset}"
  echo SSL_SERVER_I_DN_CN="${SSL_SERVER_I_DN_CN-unset}"
  echo SSL_SERVER_I_DN_T="${SSL_SERVER_I_DN_T-unset}"
  echo SSL_SERVER_I_DN_I="${SSL_SERVER_I_DN_I-unset}"
  echo SSL_SERVER_I_DN_G="${SSL_SERVER_I_DN_G-unset}"
  echo SSL_SERVER_I_DN_S="${SSL_SERVER_I_DN_S-unset}"
  echo SSL_SERVER_I_DN_D="${SSL_SERVER_I_DN_D-unset}"
  echo SSL_SERVER_I_DN_UID="${SSL_SERVER_I_DN_UID-unset}"
  echo SSL_SERVER_I_DN_Email="${SSL_SERVER_I_DN_Email-unset}"
  echo SSL_SERVER_V_START="${SSL_SERVER_V_START-unset}"
  echo SSL_SERVER_V_END="${SSL_SERVER_V_END-unset}"
  echo SSL_SERVER_A_SIG="${SSL_SERVER_A_SIG-unset}"
  echo SSL_SERVER_A_KEY="${SSL_SERVER_A_KEY-unset}"
  echo SSL_SERVER_CERT="${SSL_SERVER_CERT-unset}"

  echo SSL_CLIENT_M_VERSION="${SSL_CLIENT_M_VERSION-unset}"
  echo SSL_CLIENT_M_SERIAL="${SSL_CLIENT_M_SERIAL-unset}"
  echo SSL_CLIENT_S_DN="${SSL_CLIENT_S_DN-unset}"
  echo SSL_CLIENT_S_DN_C="${SSL_CLIENT_S_DN_C-unset}"
  echo SSL_CLIENT_S_DN_ST="${SSL_CLIENT_S_DN_ST-unset}"
  echo SSL_CLIENT_S_DN_L="${SSL_CLIENT_S_DN_L-unset}"
  echo SSL_CLIENT_S_DN_O="${SSL_CLIENT_S_DN_O-unset}"
  echo SSL_CLIENT_S_DN_OU="${SSL_CLIENT_S_DN_OU-unset}"
  echo SSL_CLIENT_S_DN_CN="${SSL_CLIENT_S_DN_CN-unset}"
  echo SSL_CLIENT_S_DN_T="${SSL_CLIENT_S_DN_T-unset}"
  echo SSL_CLIENT_S_DN_I="${SSL_CLIENT_S_DN_I-unset}"
  echo SSL_CLIENT_S_DN_G="${SSL_CLIENT_S_DN_G-unset}"
  echo SSL_CLIENT_S_DN_S="${SSL_CLIENT_S_DN_S-unset}"
  echo SSL_CLIENT_S_DN_D="${SSL_CLIENT_S_DN_D-unset}"
  echo SSL_CLIENT_S_DN_UID="${SSL_CLIENT_S_DN_UID-unset}"
  echo SSL_CLIENT_S_DN_Email="${SSL_CLIENT_S_DN_Email-unset}"
  echo SSL_CLIENT_I_DN="${SSL_CLIENT_I_DN-unset}"
  echo SSL_CLIENT_I_DN_C="${SSL_CLIENT_I_DN_C-unset}"
  echo SSL_CLIENT_I_DN_ST="${SSL_CLIENT_I_DN_ST-unset}"
  echo SSL_CLIENT_I_DN_L="${SSL_CLIENT_I_DN_L-unset}"
  echo SSL_CLIENT_I_DN_O="${SSL_CLIENT_I_DN_O-unset}"
  echo SSL_CLIENT_I_DN_OU="${SSL_CLIENT_I_DN_OU-unset}"
  echo SSL_CLIENT_I_DN_CN="${SSL_CLIENT_I_DN_CN-unset}"
  echo SSL_CLIENT_I_DN_T="${SSL_CLIENT_I_DN_T-unset}"
  echo SSL_CLIENT_I_DN_I="${SSL_CLIENT_I_DN_I-unset}"
  echo SSL_CLIENT_I_DN_G="${SSL_CLIENT_I_DN_G-unset}"
  echo SSL_CLIENT_I_DN_S="${SSL_CLIENT_I_DN_S-unset}"
  echo SSL_CLIENT_I_DN_D="${SSL_CLIENT_I_DN_D-unset}"
  echo SSL_CLIENT_I_DN_UID="${SSL_CLIENT_I_DN_UID-unset}"
  echo SSL_CLIENT_I_DN_Email="${SSL_CLIENT_I_DN_Email-unset}"
  echo SSL_CLIENT_V_START="${SSL_CLIENT_V_START-unset}"
  echo SSL_CLIENT_V_END="${SSL_CLIENT_V_END-unset}"
  echo SSL_CLIENT_A_SIG="${SSL_CLIENT_A_SIG-unset}"
  echo SSL_CLIENT_A_KEY="${SSL_CLIENT_A_KEY-unset}"
  echo SSL_CLIENT_CERT="${SSL_CLIENT_CERT-unset}"
  echo SSL_CLIENT_CERT_CHAIN_0="${SSL_CLIENT_CERT_CHAIN_0-unset}"
  echo SSL_CLIENT_CERT_CHAIN_1="${SSL_CLIENT_CERT_CHAIN_1-unset}"

' > print
chmod 755 print

sanitize() {
  sed -e 's/^SSL_SESSION_ID=.*/SSL_SESSION_ID=.../' \
      -e 's/^SSLREMOTEPORT=.*/SSLREMOTEPORT=.../' \
      -e 's/^SSLLOCALPORT=.*/SSLLOCALPORT=.../' \
      -e 's/^TCPREMOTEPORT=.*/TCPREMOTEPORT=.../' \
      -e 's/^TCPLOCALPORT=.*/TCPLOCALPORT=.../' \
      -e 's/^SSL_VERSION_LIBRARY=.*/SSL_VERSION_LIBRARY=.../' \
      -e 's/^SSL_CIPHER_USEKEYSIZE=.*/SSL_CIPHER_USEKEYSIZE=.../' \
      -e 's/^SSL_CIPHER_ALGKEYSIZE=.*/SSL_CIPHER_ALGKEYSIZE=.../' \
      -e 's/^SSL_CIPHER=.*/SSL_CIPHER=.../'
}

# Assumptions:
#   ucspi-tcp
#   available TCP ports on 127.0.0.1: 50013--50021
#
# Not tested:
#   setting UID or GID
#   rules
#   write timeout

sslserver -w 2 \
-s -c 1 -Bbanner -vo -D -1 -3 -Xx rules.cdb -Rt5 -hp -l Localserver -b 2 \
-a -A \
127.0.0.1 50016 ./print 3< ../127.0.0.1.pw > log.50016 2>&1 &
pid_50016=$!

sslserver -w 2 \
-s -c 1 -Bbanner -vo -D -1 -3 -Xx rules.cdb -t5 -Rhp -l Localserver -b 2 -i \
127.0.0.1 50015 ./print 3< ../127.0.0.1.pw > log.50015 2>&1 &
pid_50015=$!

CIPHERS='DEFAULT' sslserver -w 2 \
-s -e -c 1 -Bbanner -vo -D -1 -3 -Xx rules.cdb -Rt5 -Hp -l Localserver -b 2 \
127.0.0.1 50014 ./print >log.50014 3< ../127.0.0.1.pw 2>&1 &
pid_50014=$!
sleep 1

sslserver -w 2 \
-s -e -c 1 -Bbanner -vo -D -1 -3 -Xx rules.cdb -Rt5 -Hp -l Localserver -b 2 \
127.0.0.1 50013 cat - >log.50013 3< ../127.0.0.1.pw 2>&1 &
pid_50013=$!
sleep 1

echo '--- sslclient prints usage message without enough arguments'
sslclient 0 0; echo $?

echo '--- sslclient prints error message with unknown port name'
sslclient 0 nonexistentport echo wrong; echo $?

echo '--- sslclient prints error message when connection fails'
sslclient 0 016 echo wrong; echo $?

echo '--- sslclient -q does not print error message when connection fails'
sslclient -q 0 016 echo wrong; echo $?

echo '--- sslclient understands empty host name as synonym for 0'
sslclient '' 016 echo wrong; echo $?

echo '--- sslclient understands unbracketed IP address'
sslclient '127.000.000.001' 016 echo wrong; echo $?

echo '--- sslclient understands bracketed IP address'
sslclient '[127.000.000.001]' 016 echo wrong; echo $?

echo '--- sslclient prints error message with unknown host name'
sslclient nonexistent.local. 016 echo wrong; echo $?

echo '--- sslclient prints error message with unresolvable host name'
sslclient thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 50016 echo wrong; echo $?

echo '--- sslserver prints usage message without enough arguments'
sslserver 0 0; echo $?

echo '--- sslserver prints error message with unknown port name'
sslserver 0 nonexistentport echo wrong; echo $?

echo '--- sslserver prints error message with unknown host name'
sslserver nonexistent.local. 016 echo wrong; echo $?

echo '--- sslserver prints error message with unresolvable host name'
sslserver thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 50016 echo wrong; echo $?

echo '--- sslserver prints error message with non-local host name'
( sslserver 1.2.3.4 016 echo wrong 2>&1
  echo $?
) | sed -e 's/unable to bind: .*$/unable to bind: .../'

echo '--- sslserver sets basic environment variables' 
{
  sslclient -p 50017 -R -H -T 10 -l Local -a "$CAFILE" 0 50016 sh -c 'cat <&6'
  echo $?
} | sanitize

echo '--- sslserver -e also sets TCP environment variables' 
{
  sslclient -R -H -T 10 -l Local -a "$CAFILE" 0 50014 sh -c 'cat <&6'
  echo $?
} | sanitize

echo '--- sslclient recognizes -D, -i, -r, -h, -t'
{
  sslclient -Di 127.0.0.1 -p 50018 -hrt1 -l Local -a "$CAFILE" \
    127.0.0.1 50016 sh -c 'cat <&6'
  echo $?
} | sanitize

echo '--- sslclient sets basic environment variables' 
{
  sslclient -p 50019 -R -H -l Local -a "$CAFILE" 0 50016 ./print
  echo $?
} | sanitize

echo '--- sslclient -e sets TCP environment variables' 
{
  sslclient -e -R -H -l Local -a "$CAFILE" 0 50016 ./print
  echo $?
} | sanitize

echo '--- sslclient -s sets SSL environment variables' 
{
  sslclient -s -R -H -l Local -a "$CAFILE" 0 50016 ./print
  echo $?
} | sanitize

echo '--- sslclient looks up host names properly'
{
  sslclient -p 50020 -R -a "$CAFILE" 0 50016 ./print
  echo $?
} | sanitize

echo '--- sslclient -v works' 
sslclient -v -R -H -l Local -a "$CAFILE" 0 50016 echo ok
echo $?

echo '--- sslserver prints error message with used port'
( exec 3<../127.0.0.1.pw
  sslserver -v -1 -3 -R -H -l Localserver 127.0.0.1 50016 echo wrong
  echo $?
)

echo '--- sslcat works'
{
  sslcat 0 50016 -a "$CAFILE"
  echo $?
} | sanitize

echo '--- sslconnect works'
{
  sslconnect 0 50016 -a "$CAFILE" </dev/null
  echo $?
} | sanitize

echo '--- https@ works'
https@ 0 somefile 50016 -a "$CAFILE"
echo $?

echo '--- sslserver prints error for no client certificate' 
( exec 2>&1
  sslclient -v -R -H -l 127.0.0.1 -a "$CAFILE" 0 50015 \
    sh -c 'sleep 1; echo ok'
  echo $?
) | sed  -e 's} speak SSL: .*} speak SSL: ...}'

echo '--- sslserver prints error for bad client certificate' 
( exec 2>&1
  exec 3<../127.0.0.1.pw
  sslclient -v -R -H -l 127.0.0.1 -a "$CAFILE" -c "$CERTFILE" -k "$KEYFILE" -3 \
    0 50015 sh -c 'sleep 1; echo ok'
  echo $?
) | sed  -e 's} speak SSL: .*} speak SSL: ...}'

echo '--- sslserver -H does not check certificate CN' 
( exec 2>&1
  exec 3<../127.0.0.1.pw
  sslclient -v -R -H -l 127.0.0.1 -a "$CAFILE" -c "$CERTFILE" -k "$KEYFILE" -3 \
    -x -C 'DEFAULT' 0 50014 sh -c 'sleep 1; echo ok'
  echo $?
) | sed  -e 's} speak SSL: .*} speak SSL: ...}'

echo '--- sslserver and sslclient print errors for incompatible cipher lists' 
( exec 2>&1
  exec 3<../127.0.0.1.pw
  sslclient -v -R -H -l 127.0.0.1 -a "$CAFILE" -c "$CERTFILE" -k "$KEYFILE" -3 \
    -C '!DEFAULT' 0 50014 sh -c 'sleep 1; echo ok'
  echo $?
) | sed  -e 's} speak SSL: .*} speak SSL: ...}'

echo '--- sslclient -X does not verify server certificate' 
( exec 2>&1
  sslclient -v -R -H -l 127.0.0.1 -X \
    0 50014 sh -c 'sleep 1; echo ok'
  echo $?
) | sanitize

echo '--- sslclient uses certificates' 
( exec 2>&1
  exec 3<../localhost.pw
  sslclient -v -s -R -H -l 127.0.0.1 \
    -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 \
    0 50015 sh -c 'cat <&6; ./print'
  echo $?
) | sanitize

echo '--- sslclient and sslserver handle larger data' 
( exec 2>&1
  exec 3<../localhost.pw
  { for i in 0 1 2 3 4 5 6 7 8 9
    do
      for j in 0 1 2 3 4 5 6 7 8 9
      do
	for k in 0 1 2 3 4 5 6 7 8 9
	do
	  echo "abcdefghijklmnopqrstuvwxyz"
	  echo "abcdefghijklmnopqrstuvwxyz"
	  echo "abcdefghijklmnopqrstuvwxyz"
	  echo "abcdefghijklmnopqrstuvwxyz"
	done
      done
    done
  } | sslconnect 127.0.0.1 50013 -v -s \
    -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 > /dev/null
  echo $?
) | sanitize

echo '--- sslserver times out' 
( exec 2>&1
  exec 3<../localhost.pw
  ( exec echo hereur ) | sslconnect 127.0.0.1 50013 -v -s \
    -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3
  echo $?
) | sanitize

( exec 2>&1
  exec 3<../localhost.pw
  ( sleep 9; exec echo hereur; ) | sslconnect 127.0.0.1 50013 -v -s \
    -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3
  echo $?
) | sanitize



kill -TERM $pid_50013
kill -TERM $pid_50014
kill -TERM $pid_50015
kill -TERM $pid_50016
wait $pid_50013
wait $pid_50014
wait $pid_50015
wait $pid_50016

sslprint \
-s -c 1 -Bsslprint -vo -D -e -1 -3 -Xx rules.cdb -Rt5 -hp -l Localserver -b 2 \
127.0.0.1 50021 3< ../127.0.0.1.pw > log.sslprint 2>&1 &
pid_50021=$!
sleep 2

echo '--- sslprint prints usage message without enough arguments'
sslprint 0; echo $?

echo '--- sslprint prints error message with unknown port name'
sslprint 0 nonexistentport; echo $?

echo '--- sslprint prints error message with unknown host name'
sslprint nonexistent.local. 016; echo $?

echo '--- sslprint prints error message with unresolvable host name'
sslprint thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 016; echo $?

echo '--- sslprint prints error message with non-local host name'
( sslprint 1.2.3.4 016 2>&1
  echo $?
) | sed -e 's/unable to bind: .*/unable to bind: .../'

echo '--- sslprint prints error message with used port'
sslprint -R -H -l Localserver 127.0.0.1 50021 echo wrong
echo $?

echo '--- sslprint sets basic environment variables' 
{ sslclient -R -H -T 10 -l Local -a "$CAFILE" 0 50021 sh -c 'cat <&6'
  echo $?
} | sanitize

echo '--- sslprint exits when environment changes'
{ sslclient -R -H -T 10 -l Local -a "$CAFILE" 0 50021 sh -c 'cat <&6'
  echo $?
} | sanitize

echo '--- sslprint does not lose descriptors' 
( sslclient -R -H -T 10 -l Local -a "$CAFILE" 0 50021 sh -c 'cat <&6' \
  0<&- 2<&-
  echo $?
) | sanitize

sleep 1
kill -TERM $pid_50021
wait $pid_50021

echo '--- sslserver -1v prints proper messages'
cat log.50016 log.50015 log.50014 log.50013 log.sslprint | \
sed -e 's/::.*/::x/' -e 's/ [0-9]* / x /' \
  -e 's} cafile x .*/\([^/]*\)} cafile x xxx/\1}' \
  -e 's} ccafile x .*/\([^/]*\)} ccafile x xxx/\1}' \
  -e 's} cadir x .*/\([^/]*\)} cadir x xxx/\1}' \
  -e 's} cert x .*/\([^/]*\)} cert x xxx/\1}' \
  -e 's} key x .*/\([^/]*\)} key x xxx/\1}' \
  -e 's/ param x .*/ param x xxx/' \
  -e 's/ speak SSL: .*/ speak SSL: .../' \
  -e 's/ accept SSL: .*/ accept SSL: .../' \
  -e 's/ done [0-9]*$/ done .../'

exit 0
