From 4dff0700b37ea5e2bbd74d6be5ab123e1acb43bd Mon Sep 17 00:00:00 2001 From: Henrik Bengtsson Date: Sat, 18 May 2024 10:33:40 -0700 Subject: [PATCH] DEFUNCT: Dropping support for --method=pulse and all code related to it --- NEWS.md | 12 +- README.md | 31 +-- bin/ucsf-vpn | 585 ++++----------------------------------------- src/incl/output.sh | 8 + src/incl/pulse.sh | 391 ------------------------------ src/ucsf-vpn.sh | 187 +++------------ 6 files changed, 101 insertions(+), 1113 deletions(-) delete mode 100755 src/incl/pulse.sh diff --git a/NEWS.md b/NEWS.md index 4d9dae1..7fa189d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,8 +3,16 @@ ucsf-vpn ## Version (development version) - * ... - +### Significant changes + + * OpenConnect is now the only supported method. Support for Pulse + Secure GUI client has been dropped. + +### Deprecated and Defunct + + * The use of `--method=pulse`, which uses the Pulse Secure GUI client + to establish a VPN connection, is defunct. + ## Version 5.8.0 (2024-05-18) diff --git a/README.md b/README.md index b34c643..bf394c0 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,6 @@ Commands: details Display connection details in JSON format routing Display IP routing details log Display log file - troubleshoot Scan log file for errors (only for '--method=pulse') Options: --token= One-time two-factor authentication (2FA) token or method: @@ -162,16 +161,6 @@ Environment variables: UCSF_VPN_PING_TIMEOUT Ping timeout (default: 1.0 seconds) UCSF_VPN_EXTRAS Additional arguments passed to OpenConnect -Commands and Options for Pulse Security Client only (--method=pulse): - open-gui Open the Pulse Secure GUI - close-gui Close the Pulse Secure GUI (and any VPN connections) - - --gui Connect to VPN via Pulse Secure GUI - --no-gui Connect to VPN via Pulse Secure CLI (default) - --speed= Control speed of --gui interactions (default is 1.0) - -Any other options are passed to Pulse Secure CLI as is (only --no-gui). - User credentials: If user credentials (--user and --pwd) are neither specified nor given in ~/.netrc, then you will be prompted to enter them. To specify them @@ -189,12 +178,6 @@ Requirements: * Requirements when using OpenConnect (CLI): - OpenConnect (>= 7.08) (installed: 8.20-1) - sudo -* Requirements when using Junos Pulse Secure Client (GUI): - - Junos Pulse Secure client (>= 5.3) (installed: ) - - Ports 4242 (UDP) and 443 (TCP) - - `curl` - - `xdotool` (when using 'ucsf-vpn start --method=pulse --gui') - - No need for sudo rights VPN Protocol: Different versions of OpenConnect support different VPN protocols. @@ -205,22 +188,10 @@ and 'pulse' the newer "Pulse Secure" protocol. For older version of OpenConnect that recognizes neither, specify '--protocol=juniper', which will results in using 'openconnect' legacy option '--juniper'. -Pulse Secure GUI configuration: -Calling 'ucsf-vpn start --method=pulse --gui' will, if missing, -automatically add a valid VPN connection to the Pulse Secure GUI -with the following details: - - Name: UCSF - - URL: https://remote.ucsf.edu/pulse -You may change the name to you own liking. - Troubleshooting: * Verify your username and password at https://remote.ucsf.edu/. This should be your UCSF Active Directory ID (username); neither MyAccess SFID (e.g. 'sf*****') nor UCSF email address will work. -* If you are using the Pulse Secure client (`ucsf-vpn --method=pulse`), - - Make sure ports 4242 & 443 are not used by other processes - - Make sure 'https://remote.ucsf.edu/pulse' is used as the URL - - Run 'ucsf-vpn troubleshoot' to inspect the Pulse Secure logs Useful resources: * UCSF VPN information: @@ -233,7 +204,7 @@ Useful resources: * UCSF Managing Your Passwords: - https://it.ucsf.edu/services/managing-your-passwords -Version: 5.8.0 +Version: 5.8.0-9001 Copyright: Henrik Bengtsson (2016-2024) License: GPL (>= 2.1) [https://www.gnu.org/licenses/gpl.html] Source: https://github.com/HenrikBengtsson/ucsf-vpn diff --git a/bin/ucsf-vpn b/bin/ucsf-vpn index dbea8ad..44351ee 100755 --- a/bin/ucsf-vpn +++ b/bin/ucsf-vpn @@ -16,7 +16,6 @@ ### details Display connection details in JSON format ### routing Display IP routing details ### log Display log file -### troubleshoot Scan log file for errors (only for '--method=pulse') ### ### Options: ### --token= One-time two-factor authentication (2FA) token or method: @@ -69,16 +68,6 @@ ### UCSF_VPN_PING_TIMEOUT Ping timeout (default: 1.0 seconds) ### UCSF_VPN_EXTRAS Additional arguments passed to OpenConnect ### -### Commands and Options for Pulse Security Client only (--method=pulse): -### open-gui Open the Pulse Secure GUI -### close-gui Close the Pulse Secure GUI (and any VPN connections) -### -### --gui Connect to VPN via Pulse Secure GUI -### --no-gui Connect to VPN via Pulse Secure CLI (default) -### --speed= Control speed of --gui interactions (default is 1.0) -### -### Any other options are passed to Pulse Secure CLI as is (only --no-gui). -### ### User credentials: ### If user credentials (--user and --pwd) are neither specified nor given ### in ~/.netrc, then you will be prompted to enter them. To specify them @@ -96,12 +85,6 @@ ### * Requirements when using OpenConnect (CLI): ### - OpenConnect (>= 7.08) (installed: {{openconnect_version}}) ### - sudo -### * Requirements when using Junos Pulse Secure Client (GUI): -### - Junos Pulse Secure client (>= 5.3) (installed: {{pulsesvc_version}}) -### - Ports 4242 (UDP) and 443 (TCP) -### - `curl` -### - `xdotool` (when using 'ucsf-vpn start --method=pulse --gui') -### - No need for sudo rights ### ### VPN Protocol: ### Different versions of OpenConnect support different VPN protocols. @@ -112,22 +95,10 @@ ### OpenConnect that recognizes neither, specify '--protocol=juniper', ### which will results in using 'openconnect' legacy option '--juniper'. ### -### Pulse Secure GUI configuration: -### Calling 'ucsf-vpn start --method=pulse --gui' will, if missing, -### automatically add a valid VPN connection to the Pulse Secure GUI -### with the following details: -### - Name: UCSF -### - URL: https://remote.ucsf.edu/pulse -### You may change the name to you own liking. -### ### Troubleshooting: ### * Verify your username and password at https://remote.ucsf.edu/. ### This should be your UCSF Active Directory ID (username); neither ### MyAccess SFID (e.g. 'sf*****') nor UCSF email address will work. -### * If you are using the Pulse Secure client (`ucsf-vpn --method=pulse`), -### - Make sure ports 4242 & 443 are not used by other processes -### - Make sure 'https://remote.ucsf.edu/pulse' is used as the URL -### - Run 'ucsf-vpn troubleshoot' to inspect the Pulse Secure logs ### ### Useful resources: ### * UCSF VPN information: @@ -140,16 +111,12 @@ ### * UCSF Managing Your Passwords: ### - https://it.ucsf.edu/services/managing-your-passwords ### -### Version: 5.8.0-9000 +### Version: 5.8.0-9001 ### Copyright: Henrik Bengtsson (2016-2024) ### License: GPL (>= 2.1) [https://www.gnu.org/licenses/gpl.html] ### Source: https://github.com/HenrikBengtsson/ucsf-vpn call="$0 $*" -export PULSEPATH=${PULSEPATH:-/usr/local/pulse} -export PATH="${PULSEPATH}:${PATH}" -export LD_LIBRARY_PATH="${PULSEPATH}:${LD_LIBRARY_PATH}" - # ------------------------------------------------------------------------- # Output utility functions @@ -162,6 +129,7 @@ function _tput() { } function mecho() { echo "$@" 1>&2; } + function mdebug() { if ! $debug; then return @@ -172,6 +140,7 @@ function mdebug() { _tput sgr0 ## reset } 1>&2 } + function merror() { local info version { @@ -189,6 +158,7 @@ function merror() { } 1>&2 _exit 1 } + function mwarn() { { _tput setaf 3 ## yellow @@ -196,6 +166,7 @@ function mwarn() { _tput sgr0 ## reset } 1>&2 } + function minfo() { if ! $verbose; then return @@ -206,6 +177,8 @@ function minfo() { _tput sgr0 ## reset } 1>&2 } + +# shellcheck disable=SC2317 function mok() { { _tput setaf 2 ## green @@ -213,6 +186,7 @@ function mok() { _tput sgr0 ## reset } 1>&2 } + function mdefunct() { { _tput setaf 1 ## red @@ -221,6 +195,7 @@ function mdefunct() { exit 1 } 1>&2 } + function mnote() { { _tput setaf 11 ## bright yellow @@ -800,399 +775,6 @@ function prompt_token() { } -# ------------------------------------------------------------------------- -# Pulse Secure Client -# ------------------------------------------------------------------------- -function div() { - if [ "$2" == "1" ] || [ "$2" == "1.0" ]; then - echo "$1" - else - # shellcheck disable=SC2003 - echo "$1/$2" | bc -l - fi -} - -function pulsesvc_version() { - local res - - res=$(pulsesvc --version 2> /dev/null) - # shellcheck disable=SC2181 - if [[ $? -ne 0 ]]; then - echo "" - else - printf "%s\\n" "${res[@]}" | grep -F "Release Version" | sed -E 's/.*:[ ]+//' - fi -} - -function is_pulseUi_running() { - ps -C pulseUi > /dev/null -} - -function pulseUi_find_connection() { - local config_home confile con # IFS too? - local -i idx ii - - config_home="$HOME/.pulse_secure/pulse" - confile="$config_home/.pulse_Connections.txt" - [[ -f "$confile" ]] || pulseUi_add_connection - [[ -f "$confile" ]] || merror "No Pulse GUI connection file: $confile" - mdebug "Pulse connections file: $confile" - mdebug "$(< "$confile")" - - # shellcheck disable=SC2207 - IFS=$'\r\n' cons=( $(grep -E "^[ \\t]*{.+}[ \\t]*$" < "$confile") ) - mdebug "Number of connections: ${#cons[@]}" - mdebug "Searching for VPN URL: $url" - - idx=-1 - for ii in "${!cons[@]}"; do - con="${cons[$ii]/^ */}" - mdebug "- connection $ii: $con" - if echo "$con" | grep -q -F "\"$url\"" &> /dev/null; then - idx=$ii - break - fi - done - - mdebug "Index of connection found: $idx" - - echo $idx -} - -function pulseUi_add_connection() { - local config_home confile name con - - config_home="$HOME/.pulse_secure/pulse" - confile="$config_home/.pulse_Connections.txt" - name="UCSF" - mdebug "Pulse connections file: $confile" - con="{\"connName\": \"$name\", \"preferredCert\": \"\", \"baseUrl\": \"$url\"}" - mdebug "Appending connection: $con" - echo "$con" >> "$confile" - mecho "Appended missing '$name' connection: $url" -} - -function pulse_start_gui() { - if is_pulseUi_running; then - mwarn "Pulse Secure GUI is already running" - return - fi - - ## Start the Pulse Secure GUI - ## NOTE: Sending stderr to dev null to silence warnings on - ## "(pulseUi:26614): libsoup-CRITICAL **: soup_cookie_jar_get_cookies: - ## assertion 'SOUP_IS_COOKIE_JAR (jar)' failed" - mdebug "Pulse Secure GUI client: $(command -v pulseUi)" - minfo "Launching the Pulse Secure GUI ($(command -v pulseUi))" - pulseUi 2> /dev/null & -} - -function pulse_open_gui() { - if ! $force; then - if is_connected; then - mwarn "Already connected to the VPN [$(public_info)]" - _exit 0 - fi - fi - - mdebug "call: $call" - mdebug "call: pulseUi" - - if $dryrun; then - _exit 0 - fi - - ## Start the Pulse Secure GUI - pulse_start_gui -} - -function pulse_close_gui() { - if ! is_pulseUi_running; then return; fi - - mdebug "Closing Pulse Secure GUI" - - ## Try with 'xdotool'? - if command -v xdotool &> /dev/null; then - xdotool search --all --onlyvisible --pid "$(pidof pulseUi)" --name "Pulse Secure" windowkill - else - pkill -QUIT pulseUi && mdebug "Killed Pulse Secure GUI" - fi -} - -function wait_for_pulse_window_to_close() { - local wid wids - - wid=$1 - mdebug "Waiting for Pulse Secure Window ID ($wid) to close ..." - while true; do - wids=$(xdotool search --all --onlyvisible --name "Pulse Secure") - echo "$wids" | grep -q "$wid" && break - sleep 0.2 - done - mdebug "Waiting for Pulse Secure Window ID ($wid) to close ... done" -} - -function pulse_start() { - local wid wid2 wid3 cmd opts extra - local -i conidx step - - ## Validate request - if [[ "$realm" == "Dual-Factor Pulse Clients" ]]; then - if ! $gui; then - merror "Using --realm='$realm' (two-factor authentication; 2FA) is not supported when using --no-gui" - fi - elif [[ "$realm" == "Single-Factor Pulse Clients" ]]; then - if [ -n "${token}" ] && [ "${token}" != "false" ]; then - merror "Passing a --token='$token' with --realm='$realm' (two-factor authentication; 2FA) does not make sense" - fi - fi - if [ -n "${token}" ] && [ "${token}" != "false" ]; then - if ! $gui; then - merror "Using --token='$token' suggests two-factor authentication (2FA), which is currently not supported when using --no-gui" - fi - fi - - if ! $force; then - if is_connected; then - mwarn "Already connected to the VPN [$(public_info)]" - _exit 0 - fi - fi - - ## Check for valid connection in Pulse Secure GUI - conidx=-1 - if $gui; then - ## If Pulse Secure GUI is open, we need to close it - ## before peeking at its connections config file. - if is_pulseUi_running; then - close_gui - sleep "$(div 0.5 "$speed")" - fi - conidx=$(pulseUi_find_connection) - [[ $conidx -eq -1 ]] && pulseUi_add_connection - conidx=$(pulseUi_find_connection) - [[ $conidx -eq -1 ]] && merror "Pulse Secure GUI does not have a connection for the VPN: $url" - fi - - ## Load user credentials from file? - source_netrc - - ## Prompt for username and password, if missing - prompt_user "${user}" - prompt_pwd "${pwd}" - - ## Prompt for 2FA token? - if [[ "$realm" == "Dual-Factor Pulse Clients" ]]; then - ## Prompt for one-time token, if requested - prompt_token "${token}" - fi - - if $gui; then - step=1 - - ## Check for 'xdotool' - command -v xdotool &> /dev/null || merror "Cannot enter credentials in GUI, because 'xdotool' could not be located." - - ## Start Pulse Secure GUI - pulse_start_gui - - sleep "$(div 1.0 "$speed")" - wid=$(xdotool search --all --onlyvisible --pid "$(pidof pulseUi)" --name "Pulse Secure") - if [[ -z "$wid" ]]; then - merror "Failed to locate the Pulse Secure GUI window" - fi - mecho "Pulse Secure GUI automation:" - mdebug "Pulse Secure Window ID: $wid" - mdebug "Clicking pulseUi 'Connect': $((7 + 2 * conidx)) TABs + ENTER" - cmd="xdotool search --all --onlyvisible --pid $(pidof pulseUi) --name 'Pulse Secure' windowmap --sync windowactivate --sync windowfocus --sync windowraise mousemove --window %1 --sync 0 0 sleep 0.1 click 1 sleep 0.1 key --delay 50 --repeat "$((7 + 2 * conidx))" Tab sleep 0.1 key Return" - mdebug " - $cmd" - mecho " ${step}. selecting connection" - step=$((step + 1)) - eval "$cmd" - - mdebug "Minimizing Pulse Secure GUI" - xdotool windowminimize "$wid" - - sleep "$(div 2.0 "$speed")" - wid2=$(xdotool search --all --onlyvisible --name "Pulse Secure") - mdebug "Pulse Secure Window IDs: $wid2" - wid2=$(echo "$wid2" | grep -vF "$wid") - mdebug "Pulse Secure Popup Window ID: $wid2" - if [[ -z "$wid2" ]]; then - merror "Failed to locate the Pulse Secure GUI popup window" - fi - - ## Click-through UCSF announcement message? - if $notification; then - mdebug "Clicking on 'Proceed'" - cmd="xdotool windowactivate --sync $wid2 key --delay 50 --repeat 2 Tab key Return" - mdebug " - $cmd" - eval "$cmd" - mecho " ${step}. clicking through UCSF notification popup window (--no-notification if it doesn't exist)" - step=$((step + 1)) - sleep "$(div 2.0 "$speed")" - else - mecho " ${step}. skipping UCSF notification popup window (--notification if it exists)" - step=$((step + 1)) - fi - - mdebug "Entering user credentials (username and password)" - xdotool windowactivate --sync "$wid2" type "$user" - xdotool windowactivate --sync "$wid2" key --delay 50 Tab type "$pwd" - ## Single- or Dual-Factor Pulse Clients? - extra= - [[ "$realm" == "Dual-Factor Pulse Clients" ]] && extra="Down" - cmd="xdotool windowactivate --sync $wid2 key --delay 50 Tab $extra Tab Return" - mdebug " - $cmd" - eval "$cmd" - mecho " ${step}. entering user credentials and selecting realm" - step=$((step + 1)) - - - if [[ ${token} != "false" ]]; then - mdebug "Using two-factor authentication (2FA) token" - - sleep "$(div 1.0 "$speed")" - wid3=$(xdotool search --all --onlyvisible --name "Pulse Secure") - mdebug "Pulse Secure Window IDs: $wid3" - wid3=$(echo "$wid3" | grep -vF "$wid") - mdebug "Pulse Secure Popup Window ID: $wid3" - if [[ -z "$wid3" ]]; then - merror "Failed to locate the Pulse Secure GUI popup window" - fi - - mdebug "Entering token" - mecho " ${step}. entering 2FA token" - step=$((step + 1)) - cmd="xdotool windowactivate --sync $wid3 type $token" - mdebug " - $cmd" - eval "$cmd" - cmd="xdotool windowactivate --sync $wid3 key Return" - mdebug " - $cmd" - eval "$cmd" - - ## Wait for popup window to close - wait_for_pulse_window_to_close "$wid3" - else - ## Wait for popup window to close - wait_for_pulse_window_to_close "$wid2" - fi - mecho " ${step}. connecting ..." - step=$((step + 1)) - else - if [[ "$realm" == "Dual-Factor Pulse Clients" ]]; then - merror "Using --realm='$realm' (two-factor authentication; 2FA) is not supported when using --no-gui" - fi - if [ -n "${token}" ] && [ "${token}" != "false" ]; then - merror "Using --token='$token' suggests two-factor authentication (2FA), which is currently not supported when using --no-gui" - fi - ## Pulse Secure options - opts="${extras[*]}" - opts="$opts -h ${server}" - - if [[ -n $user ]]; then - opts="-u $user $opts" - fi - - if ! $debug; then - opts="-log-level 5 $opts" - fi - - mdebug "call: $call" - mdebug "user: $user" - if [[ -n $pwd ]]; then - mdebug "pwd: " - else - mdebug "pwd: " - fi - mdebug "opts: $opts" - mdebug "call: pulsesvc $opts -r \"${realm}\"" - - if $dryrun; then - if [[ -n $pwd ]]; then - echo "echo \"\" | pulsesvc $opts -r \"${realm}\" | grep -viF password &" - else - echo "pulsesvc $opts -r \"${realm}\" &" - fi - _exit 0 - fi - - if [[ -n $pwd ]]; then - echo "$pwd" | pulsesvc "$opts" -r "${realm}" | grep -viF password & - else - pulsesvc "$opts" -r "${realm}" & - fi - fi -} - -function pulse_stop() { - if ! $force; then - if is_connected; then - ## Close/kill the Pulse Secure GUI - pulse_close_gui - - mwarn "Already connected to the VPN [$(public_info)]" - _exit 0 - fi - mdebug "Public IP (before): $ip" - fi - - ## Close/kill the Pulse Secure GUI - pulse_close_gui - - ## Kill any running pulsesvc processes - pulsesvc -Kill - mdebug "Killed local ('pulsesvc') VPN process" -} - - -function pulse_troubleshoot() { - local config_home confile match con prefix logfile ## IFS too? - local -i ii - - minfo "Assumed path to Pulse Secure (PULSEPATH): $PULSEPATH" - command -v pulsesvc || merror "Pulse Secure software 'pulsesvc' not found (in neither PULSEPATH nor PATH)." - - minfo "Pulse Secure software: $res" - pulsesvc --version - - config_home="$HOME/.pulse_secure/pulse" - [[ -d "$config_home" ]] || merror "Pulse user-specific folder: $config_home" - minfo "Pulse user configuration folder: $config_home" - - confile="$config_home/.pulse_Connections.txt" - [[ -f "$confile" ]] || merror "No Pulse GUI connection file: $confile" - minfo "Pulse connections file: $confile" - # shellcheck disable=SC2207 - IFS=$'\r\n' cons=( $(grep -E "^[ \\t]*{.+}[ \\t]*$" < "$confile") ) - minfo "Number of connections: ${#cons[@]}" - match=false - for ii in "${!cons[@]}"; do - con="${cons[$ii]/^ */}" - if echo "$con" | grep -q -F "\"$url\"" &> /dev/null; then - prefix=">>>" - match=true - else - prefix=" " - fi - >&2 printf " %s %d. %s\\n" "$prefix" "$((ii + 1))" "${con/ *$/}" - done - if $match; then - minfo "Found connection with URL of interest: $url" - else - mwarn "No connection with URL of interest: $url" - fi - - logfile="$config_home/pulsesvc.log" - [[ -f "$logfile" ]] || merror "No log file: $logfile" - - minfo "Log file: $logfile" - grep -q -F Error "$logfile" &> /dev/null || { mok "No errors found: $logfile"; _exit 0; } - - mwarn "Detected the following errors in the log file: $(grep -F Error "$logfile" | >&2 tail -3)" -} - - # ------------------------------------------------------------------------- # OpenConnect # ------------------------------------------------------------------------- @@ -1679,6 +1261,13 @@ function logfile() { } +# ------------------------------------------------------------------------- +# Deprecated and defunct +# ------------------------------------------------------------------------- +pulse_is_defunct() { + merror "Support for the Pulse Secure GUI, and command-line options associated with it, are defunct as of ucsf-vpn 5.9.0 (2024-05) in favor of OpenConnect (--method=openconnect; default)" +} + # ------------------------------------------------------------------------- # MAIN # ------------------------------------------------------------------------- @@ -1689,10 +1278,11 @@ pii_file=$(make_pii_file) source_envs + ## Actions action= -## VPN method: 'openconnect' or 'pulse' (default) +## VPN method: 'openconnect' (default) method=${UCSF_VPN_METHOD:-openconnect} ## Options @@ -1708,9 +1298,6 @@ dryrun=false realm= extras=("${UCSF_VPN_EXTRAS[@]}") protocol=${UCSF_VPN_PROTOCOL:-nc} -gui=true -notification=false -speed=1.0 presudo=${UCSF_VPN_PRESUDO:-true} flavor=${UCSF_VPN_FLAVOR} @@ -1743,11 +1330,11 @@ while [[ $# -gt 0 ]]; do elif [[ "$1" == "log" ]]; then action=log elif [[ "$1" == "troubleshoot" ]]; then - action=troubleshoot + pulse_is_defunct elif [[ "$1" == "open-gui" ]]; then - action=open-gui + pulse_is_defunct elif [[ "$1" == "close-gui" ]]; then - action=close-gui + pulse_is_defunct ## Options (--flags): elif [[ "$1" =~ ^--[^=]*$ ]]; then @@ -1775,13 +1362,13 @@ while [[ $# -gt 0 ]]; do elif [[ "$flag" == "dryrun" ]]; then merror "Did you mean to use '--dry-run'?" elif [[ "$flag" == "notification" ]]; then - notification=true + pulse_is_defunct elif [[ "$flag" == "no-notification" ]]; then - notification=false + pulse_is_defunct elif [[ "$flag" == "gui" ]]; then - gui=true + pulse_is_defunct elif [[ "$flag" == "no-gui" ]]; then - gui=false + pulse_is_defunct else merror "Unknown option: '$1'" fi @@ -1812,7 +1399,7 @@ while [[ $# -gt 0 ]]; do elif [[ "$key" == "token" ]]; then token=$value elif [[ "$key" == "speed" ]]; then - speed=$value + pulse_is_defunct elif [[ "$key" == "theme" ]]; then theme=$value elif [[ "$key" == "validate" ]]; then @@ -1864,19 +1451,14 @@ fi if [[ ${method} == "openconnect" ]]; then mdebug "Method: $method" elif [[ ${method} == "pulse" ]]; then - mdebug "Method: $method" - mwarn "Using Pulse Secure is deprecated as of ucsf-vpn 5.7.0 (2024-04-27) in favor of the default --method=openconnect. Support for --method=pulse will be removed in a near-future release." + pulse_is_defunct else merror "Unknown value on option --method: '$method'" fi ## Validate 'realm' if [[ -z $realm ]]; then - if $gui; then - realm="Dual-Factor Pulse Clients" - else - realm="Single-Factor Pulse Clients" - fi + realm="Dual-Factor Pulse Clients" fi if [[ $realm == "Single-Factor Pulse Clients" ]]; then true @@ -1910,22 +1492,10 @@ if [[ ! $theme =~ ^(cli|none)$ ]]; then fi ## Validate 'validate' -if [[ $method == "openconnect" ]]; then - if [[ -z $validate ]]; then - validate=${UCSF_VPN_VALIDATE:-pid,iproute,ipinfo} - fi -elif [[ $method == "pulse" ]]; then - if [[ -z $validate ]]; then - validate=${UCSF_VPN_VALIDATE:-ipinfo} - elif [[ ! $validate =~ ^(ipinfo)$ ]]; then - merror "Unknown --validate value: '$validate'" - fi +if [[ -z $validate ]]; then + validate=${UCSF_VPN_VALIDATE:-pid,iproute,ipinfo} fi -## Validate 'speed' -if [[ ! ${speed} =~ ^[0-9]+[.0-9]*$ ]]; then - merror "Invalid --speed argument: '$speed'" -fi # ------------------------------------------------------------------------- @@ -1964,8 +1534,6 @@ mdebug "validate: $validate" mdebug "dryrun: $dryrun" mdebug "extras: [n=${#extras[@]}] ${extras[*]}" mdebug "method: $method" -mdebug "gui: $gui" -mdebug "speed: $speed" mdebug "netrc_machines: ${netrc_machines[*]}" mdebug "pid_file: $pid_file" mdebug "openconnect_pid: $(openconnect_pid)" @@ -1993,99 +1561,36 @@ elif [[ $action == "details" ]]; then elif [[ $action == "routing" ]]; then routing_details _exit $? -elif [[ $action == "open-gui" ]]; then - if [[ $method != "pulse" ]]; then - merror "ucsf vpn open-gui requires --method=pulse: $method" - fi - pulse_open_gui - res=$? - _exit $res -elif [[ $action == "close-gui" ]]; then - if [[ $method != "pulse" ]]; then - merror "ucsf vpn open-gui requires --method=pulse: $method" - fi - pulse_close_gui - res=$? - _exit $res elif [[ $action == "start" ]]; then - if [[ $method == "openconnect" ]]; then - openconnect_start - res=$? - elif [[ $method == "pulse" ]]; then - pulse_start - res=$? - sleep "$(div 4.0 "$speed")" - fi + openconnect_start + res=$? status "connected" elif [[ $action == "stop" ]]; then - if [[ $method == "openconnect" ]]; then - openconnect_stop - res=$? - elif [[ $method == "pulse" ]]; then - pulse_stop - res=$? - sleep "$(div 1.0 "$speed")" - fi + openconnect_stop status "disconnected" elif [[ $action == "restart" ]]; then - if [[ $method == "openconnect" ]]; then - if $force || is_connected; then - openconnect_stop - fi - openconnect_start - res=$? - elif [[ $method == "pulse" ]]; then - pulse_stop - sleep "$(div 1.0 "$speed")" - is_online - pulse_start - sleep "$(div 4.0 "$speed")" - res=$? + if $force || is_connected; then + openconnect_stop fi + openconnect_start + res=$? status "connected" elif [[ $action == "toggle" ]]; then if ! is_connected; then - if [[ $method == "openconnect" ]]; then - openconnect_start - elif [[ $method == "pulse" ]]; then - pulse_start - sleep "$(div 4.0 "$speed")" - fi + openconnect_start status "connected" else - if [[ $method == "openconnect" ]]; then - openconnect_stop - elif [[ $method == "pulse" ]]; then - pulse_stop - sleep "$(div 1.0 "$speed")" - fi + openconnect_stop status "disconnected" fi elif [[ $action == "log" ]]; then - if [[ $method == "openconnect" ]]; then - LOGFILE=/var/log/syslog - minfo "Displaying 'VPN' entries in log file: $LOGFILE" - if [[ ! -f $LOGFILE ]]; then - mwarn "No such log file: $LOGFILE" - _exit 1 - fi - grep VPN "$LOGFILE" - elif [[ $method == "pulse" ]]; then - LOGFILE=$HOME/.pulse_secure/pulse/pulsesvc.log - minfo "Displaying log file: $LOGFILE" - if [[ ! -f $LOGFILE ]]; then - mwarn "No such log file: $LOGFILE" - _exit 1 - fi - cat "$LOGFILE" - fi -elif [[ $action == "troubleshoot" ]]; then - if [[ $method == "openconnect" ]]; then - merror "ucsf-vpn troubleshoot is not implemented for --method=openconnect" - elif [[ $method == "pulse" ]]; then - pulse_troubleshoot + LOGFILE=/var/log/syslog + minfo "Displaying 'VPN' entries in log file: $LOGFILE" + if [[ ! -f $LOGFILE ]]; then + mwarn "No such log file: $LOGFILE" + _exit 1 fi + grep VPN "$LOGFILE" fi - _exit 0 diff --git a/src/incl/output.sh b/src/incl/output.sh index 2a5721d..3031370 100755 --- a/src/incl/output.sh +++ b/src/incl/output.sh @@ -9,6 +9,7 @@ function _tput() { } function mecho() { echo "$@" 1>&2; } + function mdebug() { if ! $debug; then return @@ -19,6 +20,7 @@ function mdebug() { _tput sgr0 ## reset } 1>&2 } + function merror() { local info version { @@ -36,6 +38,7 @@ function merror() { } 1>&2 _exit 1 } + function mwarn() { { _tput setaf 3 ## yellow @@ -43,6 +46,7 @@ function mwarn() { _tput sgr0 ## reset } 1>&2 } + function minfo() { if ! $verbose; then return @@ -53,6 +57,8 @@ function minfo() { _tput sgr0 ## reset } 1>&2 } + +# shellcheck disable=SC2317 function mok() { { _tput setaf 2 ## green @@ -60,6 +66,7 @@ function mok() { _tput sgr0 ## reset } 1>&2 } + function mdefunct() { { _tput setaf 1 ## red @@ -68,6 +75,7 @@ function mdefunct() { exit 1 } 1>&2 } + function mnote() { { _tput setaf 11 ## bright yellow diff --git a/src/incl/pulse.sh b/src/incl/pulse.sh deleted file mode 100755 index bc22ebf..0000000 --- a/src/incl/pulse.sh +++ /dev/null @@ -1,391 +0,0 @@ -# ------------------------------------------------------------------------- -# Pulse Secure Client -# ------------------------------------------------------------------------- -function div() { - if [ "$2" == "1" ] || [ "$2" == "1.0" ]; then - echo "$1" - else - # shellcheck disable=SC2003 - echo "$1/$2" | bc -l - fi -} - -function pulsesvc_version() { - local res - - res=$(pulsesvc --version 2> /dev/null) - # shellcheck disable=SC2181 - if [[ $? -ne 0 ]]; then - echo "" - else - printf "%s\\n" "${res[@]}" | grep -F "Release Version" | sed -E 's/.*:[ ]+//' - fi -} - -function is_pulseUi_running() { - ps -C pulseUi > /dev/null -} - -function pulseUi_find_connection() { - local config_home confile con # IFS too? - local -i idx ii - - config_home="$HOME/.pulse_secure/pulse" - confile="$config_home/.pulse_Connections.txt" - [[ -f "$confile" ]] || pulseUi_add_connection - [[ -f "$confile" ]] || merror "No Pulse GUI connection file: $confile" - mdebug "Pulse connections file: $confile" - mdebug "$(< "$confile")" - - # shellcheck disable=SC2207 - IFS=$'\r\n' cons=( $(grep -E "^[ \\t]*{.+}[ \\t]*$" < "$confile") ) - mdebug "Number of connections: ${#cons[@]}" - mdebug "Searching for VPN URL: $url" - - idx=-1 - for ii in "${!cons[@]}"; do - con="${cons[$ii]/^ */}" - mdebug "- connection $ii: $con" - if echo "$con" | grep -q -F "\"$url\"" &> /dev/null; then - idx=$ii - break - fi - done - - mdebug "Index of connection found: $idx" - - echo $idx -} - -function pulseUi_add_connection() { - local config_home confile name con - - config_home="$HOME/.pulse_secure/pulse" - confile="$config_home/.pulse_Connections.txt" - name="UCSF" - mdebug "Pulse connections file: $confile" - con="{\"connName\": \"$name\", \"preferredCert\": \"\", \"baseUrl\": \"$url\"}" - mdebug "Appending connection: $con" - echo "$con" >> "$confile" - mecho "Appended missing '$name' connection: $url" -} - -function pulse_start_gui() { - if is_pulseUi_running; then - mwarn "Pulse Secure GUI is already running" - return - fi - - ## Start the Pulse Secure GUI - ## NOTE: Sending stderr to dev null to silence warnings on - ## "(pulseUi:26614): libsoup-CRITICAL **: soup_cookie_jar_get_cookies: - ## assertion 'SOUP_IS_COOKIE_JAR (jar)' failed" - mdebug "Pulse Secure GUI client: $(command -v pulseUi)" - minfo "Launching the Pulse Secure GUI ($(command -v pulseUi))" - pulseUi 2> /dev/null & -} - -function pulse_open_gui() { - if ! $force; then - if is_connected; then - mwarn "Already connected to the VPN [$(public_info)]" - _exit 0 - fi - fi - - mdebug "call: $call" - mdebug "call: pulseUi" - - if $dryrun; then - _exit 0 - fi - - ## Start the Pulse Secure GUI - pulse_start_gui -} - -function pulse_close_gui() { - if ! is_pulseUi_running; then return; fi - - mdebug "Closing Pulse Secure GUI" - - ## Try with 'xdotool'? - if command -v xdotool &> /dev/null; then - xdotool search --all --onlyvisible --pid "$(pidof pulseUi)" --name "Pulse Secure" windowkill - else - pkill -QUIT pulseUi && mdebug "Killed Pulse Secure GUI" - fi -} - -function wait_for_pulse_window_to_close() { - local wid wids - - wid=$1 - mdebug "Waiting for Pulse Secure Window ID ($wid) to close ..." - while true; do - wids=$(xdotool search --all --onlyvisible --name "Pulse Secure") - echo "$wids" | grep -q "$wid" && break - sleep 0.2 - done - mdebug "Waiting for Pulse Secure Window ID ($wid) to close ... done" -} - -function pulse_start() { - local wid wid2 wid3 cmd opts extra - local -i conidx step - - ## Validate request - if [[ "$realm" == "Dual-Factor Pulse Clients" ]]; then - if ! $gui; then - merror "Using --realm='$realm' (two-factor authentication; 2FA) is not supported when using --no-gui" - fi - elif [[ "$realm" == "Single-Factor Pulse Clients" ]]; then - if [ -n "${token}" ] && [ "${token}" != "false" ]; then - merror "Passing a --token='$token' with --realm='$realm' (two-factor authentication; 2FA) does not make sense" - fi - fi - if [ -n "${token}" ] && [ "${token}" != "false" ]; then - if ! $gui; then - merror "Using --token='$token' suggests two-factor authentication (2FA), which is currently not supported when using --no-gui" - fi - fi - - if ! $force; then - if is_connected; then - mwarn "Already connected to the VPN [$(public_info)]" - _exit 0 - fi - fi - - ## Check for valid connection in Pulse Secure GUI - conidx=-1 - if $gui; then - ## If Pulse Secure GUI is open, we need to close it - ## before peeking at its connections config file. - if is_pulseUi_running; then - close_gui - sleep "$(div 0.5 "$speed")" - fi - conidx=$(pulseUi_find_connection) - [[ $conidx -eq -1 ]] && pulseUi_add_connection - conidx=$(pulseUi_find_connection) - [[ $conidx -eq -1 ]] && merror "Pulse Secure GUI does not have a connection for the VPN: $url" - fi - - ## Load user credentials from file? - source_netrc - - ## Prompt for username and password, if missing - prompt_user "${user}" - prompt_pwd "${pwd}" - - ## Prompt for 2FA token? - if [[ "$realm" == "Dual-Factor Pulse Clients" ]]; then - ## Prompt for one-time token, if requested - prompt_token "${token}" - fi - - if $gui; then - step=1 - - ## Check for 'xdotool' - command -v xdotool &> /dev/null || merror "Cannot enter credentials in GUI, because 'xdotool' could not be located." - - ## Start Pulse Secure GUI - pulse_start_gui - - sleep "$(div 1.0 "$speed")" - wid=$(xdotool search --all --onlyvisible --pid "$(pidof pulseUi)" --name "Pulse Secure") - if [[ -z "$wid" ]]; then - merror "Failed to locate the Pulse Secure GUI window" - fi - mecho "Pulse Secure GUI automation:" - mdebug "Pulse Secure Window ID: $wid" - mdebug "Clicking pulseUi 'Connect': $((7 + 2 * conidx)) TABs + ENTER" - cmd="xdotool search --all --onlyvisible --pid $(pidof pulseUi) --name 'Pulse Secure' windowmap --sync windowactivate --sync windowfocus --sync windowraise mousemove --window %1 --sync 0 0 sleep 0.1 click 1 sleep 0.1 key --delay 50 --repeat "$((7 + 2 * conidx))" Tab sleep 0.1 key Return" - mdebug " - $cmd" - mecho " ${step}. selecting connection" - step=$((step + 1)) - eval "$cmd" - - mdebug "Minimizing Pulse Secure GUI" - xdotool windowminimize "$wid" - - sleep "$(div 2.0 "$speed")" - wid2=$(xdotool search --all --onlyvisible --name "Pulse Secure") - mdebug "Pulse Secure Window IDs: $wid2" - wid2=$(echo "$wid2" | grep -vF "$wid") - mdebug "Pulse Secure Popup Window ID: $wid2" - if [[ -z "$wid2" ]]; then - merror "Failed to locate the Pulse Secure GUI popup window" - fi - - ## Click-through UCSF announcement message? - if $notification; then - mdebug "Clicking on 'Proceed'" - cmd="xdotool windowactivate --sync $wid2 key --delay 50 --repeat 2 Tab key Return" - mdebug " - $cmd" - eval "$cmd" - mecho " ${step}. clicking through UCSF notification popup window (--no-notification if it doesn't exist)" - step=$((step + 1)) - sleep "$(div 2.0 "$speed")" - else - mecho " ${step}. skipping UCSF notification popup window (--notification if it exists)" - step=$((step + 1)) - fi - - mdebug "Entering user credentials (username and password)" - xdotool windowactivate --sync "$wid2" type "$user" - xdotool windowactivate --sync "$wid2" key --delay 50 Tab type "$pwd" - ## Single- or Dual-Factor Pulse Clients? - extra= - [[ "$realm" == "Dual-Factor Pulse Clients" ]] && extra="Down" - cmd="xdotool windowactivate --sync $wid2 key --delay 50 Tab $extra Tab Return" - mdebug " - $cmd" - eval "$cmd" - mecho " ${step}. entering user credentials and selecting realm" - step=$((step + 1)) - - - if [[ ${token} != "false" ]]; then - mdebug "Using two-factor authentication (2FA) token" - - sleep "$(div 1.0 "$speed")" - wid3=$(xdotool search --all --onlyvisible --name "Pulse Secure") - mdebug "Pulse Secure Window IDs: $wid3" - wid3=$(echo "$wid3" | grep -vF "$wid") - mdebug "Pulse Secure Popup Window ID: $wid3" - if [[ -z "$wid3" ]]; then - merror "Failed to locate the Pulse Secure GUI popup window" - fi - - mdebug "Entering token" - mecho " ${step}. entering 2FA token" - step=$((step + 1)) - cmd="xdotool windowactivate --sync $wid3 type $token" - mdebug " - $cmd" - eval "$cmd" - cmd="xdotool windowactivate --sync $wid3 key Return" - mdebug " - $cmd" - eval "$cmd" - - ## Wait for popup window to close - wait_for_pulse_window_to_close "$wid3" - else - ## Wait for popup window to close - wait_for_pulse_window_to_close "$wid2" - fi - mecho " ${step}. connecting ..." - step=$((step + 1)) - else - if [[ "$realm" == "Dual-Factor Pulse Clients" ]]; then - merror "Using --realm='$realm' (two-factor authentication; 2FA) is not supported when using --no-gui" - fi - if [ -n "${token}" ] && [ "${token}" != "false" ]; then - merror "Using --token='$token' suggests two-factor authentication (2FA), which is currently not supported when using --no-gui" - fi - ## Pulse Secure options - opts="${extras[*]}" - opts="$opts -h ${server}" - - if [[ -n $user ]]; then - opts="-u $user $opts" - fi - - if ! $debug; then - opts="-log-level 5 $opts" - fi - - mdebug "call: $call" - mdebug "user: $user" - if [[ -n $pwd ]]; then - mdebug "pwd: " - else - mdebug "pwd: " - fi - mdebug "opts: $opts" - mdebug "call: pulsesvc $opts -r \"${realm}\"" - - if $dryrun; then - if [[ -n $pwd ]]; then - echo "echo \"\" | pulsesvc $opts -r \"${realm}\" | grep -viF password &" - else - echo "pulsesvc $opts -r \"${realm}\" &" - fi - _exit 0 - fi - - if [[ -n $pwd ]]; then - echo "$pwd" | pulsesvc "$opts" -r "${realm}" | grep -viF password & - else - pulsesvc "$opts" -r "${realm}" & - fi - fi -} - -function pulse_stop() { - if ! $force; then - if is_connected; then - ## Close/kill the Pulse Secure GUI - pulse_close_gui - - mwarn "Already connected to the VPN [$(public_info)]" - _exit 0 - fi - mdebug "Public IP (before): $ip" - fi - - ## Close/kill the Pulse Secure GUI - pulse_close_gui - - ## Kill any running pulsesvc processes - pulsesvc -Kill - mdebug "Killed local ('pulsesvc') VPN process" -} - - -function pulse_troubleshoot() { - local config_home confile match con prefix logfile ## IFS too? - local -i ii - - minfo "Assumed path to Pulse Secure (PULSEPATH): $PULSEPATH" - command -v pulsesvc || merror "Pulse Secure software 'pulsesvc' not found (in neither PULSEPATH nor PATH)." - - minfo "Pulse Secure software: $res" - pulsesvc --version - - config_home="$HOME/.pulse_secure/pulse" - [[ -d "$config_home" ]] || merror "Pulse user-specific folder: $config_home" - minfo "Pulse user configuration folder: $config_home" - - confile="$config_home/.pulse_Connections.txt" - [[ -f "$confile" ]] || merror "No Pulse GUI connection file: $confile" - minfo "Pulse connections file: $confile" - # shellcheck disable=SC2207 - IFS=$'\r\n' cons=( $(grep -E "^[ \\t]*{.+}[ \\t]*$" < "$confile") ) - minfo "Number of connections: ${#cons[@]}" - match=false - for ii in "${!cons[@]}"; do - con="${cons[$ii]/^ */}" - if echo "$con" | grep -q -F "\"$url\"" &> /dev/null; then - prefix=">>>" - match=true - else - prefix=" " - fi - >&2 printf " %s %d. %s\\n" "$prefix" "$((ii + 1))" "${con/ *$/}" - done - if $match; then - minfo "Found connection with URL of interest: $url" - else - mwarn "No connection with URL of interest: $url" - fi - - logfile="$config_home/pulsesvc.log" - [[ -f "$logfile" ]] || merror "No log file: $logfile" - - minfo "Log file: $logfile" - grep -q -F Error "$logfile" &> /dev/null || { mok "No errors found: $logfile"; _exit 0; } - - mwarn "Detected the following errors in the log file: $(grep -F Error "$logfile" | >&2 tail -3)" -} diff --git a/src/ucsf-vpn.sh b/src/ucsf-vpn.sh index 5bb2bcc..99bbf4b 100755 --- a/src/ucsf-vpn.sh +++ b/src/ucsf-vpn.sh @@ -13,7 +13,6 @@ ### details Display connection details in JSON format ### routing Display IP routing details ### log Display log file -### troubleshoot Scan log file for errors (only for '--method=pulse') ### ### Options: ### --token= One-time two-factor authentication (2FA) token or method: @@ -66,16 +65,6 @@ ### UCSF_VPN_PING_TIMEOUT Ping timeout (default: 1.0 seconds) ### UCSF_VPN_EXTRAS Additional arguments passed to OpenConnect ### -### Commands and Options for Pulse Security Client only (--method=pulse): -### open-gui Open the Pulse Secure GUI -### close-gui Close the Pulse Secure GUI (and any VPN connections) -### -### --gui Connect to VPN via Pulse Secure GUI -### --no-gui Connect to VPN via Pulse Secure CLI (default) -### --speed= Control speed of --gui interactions (default is 1.0) -### -### Any other options are passed to Pulse Secure CLI as is (only --no-gui). -### ### User credentials: ### If user credentials (--user and --pwd) are neither specified nor given ### in ~/.netrc, then you will be prompted to enter them. To specify them @@ -93,12 +82,6 @@ ### * Requirements when using OpenConnect (CLI): ### - OpenConnect (>= 7.08) (installed: {{openconnect_version}}) ### - sudo -### * Requirements when using Junos Pulse Secure Client (GUI): -### - Junos Pulse Secure client (>= 5.3) (installed: {{pulsesvc_version}}) -### - Ports 4242 (UDP) and 443 (TCP) -### - `curl` -### - `xdotool` (when using 'ucsf-vpn start --method=pulse --gui') -### - No need for sudo rights ### ### VPN Protocol: ### Different versions of OpenConnect support different VPN protocols. @@ -109,22 +92,10 @@ ### OpenConnect that recognizes neither, specify '--protocol=juniper', ### which will results in using 'openconnect' legacy option '--juniper'. ### -### Pulse Secure GUI configuration: -### Calling 'ucsf-vpn start --method=pulse --gui' will, if missing, -### automatically add a valid VPN connection to the Pulse Secure GUI -### with the following details: -### - Name: UCSF -### - URL: https://remote.ucsf.edu/pulse -### You may change the name to you own liking. -### ### Troubleshooting: ### * Verify your username and password at https://remote.ucsf.edu/. ### This should be your UCSF Active Directory ID (username); neither ### MyAccess SFID (e.g. 'sf*****') nor UCSF email address will work. -### * If you are using the Pulse Secure client (`ucsf-vpn --method=pulse`), -### - Make sure ports 4242 & 443 are not used by other processes -### - Make sure 'https://remote.ucsf.edu/pulse' is used as the URL -### - Run 'ucsf-vpn troubleshoot' to inspect the Pulse Secure logs ### ### Useful resources: ### * UCSF VPN information: @@ -137,16 +108,12 @@ ### * UCSF Managing Your Passwords: ### - https://it.ucsf.edu/services/managing-your-passwords ### -### Version: 5.8.0 +### Version: 5.8.0-9001 ### Copyright: Henrik Bengtsson (2016-2024) ### License: GPL (>= 2.1) [https://www.gnu.org/licenses/gpl.html] ### Source: https://github.com/HenrikBengtsson/ucsf-vpn call="$0 $*" -export PULSEPATH=${PULSEPATH:-/usr/local/pulse} -export PATH="${PULSEPATH}:${PATH}" -export LD_LIBRARY_PATH="${PULSEPATH}:${LD_LIBRARY_PATH}" - this="${BASH_SOURCE%/}"; [[ -L "${this}" ]] && this=$(readlink "${this}") incl="$(dirname "${this}")/incl" @@ -277,9 +244,6 @@ function status() { # shellcheck source=incl/auth.sh source "${incl}/auth.sh" -# shellcheck source=incl/pulse.sh -source "${incl}/pulse.sh" - # shellcheck source=incl/openconnect.sh source "${incl}/openconnect.sh" @@ -405,6 +369,13 @@ function logfile() { } +# ------------------------------------------------------------------------- +# Deprecated and defunct +# ------------------------------------------------------------------------- +pulse_is_defunct() { + merror "Support for the Pulse Secure GUI, and command-line options associated with it, are defunct as of ucsf-vpn 5.9.0 (2024-05) in favor of OpenConnect (--method=openconnect; default)" +} + # ------------------------------------------------------------------------- # MAIN # ------------------------------------------------------------------------- @@ -415,10 +386,11 @@ pii_file=$(make_pii_file) source_envs + ## Actions action= -## VPN method: 'openconnect' or 'pulse' (default) +## VPN method: 'openconnect' (default) method=${UCSF_VPN_METHOD:-openconnect} ## Options @@ -434,9 +406,6 @@ dryrun=false realm= extras=("${UCSF_VPN_EXTRAS[@]}") protocol=${UCSF_VPN_PROTOCOL:-nc} -gui=true -notification=false -speed=1.0 presudo=${UCSF_VPN_PRESUDO:-true} flavor=${UCSF_VPN_FLAVOR} @@ -469,11 +438,11 @@ while [[ $# -gt 0 ]]; do elif [[ "$1" == "log" ]]; then action=log elif [[ "$1" == "troubleshoot" ]]; then - action=troubleshoot + pulse_is_defunct elif [[ "$1" == "open-gui" ]]; then - action=open-gui + pulse_is_defunct elif [[ "$1" == "close-gui" ]]; then - action=close-gui + pulse_is_defunct ## Options (--flags): elif [[ "$1" =~ ^--[^=]*$ ]]; then @@ -501,13 +470,13 @@ while [[ $# -gt 0 ]]; do elif [[ "$flag" == "dryrun" ]]; then merror "Did you mean to use '--dry-run'?" elif [[ "$flag" == "notification" ]]; then - notification=true + pulse_is_defunct elif [[ "$flag" == "no-notification" ]]; then - notification=false + pulse_is_defunct elif [[ "$flag" == "gui" ]]; then - gui=true + pulse_is_defunct elif [[ "$flag" == "no-gui" ]]; then - gui=false + pulse_is_defunct else merror "Unknown option: '$1'" fi @@ -538,7 +507,7 @@ while [[ $# -gt 0 ]]; do elif [[ "$key" == "token" ]]; then token=$value elif [[ "$key" == "speed" ]]; then - speed=$value + pulse_is_defunct elif [[ "$key" == "theme" ]]; then theme=$value elif [[ "$key" == "validate" ]]; then @@ -590,19 +559,14 @@ fi if [[ ${method} == "openconnect" ]]; then mdebug "Method: $method" elif [[ ${method} == "pulse" ]]; then - mdebug "Method: $method" - mwarn "Using Pulse Secure is deprecated as of ucsf-vpn 5.7.0 (2024-04-27) in favor of the default --method=openconnect. Support for --method=pulse will be removed in a near-future release." + pulse_is_defunct else merror "Unknown value on option --method: '$method'" fi ## Validate 'realm' if [[ -z $realm ]]; then - if $gui; then - realm="Dual-Factor Pulse Clients" - else - realm="Single-Factor Pulse Clients" - fi + realm="Dual-Factor Pulse Clients" fi if [[ $realm == "Single-Factor Pulse Clients" ]]; then true @@ -636,22 +600,10 @@ if [[ ! $theme =~ ^(cli|none)$ ]]; then fi ## Validate 'validate' -if [[ $method == "openconnect" ]]; then - if [[ -z $validate ]]; then - validate=${UCSF_VPN_VALIDATE:-pid,iproute,ipinfo} - fi -elif [[ $method == "pulse" ]]; then - if [[ -z $validate ]]; then - validate=${UCSF_VPN_VALIDATE:-ipinfo} - elif [[ ! $validate =~ ^(ipinfo)$ ]]; then - merror "Unknown --validate value: '$validate'" - fi +if [[ -z $validate ]]; then + validate=${UCSF_VPN_VALIDATE:-pid,iproute,ipinfo} fi -## Validate 'speed' -if [[ ! ${speed} =~ ^[0-9]+[.0-9]*$ ]]; then - merror "Invalid --speed argument: '$speed'" -fi # ------------------------------------------------------------------------- @@ -690,8 +642,6 @@ mdebug "validate: $validate" mdebug "dryrun: $dryrun" mdebug "extras: [n=${#extras[@]}] ${extras[*]}" mdebug "method: $method" -mdebug "gui: $gui" -mdebug "speed: $speed" mdebug "netrc_machines: ${netrc_machines[*]}" mdebug "pid_file: $pid_file" mdebug "openconnect_pid: $(openconnect_pid)" @@ -719,99 +669,36 @@ elif [[ $action == "details" ]]; then elif [[ $action == "routing" ]]; then routing_details _exit $? -elif [[ $action == "open-gui" ]]; then - if [[ $method != "pulse" ]]; then - merror "ucsf vpn open-gui requires --method=pulse: $method" - fi - pulse_open_gui - res=$? - _exit $res -elif [[ $action == "close-gui" ]]; then - if [[ $method != "pulse" ]]; then - merror "ucsf vpn open-gui requires --method=pulse: $method" - fi - pulse_close_gui - res=$? - _exit $res elif [[ $action == "start" ]]; then - if [[ $method == "openconnect" ]]; then - openconnect_start - res=$? - elif [[ $method == "pulse" ]]; then - pulse_start - res=$? - sleep "$(div 4.0 "$speed")" - fi + openconnect_start + res=$? status "connected" elif [[ $action == "stop" ]]; then - if [[ $method == "openconnect" ]]; then - openconnect_stop - res=$? - elif [[ $method == "pulse" ]]; then - pulse_stop - res=$? - sleep "$(div 1.0 "$speed")" - fi + openconnect_stop status "disconnected" elif [[ $action == "restart" ]]; then - if [[ $method == "openconnect" ]]; then - if $force || is_connected; then - openconnect_stop - fi - openconnect_start - res=$? - elif [[ $method == "pulse" ]]; then - pulse_stop - sleep "$(div 1.0 "$speed")" - is_online - pulse_start - sleep "$(div 4.0 "$speed")" - res=$? + if $force || is_connected; then + openconnect_stop fi + openconnect_start + res=$? status "connected" elif [[ $action == "toggle" ]]; then if ! is_connected; then - if [[ $method == "openconnect" ]]; then - openconnect_start - elif [[ $method == "pulse" ]]; then - pulse_start - sleep "$(div 4.0 "$speed")" - fi + openconnect_start status "connected" else - if [[ $method == "openconnect" ]]; then - openconnect_stop - elif [[ $method == "pulse" ]]; then - pulse_stop - sleep "$(div 1.0 "$speed")" - fi + openconnect_stop status "disconnected" fi elif [[ $action == "log" ]]; then - if [[ $method == "openconnect" ]]; then - LOGFILE=/var/log/syslog - minfo "Displaying 'VPN' entries in log file: $LOGFILE" - if [[ ! -f $LOGFILE ]]; then - mwarn "No such log file: $LOGFILE" - _exit 1 - fi - grep VPN "$LOGFILE" - elif [[ $method == "pulse" ]]; then - LOGFILE=$HOME/.pulse_secure/pulse/pulsesvc.log - minfo "Displaying log file: $LOGFILE" - if [[ ! -f $LOGFILE ]]; then - mwarn "No such log file: $LOGFILE" - _exit 1 - fi - cat "$LOGFILE" - fi -elif [[ $action == "troubleshoot" ]]; then - if [[ $method == "openconnect" ]]; then - merror "ucsf-vpn troubleshoot is not implemented for --method=openconnect" - elif [[ $method == "pulse" ]]; then - pulse_troubleshoot + LOGFILE=/var/log/syslog + minfo "Displaying 'VPN' entries in log file: $LOGFILE" + if [[ ! -f $LOGFILE ]]; then + mwarn "No such log file: $LOGFILE" + _exit 1 fi + grep VPN "$LOGFILE" fi - _exit 0