Skip to content

Commit

Permalink
Now the source code is in different files under src/. Use 'make build…
Browse files Browse the repository at this point in the history
…' to rebuild bin/ucsf-vpn - part 1
  • Loading branch information
HenrikBengtsson committed May 18, 2024
1 parent f08058f commit b935918
Show file tree
Hide file tree
Showing 10 changed files with 1,176 additions and 1,285 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ all: README.md shellcheck spelling

.PHONY: help

build:
./build.sh


## Regenerate README.md
README.md: README.md.tmpl bin/ucsf-vpn
@bfr=`cat $<`; \
Expand Down
5 changes: 5 additions & 0 deletions bin/ucsf-vpn
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#! /usr/bin/env bash
###################################################################
# DON'T EDIT: This file is automatically generated from src/ files
###################################################################
### Connect to and Disconnect from the UCSF VPN
###
### Usage:
Expand Down Expand Up @@ -147,6 +150,7 @@ export PULSEPATH=${PULSEPATH:-/usr/local/pulse}
export PATH="${PULSEPATH}:${PATH}"
export LD_LIBRARY_PATH="${PULSEPATH}:${LD_LIBRARY_PATH}"


# -------------------------------------------------------------------------
# Output utility functions
# -------------------------------------------------------------------------
Expand Down Expand Up @@ -470,6 +474,7 @@ function wait_for_ip_route() {
done
}


function status() {
local assert mcmd msg ok
local -i pid
Expand Down
31 changes: 31 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
tmpl=${1:-src/ucsf-vpn}
target=${2:-bin/ucsf-vpn}

echo "Building ${target} from ${tmpl} ..."

## Assert there are source statements
grep -q -F 'source "${incl}/' "${tmpl}"

{
while IFS= read -r line; do \
if [[ "${line}" == "source "* ]]; then \
file=$(sed -E 's/source "[$][{](incl)[}][/]([^.]+[.]sh)"/\1\/\2/' <<< "${line}")
cat "src/${file}"
echo
elif ! grep -q -E "^(# shellcheck source=|this=|incl=)" <<< "${line}"; then
echo "${line}"
if [[ "${line}" == "#! /usr/bin/env bash" ]]; then
echo "###################################################################"
echo "# DON'T EDIT: This file is automatically generated from src/ files"
echo "###################################################################"
fi
fi
done < "${tmpl}"
} > "${target}.tmp"
chmod ugo+x "${target}.tmp"
mv "${target}.tmp" "${target}"
ls -l "${target}"

echo "Version built: $(bash "${target}" --version)"

echo "Building ${target} from ${tmpl} ... done"
211 changes: 211 additions & 0 deletions src/incl/auth.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
# -------------------------------------------------------------------------
# Credentials, e.g. .netrc, prompting for password, etc.
# -------------------------------------------------------------------------
function source_netrc() {
local rcfile pattern found bfr home

if [[ -z ${NETRC} ]]; then
if [[ ${EUID} -eq 0 ]]; then
## Identify the HOME folder of the logged in user, even when
## 'ucsf-vpn' is called via sudo
home=$(getent passwd "$(logname)" | cut -d ":" -f 6)
## Fall back to HOME, if the above failed
if [[ ! -d "${home}" ]]; then
home=${HOME}
fi
else
home=${HOME}
fi
rcfile=${home}/.netrc
else
rcfile=${NETRC}
fi

## No such file?
if [[ ! -f "${rcfile}" ]]; then
mdebug "No .netrc file: $rcfile"
return
fi
mdebug "Detected .netrc file: $rcfile"

## Nothing to do?
if [[ -n "$user" && -n "$pwd" ]]; then
mdebug "Both 'user' and 'pwd' already set. Skipping .netrc file"
return
fi

## Force file to be accessible only by user
chmod go-rwx "${rcfile}"

mdebug "- search: ${netrc_machines[*]}"
found=false
for machine in "${netrc_machines[@]}"; do
pattern="^[ \\t]*machine[ \\t]+${machine}([ \\t]+|$)"
mdebug "- search pattern: ${pattern}"

## No such machine?
grep -q -E "${pattern}" "${rcfile}"

# shellcheck disable=SC2181
if [[ $? -eq 0 ]]; then
mdebug "- found: ${machine}"
found=true
break
fi
done

if ! $found; then
mdebug "- no such machine: $machine"
return 0
fi

bfr=$(awk "/${pattern}/{print; flag=1; next}/machine[ \\t]/{flag=0} flag;" "${rcfile}")
[[ -z $bfr ]] && merror "Internal error - failed to extract ${server} credentials from ${rcfile} searching for ${netrc_machines}"

if [[ -z "$user" ]]; then
user=$(echo "${bfr}" | grep -F "login" | sed -E 's/.*login[[:space:]]+([^[:space:]]+).*/\1/g')
fi

if [[ -z "$pwd" ]]; then
pwd=$(echo "${bfr}" | grep -F "password" | sed -E 's/.*password[[:space:]]+([^[:space:]]+).*/\1/g')
fi

mdebug "- user=${user}"
if [[ -z "${pwd}" ]]; then
mdebug "- pwd=<missing>"
else
mdebug "- pwd=<hidden>"
fi
}

function prompt_user() {
user=$1
if [[ -n "${user}" ]]; then return; fi
mdebug "PROMPT: Asking user to enter username:"
while [ -z "${user}" ]; do
{
_tput setaf 11 ## bright yellow
printf "Enter your UCSF Active Directory username: "
_tput setaf 15 ## bright white
read -r user
_tput sgr0 ## reset
} 1>&2
user=${user/ /}
done
mdebug "- user=${user}"
}

function prompt_pwd() {
pwd=$1
if [[ -n "${pwd}" ]]; then return; fi
mdebug "PROMPT: Asking user to enter password:"
while [ -z "${pwd}" ]; do
{
_tput setaf 11 ## bright yellow
printf "Enter your UCSF Active Directory password: "
_tput setaf 15 ## bright white
read -r -s pwd
_tput sgr0 ## reset
} 1>&2
pwd=${pwd/ /}
done
mecho "<password>"

if [[ -z "${pwd}" ]]; then
mdebug "- pwd=<missing>"
else
mdebug "- pwd=<hidden>"
fi
}

function type_of_token() {
local token

token=$1

## Hardcoded methods
if [[ ${token} =~ ^phone[1-9]*$ ]]; then
## Tested with 'phone' and 'phone2', but for some reason
## the same phone number is called although I've got two
## different registered. Also 'phone1' and 'phone3' gives
## an error.
mdebug "Will authenticate via a call to a registered phone number"
echo "phone call"
return
elif [[ ${token} == "push" ]]; then
mdebug "Will authenticate via push (approve and confirm in Duo app)"
echo "push"
return
elif [[ ${token} =~ ^(sms|text)[1-9]*$ ]]; then
mdebug "Will send token via SMS"
echo "SMS token"
return
elif [[ ${token} == "false" ]]; then
mdebug "Will not use token (in the form)"
echo "none"
return
fi

## YubiKey token (44 lower-case letters)
if [[ ${#token} -eq 44 ]] && [[ ${token} =~ ^[a-z]+$ ]]; then
mdebug "YubiKey token detected"
echo "YubiKey token"
return
fi

## Digital token
if [[ ${token} =~ ^[0-9]+$ ]]; then
if [[ ${#token} -eq 6 ]]; then
mdebug "Six-digit token detected"
echo "six-digit token"
return
elif [[ ${#token} -eq 7 ]]; then
mdebug "Seven-digit token detected"
echo "seven-digit token"
return
fi
fi

echo "unknown"
}

function prompt_token() {
local type

token=$1
if [[ ${token} == "prompt" || ${token} == "true" ]]; then token=; fi
if [[ -n "${token}" ]]; then return; fi

mdebug "PROMPT: Asking user to enter one-time token:"
type="unknown token"
while [ -z "${token}" ]; do
{
_tput setaf 11 ## bright yellow
printf "Enter 'push' (default), 'phone', 'sms', a 6 or 7 digit token, or press your YubiKey: "
_tput setaf 15 ## bright white
read -r -s token
_tput sgr0 ## reset
## Default?
if [[ -z $token ]]; then
token="push"
fi
} 1>&2
token=${token/ /}
type=$(type_of_token "$token")
if [[ $type == "unknown token" ]]; then
{
_tput setaf 1 ## red
printf "\\nERROR: Not a valid token ('push', 'phone', 'sms', 6 or 7 digits, or 44-letter YubiKey sequence)\\n"
_tput sgr0 ## reset
} 1>&2
token=
fi
done
mecho "<$type>"

if [[ -z "${token}" ]]; then
mdebug "- token=<missing>"
else
mdebug "- token=<hidden>"
fi
}
24 changes: 24 additions & 0 deletions src/incl/cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -------------------------------------------------------------------------
# CLI utility functions
# -------------------------------------------------------------------------
function version() {
grep -E "^###[ ]*Version:[ ]*" "$0" | sed 's/###[ ]*Version:[ ]*//g'
}

function help() {
local what res

what=$1
res=$(grep "^###" "$0" | grep -vE '^(####|### whatis: )' | cut -b 5- | sed "s/{{pulsesvc_version}}/$(pulsesvc_version)/" | sed "s/{{openconnect_version}}/$(openconnect_version)/")

if [[ $what == "full" ]]; then
res=$(echo "$res" | sed '/^---/d')
else
res=$(echo "$res" | sed '/^---/Q')
fi

if [[ ${UCSF_TOOLS} == "true" ]]; then
res=$(printf "%s\\n" "${res[@]}" | sed -E 's/([^/])ucsf-vpn/\1ucsf vpn/')
fi
printf "%s\\n" "${res[@]}"
}
Loading

0 comments on commit b935918

Please sign in to comment.