-
-
Save nonamed01/0961d8a79955206ebdc00abcaa56aefe to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# Uncomment the following line to debug the script: | |
#set -x | |
##################################################################################### | |
# fuckForticlient.sh | |
# | |
# Script to authenticate against Fortinet SAML servers using Firefox and | |
# openfortivpn. This replaces Forticlient for GNU/Linux completely. | |
# Because openfortivpn does not support SAML login (yet), this script uses Firefox | |
# to authenticate, grabs SVPNCOOKIE and then calls openfortivpn to setup | |
# the VPN service. | |
# | |
# See: | |
# https://github.com/adrienverge/openfortivpn/pull/1042#issuecomment-1344211491 | |
# | |
# 2022-2023 by Toni Castillo Girona (@Disbauxes) | |
# | |
# INSTALLATION | |
# > First, install the following packages: | |
# sudo apt-get install liblz4-dev lz4json jq firefox-esr git inotify-tools \ | |
# libssl-dev autoconf make gcc pkg-config | |
# > Next, install all the dependencies to build openfortivpn: | |
# sudo apt-get build-dep openfortivpn | |
# | |
# Please notice that if your OS provides an openfortivpn package with | |
# support for the "--cookie-on-stdin" parameter, you do not need to | |
# install these dependencies or build openfortivpn from scratch. | |
# | |
# > Now clone and build openfortivpn: | |
# git clone https://github.com/adrienverge/openfortivpn.git | |
# cd openfortivpn | |
# ./autogen.sh | |
# ./configure && make | |
# > And finally, install it system-wide: | |
# sudo make install | |
# | |
# The user running this script must belong to the sudo group. In case they | |
# don't, run: | |
# sudo usermod -aG sudo USER | |
# | |
# HOW IT WORKS | |
# 1. Opens firefox and navigates to https://${SERVER}/remote/login | |
# 2. After a succesful authentication, SVPNCOOKIE | |
# is saved to sessionstore-backups/recovery.jsonlz4 on Firefox's profile. | |
# 2. The script will use openfortivpn to start the tunnel providing it | |
# with SVPNCOOKIE (--cookie-on-stdin < cookie_file) because | |
# it does not support SAML (yet!). | |
# | |
# NOTES | |
# > Firefox will store cookies in sessionstore-backups/recovery.jsonlz4 only when | |
# the following options within "Privacy&Security/History" are not enabled: | |
# "Always use private(...)" and "Clear history when Firefox closes". | |
# > SVPNCOOKIE is saved into ~/.${USER}.svpncookie with 0600 perms and removed | |
# when exiting the script (thanks to trap). | |
# > Remember, this script is a HACK. So if something does not work for you, | |
# change whatever you think needs to be changed and please, READ these notes | |
# BEFORE assuming that it won't work at all! | |
# > This script has been tested on some OS but not all. And remember that, for | |
# some systems, custom configurations of Firefox may affect this script in | |
# different ways. So please UNDERSTAND how this script works and then adjust | |
# whatever you think you need to adjust to make it work. | |
# > Tested on: Raspbian 11; Debian 10, 11; Ubuntu/Kubuntu 20.04,22.04. | |
# | |
# USAGE | |
# Run the script like this to start a new authentication process against | |
# a SAML server and get the VPN up and running automatically: | |
# | |
# ./fuckForticlient.sh -S vpnserver -c | |
# | |
# In case you already have a valid non-expired SVPNCOOKIE, you can re-use | |
# it like this: | |
# | |
# ./fuckForticlient.sh -S myvpnserver -s | |
# | |
# Once the vpn is up and running, you can close the terminal and the | |
# connection will hold; you can disconnect by pressing CTRL+c at any | |
# time. If you close the terminal and the connection is still alive, | |
# you can kill it with: | |
# | |
# sudo kill `pidof openfortivpn` | |
# | |
# Run the script with "-h" to get a list of valid options and some | |
# running examples. | |
# | |
##################################################################################### | |
VERSION="1.1" | |
AUTHOR="Toni Castillo Girona" | |
EMAIL="toni.castillo@upc.edu" | |
TWITTER="@Disbauxes" | |
# Fortinet VPN SAML server, replace with your own or use -S SERVER | |
# E.g: /fuckForticlient.sh -S myvpnserver.domain.org -c | |
SERVER="" | |
# Default timeout in seconds to wait for the SVPNCOOKIE to appear: | |
TIMEOUT=120 | |
# Options to pass to the firefox browser (it only applies when there's no | |
# previous Firefox instance already running): | |
OPTIONS="--window-size 150,150" | |
# By default, we don't show the SVPNCOOKIE on screen: | |
SHOWCOOKIE=0 | |
# We get the current distro: | |
DISTRO=`lsb_release -i|cut -d":" -f2|tr -d '\t'` | |
DISTROV=`lsb_release -r|awk '{print $2}'` | |
# No debug by default (use -D to change it) | |
DEBUG=0 | |
##################################################################################### | |
# Colors | |
##################################################################################### | |
clRed='\033[1;31m' | |
clYellow='\033[1;33m' | |
clGreen='\033[1;32m' | |
clNone='\033[0m' | |
##################################################################################### | |
# cleanup() | |
##################################################################################### | |
cleanup(){ | |
# Removes SVPNCOOKIE: | |
test -r $HOME/.${USER}.svpncookie && rm $HOME/.${USER}.svpncookie | |
test -d /tmp/openfortivpn && rm -rf /tmp/openfortivpn | |
} | |
##################################################################################### | |
# banner() | |
# Shows the banner ;-) | |
##################################################################################### | |
banner (){ | |
echo " ___ __ ____ __ _ ___ __ " | |
echo " / _/_ ______/ /__ / __/__ ____/ /_(_)___/ (_)__ ___ / /_" | |
echo " / _/ // / __/ '_// _// _ \/ __/ __/ / __/ / / -_) _ \/ __/" | |
echo -e "/_/ \_,_/\__/_/\_\/_/ \___/_/ \__/_/\__/_/_/\__/_//_/\__/ ${clRed}v${VERSION}" | |
echo "" | |
echo -e "${clYellow}2022-2023 by: $AUTHOR ($TWITTER)" | |
echo -e "${clNone}" | |
} | |
##################################################################################### | |
# getProfilePath() | |
# Gets the Firefox profile path or returns an error. Depending on the distro, | |
# sometimes the profile path is not on the usual path (like with Ubuntu because | |
# it uses SNAPd) | |
##################################################################################### | |
getProfilePath(){ | |
profilepath="" | |
case $DISTRO in | |
Debian|Raspbian|Parrot) | |
if [ ! -d ${HOME}/.mozilla/firefox ]; then | |
return -1 | |
fi | |
profilepath="${HOME}/.mozilla/firefox" | |
;; | |
Ubuntu) | |
if [ "$DISTROV" != "20.04" ]; then | |
if [ ! -d ${HOME}/snap/firefox/common/.mozilla/firefox ]; then | |
return -1 | |
fi | |
profilepath="${HOME}/snap/firefox/common/.mozilla/firefox" | |
else | |
if [ ! -d ${HOME}/.mozilla/firefox ]; then | |
return -1 | |
fi | |
profilepath="${HOME}/.mozilla/firefox" | |
fi | |
;; | |
*) | |
# We return the usual path, but who knows if it even works at all! | |
profilepath="${HOME}/.mozilla/firefox" | |
;; | |
esac | |
echo "${profilepath}" | |
return 0 | |
} | |
##################################################################################### | |
# enumerateProfiles() | |
# Enumerates all profiles available by reading profiles.ini. This can be used | |
# to determine which profile to use to override the automatic detection of the | |
# default profile with -p. | |
##################################################################################### | |
enumerateProfiles(){ | |
profilepath=`getProfilePath` | |
if [ $? -eq 0 ]; then | |
profs=`cat ${profilepath}/profiles.ini|grep Path|cut -d"=" -f2|xargs` | |
for p in ${profs}; do | |
pName=`echo ${p}|cut -d"." -f2` | |
echo -e " [>] Name : ${clGreen}${pName}" | |
echo -en "${clNone}" | |
echo -e " [>] Path (-p): ${clGreen}${profilepath}/${p}" | |
echo -en "${clNone}" | |
echo "" | |
done | |
else | |
echo "[!] Unable to determine Firefox profile PATH!!!" | |
return -1 | |
fi | |
} | |
##################################################################################### | |
# getFirefoxProfile() | |
# Returns the path for the default Firefox profile or "" if it cannot determine | |
# where it is. Using -p overrrides this function. | |
# If the user has decided to write the profile-path to use right in the file | |
# ~/.${USER}.fuckforticlient-profile, this functions simply returns the contents | |
# of ~/.${USER}.fuckforticlient-profile. | |
##################################################################################### | |
getFirefoxProfile(){ | |
# Do we have a saved profile to use? | |
if [ -r ~/.${USER}.fuckforticlient-profile ]; then | |
profilep=`cat -v ~/.${USER}.fuckforticlient-profile` | |
# If it's not empty and the directory is valid: | |
if [ ! -z "${profilep}" -a -d "${profilep}" ]; then | |
echo "${profilep}" | |
return 0 | |
fi | |
fi | |
# First, we get the profile path depending on the Distro: | |
profilepath=`getProfilePath` | |
if [ $? -eq 0 ]; then | |
prof=`cat ${profilepath}/profiles.ini |grep Path=|grep -i default|tail -1|cut -d"=" -f2` | |
if [ ! -z "$prof" ]; then | |
echo "${profilepath}/${prof}/sessionstore-backups" | |
return 0 | |
else | |
echo "" | |
return -2 | |
fi | |
else | |
echo "" | |
return -2 | |
fi | |
} | |
##################################################################################### | |
# getCookie(profile,waitForIt) | |
# Waits up to TIMEOUT seconds for the SVPNCOOKIE to appear. Stores the cookie in | |
# $HOME/${USER].svpncookie and returns 0; returns 1 otherwise. | |
##################################################################################### | |
getCookie(){ | |
# Storage file where the cookie is stored in firefox: | |
storage="$1" | |
waitForIt=$2 | |
# We save the current umask value first: | |
curUmask=`umask` | |
# We change it to 0077: | |
umask 077 | |
# We try to grab the cookie right away: | |
c=`lz4jsoncat ${storage}/recovery.jsonlz4 2>/dev/null|jq '.cookies[]|select(.name!=null)|select(.name|contains("SVPNCOOKIE"))|.value'` | |
if [ ! -z "$c" ]; then | |
echo "SVPNCOOKIE=${c}" > $HOME/.${USER}.svpncookie | |
sed -i 's/\"//g' $HOME/.${USER}.svpncookie | |
# We restore umask: | |
umask $curUmask | |
return 0 | |
fi | |
# We only wait if waitForIt == 1 | |
test $waitForIt -eq 0 && return 1 | |
# We will wait until the cookie is already there... | |
while inotifywait -e modify -t $TIMEOUT --format '%w%f' ${storage} -q >/dev/null 2>&1; | |
do | |
if [ -r ${storage}/recovery.jsonlz4 ]; then | |
# Make sure we check for the cookie once the file changes: | |
c=`lz4jsoncat ${storage}/recovery.jsonlz4 2>/dev/null|jq '.cookies[]|select(.name!=null)|select(.name|contains("SVPNCOOKIE"))|.value'` | |
if [ ! -z "$c" ]; then | |
#echo ${c} | |
echo "SVPNCOOKIE=${c}" > $HOME/.${USER}.svpncookie | |
sed -i 's/\"//g' $HOME/.${USER}.svpncookie | |
# We restore umask | |
umask $curUmask | |
return 0 | |
fi | |
fi | |
done | |
# If we reach this, we exit with error (timeout!): | |
# We restore umask: | |
umask $curUmask | |
return 1 | |
} | |
##################################################################################### | |
# usage() | |
# Shows the help screen and some examples and exits | |
##################################################################################### | |
usage(){ | |
echo "" | |
echo -ne "Usage: `basename $0` -L|-u|-d|[-p][-P][-t][-v][-S][-c][-s] \n" \ | |
"\t-h Shows this help and exits.\n" \ | |
"\t-c Opens firefox to perform SAML Authentication.\n" \ | |
"\t-s Tries to re-use a previous SVPNCOOKIE.\n" \ | |
"\t-p PATH Overrides the detection of the Firefox Profile to use.\n" \ | |
"\t-P Saves chosen Firefox Profile (-p) as the default one.\n" \ | |
"\t-t SECONDS Sets the timeout to wait for the SVPNCOOKIE cookie to SECONDS.\n" \ | |
"\t-v Shows the SVPNCOOKIE cookie on screen.\n" \ | |
"\t-S SERVER Authenticates against VPN server SERVER .\n" \ | |
"\t-L Lists all Firefox profiles detected and exits.\n" \ | |
"\t-d Removes Forticlient from the system and exits.\n" \ | |
"\t-u Updates openfortivpn and exits.\n" \ | |
"\t-i Shows current assigned VPN Ip address and exits.\n" \ | |
"\t-D Runs the script in debug mode.\n" \ | |
"Examples:\n" \ | |
"\t`basename $0` -L \n" \ | |
"\t`basename $0` -S myserver.org.edu -c\n" \ | |
"\t`basename $0` -i\n" \ | |
"\t`basename $0` -t 200 -S myvpnserver.com -c \n" \ | |
"\t`basename $0` -p /home/u1/.mozilla/firefox/myprofile -S vpnsrv -c\n" \ | |
"\t`basename $0` -p /home/u1/.mozilla/firefox/myprofile -P -S vpnsrv -c\n" \ | |
"\t`basename $0` -p /home/u1/.mozilla/firefox/myprofile -S vpnsrv -s\n" \ | |
"\t`basename $0` -t 200 -p /home/u1/.mozilla/firefox/myprofile -S vpnsrv -c\n" \ | |
"\n" \ | |
"Extra options for openfortivpn \n" \ | |
"\t FUCKFORTICLIENT_OPTS=\"--op1 --op2 ...\" `basename $0` options ... \n" \ | |
"Example:\n" \ | |
"\tFUCKFORTICLIENT_OPTS=\"--no-dns\" `basename $0` -S myserver.org.edu -c\n" | |
exit 0 | |
} | |
##################################################################################### | |
# sanityCheck() | |
# Performs some trivial sanity checks before attempting to run the script. | |
##################################################################################### | |
sanityCheck(){ | |
# Test for jq presence: | |
type jq >/dev/null 2>&1|| return 1 | |
# Test for lz4jsoncat | |
type lz4jsoncat >/dev/null 2>&1 || return 1 | |
# Test for openfortivpn: | |
type openfortivpn >/dev/null 2>&1|| return 1 | |
# Make sure openfortivpn supports "--cookie-on-stdin": | |
/usr/local/bin/openfortivpn --help|grep cookie >/dev/null|| return 1 | |
# Make sure we have Firefox installed: | |
type firefox >/dev/null 2>&1 || return 1 | |
# Make sure the user running this script belongs to the sudo group: | |
id -Gn |grep sudo >/dev/null || return 1 | |
return 0 | |
} | |
##################################################################################### | |
# checkFirefoxSettings() | |
# Makes sure the following two options ARE not enabled on the chosen | |
# firefox profile to ensure the SVPNCOOKIE cookie will be stored in the | |
# sessionstore-backups/recovery.jsonlz4 file: | |
# | |
# browser.privatebrowsing.autostart | |
# privacy.sanitize.pending | |
##################################################################################### | |
checkFirefoxSettings(){ | |
# Now, if the sessionstore-backups directory DOES NOT EXIST at all, | |
# it is obvious these options are ALREADY ENABLED! | |
if [ ! -d "${fProfile}" ]; then | |
return 1 | |
else | |
# Otherwise, make sure everything else fits: | |
grep -q "browser.privatebrowsing.autostart" "${fProfile}/../prefs.js" | |
# Not found, maybe the next option? | |
if [ $? -eq 1 ]; then | |
# sanitize pending should'nt have anything between "[]": | |
sa=`cat "${fProfile}/../prefs.js"|grep "privacy.sanitize.pending"|awk '{print $2}'|cut -d"\"" -f2` | |
if [ "${sa}" != "[]" ]; then | |
if [ "${sa}" != "[{\\" ]; then | |
return 1 | |
else | |
return 0 | |
fi | |
else | |
return 0 | |
fi | |
fi | |
return 1 | |
fi | |
} | |
##################################################################################### | |
# getVPNIp() | |
# Returns the current assigned VPN IP Address or error | |
# It assumes the VPN device used by openfortivpn is always "ppp0", quite naive!! | |
##################################################################################### | |
getVPNIp(){ | |
data=`ip a list ppp0 2>/dev/null|grep "inet"` | |
if [ $? -eq 0 ]; then | |
echo ${data}|awk '{print $2}' | |
return 0 | |
else | |
echo "" | |
return 1 | |
fi | |
} | |
##################################################################################### | |
# checkAnotherInstance() | |
# Checks whether there's a running instance of openfortivpn. If there is, | |
# exits with error. Otherwise, returns 0. | |
##################################################################################### | |
checkAnotherInstance(){ | |
pidof -q openfortivpn | |
if [ $? -eq 0 ]; then | |
echo -e "${clRed}[!] Another openfortivpn instance detected!${clNone}" | |
# If there is another instance running, it is probably because there is | |
# an active VPN connection running already: | |
ipvpn=`getVPNIp` | |
if [ $? -eq 0 ]; then | |
echo -e "[+] Current VPN IP: ${clGreen}${ipvpn}${clNone}" | |
echo -e "${clRed}[!] If you kill openfortivpn instance, you will be disconnected!${clNone}" | |
fi | |
echo -e "[!] Run: ${clGreen} sudo kill `pidof openfortivpn`${clNone} or just press CTRL+c on the terminal window..." | |
exit 1 | |
fi | |
return 0 | |
} | |
##################################################################################### | |
# checkOpenfortivpn() | |
# Returns 0 if the installed version of Openfortivpn is from the repo or 1 | |
# otherwise. For some distros, the included openfortivpn from the official repos | |
# does not support "--cookie-on-stdin" | |
##################################################################################### | |
checkOpenfortivpn(){ | |
dpkg -l |grep openfortivpn|grep -E "^ii" >/dev/null 2>&1 | |
return $? | |
} | |
# Tiddy things up if we cancel or finish the script: | |
trap "cleanup" EXIT | |
# We show the banner: | |
banner | |
# We show the detected distro: | |
echo -e "[*] Detected distro: ${clRed}$DISTRO${clNone}, version: ${clRed}$DISTROV" | |
echo -ne "${clNone}" | |
# First of all, we perform a trivial sanity check: | |
sanityCheck | |
if [ ! $? -eq 0 ]; then | |
echo "[!] Sanity check reported an error." | |
echo "[!] Make sure you have installed all the pre-requisites first." | |
echo "[!] Make sure you belong to the sudo group also." | |
exit 0 | |
fi | |
# We get Firefox default profile first thing: | |
fProfile=`getFirefoxProfile` | |
if [ ! $? -eq 0 ]; then | |
# Has the user provided us with a custom profile path? | |
args="$*" | |
if [[ "$args" != *"-p"* ]]; then | |
echo -e "${clRed}[!] Unable to determine the default firefox profile!...${clNone}" | |
echo "[+] Enumerating all profiles now...:" | |
# So we show all the detected profiles just in case: | |
enumerateProfiles | |
echo "[!] Please, re-run this script with the -p option! Aborting..." | |
exit 1 | |
fi | |
else | |
echo -e "[*] Auto-detected firefox profile: ${clRed}$fProfile" | |
echo -ne "${clNone}" | |
fi | |
# If we have a valid Firefox profile (either by auto-detecting it or because the | |
# user has specified the -p and/or -P parameters, we make sure Firefox settings | |
# will save the cookie to the restore file before going further... | |
checkFirefoxSettings | |
if [ $? -eq 1 ]; then | |
echo -e "${clRed}[!] Error; make sure the following two options are disabled on Firefox" | |
echo -e "\t>Never Remember History" | |
echo -e "\t>Always use private browsing mode" | |
echo -e "\t>Clear history when Firefox closes" | |
echo -e "${clNone}[!] Go to ${clGreen}Preferences/Privacy&Security/History ${clNone}to fix it!" | |
echo "[!] Aborting now ... " | |
exit 1 | |
fi | |
# We get openfortivpn version and show it: | |
opv=`openfortivpn --version` | |
echo -e "[*] Openfortivpn version: ${clRed}$opv" | |
echo -en "${clNone}" | |
# Is it installed from a repo or from github? | |
checkOpenfortivpn | |
if [ $? -eq 0 ]; then | |
echo -e "[*] Openfortivpn installed from: ${clRed}REPO" | |
else | |
echo -e "[*] Openfortivpn installed from: ${clRed}GITHUB" | |
fi | |
echo -en "${clNone}" | |
# Show any extra openfortivpn parameter: | |
if [ ! -z "$FUCKFORTICLIENT_OPTS" ]; then | |
echo -e "[*] Openfortivpn extra args: $clGreen$FUCKFORTICLIENT_OPTS " | |
echo -en "${clNone}" | |
fi | |
# Process arguments: | |
while getopts "Licshut:p:PvdDS:" opt; do | |
case "$opt" in | |
# Shows usage message and exits: | |
h) | |
usage | |
exit 0 | |
;; | |
D) | |
echo -e "[*]${clYellow} Debug mode enabled!${clNone}" | |
DEBUG=1 | |
set -x | |
;; | |
u) | |
# Clones the repository first: | |
echo "[*] Updating openfortivpn ... " | |
echo -e "\t[>] Cloning ..." | |
git clone https://github.com/adrienverge/openfortivpn.git /tmp/openfortivpn>/dev/null 2>&1 | |
if [ $? -eq 0 ]; then | |
cd /tmp/openfortivpn >/dev/null 2>&1 | |
echo -e "\t[>] Running autogen.sh ... " | |
./autogen.sh >/dev/null 2>&1 | |
echo -e "\t[>] Running configure & make ..." | |
( ./configure && make )> /dev/null 2>&1 | |
echo -e "\t[>] Running make install ... " | |
sudo make install >/dev/null 2>&1 | |
if [ $? -eq 0 ]; then | |
echo -e "[*] ${clGreen}openfortivpn updated sucessfully!" | |
echo -ne "${clNone}" | |
else | |
echo -e "[!] ${clRed}error updating openfortivpn." | |
echo -ne "${clNone}" | |
fi | |
# We clean the directory: | |
cd .. && rm -rf /tmp/openfortivpn >/dev/null 2>&1 | |
else | |
echo -e "[!] ${clRed}Unable to clone openfortivpn!" | |
exit -1 | |
fi | |
;; | |
# Shows current assigned VPN Ip address (if any) and exits: | |
i) | |
ipvpn=`getVPNIp` | |
if [ $? -eq 0 ]; then | |
echo -e "[+] Current VPN Ip: ${clGreen}${ipvpn}${clNone}" | |
else | |
echo -e "[!] ${clRed}You are not connected to the VPN!${clNone}" | |
fi | |
exit 0 | |
;; | |
# It will show the SVPNCOOKIE on screen: | |
v) | |
SHOWCOOKIE=1 | |
;; | |
# Shows all detected profiles and quits: | |
L) | |
echo "[*] Enumerating Firefox profiles ... " | |
enumerateProfiles | |
exit 0 | |
;; | |
# Firefox default profile override: | |
p) | |
fProfile="$OPTARG/sessionstore-backups" | |
echo "[*] Overriding detected Firefox profile" | |
# Make sure the directory is valid: | |
if [ ! -d "$fProfile" ]; then | |
echo "[!] Error, ${fProfile} does not exist! Aborting..." | |
exit 1 | |
fi | |
;; | |
P) | |
# We do not really care if the fProfile variable has been filled | |
# by autodetecting the Firefox profile or because the user has | |
# used the "-p" parameter; we save it to ~/.${USER}-fuckforticlient-profile | |
# anyways...: | |
echo -e "[+] Saving profile to: ${clGreen}~/.${USER}.fuckforticlient-profile" | |
echo -ne "${clNone}" | |
echo -n "${fProfile}" > ~/.${USER}.fuckforticlient-profile | |
;; | |
# Timeout for the SVPNCOOKIE override: | |
t) | |
TIMEOUT=$OPTARG | |
;; | |
# Overrides SERVER and tries to authenticate against -S SERVER: | |
S) | |
SERVER="$OPTARG" | |
;; | |
# Removes Forticlient: | |
d) | |
echo "[*] Removing Forticlient as requested ... " | |
dpkg -l forticlient >/dev/null 2>&1 | |
if [ $? -eq 0 ]; then | |
sudo dpkg --purge forticlient | |
else | |
echo "[!] Forticlient is not installed!" | |
fi | |
exit 0 | |
;; | |
# Tries to get the SVPNCOOKIE without re-opening firefox and | |
# then uses the cookie to start the VPN: | |
s) | |
# First of all, if there is a running openfortivpn instance, | |
# we exit and we do not try to re-connect: | |
checkAnotherInstance | |
# We do nothing if we do not specify a valid VPN-SSL server: | |
if [ -z "$SERVER" ]; then | |
echo "[!] Please, re-run the script with -S VPNSERVER" | |
exit 0 | |
fi | |
echo -e "[*] Firefox profile: ${clRed}$fProfile" | |
echo -ne "${clNone}" | |
echo "[*] Trying to re-use a previous SVPNCOOKIE..." | |
getCookie "$fProfile" "0" | |
if [ ! $? -eq 0 ]; then | |
echo "[!] Unable to get SVPNCOOKIE; aborting..." | |
exit 0 | |
else | |
test $SHOWCOOKIE -eq 1 && echo "[*] `cat $HOME/.${USER}.svpncookie`" | |
echo -e "[*] ${clGreen}SVPNCOOKIE sucessfully retrieved!" | |
echo -ne "${clNone}" | |
# We save the cookie file to a variable first: | |
cookie=$HOME/.${USER}.svpncookie | |
# We connect to the vpn now: | |
test $DEBUG -eq 1 && dbg="-vvv" | |
sudo /usr/local/bin/openfortivpn $SERVER:443 --cookie-on-stdin < ${cookie} ${dbg} ${FUCKFORTICLIENT_OPTS} | |
if [ ! $? -eq 0 ]; then | |
echo "${clRed}[!] Error, expired cookie probably...${clNone}" | |
echo "[!] Close Firefox and re-lanch the script using -c" | |
exit 1 | |
fi | |
fi | |
;; | |
# Establishes a new connection by opening Firefox first. The user | |
# needs to authenticate against the Fortinet server first: | |
c) | |
# First of all, if there is a running openfortivpn instance, | |
# we exit and we do not try to re-connect: | |
checkAnotherInstance | |
# We do nothing if we do not specify a valid VPN-SSL server: | |
if [ -z "$SERVER" ]; then | |
echo "[!] Please, re-run the script with -S VPNSERVER" | |
exit 0 | |
fi | |
# FIX: make sure to use the right profile!!!! | |
profName=`dirname ${fProfile}|rev|cut -d"." -f1|rev|cut -d"/" -f1` | |
echo -e "[*] Opening Firefox for SAML login with: ${clGreen}-P ${profName}...${clNone}" | |
firefox -P ${profName} ${OPTIONS} https://${SERVER}/remote/login >/dev/null 2>&1 & | |
echo -e "[*] Firefox profile: ${clRed}$fProfile" | |
echo -ne "${clNone}" | |
echo -e "[*] Authenticating against ${clRed}https://$SERVER ..." | |
echo -ne "${clNone}" | |
# There's some delay before firefox stores the cookie unless it is closed, | |
# in which case it's inmediately there. | |
echo -e "[*] Waiting up to ${clRed}$TIMEOUT seconds${clNone} until the cookie appears..." | |
# Gets the cookie: | |
getCookie "$fProfile" "1" | |
if [ ! $? -eq 0 ]; then | |
echo "[!] Unable to get SVPNCOOKIE; aborting..." | |
exit 0 | |
else | |
test $SHOWCOOKIE -eq 1 && echo "[*] `cat $HOME/.${USER}.svpncookie`" | |
echo -e "[*] ${clGreen}SVPNCOOKIE sucessfully retrieved!" | |
echo -ne "${clNone}" | |
# We save the cookie file to a variable first: | |
cookie=$HOME/.${USER}.svpncookie | |
# We connect to the vpn now: | |
test $DEBUG -eq 1 && dbg="-vvv" | |
sudo /usr/local/bin/openfortivpn ${SERVER}:443 --cookie-on-stdin < ${cookie} ${dbg} ${FUCKFORTICLIENT_OPTS} | |
if [ ! $? -eq 0 ]; then | |
echo -e "${clRed}[!] Error, expired cookie probably...${clNone}" | |
echo "[!] Close Firefox and re-lanch the script using -c" | |
exit 1 | |
fi | |
fi | |
;; | |
esac | |
done |
If someone interested
For external browser I implemented a script to retrieve token on repository https://github.com/filippor/XdgOpenSaml
the process is
1 start a server to listen on localhost:8020/?id=
2 open in external browser url + "/remote/saml/start?redirect=1"
3 server receive a call and with retieved id call url + "/remote/saml/auth_id?id=" + id to retrieve cookie
you can see a sample implementation in this repo https://github.com/filippor/XdgOpenSaml/blob/main/XdgOpenSaml.java that write the cookie to standard out like openfortivpn-webview
XdgOpenSaml url:port | sudo openfortivpn url:port --cookie-on-stdin --pppd-use-peerdns=
Just a FYI: I created a script that can arrange the login against Azure AD without starting a browser GUI. Nice to automate the login process. The script is available here:
https://github.com/zizzencs/openfortivpn-azure-ad-login-helper
lz4json package does not exist, not sure how to build it, so yeah, no solution for Fedora unfortunately... And official Forticlient for Linux is garbage.