This commit is contained in:
Adam Warner 2023-01-15 20:02:04 +00:00 committed by GitHub
commit 9048429bbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 483 additions and 376 deletions

View file

@ -25,7 +25,7 @@ jobs:
steps: steps:
- -
name: Checkout repository name: Checkout repository
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- -
name: Initialize CodeQL name: Initialize CodeQL

View file

@ -18,4 +18,4 @@ jobs:
dirtyLabel: "PR: Merge Conflict" dirtyLabel: "PR: Merge Conflict"
repoToken: "${{ secrets.GITHUB_TOKEN }}" repoToken: "${{ secrets.GITHUB_TOKEN }}"
commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request." commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request."
commentOnClean: "Conflicts have been resolved. A maintainer will review the pull request shortly." commentOnClean: "Conflicts have been resolved."

View file

@ -13,7 +13,7 @@ jobs:
issues: write issues: write
steps: steps:
- uses: actions/stale@v6.0.1 - uses: actions/stale@v7.0.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30 days-before-stale: 30

View file

@ -11,7 +11,7 @@ jobs:
name: Syncing branches name: Syncing branches
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- name: Opening pull request - name: Opening pull request
run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal'
env: env:

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- name: Check scripts in repository are executable - name: Check scripts in repository are executable
run: | run: |
@ -57,18 +57,22 @@ jobs:
centos_9, centos_9,
fedora_35, fedora_35,
fedora_36, fedora_36,
fedora_37,
] ]
env: env:
DISTRO: ${{matrix.distro}} DISTRO: ${{matrix.distro}}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3.1.0 uses: actions/checkout@v3.3.0
- name: Set up Python 3.10 - name: Set up Python 3.10
uses: actions/setup-python@v4.3.0 uses: actions/setup-python@v4.5.0
with: with:
python-version: "3.10" python-version: "3.10"
- name: Install wheel
run: pip install wheel
- name: Install dependencies - name: Install dependencies
run: pip install -r test/requirements.txt run: pip install -r test/requirements.txt

View file

@ -394,41 +394,53 @@ os_check() {
# Extract dig response # Extract dig response
response="${cmdResult%%$'\n'*}" response="${cmdResult%%$'\n'*}"
IFS=" " read -r -a supportedOS < <(echo "${response}" | tr -d '"') if [ "${digReturnCode}" -ne 0 ]; then
for distro_and_versions in "${supportedOS[@]}" log_write "${INFO} Distro: ${detected_os^}"
do log_write "${INFO} Version: ${detected_version}"
distro_part="${distro_and_versions%%=*}" log_write "${CROSS} dig return code: ${COL_RED}${digReturnCode}${COL_NC}"
versions_part="${distro_and_versions##*=}" log_write "${CROSS} dig response: ${response}"
log_write "${CROSS} Error: ${COL_RED}dig command failed - Unable to check OS${COL_NC}"
if [[ "${detected_os^^}" =~ ${distro_part^^} ]]; then
valid_os=true
IFS="," read -r -a supportedVer <<<"${versions_part}"
for version in "${supportedVer[@]}"
do
if [[ "${detected_version}" =~ $version ]]; then
valid_version=true
break
fi
done
break
fi
done
log_write "${INFO} dig return code: ${digReturnCode}"
log_write "${INFO} dig response: ${response}"
if [ "$valid_os" = true ]; then
log_write "${TICK} Distro: ${COL_GREEN}${detected_os^}${COL_NC}"
if [ "$valid_version" = true ]; then
log_write "${TICK} Version: ${COL_GREEN}${detected_version}${COL_NC}"
else
log_write "${CROSS} Version: ${COL_RED}${detected_version}${COL_NC}"
log_write "${CROSS} Error: ${COL_RED}${detected_os^} is supported but version ${detected_version} is currently unsupported (${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}"
fi
else else
log_write "${CROSS} Distro: ${COL_RED}${detected_os^}${COL_NC}" IFS=" " read -r -a supportedOS < <(echo "${response}" | tr -d '"')
log_write "${CROSS} Error: ${COL_RED}${detected_os^} is not a supported distro (${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}" for distro_and_versions in "${supportedOS[@]}"
do
distro_part="${distro_and_versions%%=*}"
versions_part="${distro_and_versions##*=}"
if [[ "${detected_os^^}" =~ ${distro_part^^} ]]; then
valid_os=true
IFS="," read -r -a supportedVer <<<"${versions_part}"
for version in "${supportedVer[@]}"
do
if [[ "${detected_version}" =~ $version ]]; then
valid_version=true
break
fi
done
break
fi
done
local finalmsg
if [ "$valid_os" = true ]; then
log_write "${TICK} Distro: ${COL_GREEN}${detected_os^}${COL_NC}"
if [ "$valid_version" = true ]; then
log_write "${TICK} Version: ${COL_GREEN}${detected_version}${COL_NC}"
finalmsg="${TICK} ${COL_GREEN}Distro and version supported${COL_NC}"
else
log_write "${CROSS} Version: ${COL_RED}${detected_version}${COL_NC}"
finalmsg="${CROSS} Error: ${COL_RED}${detected_os^} is supported but version ${detected_version} is currently unsupported ${COL_NC}(${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}"
fi
else
log_write "${CROSS} Distro: ${COL_RED}${detected_os^}${COL_NC}"
finalmsg="${CROSS} Error: ${COL_RED}${detected_os^} is not a supported distro ${COL_NC}(${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}"
fi
# Print dig response and the final check result
log_write "${TICK} dig return code: ${COL_GREEN}${digReturnCode}${COL_NC}"
log_write "${INFO} dig response: ${response}"
log_write "${finalmsg}"
fi fi
} }

View file

@ -77,7 +77,7 @@ fi
# Strip valid options, leaving only the domain and invalid options # Strip valid options, leaving only the domain and invalid options
# This allows users to place the options before or after the domain # This allows users to place the options before or after the domain
options=$(sed -E 's/ ?-(adlists?|all|exact) ?//g' <<< "${options}") options=$(sed -E 's/ ?-(all|exact) ?//g' <<< "${options}")
# Handle remaining options # Handle remaining options
# If $options contain non ASCII characters, convert to punycode # If $options contain non ASCII characters, convert to punycode

View file

@ -0,0 +1,13 @@
#!/usr/bin/env sh
# Source utils.sh for getFTLPIDFile()
PI_HOLE_SCRIPT_DIR='/opt/pihole'
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090
. "${utilsfile}"
# Get file paths
FTL_PID_FILE="$(getFTLPIDFile)"
# Cleanup
rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}"

View file

@ -0,0 +1,38 @@
#!/usr/bin/env sh
# Source utils.sh for getFTLPIDFile()
PI_HOLE_SCRIPT_DIR='/opt/pihole'
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090
. "${utilsfile}"
# Get file paths
FTL_PID_FILE="$(getFTLPIDFile)"
# Touch files to ensure they exist (create if non-existing, preserve if existing)
# shellcheck disable=SC2174
mkdir -pm 0755 /run/pihole /var/log/pihole
[ -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 644 -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 /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases
# Ensure that permissions are set so that pihole-FTL can edit all necessary files
chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases
# Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist
chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole/FTL.log
chmod -f 0640 /var/log/pihole/pihole.log
# Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist
chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db
# Chmod database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist
chmod -f 0664 /etc/pihole/pihole-FTL.db
# Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole
# Should be removed with Pi-hole v6.0
if [ ! -f /var/log/pihole.log ]; then
ln -sf /var/log/pihole/pihole.log /var/log/pihole.log
chown -h pihole:pihole /var/log/pihole.log
fi
if [ ! -f /var/log/pihole-FTL.log ]; then
ln -sf /var/log/pihole/FTL.log /var/log/pihole-FTL.log
chown -h pihole:pihole /var/log/pihole-FTL.log
fi

View file

@ -9,9 +9,10 @@
# Description: Enable service provided by pihole-FTL daemon # Description: Enable service provided by pihole-FTL daemon
### END INIT INFO ### END INIT INFO
#source utils.sh for getFTLPIDFile(), getFTLPID () # Source utils.sh for getFTLPIDFile(), getFTLPID()
PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_SCRIPT_DIR="/opt/pihole"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090
. "${utilsfile}" . "${utilsfile}"
@ -28,33 +29,8 @@ start() {
if is_running; then if is_running; then
echo "pihole-FTL is already running" echo "pihole-FTL is already running"
else else
# Touch files to ensure they exist (create if non-existing, preserve if existing) # Run pre-start script, which pre-creates all expected files with correct permissions
mkdir -pm 0755 /run/pihole /var/log/pihole sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-prestart.sh"
[ ! -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 644 -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 /etc/pihole/dhcp.leases ] && install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases
# Ensure that permissions are set so that pihole-FTL can edit all necessary files
chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases
# Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist
chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole/FTL.log
chmod -f 0640 /var/log/pihole/pihole.log
# Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist
chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db
# Chown database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist
chmod -f 0664 /etc/pihole/pihole-FTL.db
# Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole/
# Should be removed with Pi-hole v6.0
if [ ! -f /var/log/pihole.log ]; then
ln -s /var/log/pihole/pihole.log /var/log/pihole.log
chown -h pihole:pihole /var/log/pihole.log
fi
if [ ! -f /var/log/pihole-FTL.log ]; then
ln -s /var/log/pihole/FTL.log /var/log/pihole-FTL.log
chown -h pihole:pihole /var/log/pihole-FTL.log
fi
if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip "/usr/bin/pihole-FTL"; then if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip "/usr/bin/pihole-FTL"; then
su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole || exit $? su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole || exit $?
@ -89,8 +65,8 @@ stop() {
else else
echo "Not running" echo "Not running"
fi fi
# Cleanup # Run post-stop script, which does cleanup among runtime files
rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}" sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-poststop.sh"
echo echo
} }
@ -108,11 +84,11 @@ status() {
### main logic ### ### main logic ###
# Get file paths # Get FTL's PID file path
FTL_PID_FILE="$(getFTLPIDFile)" FTL_PID_FILE="$(getFTLPIDFile)"
# Get FTL's current PID # Get FTL's current PID
FTL_PID="$(getFTLPID ${FTL_PID_FILE})" FTL_PID="$(getFTLPID "${FTL_PID_FILE}")"
case "$1" in case "$1" in
stop) stop)

View file

@ -0,0 +1,41 @@
[Unit]
Description=Pi-hole FTL
# This unit is supposed to indicate when network functionality is available, but it is only
# very weakly defined what that is supposed to mean, with one exception: at shutdown, a unit
# that is ordered after network-online.target will be stopped before the network
Wants=network-online.target
After=network-online.target
# A target that should be used as synchronization point for all host/network name service lookups.
# All services for which the availability of full host/network name resolution is essential should
# be ordered after this target, but not pull it in.
Wants=nss-lookup.target
Before=nss-lookup.target
# Limit (re)start loop to 5 within 1 minute
StartLimitBurst=5
StartLimitIntervalSec=60s
[Service]
User=pihole
PermissionsStartOnly=true
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_NICE CAP_IPC_LOCK CAP_CHOWN
ExecStartPre=/opt/pihole/pihole-FTL-prestart.sh
ExecStart=/usr/bin/pihole-FTL -f
Restart=on-failure
RestartSec=5s
ExecReload=/bin/kill -HUP $MAINPID
ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh
# Use graceful shutdown with a reasonable timeout
TimeoutStopSec=10s
# Make /usr, /boot, /etc and possibly some more folders read-only...
ProtectSystem=full
# ... except /etc/pihole
# This merely retains r/w access rights, it does not add any new.
# Must still be writable on the host!
ReadWriteDirectories=/etc/pihole
[Install]
WantedBy=multi-user.target

View file

@ -1,81 +0,0 @@
<?php
/* Pi-hole: A black hole for Internet advertisements
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
// Sanitize SERVER_NAME output
$serverName = htmlspecialchars($_SERVER["SERVER_NAME"]);
// Remove external ipv6 brackets if any
$serverName = preg_replace('/^\[(.*)\]$/', '${1}', $serverName);
// Set landing page location, found within /var/www/html/
$landPage = "../landing.php";
// Define array for hostnames to be accepted as self address for splash page
$authorizedHosts = [ "localhost" ];
if (!empty($_SERVER["FQDN"])) {
// If setenv.add-environment = ("fqdn" => "true") is configured in lighttpd,
// append $serverName to $authorizedHosts
array_push($authorizedHosts, $serverName);
} else if (!empty($_SERVER["VIRTUAL_HOST"])) {
// Append virtual hostname to $authorizedHosts
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
}
// Determine block page type
if ($serverName === "pi.hole"
|| (!empty($_SERVER["VIRTUAL_HOST"]) && $serverName === $_SERVER["VIRTUAL_HOST"])) {
// Redirect to Web Interface
header("Location: /admin");
exit();
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
// When directly browsing via IP or authorized hostname
// Render splash/landing page based off presence of $landPage file
// Unset variables so as to not be included in $landPage or $splashPage
unset($authorizedHosts);
// If $landPage file is present
if (is_file(getcwd()."/$landPage")) {
unset($serverName, $viewPort); // unset extra variables not to be included in $landpage
include $landPage;
exit();
}
// If $landPage file was not present, Set Splash Page output
$splashPage = <<<EOT
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<title> $serverName</title>
<link rel='shortcut icon' href='/admin/img/favicons/favicon.ico' type='image/x-icon'>
<style>
html, body { height: 100% }
body { margin: 0; font: 13pt "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; }
body { background: #222; color: rgba(255, 255, 255, 0.7); text-align: center; }
p { margin: 0; }
a { color: #3c8dbc; text-decoration: none; }
a:hover { color: #72afda; text-decoration: underline; }
#splashpage { display: flex; align-items: center; justify-content: center; }
#splashpage img { margin: 5px; width: 256px; }
#splashpage b { color: inherit; }
</style>
</head>
<body id='splashpage'>
<div>
<img src='/admin/img/logo.svg' alt='Pi-hole logo' width='256' height='377'>
<br>
<p>Pi-<strong>hole</strong>: Your black hole for Internet advertisements</p>
<a href='/admin'>Did you mean to go to the admin panel?</a>
</div>
</body>
</html>
EOT;
exit($splashPage);
}
header("HTTP/1.1 404 Not Found");
exit();
?>

View file

@ -26,7 +26,6 @@ server.modules = (
) )
server.document-root = "/var/www/html" server.document-root = "/var/www/html"
server.error-handler-404 = "/pihole/index.php"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error-pihole.log" server.errorlog = "/var/log/lighttpd/error-pihole.log"
server.pid-file = "/run/lighttpd.pid" server.pid-file = "/run/lighttpd.pid"
@ -67,48 +66,9 @@ mimetype.assign = (
".woff2" => "font/woff2" ".woff2" => "font/woff2"
) )
# Add user chosen options held in external file # Add user chosen options held in (optional) external file
# This uses include_shell instead of an include wildcard for compatibility include "external*.conf"
include_shell "cat external.conf 2>/dev/null"
# default listening port for IPv6 falls back to the IPv4 port # default listening port for IPv6 falls back to the IPv4 port
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
include "/etc/lighttpd/conf-enabled/*.conf"
# Prevent Lighttpd from enabling Let's Encrypt SSL for every blocked domain
#include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
include_shell "find /etc/lighttpd/conf-enabled -name '*.conf' -a ! -name 'letsencrypt.conf' -printf 'include \"%p\"\n' 2>/dev/null"
# If the URL starts with /admin, it is the Web interface
$HTTP["url"] =~ "^/admin/" {
# X-Pi-hole is a response header for debugging using curl -I
# X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >.
# X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input.
# X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code.
# Content-Security-Policy tells the browser where resources are allowed to be loaded and if its allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS).
# X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains.
# Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all.
setenv.add-response-header = (
"X-Pi-hole" => "The Pi-hole Web interface is working!",
"X-Frame-Options" => "DENY",
"X-XSS-Protection" => "1; mode=block",
"X-Content-Type-Options" => "nosniff",
"Content-Security-Policy" => "default-src 'self' 'unsafe-inline';",
"X-Permitted-Cross-Domain-Policies" => "none",
"Referrer-Policy" => "same-origin"
)
}
# Block . files from being served, such as .git, .github, .gitignore
$HTTP["url"] =~ "^/admin/\.(.*)" {
url.access-deny = ("")
}
# allow teleporter and API qr code iframe on settings page
$HTTP["url"] =~ "/(teleporter|api_token)\.php$" {
$HTTP["referer"] =~ "/admin/settings\.php" {
setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" )
}
}
# Default expire header
expire.url = ( "" => "access plus 0 seconds" )

View file

@ -27,7 +27,6 @@ server.modules = (
) )
server.document-root = "/var/www/html" server.document-root = "/var/www/html"
server.error-handler-404 = "/pihole/index.php"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error-pihole.log" server.errorlog = "/var/log/lighttpd/error-pihole.log"
server.pid-file = "/run/lighttpd.pid" server.pid-file = "/run/lighttpd.pid"
@ -68,9 +67,8 @@ mimetype.assign = (
".woff2" => "font/woff2" ".woff2" => "font/woff2"
) )
# Add user chosen options held in external file # Add user chosen options held in (optional) external file
# This uses include_shell instead of an include wildcard for compatibility include "external*.conf"
include_shell "cat external.conf 2>/dev/null"
# default listening port for IPv6 falls back to the IPv4 port # default listening port for IPv6 falls back to the IPv4 port
#include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port #include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
@ -86,37 +84,4 @@ fastcgi.server = (
) )
) )
# If the URL starts with /admin, it is the Web interface include "/etc/lighttpd/conf.d/pihole-admin.conf"
$HTTP["url"] =~ "^/admin/" {
# X-Pi-hole is a response header for debugging using curl -I
# X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >.
# X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input.
# X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code.
# Content-Security-Policy tells the browser where resources are allowed to be loaded and if its allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS).
# X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains.
# Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all.
setenv.add-response-header = (
"X-Pi-hole" => "The Pi-hole Web interface is working!",
"X-Frame-Options" => "DENY",
"X-XSS-Protection" => "1; mode=block",
"X-Content-Type-Options" => "nosniff",
"Content-Security-Policy" => "default-src 'self' 'unsafe-inline';",
"X-Permitted-Cross-Domain-Policies" => "none",
"Referrer-Policy" => "same-origin"
)
}
# Block . files from being served, such as .git, .github, .gitignore
$HTTP["url"] =~ "^/admin/\.(.*)" {
url.access-deny = ("")
}
# allow teleporter and API qr code iframe on settings page
$HTTP["url"] =~ "/(teleporter|api_token)\.php$" {
$HTTP["referer"] =~ "/admin/settings\.php" {
setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" )
}
}
# Default expire header
expire.url = ( "" => "access plus 0 seconds" )

View file

@ -0,0 +1,82 @@
# Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# Lighttpd config for Pi-hole
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
###############################################################################
# FILE AUTOMATICALLY OVERWRITTEN BY PI-HOLE INSTALL/UPDATE PROCEDURE. #
# ANY CHANGES MADE TO THIS FILE AFTER INSTALL WILL BE LOST ON THE NEXT UPDATE #
###############################################################################
server.errorlog := "/var/log/lighttpd/error-pihole.log"
$HTTP["url"] =~ "^/admin/" {
server.document-root = "/var/www/html"
server.stream-response-body = 1
accesslog.filename = "/var/log/lighttpd/access-pihole.log"
accesslog.format = "%{%s}t|%h|%V|%r|%s|%b"
fastcgi.server = (
".php" => (
"localhost" => (
"socket" => "/tmp/pihole-php-fastcgi.socket",
"bin-path" => "/usr/bin/php-cgi",
"min-procs" => 0,
"max-procs" => 1,
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "4",
"PHP_FCGI_MAX_REQUESTS" => "10000",
),
"bin-copy-environment" => (
"PATH", "SHELL", "USER"
),
"broken-scriptfilename" => "enable",
)
)
)
# X-Pi-hole is a response header for debugging using curl -I
# X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >.
# X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input. (deprecated; disabled)
# X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code.
# Content-Security-Policy tells the browser where resources are allowed to be loaded and if its allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS).
# X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains.
# Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all.
setenv.add-response-header = (
"X-Pi-hole" => "The Pi-hole Web interface is working!",
"X-Frame-Options" => "DENY",
"X-XSS-Protection" => "0",
"X-Content-Type-Options" => "nosniff",
"Content-Security-Policy" => "default-src 'self' 'unsafe-inline';",
"X-Permitted-Cross-Domain-Policies" => "none",
"Referrer-Policy" => "same-origin"
)
# Block . files from being served, such as .git, .github, .gitignore
$HTTP["url"] =~ "^/admin/\." {
url.access-deny = ("")
}
# allow teleporter and API qr code iframe on settings page
$HTTP["url"] =~ "/(teleporter|api_token)\.php$" {
$HTTP["referer"] =~ "/admin/settings\.php" {
setenv.set-response-header = ( "X-Frame-Options" => "SAMEORIGIN" )
}
}
}
else $HTTP["url"] == "/admin" {
url.redirect = ("" => "/admin/")
}
$HTTP["host"] == "pi.hole" {
$HTTP["url"] == "/" {
url.redirect = ("" => "/admin/")
}
}
# (keep this on one line for basic-install.sh filtering during install)
server.modules += ( "mod_access", "mod_redirect", "mod_fastcgi", "mod_setenv" )

View file

@ -82,7 +82,6 @@ PI_HOLE_FILES=(chronometer list piholeDebug piholeLogFlush setupLCD update versi
PI_HOLE_INSTALL_DIR="/opt/pihole" PI_HOLE_INSTALL_DIR="/opt/pihole"
PI_HOLE_CONFIG_DIR="/etc/pihole" PI_HOLE_CONFIG_DIR="/etc/pihole"
PI_HOLE_BIN_DIR="/usr/local/bin" PI_HOLE_BIN_DIR="/usr/local/bin"
PI_HOLE_404_DIR="${webroot}/pihole"
FTL_CONFIG_FILE="${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" FTL_CONFIG_FILE="${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf"
if [ -z "$useUpdateVars" ]; then if [ -z "$useUpdateVars" ]; then
useUpdateVars=false useUpdateVars=false
@ -1380,37 +1379,80 @@ installConfigs() {
fi fi
fi fi
# Install pihole-FTL.service # Install pihole-FTL systemd or init.d service, based on whether systemd is the init system or not
install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" "/etc/init.d/pihole-FTL" # Follow debhelper logic, which checks for /run/systemd/system to derive whether systemd is the init system
if [[ -d '/run/systemd/system' ]]; then
install -T -m 0644 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.systemd" '/etc/systemd/system/pihole-FTL.service'
# Remove init.d service if present
if [[ -e '/etc/init.d/pihole-FTL' ]]; then
rm '/etc/init.d/pihole-FTL'
update-rc.d pihole-FTL remove
fi
# Load final service
systemctl daemon-reload
else
install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" '/etc/init.d/pihole-FTL'
fi
install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL-prestart.sh" "${PI_HOLE_INSTALL_DIR}/pihole-FTL-prestart.sh"
install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL-poststop.sh" "${PI_HOLE_INSTALL_DIR}/pihole-FTL-poststop.sh"
# If the user chose to install the dashboard, # If the user chose to install the dashboard,
if [[ "${INSTALL_WEB_SERVER}" == true ]]; then if [[ "${INSTALL_WEB_SERVER}" == true ]]; then
# and if the Web server conf directory does not exist, if grep -q -F "FILE AUTOMATICALLY OVERWRITTEN BY PI-HOLE" "${lighttpdConfig}"; then
if [[ ! -d "/etc/lighttpd" ]]; then # Attempt to preserve backwards compatibility with older versions
# make it and set the owners install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} "${lighttpdConfig}"
install -d -m 755 -o "${USER}" -g root /etc/lighttpd # Make the directories if they do not exist and set the owners
# Otherwise, if the config file already exists mkdir -p /run/lighttpd
elif [[ -f "${lighttpdConfig}" ]]; then chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /run/lighttpd
# back up the original mkdir -p /var/cache/lighttpd/compress
mv "${lighttpdConfig}"{,.orig} chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/cache/lighttpd/compress
mkdir -p /var/cache/lighttpd/uploads
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/cache/lighttpd/uploads
fi fi
# and copy in the config file Pi-hole needs # Copy the config file to include for pihole admin interface
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} "${lighttpdConfig}" if [[ -d "/etc/lighttpd/conf.d" ]]; then
# Make sure the external.conf file exists, as lighttpd v1.4.50 crashes without it install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/pihole-admin.conf /etc/lighttpd/conf.d/pihole-admin.conf
if [ ! -f /etc/lighttpd/external.conf ]; then if grep -q -F 'include "/etc/lighttpd/conf.d/pihole-admin.conf"' "${lighttpdConfig}"; then
install -m 644 /dev/null /etc/lighttpd/external.conf :
else
echo 'include "/etc/lighttpd/conf.d/pihole-admin.conf"' >> "${lighttpdConfig}"
fi
# Avoid some warnings trace from lighttpd, which might break tests
conf=/etc/lighttpd/conf.d/pihole-admin.conf
if lighttpd -f "${lighttpdConfig}" -tt 2>&1 | grep -q -F "WARNING: unknown config-key: dir-listing\."; then
echo '# Avoid some warnings trace from lighttpd, which might break tests' >> $conf
echo 'server.modules += ( "mod_dirlisting" )' >> $conf
fi
if lighttpd -f "${lighttpdConfig}" -tt 2>&1 | grep -q -F "warning: please use server.use-ipv6"; then
echo '# Avoid some warnings trace from lighttpd, which might break tests' >> $conf
echo 'server.use-ipv6 := "disable"' >> $conf
fi
elif [[ -d "/etc/lighttpd/conf-available" ]]; then
conf=/etc/lighttpd/conf-available/15-pihole-admin.conf
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/pihole-admin.conf $conf
# disable server.modules += ( ... ) in $conf to avoid module dups
# (needed until Debian 10 no longer supported by pi-hole)
# (server.modules duplication is ignored in lighttpd 1.4.56+)
if awk '!/^server\.modules/{print}' $conf > $conf.$$ && mv $conf.$$ $conf; then
:
else
rm $conf.$$
fi
chmod 644 $conf
if is_command lighty-enable-mod ; then
lighty-enable-mod pihole-admin access redirect fastcgi setenv > /dev/null || true
else
# Otherwise, show info about installing them
printf " %b Warning: 'lighty-enable-mod' utility not found\\n" "${INFO}"
printf " Please ensure fastcgi is enabled if you experience issues\\n"
fi
else
# lighttpd config include dir not found
printf " %b Warning: lighttpd config include dir not found\\n" "${INFO}"
printf " Please manually install pihole-admin.conf\\n"
fi fi
# If there is a custom block page in the html/pihole directory, replace 404 handler in lighttpd config
if [[ -f "${PI_HOLE_404_DIR}/custom.php" ]]; then
sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"\/pihole\/custom\.php"/' "${lighttpdConfig}"
fi
# Make the directories if they do not exist and set the owners
mkdir -p /run/lighttpd
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /run/lighttpd
mkdir -p /var/cache/lighttpd/compress
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/cache/lighttpd/compress
mkdir -p /var/cache/lighttpd/uploads
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/cache/lighttpd/uploads
fi fi
} }
@ -1661,30 +1703,6 @@ install_dependent_packages() {
# Install the Web interface dashboard # Install the Web interface dashboard
installPiholeWeb() { installPiholeWeb() {
printf "\\n %b Installing 404 page...\\n" "${INFO}"
local str="Creating directory for 404 page, and copying files"
printf " %b %s..." "${INFO}" "${str}"
# Install the directory
install -d -m 0755 ${PI_HOLE_404_DIR}
# and the 404 handler
install -D -m 644 ${PI_HOLE_LOCAL_REPO}/advanced/index.php ${PI_HOLE_404_DIR}/
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
local str="Backing up index.lighttpd.html"
printf " %b %s..." "${INFO}" "${str}"
# If the default index file exists,
if [[ -f "${webroot}/index.lighttpd.html" ]]; then
# back it up
mv ${webroot}/index.lighttpd.html ${webroot}/index.lighttpd.orig
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
else
# Otherwise, don't do anything
printf "%b %b %s\\n" "${OVER}" "${INFO}" "${str}"
printf " No default index.lighttpd.html file found... not backing up\\n"
fi
# Install Sudoers file # Install Sudoers file
local str="Installing sudoer file" local str="Installing sudoer file"
printf "\\n %b %s..." "${INFO}" "${str}" printf "\\n %b %s..." "${INFO}" "${str}"
@ -1760,20 +1778,35 @@ create_pihole_user() {
else else
# If the pihole user doesn't exist, # If the pihole user doesn't exist,
printf "%b %b %s" "${OVER}" "${CROSS}" "${str}" printf "%b %b %s" "${OVER}" "${CROSS}" "${str}"
local str="Creating user 'pihole'" local str="Checking for group 'pihole'"
printf "%b %b %s..." "${OVER}" "${INFO}" "${str}" printf " %b %s..." "${INFO}" "${str}"
# create her with the useradd command,
if getent group pihole > /dev/null 2>&1; then if getent group pihole > /dev/null 2>&1; then
# then add her to the pihole group (as it already exists) # group pihole exists
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# then create and add her to the pihole group
local str="Creating user 'pihole'"
printf "%b %b %s..." "${OVER}" "${INFO}" "${str}"
if useradd -r --no-user-group -g pihole -s /usr/sbin/nologin pihole; then if useradd -r --no-user-group -g pihole -s /usr/sbin/nologin pihole; then
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
else else
printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
fi fi
else else
# add user pihole with default group settings # group pihole does not exist
if useradd -r -s /usr/sbin/nologin pihole; then printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
local str="Creating group 'pihole'"
# if group can be created
if groupadd pihole; then
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# create and add pihole user to the pihole group
local str="Creating user 'pihole'"
printf "%b %b %s..." "${OVER}" "${INFO}" "${str}"
if useradd -r --no-user-group -g pihole -s /usr/sbin/nologin pihole; then
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
else
printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
fi
else else
printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
fi fi
@ -1872,15 +1905,6 @@ installPihole() {
# Give lighttpd access to the pihole group so the web interface can # Give lighttpd access to the pihole group so the web interface can
# manage the gravity.db database # manage the gravity.db database
usermod -a -G pihole ${LIGHTTPD_USER} usermod -a -G pihole ${LIGHTTPD_USER}
# If the lighttpd command is executable,
if is_command lighty-enable-mod ; then
# enable fastcgi and fastcgi-php
lighty-enable-mod fastcgi fastcgi-php > /dev/null || true
else
# Otherwise, show info about installing them
printf " %b Warning: 'lighty-enable-mod' utility not found\\n" "${INFO}"
printf " Please ensure fastcgi is enabled if you experience issues\\n"
fi
fi fi
fi fi
# Install base files and web interface # Install base files and web interface
@ -2693,12 +2717,12 @@ main() {
restart_service pihole-FTL restart_service pihole-FTL
# Download and compile the aggregated block list
runGravity
# Update local and remote versions via updatechecker # Update local and remote versions via updatechecker
/opt/pihole/updatecheck.sh /opt/pihole/updatecheck.sh
# Download and compile the aggregated block list
runGravity
if [[ "${useUpdateVars}" == false ]]; then if [[ "${useUpdateVars}" == false ]]; then
displayFinalMessage "${pw}" displayFinalMessage "${pw}"
fi fi

View file

@ -131,6 +131,7 @@ removeNoPurge() {
fi fi
if package_check lighttpd > /dev/null; then if package_check lighttpd > /dev/null; then
# Attempt to preserve backwards compatibility with older versions
if [[ -f /etc/lighttpd/lighttpd.conf.orig ]]; then if [[ -f /etc/lighttpd/lighttpd.conf.orig ]]; then
${SUDO} mv /etc/lighttpd/lighttpd.conf.orig /etc/lighttpd/lighttpd.conf ${SUDO} mv /etc/lighttpd/lighttpd.conf.orig /etc/lighttpd/lighttpd.conf
fi fi
@ -139,6 +140,29 @@ removeNoPurge() {
${SUDO} rm /etc/lighttpd/external.conf ${SUDO} rm /etc/lighttpd/external.conf
fi fi
# Fedora-based
if [[ -f /etc/lighttpd/conf.d/pihole-admin.conf ]]; then
${SUDO} rm /etc/lighttpd/conf.d/pihole-admin.conf
conf=/etc/lighttpd/lighttpd.conf
tconf=/tmp/lighttpd.conf.$$
if awk '!/^include "\/etc\/lighttpd\/conf\.d\/pihole-admin\.conf"$/{print}' \
$conf > $tconf && mv $tconf $conf; then
:
else
rm $tconf
fi
${SUDO} chown root:root $conf
${SUDO} chmod 644 $conf
fi
# Debian-based
if [[ -f /etc/lighttpd/conf-available/pihole-admin.conf ]]; then
if is_command lighty-disable-mod ; then
${SUDO} lighty-disable-mod pihole-admin > /dev/null || true
fi
${SUDO} rm /etc/lighttpd/conf-available/15-pihole-admin.conf
fi
echo -e " ${TICK} Removed lighttpd configs" echo -e " ${TICK} Removed lighttpd configs"
fi fi

View file

@ -524,15 +524,20 @@ num_target_lines=0
num_source_lines=0 num_source_lines=0
num_invalid=0 num_invalid=0
parseList() { parseList() {
local adlistID="${1}" src="${2}" target="${3}" incorrect_lines local adlistID="${1}" src="${2}" target="${3}" incorrect_lines sample_incorrect_lines
# This sed does the following things: # This sed does the following things:
# 1. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_) # 1. Remove all lines containing no domains
# 2. Append ,adlistID to every line # 2. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_)
# 3. Remove trailing period (see https://github.com/pi-hole/pi-hole/issues/4701) # 3. Append ,adlistID to every line
# 4. Ensures there is a newline on the last line # 4. Remove trailing period (see https://github.com/pi-hole/pi-hole/issues/4701)
sed -e "/[^a-zA-Z0-9.\_-]/d;s/\.$//;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}" # 5. Ensures there is a newline on the last line
# Find (up to) five domains containing invalid characters (see above) sed -r "/([^\.]+\.)+[^\.]{2,}/!d;/[^a-zA-Z0-9.\_-]/d;s/\.$//;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}"
incorrect_lines="$(sed -e "/[^a-zA-Z0-9.\_-]/!d" "${src}" | head -n 5)"
# Find lines containing no domains or with invalid characters (see above)
# Remove duplicates and limit to 5 domains
mapfile -t incorrect_lines <<< "$(sed -r "/([^\.]+\.)+[^\.]{2,}/d" < "${src}")"
mapfile -t -O "${#incorrect_lines[@]}" incorrect_lines <<< "$(sed -r "/[^a-zA-Z0-9.\_-]/!d" < "${src}")"
IFS=" " read -r -a sample_incorrect_lines <<< "$(tr ' ' '\n' <<< "${incorrect_lines[@]}" | sort -u | head -n 5| tr '\n' ' ')"
local num_target_lines_new num_correct_lines local num_target_lines_new num_correct_lines
# Get number of lines in source file # Get number of lines in source file
@ -551,11 +556,12 @@ parseList() {
fi fi
# Display sample of invalid lines if we found some # Display sample of invalid lines if we found some
if [[ -n "${incorrect_lines}" ]]; then if [ ${#sample_incorrect_lines[@]} -ne 0 ]; then
echo " Sample of invalid domains:" echo " Sample of invalid domains:"
while IFS= read -r line; do for each in "${sample_incorrect_lines[@]}"
echo " - ${line}" do
done <<< "${incorrect_lines}" echo " - ${each}"
done
fi fi
} }
compareLists() { compareLists() {
@ -731,13 +737,13 @@ gravity_ParseFileIntoDomains() {
# 3) Remove comments (text starting with "#", include possible spaces before the hash sign) # 3) Remove comments (text starting with "#", include possible spaces before the hash sign)
# 4) Remove lines containing "/" # 4) Remove lines containing "/"
# 5) Remove leading tabs, spaces, etc. # 5) Remove leading tabs, spaces, etc.
# 6) Delete lines not matching domain names # 6) Remove empty lines
< "${src}" tr -d '\r' | \ < "${src}" tr -d '\r' | \
tr '[:upper:]' '[:lower:]' | \ tr '[:upper:]' '[:lower:]' | \
sed 's/\s*#.*//g' | \ sed 's/\s*#.*//g' | \
sed -r '/(\/).*$/d' | \ sed -r '/(\/).*$/d' | \
sed -r 's/^.*\s+//g' | \ sed -r 's/^.*\s+//g' | \
sed -r '/([^\.]+\.)+[^\.]{2,}/!d' > "${destination}" sed '/^$/d'> "${destination}"
chmod 644 "${destination}" chmod 644 "${destination}"
} }

View file

@ -23,7 +23,7 @@ Pi-hole : A black-hole for internet advertisements
.br .br
pihole -r pihole -r
.br .br
pihole -t \fBpihole\fR \fB-t\fR [arg]
.br .br
pihole -g\fR pihole -g\fR
.br .br
@ -113,11 +113,15 @@ Available commands and options:
Reconfigure or Repair Pi-hole subsystems Reconfigure or Repair Pi-hole subsystems
.br .br
\fB-t, tail\fR \fB-t, tail\fR [arg]
.br .br
View the live output of the Pi-hole log View the live output of the Pi-hole log
.br .br
[arg] Optional argument to filter the log for
(regular expressions are supported)
.br
\fB-a, admin\fR [options] \fB-a, admin\fR [options]
.br .br

34
pihole
View file

@ -23,6 +23,9 @@ source "${colfile}"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
source "${utilsfile}" source "${utilsfile}"
versionsfile="/etc/pihole/versions"
source "${versionsfile}"
webpageFunc() { webpageFunc() {
source "${PI_HOLE_SCRIPT_DIR}/webpage.sh" source "${PI_HOLE_SCRIPT_DIR}/webpage.sh"
main "$@" main "$@"
@ -63,14 +66,22 @@ arpFunc() {
} }
updatePiholeFunc() { updatePiholeFunc() {
shift if [ -n "${DOCKER_VERSION}" ]; then
"${PI_HOLE_SCRIPT_DIR}"/update.sh "$@" unsupportedFunc
exit 0 else
shift
"${PI_HOLE_SCRIPT_DIR}"/update.sh "$@"
exit 0
fi
} }
reconfigurePiholeFunc() { reconfigurePiholeFunc() {
/etc/.pihole/automated\ install/basic-install.sh --reconfigure if [ -n "${DOCKER_VERSION}" ]; then
exit 0; unsupportedFunc
else
/etc/.pihole/automated\ install/basic-install.sh --reconfigure
exit 0;
fi
} }
updateGravityFunc() { updateGravityFunc() {
@ -91,8 +102,12 @@ chronometerFunc() {
uninstallFunc() { uninstallFunc() {
"${PI_HOLE_SCRIPT_DIR}"/uninstall.sh if [ -n "${DOCKER_VERSION}" ]; then
exit 0 unsupportedFunc
else
"${PI_HOLE_SCRIPT_DIR}"/uninstall.sh
exit 0
fi
} }
versionFunc() { versionFunc() {
@ -429,6 +444,11 @@ updateCheckFunc() {
exit 0 exit 0
} }
unsupportedFunc(){
echo "Function not supported in Docker images"
exit 0
}
helpFunc() { helpFunc() {
echo "Usage: pihole [options] echo "Usage: pihole [options]
Example: 'pihole -w -h' Example: 'pihole -w -h'

View file

@ -0,0 +1,18 @@
FROM fedora:37
RUN dnf install -y git initscripts
ENV GITDIR /etc/.pihole
ENV SCRIPTDIR /opt/pihole
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
ADD . $GITDIR
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
RUN true && \
chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL true
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View file

@ -1,5 +1,6 @@
docker-compose docker-compose == 1.29.2
pytest pytest == 7.2.1
pytest-xdist pytest-xdist == 3.1.0
pytest-testinfra pytest-testinfra == 7.0.0
tox tox == 4.2.8

View file

@ -129,34 +129,16 @@ def test_installPiholeWeb_fresh_install_no_errors(host):
installPiholeWeb installPiholeWeb
""" """
) )
expected_stdout = info_box + " Installing 404 page..."
assert expected_stdout in installWeb.stdout
expected_stdout = tick_box + (
" Creating directory for 404 page, " "and copying files"
)
assert expected_stdout in installWeb.stdout
expected_stdout = info_box + " Backing up index.lighttpd.html"
assert expected_stdout in installWeb.stdout
expected_stdout = "No default index.lighttpd.html file found... " "not backing up"
assert expected_stdout in installWeb.stdout
expected_stdout = tick_box + " Installing sudoer file" expected_stdout = tick_box + " Installing sudoer file"
assert expected_stdout in installWeb.stdout assert expected_stdout in installWeb.stdout
web_directory = host.run("ls -r /var/www/html/pihole").stdout
assert "index.php" in web_directory
def get_directories_recursive(host, directory): def get_directories_recursive(host, directory):
if directory is None: if directory is None:
return directory return directory
ls = host.run("ls -d {}".format(directory + "/*/")) # returns all non-hidden subdirs of 'directory'
directories = list(filter(bool, ls.stdout.splitlines())) dirs_raw = host.run("find {} -type d -not -path '*/.*'".format(directory))
dirs = directories dirs = list(filter(bool, dirs_raw.stdout.splitlines()))
for dirval in directories:
dir_rec = get_directories_recursive(host, dirval)
if isinstance(dir_rec, str):
dirs.extend([dir_rec])
else:
dirs.extend(dir_rec)
return dirs return dirs
@ -211,6 +193,8 @@ def test_installPihole_fresh_install_readableFiles(host):
maninstalled = True maninstalled = True
if (info_box + " man not installed") in install.stdout: if (info_box + " man not installed") in install.stdout:
maninstalled = False maninstalled = False
if (info_box + " man pages not installed") in install.stdout:
maninstalled = False
piholeuser = "pihole" piholeuser = "pihole"
exit_status_success = 0 exit_status_success = 0
test_cmd = 'su --shell /bin/bash --command "test -{0} {1}" -p {2}' test_cmd = 'su --shell /bin/bash --command "test -{0} {1}" -p {2}'
@ -287,6 +271,24 @@ def test_installPihole_fresh_install_readableFiles(host):
check_lighttpd = test_cmd.format("r", "/etc/lighttpd/lighttpd.conf", piholeuser) check_lighttpd = test_cmd.format("r", "/etc/lighttpd/lighttpd.conf", piholeuser)
actual_rc = host.run(check_lighttpd).rc actual_rc = host.run(check_lighttpd).rc
assert exit_status_success == actual_rc assert exit_status_success == actual_rc
# check readable /etc/lighttpd/conf*/pihole-admin.conf
check_lighttpd = test_cmd.format("r", "/etc/lighttpd/conf.d", piholeuser)
if host.run(check_lighttpd).rc == exit_status_success:
check_lighttpd = test_cmd.format(
"r", "/etc/lighttpd/conf.d/pihole-admin.conf", piholeuser
)
actual_rc = host.run(check_lighttpd).rc
assert exit_status_success == actual_rc
else:
check_lighttpd = test_cmd.format(
"r", "/etc/lighttpd/conf-available", piholeuser
)
if host.run(check_lighttpd).rc == exit_status_success:
check_lighttpd = test_cmd.format(
"r", "/etc/lighttpd/conf-available/15-pihole-admin.conf", piholeuser
)
actual_rc = host.run(check_lighttpd).rc
assert exit_status_success == actual_rc
# check readable and executable manpages # check readable and executable manpages
if maninstalled is True: if maninstalled is True:
check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser) check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser)
@ -396,7 +398,7 @@ def test_installPihole_fresh_install_readableBlockpage(host, test_webpage):
usergroup="${{LIGHTTPD_USER}}:${{LIGHTTPD_GROUP}}", usergroup="${{LIGHTTPD_USER}}:${{LIGHTTPD_GROUP}}",
chmodarg="{{}}", chmodarg="{{}}",
config="/etc/lighttpd/lighttpd.conf", config="/etc/lighttpd/lighttpd.conf",
run="/var/run/lighttpd", run="/run/lighttpd",
cache="/var/cache/lighttpd", cache="/var/cache/lighttpd",
uploads="/var/cache/lighttpd/uploads", uploads="/var/cache/lighttpd/uploads",
compress="/var/cache/lighttpd/compress", compress="/var/cache/lighttpd/compress",
@ -512,7 +514,7 @@ def test_installPihole_fresh_install_readableBlockpage(host, test_webpage):
check_admin = test_cmd.format("x", webroot + "/admin", webuser) check_admin = test_cmd.format("x", webroot + "/admin", webuser)
actual_rc = host.run(check_admin).rc actual_rc = host.run(check_admin).rc
assert exit_status_success == actual_rc assert exit_status_success == actual_rc
directories = get_directories_recursive(host, webroot + "/admin/*/") directories = get_directories_recursive(host, webroot + "/admin/")
for directory in directories: for directory in directories:
check_pihole = test_cmd.format("r", directory, webuser) check_pihole = test_cmd.format("r", directory, webuser)
actual_rc = host.run(check_pihole).rc actual_rc = host.run(check_pihole).rc
@ -536,16 +538,6 @@ def test_installPihole_fresh_install_readableBlockpage(host, test_webpage):
return bool(m) return bool(m)
if installWebInterface is True: if installWebInterface is True:
check_pihole = test_cmd.format("r", webroot + "/pihole", webuser)
actual_rc = host.run(check_pihole).rc
assert exit_status_success == actual_rc
check_pihole = test_cmd.format("x", webroot + "/pihole", webuser)
actual_rc = host.run(check_pihole).rc
assert exit_status_success == actual_rc
# check most important files in $webroot for read permission
check_index = test_cmd.format("r", webroot + "/pihole/index.php", webuser)
actual_rc = host.run(check_index).rc
assert exit_status_success == actual_rc
if test_webpage is True: if test_webpage is True:
# check webpage for unreadable files # check webpage for unreadable files
noPHPfopen = re.compile( noPHPfopen = re.compile(

View file

@ -1,8 +1,8 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _centos_8.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _centos_8.Dockerfile -t pytest_pihole:test_container ../
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _centos_9.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _centos_9.Dockerfile -t pytest_pihole:test_container ../

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _debian_10.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _debian_10.Dockerfile -t pytest_pihole:test_container ../

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _debian_11.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _debian_11.Dockerfile -t pytest_pihole:test_container ../

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _fedora_35.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _fedora_35.Dockerfile -t pytest_pihole:test_container ../

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _fedora_36.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _fedora_36.Dockerfile -t pytest_pihole:test_container ../

8
test/tox.fedora_37.ini Normal file
View file

@ -0,0 +1,8 @@
[tox]
envlist = py3
[testenv]
allowlist_externals = docker
deps = -rrequirements.txt
commands = docker build -f _fedora_37.Dockerfile -t pytest_pihole:test_container ../
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../

View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = py3 envlist = py3
[testenv] [testenv:py3]
allowlist_externals = docker allowlist_externals = docker
deps = -rrequirements.txt deps = -rrequirements.txt
commands = docker build -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../ commands = docker build -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../