mirror of
https://github.com/pi-hole/pi-hole.git
synced 2025-04-20 14:20:13 +00:00
Add 2FA handling to api.sh
Signed-off-by: Christian König <github@yubiuser.dev>
This commit is contained in:
parent
9050e47049
commit
5de9b6ae69
1 changed files with 66 additions and 24 deletions
|
@ -21,7 +21,7 @@
|
||||||
TestAPIAvailability() {
|
TestAPIAvailability() {
|
||||||
|
|
||||||
# as we are running locally, we can get the port value from FTL directly
|
# as we are running locally, we can get the port value from FTL directly
|
||||||
local chaos_api_list availabilityResponse
|
local chaos_api_list authResponse authStatus authData
|
||||||
|
|
||||||
# Query the API URLs from FTL using CHAOS TXT local.api.ftl
|
# Query the API URLs from FTL using CHAOS TXT local.api.ftl
|
||||||
# The result is a space-separated enumeration of full URLs
|
# The result is a space-separated enumeration of full URLs
|
||||||
|
@ -49,20 +49,29 @@ TestAPIAvailability() {
|
||||||
API_URL="${API_URL#\"}"
|
API_URL="${API_URL#\"}"
|
||||||
|
|
||||||
# Test if the API is available at this URL
|
# Test if the API is available at this URL
|
||||||
availabilityResponse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth")
|
authResponse=$(curl --connect-timeout 2 -skS -w "%{http_code}" "${API_URL}auth")
|
||||||
|
|
||||||
|
# authStatus are the last 3 characters
|
||||||
|
# not using ${authResponse#"${authResponse%???}"}" here because it's extremely slow on big responses
|
||||||
|
authStatus=$(printf "%s" "${authResponse}" | tail -c 3)
|
||||||
|
# data is everything from response without the last 3 characters
|
||||||
|
authData=$(printf %s "${authResponse%???}")
|
||||||
|
|
||||||
# Test if http status code was 200 (OK) or 401 (authentication required)
|
# Test if http status code was 200 (OK) or 401 (authentication required)
|
||||||
if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then
|
if [ ! "${authStatus}" = 200 ] && [ ! "${authStatus}" = 401 ]; then
|
||||||
# API is not available at this port/protocol combination
|
# API is not available at this port/protocol combination
|
||||||
API_PORT=""
|
API_PORT=""
|
||||||
else
|
else
|
||||||
# API is available at this URL combination
|
# API is available at this URL combination
|
||||||
|
|
||||||
if [ "${availabilityResponse}" = 200 ]; then
|
if [ "${authStatus}" = 200 ]; then
|
||||||
# API is available without authentication
|
# API is available without authentication
|
||||||
needAuth=false
|
needAuth=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if 2FA is required
|
||||||
|
needTOTP=$(echo "${authData}"| jq --raw-output .session.totp 2>/dev/null)
|
||||||
|
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -108,22 +117,51 @@ LoginAPI() {
|
||||||
echo "API Authentication: Trying to use CLI password"
|
echo "API Authentication: Trying to use CLI password"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Try to authenticate using the CLI password
|
# If we can read the CLI password, we can skip 2FA even when it's required otherwise
|
||||||
Authentication "${1}"
|
needTOTP=false
|
||||||
|
|
||||||
elif [ "${1}" = "verbose" ]; then
|
elif [ "${1}" = "verbose" ]; then
|
||||||
echo "API Authentication: CLI password not available"
|
echo "API Authentication: CLI password not available"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "${password}" ]; then
|
||||||
|
# no password read from CLI file
|
||||||
|
echo "Please enter your password:"
|
||||||
|
# secretly read the password
|
||||||
|
secretRead; printf '\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${needTOTP}" = true ]; then
|
||||||
|
# 2FA required
|
||||||
|
echo "Please enter the correct second factor."
|
||||||
|
echo "(Can be any number if you used the app password)"
|
||||||
|
read -r totp
|
||||||
|
fi
|
||||||
|
|
||||||
# If this did not work, ask the user for the password
|
# Try to authenticate using the supplied password (CLI file or user input) and TOTP
|
||||||
while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do
|
Authentication "${1}"
|
||||||
|
|
||||||
|
# Try to login again until the session is valid
|
||||||
|
while [ ! "${validSession}" = true ] ; do
|
||||||
echo "Authentication failed. Please enter your Pi-hole password"
|
echo "Authentication failed. Please enter your Pi-hole password"
|
||||||
|
|
||||||
|
# Print the error message if there is one
|
||||||
|
if [ ! "${sessionError}" = "null" ] && [ "${1}" = "verbose" ]; then
|
||||||
|
echo "Error: ${sessionError}"
|
||||||
|
fi
|
||||||
|
# Print the session message if there is one
|
||||||
|
if [ ! "${sessionMessage}" = "null" ] && [ "${1}" = "verbose" ]; then
|
||||||
|
echo "Error: ${sessionMessage}"
|
||||||
|
fi
|
||||||
|
|
||||||
# secretly read the password
|
# secretly read the password
|
||||||
secretRead; printf '\n'
|
secretRead; printf '\n'
|
||||||
|
|
||||||
|
if [ "${needTOTP}" = true ]; then
|
||||||
|
echo "Please enter the correct second factor:"
|
||||||
|
echo "(Can be any number if you used the app password)"
|
||||||
|
read -r totp
|
||||||
|
fi
|
||||||
|
|
||||||
# Try to authenticate again
|
# Try to authenticate again
|
||||||
Authentication "${1}"
|
Authentication "${1}"
|
||||||
done
|
done
|
||||||
|
@ -131,15 +169,19 @@ LoginAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication() {
|
Authentication() {
|
||||||
sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli " --data "{\"password\":\"${password}\"}" )"
|
sessionResponse="$(curl --connect-timeout 2 -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}" )"
|
||||||
|
|
||||||
if [ -z "${sessionResponse}" ]; then
|
if [ -z "${sessionResponse}" ]; then
|
||||||
echo "No response from FTL server. Please check connectivity"
|
echo "No response from FTL server. Please check connectivity"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# obtain validity and session ID from session response
|
# obtain validity, session ID and sessionMessage from session response
|
||||||
validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null)
|
validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null)
|
||||||
SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null)
|
SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null)
|
||||||
|
sessionMessage=$(echo "${sessionResponse}"| jq --raw-output .session.message 2>/dev/null)
|
||||||
|
|
||||||
|
# obtain the error message from the session response
|
||||||
|
sessionError=$(echo "${sessionResponse}"| jq --raw-output .error.message 2>/dev/null)
|
||||||
|
|
||||||
if [ "${1}" = "verbose" ]; then
|
if [ "${1}" = "verbose" ]; then
|
||||||
if [ "${validSession}" = true ]; then
|
if [ "${validSession}" = true ]; then
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue