diff --git a/auth.c b/auth.c index 83c186d3..510c4f97 100644 --- a/auth.c +++ b/auth.c @@ -1142,6 +1142,7 @@ static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int bufle if (asprintf(&csd_argv[i++], "\"%s:%s\"", scertbuf, ccertbuf) == -1) goto out; + csd_argv[i++] = (char *)"-url"; if (asprintf(&csd_argv[i++], "\"https://%s%s\"", vpninfo->hostname, vpninfo->csd_starturl) == -1) goto out; @@ -1149,6 +1150,8 @@ static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int bufle csd_argv[i++] = (char *)"-langselen"; csd_argv[i++] = NULL; + if (setenv("CSD_SHA256", openconnect_get_peer_cert_hash(vpninfo)+11, 1)) /* remove initial 'pin-sha256:' */ + goto out; if (setenv("CSD_TOKEN", vpninfo->csd_token, 1)) goto out; if (setenv("CSD_HOSTNAME", vpninfo->hostname, 1)) diff --git a/csd-wrapper.sh b/csd-wrapper.sh new file mode 100755 index 00000000..d7165d7f --- /dev/null +++ b/csd-wrapper.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# Cisco Anyconnect CSD wrapper for OpenConnect +# +# [05 May 2015] Written by Nikolay Panin : +# - source: https://gist.github.com/l0ki000/56845c00fd2a0e76d688 +# [27 Oct 2017] Updated by Daniel Lenski : +# - use -url argument +# - kill cstub after timeout +# - fix small typos: +# [31 May 2018] Updated by Daniel Lenski : +# - use curl with --pinnedpubkey to rely on sha256 hash of peer cert passed by openconnect + +TIMEOUT=30 +URL="https://${CSD_HOSTNAME}/CACHE" +HOSTSCAN_DIR="$HOME/.cisco/hostscan" +LIB_DIR="$HOSTSCAN_DIR/lib" +BIN_DIR="$HOSTSCAN_DIR/bin" +PINNEDPUBKEY=${CSD_SHA256:+"--pinnedpubkey sha256//$CSD_SHA256"} + +BINS=("cscan" "cstub" "cnotify") + +# parsing command line +shift + +URL= +TICKET= +STUB= +GROUP= +CERTHASH= +LANGSELEN= + +while [ "$1" ]; do + if [ "$1" == "-ticket" ]; then shift; TICKET=$1; fi + if [ "$1" == "-stub" ]; then shift; STUB=$1; fi + if [ "$1" == "-group" ]; then shift; GROUP=$1; fi + if [ "$1" == "-certhash" ]; then shift; CERTHASH=$1; fi + if [ "$1" == "-url" ]; then shift; URL=$(echo $1|tr -d '"'); fi # strip quotes + if [ "$1" == "-langselen" ];then shift; LANGSELEN=$1; fi + shift +done + +ARCH=$(uname -m) + +if [[ "$ARCH" == "x86_64" ]] +then + ARCH="linux_x64" +else + ARCH="linux_i386" +fi + +# creating dirs +for dir in $HOSTSCAN_DIR $LIB_DIR $BIN_DIR ; do + if [[ ! -f $dir ]] + then + mkdir -p $dir + fi +done + +# getting manifest, and checking binaries +curl $PINNEDPUBKEY "${URL}/sdesktop/hostscan/$ARCH/manifest" -o "$HOSTSCAN_DIR/manifest" + +# generating md5.sum with full paths from manifest +export HOSTSCAN_DIR=$HOSTSCAN_DIR +cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ cmd = "find $HOSTSCAN_DIR -iname " $2; while (cmd | getline line) { print $4, line; } }' > $HOSTSCAN_DIR/md5.sum + +# check number of files either +MD5_LINES=`wc --lines $HOSTSCAN_DIR/md5.sum | awk '{ print $1; }'` +MANIFEST_LINES=`wc --lines $HOSTSCAN_DIR/manifest | awk '{ print $1; }'` +echo "Got $MANIFEST_LINES files in manifest, locally found $MD5_LINES" + +# check md5 +md5sum -c $HOSTSCAN_DIR/md5.sum +if [[ "$?" -ne "0" || "$MD5_LINES" -ne "$MANIFEST_LINES" ]] +then + echo "Corrupted files, or whatever wrong with md5 sums, or missing some file" + # just download every file mentioned in manifest (not ideal, but hopefully should be enough) + FILES=( $(cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ print $2; }') ) + WORK_DIR=`pwd` + TMP_DIR=`mktemp -d` && cd $TMP_DIR + for i in ${FILES[@]} ; do + FILE="$(basename "$i")" + + echo "Downloading: $FILE to $TMP_DIR" + curl $PINNEDPUBKEY "${URL}/sdesktop/hostscan/$ARCH/$FILE" -o $FILE + + # some files are in gz (don't understand logic here) + if [[ ! -f $FILE || ! -s $FILE ]] + then + # remove 0 size files + if [[ ! -s $FILE ]]; then + rm $FILE + fi + + echo "Failure on $FILE, trying gz" + FILE_GZ=$FILE.gz + curl $PINNEDPUBKEY "${URL}/sdesktop/hostscan/$ARCH/$FILE_GZ" -O $FILE_GZ + gunzip --verbose --decompress $FILE_GZ + fi + + # don't know why, but my version of hostscan requires tables to be stored in libs + echo $FILE | grep --extended-regexp --quiet --invert-match ".so|tables.dat" + IS_LIB=$? + if [[ "$IS_LIB" -eq "1" ]] + then + cp --verbose $FILE $LIB_DIR + else + cp --verbose $FILE $BIN_DIR + fi + + done + + for i in ${BINS[@]} ; do + echo "Setting excecution bit on: $BIN_DIR/$i" + chmod u+x $BIN_DIR/$i + done + + cd $WORK_DIR + rm -rf $TMP_DIR + +fi + +# cstub doesn't care about logging options, sic! +#ARGS="-log debug -ticket $TICKET -stub $STUB -group $GROUP -host "$URL" -certhash $CERTHASH" +ARGS="-log error -ticket $TICKET -stub $STUB -group $GROUP -host \"$URL\" -certhash $CERTHASH" + +echo "Launching: $BIN_DIR/cstub $ARGS" +$BIN_DIR/cstub $ARGS & CSTUB_PID=$! + +sleep $TIMEOUT +if kill -0 $CSTUB_PID 2> /dev/null; then + echo "Killing cstub process after $TIMEOUT seconds" + kill $CSTUB_PID 2> /dev/null || kill -9 $CSTUB_PID 2> /dev/null +fi