#!/bin/bash
# Cisco Anyconnect CSD wrapper for OpenConnect

if [[ -z ${CSD_HOSTNAME} ]]
then
    echo "Definition of CSD_HOSTNAME is required for this script. Exiting."
    exit 1
fi

HOSTSCAN_DIR="$HOME/.cisco/hostscan"
LIB_DIR="$HOSTSCAN_DIR/lib"
BIN_DIR="$HOSTSCAN_DIR/bin"

BINS=("cscan" "cstub" "cnotify")

# use 64-bit binary for Catalina or later
ARCH="darwin_i386"
MACOS_MINOR=$(sw_vers -productVersion | awk -F '.' '{print $2}')
if [[ ${MACOS_MINOR} -ge 15 ]]; then
    ARCH="darwin_x64"
fi

# 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=$1; fi
    if [ "$1" == "-langselen" ];then shift; LANGSELEN=$1; fi
    shift
done

# 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 --fail --silent --show-error --insecure -o "$HOSTSCAN_DIR/manifest" "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/${ARCH}/manifest"
if [[ ! -f "$HOSTSCAN_DIR/manifest" ]]
then
    echo "Manifest file could not be found locally at $HOSTSCAN_DIR/manifest or remotely at https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/${ARCH}/manifest. Exiting."
    exit 2
fi


# generating md5.sum with full paths from manifest
export HOSTSCAN_DIR=$HOSTSCAN_DIR
cat $HOSTSCAN_DIR/manifest | sed -E 's/\(|\)//g' | awk '{ print $2 }' > $HOSTSCAN_DIR/fileList.txt
cat $HOSTSCAN_DIR/manifest | sed -E 's/\(|\)//g' | awk '{ cmd = "find $HOSTSCAN_DIR -iname " $2; while (cmd | getline line) { print $4, line; } }' > $HOSTSCAN_DIR/md5.sum

# download every file mentioned in manifest, which has incorrect md5 sum
FILES=( $(cat $HOSTSCAN_DIR/fileList.txt) )
WORK_DIR=`pwd`
TMP_DIR=`mktemp -d` && cd $TMP_DIR

for i in ${FILES[@]} ; do
    
    FILE="$(basename "$i")"
    FILE_PATH="$(find $HOSTSCAN_DIR -iname $FILE)"
    
    echo "---------------------------------------------------------------------------------------"
    echo "Checking $FILE ..."
    
    if [ -f "$FILE_PATH" ]; then
        MD5_MANIFEST=$(cat $HOSTSCAN_DIR/md5.sum | grep $FILE | sed -E 's/\(|\)//g' | awk '{ print $1; }')
        MD5_LOCAL=$(md5 $FILE_PATH | awk '{ print $4 }')
        
        if [ "$MD5_MANIFEST" == "$MD5_LOCAL" ]; then
          echo "$FILE is up-to-date and valid."
          echo "SUCCESS"
          continue
        fi
    fi
       
    echo "Downloading https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/${ARCH}/$FILE..."
    curl --fail --silent --show-error --insecure -o "$FILE" "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/${ARCH}/$FILE"

    # some files are in gz (don't understand logic here)
    if [[ ! -f $FILE || ! -s $FILE ]]
    then
        # remove 0 size files
        if [[ -f $FILE && ! -s $FILE ]]; then 
            rm -f $FILE
        fi
        
        FILE_GZ=$FILE.gz
        echo "Could not download $FILE, trying $FILE_GZ..."
        curl --fail --silent --show-error --insecure -o "$FILE_GZ" "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/${ARCH}/$FILE_GZ"
        gunzip --decompress $FILE_GZ
    fi
    
    if [ ! -f $FILE ]; then
        "FAILED to download $FILE - Skipping this file!"
        echo "FAILURE"
        continue
    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 ".dylib|tables.dat"
    IS_LIB=$?
    if [[ "$IS_LIB" -eq "1" ]]
    then
        echo "Copying library $FILE to $LIB_DIR..."
        cp "$FILE" "$LIB_DIR"
    else
        echo "Copying binary $FILE to $BIN_DIR..."
        cp "$FILE" "$BIN_DIR"
    fi
    
    echo "SUCCESS"
    
done

echo "---------------------------------------------------------------------------------------"
for i in ${BINS[@]} ; do
    if [ -f "$BIN_DIR/$i" ]; then
        echo "Setting execution bit on: $BIN_DIR/$i"
        chmod u+x "$BIN_DIR/$i"
    else
        echo "Could not set execution bit for binary $BIN_DIR/$i. File does not exist!"
    fi
done

cd $WORK_DIR
rm -rf $TMP_DIR

echo "---------------------------------------------------------------------------------------"
if [ -x "$BIN_DIR/cstub" ]; then
    # cstub doesn't care about logging options, sic!
    #ARGS="-log debug -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
    ARGS="-url $URL -ticket $TICKET -stub $STUB"

    if [ -n "$GROUP" ]; then ARGS="$ARGS -group $GROUP"; fi
    ARGS="$ARGS -certhash $CERTHASH"
    if [ -n "$LANGSELEN" ]; then ARGS="$ARGS -langsel $LANGSELEN"; fi

    echo "Launching: $BIN_DIR/cstub $ARGS"
    $BIN_DIR/cstub $ARGS
else
    echo "Could not launch $BIN_DIR/cstub. File does not exist!"
    exit 4
fi
