#!/bin/sh
#
# DANA Session ID Fetcher
#   Logs into a Juniper SSL VPN device and returns your session ID
#
#   *** Supports client certificates! ***************************************
#   *                                                                       *
#   * This is the only reason I wrote this script. Juniper's client doesn't *
#   * support client certificates outright, and relies on the web browser   *
#   * to hack it and return the session ID via valid cookie.                *
#   *                                                                       *
#   *************************************************************************
#
#   (c) Copyright 2009. Omachonu Ogali <oogali@idlepattern.com>
#   All rights reserved.
# 
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions
#   are met:
#
#   1. Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
# 
#   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
#   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
#   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 

if [ $# -lt 4 ]; then
  echo "$0 [hostname] [username] [password] [realm] [type:certpath]"
  echo "  [hostname] is the IP or hostname of the VPN device"
  echo "  [username] is your username"
  echo "  [password] is your password"
  echo "  [realm] is your login realm"
  echo "  [type] is one of the following: DER, PEM, ENG"
  echo "  [certpath] is the path to your client certificate"
  exit 1
fi

vpn_host=$1
username=$2
passwd=$3
realm=$4

if [ $# -eq 5 ]; then
  cert_type=`echo $5 | cut -f1 -d ':' | tr '[a-z]' '[A-Z]'`
  echo "${cert_type}" | egrep -q '^(DER|PEM|ENG)'
  if [ $? -ne 0 ]; then
    echo "invalid certificate type specified ($cert_type)"
    exit 1
  fi

  cert_file=`echo $5 | cut -f2 -d ':'`
  if [ -z "${cert_file}" ] || [ ! -f "${cert_file}" ]; then
    echo "invalid certificate path specified"
    exit 1
  fi
fi

CURL=`which curl 2>/dev/null`
if [ -z "${CURL}" ]; then
  echo "could not find curl installation"
  exit 1
fi

cookie_jar=`mktemp /tmp/vpn.XXXXXX`
if [ ! -f "${cookie_jar}" ]; then
  echo "could not create cookie jar"
  exit 1
fi

if [ ! -z "${cert_file}" ]; then
  CURL_FLAGS="-i -b ${cookie_jar} -c ${cookie_jar} --cert ${cert_file} --cert-type ${cert_type}"
else
  CURL_FLAGS="-i -b ${cookie_jar} -c ${cookie_jar}"
fi

${CURL} ${CURL_FLAGS} -s -o /dev/null https://${vpn_host}
${CURL} ${CURL_FLAGS} -s -o /dev/null https://${vpn_host}/dana-na/auth/url_default/welcome.cgi

temp_output=`mktemp /tmp/vpn.XXXXXX`
if [ ! -f "${temp_output}" ]; then
  echo "could not create temporary output"
  rm -f ${cookie_jar}
  exit 1
fi

auth_data="username=${username}&password=${passwd}&realm=${realm}&tz_offset=`date '+%z'`"
${CURL} ${CURL_FLAGS} -s -o ${temp_output} --data-ascii "${auth_data}&btnSubmit=Sign+In" https://${vpn_host}/dana-na/auth/url_default/login.cgi
grep -iq 'welcome.cgi' ${temp_output}
if [ $? -ne 0 ]; then
  echo "unsuccessful login"
  rm -f ${cookie_jar} ${temp_output}
  exit 1
fi

newurl=`grep -i '^location:' ${temp_output}`
if [ $? -ne 0 ]; then
  echo "expected 302/redirect, didn't find it"
  rm -f ${cookie_jar} ${temp_output}
  exit 1
fi
newurl=`echo ${newurl} | cut -f2 -d ' '`

${CURL} ${CURL_FLAGS} -s -o ${temp_output} ${newurl}

grep -iq 'frmConfirmation' ${temp_output}
if [ $? -eq 0 ]; then
  form_data=`grep 'DSIDFormDataStr' ${temp_output} | sed 's/.*name="\(.*\)".*value="\(.*\)">/\1=\2/; s/;/%3b/g; s/\+/%2b/g;'`
  ${CURL} ${CURL_FLAGS} -s -o ${temp_output} -H "Referer: ${referer}" --data "${form_data}&btnContinue=Continue%20the%20session" https://${vpn_host}/dana-na/auth/url_default/login.cgi
fi

grep -iq 'welcome.cgi?p=failed' ${temp_output}
if [ $? -eq 0 ]; then
  echo "unsuccessful login after redirect"
  rm -f ${cookie_jar} ${temp_output}
  exit 1
fi

newurl=`grep -i '^location:' ${temp_output}`
if [ $? -ne 0 ]; then
  echo "unsuccessful login: expected 302/redirect, didn't find it"
  rm -f ${cookie_jar} ${temp_output}
  exit 1
fi
newurl=`echo ${newurl} | cut -f2 -d ' '`

${CURL} ${CURL_FLAGS} -s -o ${temp_output} ${newurl}

dsid=`grep 'DSID' ${cookie_jar} | awk '{ print $7 }'`
if [ -z "${dsid}" ]; then
  echo "could not login successfully: could not get DSID"
  exit 1
fi

rm -f ${temp_output}
rm -f ${cookie_jar}

echo "Successfully logged in (session ID is ${dsid})"
