-
-
-
-
-
-
- Network-wide ad blocking via your own Linux hardware
+
+
+ Network-wide ad blocking via your own Linux hardware
diff --git a/advanced/Scripts/COL_TABLE b/advanced/Scripts/COL_TABLE
index 4344c7b8..f9a014fc 100644
--- a/advanced/Scripts/COL_TABLE
+++ b/advanced/Scripts/COL_TABLE
@@ -1,5 +1,6 @@
+#!/usr/bin/env sh
# Determine if terminal is capable of showing colors
-if ([ -t 1 ] && [ $(tput colors) -ge 8 ]) || [ "${WEBCALL}" ]; then
+if [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; then
# Bold and underline may not show up on all clients
# If something MUST be emphasized, use both
COL_BOLD='[1m'
diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh
index b8c7fe99..79fc90f4 100755
--- a/advanced/Scripts/api.sh
+++ b/advanced/Scripts/api.sh
@@ -21,7 +21,7 @@
TestAPIAvailability() {
# 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
# The result is a space-separated enumeration of full URLs
@@ -49,20 +49,29 @@ TestAPIAvailability() {
API_URL="${API_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)
- if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then
+ if [ ! "${authStatus}" = 200 ] && [ ! "${authStatus}" = 401 ]; then
# API is not available at this port/protocol combination
API_PORT=""
else
# API is available at this URL combination
- if [ "${availabilityResponse}" = 200 ]; then
+ if [ "${authStatus}" = 200 ]; then
# API is available without authentication
needAuth=false
fi
+ # Check if 2FA is required
+ needTOTP=$(echo "${authData}"| jq --raw-output .session.totp 2>/dev/null)
+
break
fi
@@ -108,22 +117,51 @@ LoginAPI() {
echo "API Authentication: Trying to use CLI password"
fi
- # Try to authenticate using the CLI password
- Authentication "${1}"
-
+ # If we can read the CLI password, we can skip 2FA even when it's required otherwise
+ needTOTP=false
elif [ "${1}" = "verbose" ]; then
echo "API Authentication: CLI password not available"
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
- while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do
+ # Try to authenticate using the supplied password (CLI file or user input) and TOTP
+ Authentication "${1}"
+
+ # Try to login again until the session is valid
+ while [ ! "${validSession}" = true ] ; do
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
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
Authentication "${1}"
done
@@ -131,23 +169,27 @@ LoginAPI() {
}
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
- echo "No response from FTL server. Please check connectivity"
- exit 1
- fi
- # obtain validity and session ID from session response
- validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null)
- SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null)
-
- if [ "${1}" = "verbose" ]; then
- if [ "${validSession}" = true ]; then
- echo "API Authentication: ${COL_GREEN}Success${COL_NC}"
- else
- echo "API Authentication: ${COL_RED}Failed${COL_NC}"
+ if [ -z "${sessionResponse}" ]; then
+ echo "No response from FTL server. Please check connectivity"
+ exit 1
+ fi
+ # obtain validity, session ID and sessionMessage from session response
+ validSession=$(echo "${sessionResponse}"| jq .session.valid 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 [ "${validSession}" = true ]; then
+ echo "API Authentication: ${COL_GREEN}Success${COL_NC}"
+ else
+ echo "API Authentication: ${COL_RED}Failed${COL_NC}"
+ fi
fi
- fi
}
LogoutAPI() {
diff --git a/advanced/Scripts/version.sh b/advanced/Scripts/version.sh
index 2b0883af..540924c2 100755
--- a/advanced/Scripts/version.sh
+++ b/advanced/Scripts/version.sh
@@ -12,7 +12,7 @@
# shellcheck disable=SC3043
# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
-# Source the versions file poupulated by updatechecker.sh
+# Source the versions file populated by updatechecker.sh
cachedVersions="/etc/pihole/versions"
if [ -f ${cachedVersions} ]; then
diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh
index 49b0f0d4..37d750a2 100755
--- a/advanced/Templates/pihole-FTL-prestart.sh
+++ b/advanced/Templates/pihole-FTL-prestart.sh
@@ -11,7 +11,7 @@ FTL_PID_FILE="$(getFTLConfigValue files.pid)"
# Ensure that permissions are set so that pihole-FTL can edit all necessary files
mkdir -p /var/log/pihole
-chown -R pihole:pihole /etc/pihole /var/log/pihole
+chown -R pihole:pihole /etc/pihole/ /var/log/pihole/
# allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs)
find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} +
# Set all files (except TLS-related ones) to u+rw g+r
@@ -26,4 +26,5 @@ chown root:root /etc/pihole/logrotate
[ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}"
[ -f /var/log/pihole/FTL.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log
[ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log
+[ -f /var/log/pihole/webserver.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/webserver.log
[ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases
diff --git a/gravity.sh b/gravity.sh
index 3a7db5ae..493f2b15 100755
--- a/gravity.sh
+++ b/gravity.sh
@@ -541,16 +541,14 @@ gravity_DownloadBlocklists() {
# it (in case it doesn't exist)
# First, check if the directory is writable
directory="$(dirname -- "${saveLocation}")"
- directory_permissions=$(stat -c %a ${directory})
- if [ $directory_permissions -lt 700 ]; then
+ if [ ! -w "${directory}" ]; then
echo -e " ${CROSS} Unable to write to ${directory}"
echo " Please run pihole -g as root"
echo ""
continue
fi
# Then, check if the file is writable (if it exists)
- saveLocation_permissions=$(stat -c %a ${saveLocation})
- if [ -e "${saveLocation}" ] && [ ${saveLocation_permissions} -lt 600 ]; then
+ if [ -e "${saveLocation}" ] && [ ! -w "${saveLocation}" ]; then
echo -e " ${CROSS} Unable to write to ${saveLocation}"
echo " Please run pihole -g as root"
echo ""
diff --git a/test/requirements.txt b/test/requirements.txt
index 7b7e679f..fa536e25 100644
--- a/test/requirements.txt
+++ b/test/requirements.txt
@@ -1,6 +1,6 @@
pyyaml == 6.0.2
-pytest == 8.3.4
+pytest == 8.3.5
pytest-xdist == 3.6.1
pytest-testinfra == 10.1.1
-tox == 4.24.1
+tox == 4.25.0
pytest-clarity == 1.0.1