From 9a68adf36f0fdbe260111f473384d53d68a5eff8 Mon Sep 17 00:00:00 2001 From: ryt51V Date: Wed, 2 Mar 2016 20:49:23 +0000 Subject: [PATCH] Big sudo refactor. In general: - Each script reruns itself as either root or pihole. Any $SUDO variables are removed. - Two new scripts are created that need to be run as root. - The installer creates a file in sudoers.d that allows the pihole user to run the above two scripts as root. piholeReloadServices.sh: Script to reload dnsmasq (or start it if required). piholeSetPermissions.sh: Script to set the permissions on /etc/pihole basic-install.sh: - Copy two new scripts. - Set owner and permissions on /etc/pihole - Install the sudoers file to allow the pihole user to run certain scripts as root without a password. uninstall.sh: - Remote two new scripts. - Remove sudoers file gravity.sh: - Rerun as pihole user. - Use sudo for setting permissions and reloading services. - Replaced chmod 777 with piholeSetPermissions.sh. blacklist.sh, whitelist.sh: Rerun as pihole user. Use sudo for reloading services. chronometer.sh, piholeLogFlush.sh: Rerun as pihole user. setupLCD.sh: Rerun as root. --- advanced/Scripts/blacklist.sh | 37 ++++++++++---- advanced/Scripts/chronometer.sh | 22 +++++++++ advanced/Scripts/piholeLogFlush.sh | 23 +++++++++ advanced/Scripts/piholeReloadServices.sh | 60 ++++++++++++++++++++++ advanced/Scripts/piholeSetPermissions.sh | 36 ++++++++++++++ advanced/Scripts/setupLCD.sh | 52 +++++++++++++------ advanced/Scripts/whitelist.sh | 35 ++++++++++--- automated install/basic-install.sh | 24 ++++++++- automated install/uninstall.sh | 3 ++ gravity.sh | 63 +++++++++++++----------- 10 files changed, 291 insertions(+), 64 deletions(-) create mode 100644 advanced/Scripts/piholeReloadServices.sh create mode 100644 advanced/Scripts/piholeSetPermissions.sh diff --git a/advanced/Scripts/blacklist.sh b/advanced/Scripts/blacklist.sh index 70b8131a..7f3684d0 100644 --- a/advanced/Scripts/blacklist.sh +++ b/advanced/Scripts/blacklist.sh @@ -23,6 +23,29 @@ if [[ $# = 0 ]]; then exit 1 fi +# Check if pihole user, and if not then rerun with sudo. +echo ":::" +runninguser=$(whoami) +if [[ "$runninguser" = "pihole" ]];then + echo "::: You are pihole user." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo -u pihole $@" + sudo -u pihole "$@" + exit $? + else + echo "::: Please install sudo." + exit 1 + fi +fi + #globals blacklist=/etc/pihole/blacklist.txt adList=/etc/pihole/gravity.list @@ -153,15 +176,11 @@ function Reload() { echo ":::" echo -n "::: Refresh lists in dnsmasq..." - dnsmasqPid=$(pidof dnsmasq) - - if [[ $dnsmasqPid ]]; then - # service already running - reload config - sudo kill -HUP $dnsmasqPid - else - # service not running, start it up - sudo service dnsmasq start - fi + # Reloading services requires root. + # The installer should have created a file in sudoers.d to allow pihole user + # to run piholeReloadServices.sh as root with sudo without a password + sudo --non-interactive /usr/local/bin/piholeReloadServices.sh + echo " done!" } diff --git a/advanced/Scripts/chronometer.sh b/advanced/Scripts/chronometer.sh index ebed8684..4a4da53f 100755 --- a/advanced/Scripts/chronometer.sh +++ b/advanced/Scripts/chronometer.sh @@ -10,6 +10,28 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. +# Check if pihole user, and if not then rerun with sudo. +echo ":::" +runninguser=$(whoami) +if [[ "$runninguser" = "pihole" ]];then + echo "::: You are pihole user." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo -u pihole $@" + sudo -u pihole "$@" + exit $? + else + echo "::: Please install sudo." + exit 1 + fi +fi #Functions############################################################################################################## piLog="/var/log/pihole.log" diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index bbcf1ade..fa1d4b90 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -10,4 +10,27 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. +# Check if pihole user, and if not then rerun with sudo. +echo ":::" +runninguser=$(whoami) +if [[ "$runninguser" = "pihole" ]];then + echo "::: You are pihole user." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo -u pihole $@" + sudo -u pihole "$@" + exit $? + else + echo "::: Please install sudo." + exit 1 + fi +fi + truncate -s 0 /var/log/pihole.log diff --git a/advanced/Scripts/piholeReloadServices.sh b/advanced/Scripts/piholeReloadServices.sh new file mode 100644 index 00000000..cfb14a76 --- /dev/null +++ b/advanced/Scripts/piholeReloadServices.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Pi-hole: A black hole for Internet advertisements +# (c) 2015, 2016 by Jacob Salmela +# Network-wide ad blocking via your Raspberry Pi +# http://pi-hole.net +# Restarts pihole services +# +# Pi-hole is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# Check if root, and if not then rerun with sudo. +echo ":::" +if [[ $EUID -eq 0 ]];then + echo "::: You are root." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo $@" + sudo "$@" + exit $? + else + echo "::: Please install sudo or run this script as root." + exit 1 + fi +fi + + +spinner(){ + local pid=$1 + local delay=0.001 + local spinstr='/-\|' + + spin='-\|/' + i=0 + while kill -0 $pid 2>/dev/null + do + i=$(( (i+1) %4 )) + printf "\b${spin:$i:1}" + sleep .1 + done + printf "\b" +} + +dnsmasqPid=$(pidof dnsmasq) + +if [[ $dnsmasqPid ]]; then + # service already running - reload config + $SUDO kill -HUP $dnsmasqPid & spinner $! +else + # service not running, start it up + $SUDO service dnsmasq start & spinner $! +fi diff --git a/advanced/Scripts/piholeSetPermissions.sh b/advanced/Scripts/piholeSetPermissions.sh new file mode 100644 index 00000000..66ea8693 --- /dev/null +++ b/advanced/Scripts/piholeSetPermissions.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Pi-hole: A black hole for Internet advertisements +# (c) 2015, 2016 by Jacob Salmela +# Network-wide ad blocking via your Raspberry Pi +# http://pi-hole.net +# Sets permissions to pihole files and directories +# +# Pi-hole is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# Check if root, and if not then rerun with sudo. +echo ":::" +if [[ $EUID -eq 0 ]];then + echo "::: You are root." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo $@" + sudo "$@" + exit $? + else + echo "::: Please install sudo or run this script as root." + exit 1 + fi +fi + +chown --recursive root:pihole /etc/pihole +chmod --recursive ug=rwX,o=rX /etc/pihole diff --git a/advanced/Scripts/setupLCD.sh b/advanced/Scripts/setupLCD.sh index df2be704..3d674869 100644 --- a/advanced/Scripts/setupLCD.sh +++ b/advanced/Scripts/setupLCD.sh @@ -10,6 +10,28 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. +# Check if root, and if not then rerun with sudo. +echo ":::" +if [[ $EUID -eq 0 ]];then + echo "::: You are root." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo $@" + sudo "$@" + exit $? + else + echo "::: Please install sudo or run this script as root." + exit 1 + fi +fi + ############ FUNCTIONS ########### # Run this script as root or under sudo echo ":::" @@ -45,11 +67,11 @@ getInitSys() { autoLoginPiToConsole() { if [ -e /etc/init.d/lightdm ]; then if [ $SYSTEMD -eq 1 ]; then - $SUDO systemctl set-default multi-user.target - $SUDO ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service + systemctl set-default multi-user.target + ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service else - $SUDO update-rc.d lightdm disable 2 - $SUDO sed /etc/inittab -i -e "s/1:2345:respawn:\/sbin\/getty --noclear 38400 tty1/1:2345:respawn:\/bin\/login -f pi tty1 <\/dev\/tty1 >\/dev\/tty1 2>&1/" + update-rc.d lightdm disable 2 + sed /etc/inittab -i -e "s/1:2345:respawn:\/sbin\/getty --noclear 38400 tty1/1:2345:respawn:\/bin\/login -f pi tty1 <\/dev\/tty1 >\/dev\/tty1 2>&1/" fi fi } @@ -62,27 +84,27 @@ autoLoginPiToConsole # Set chronomter to run automatically when pi logs in echo /usr/local/bin/chronometer.sh >> /home/pi/.bashrc # OR -#$SUDO echo /usr/local/bin/chronometer.sh >> /etc/profile +#echo /usr/local/bin/chronometer.sh >> /etc/profile # Set up the LCD screen based on Adafruits instuctions: # https://learn.adafruit.com/adafruit-pitft-28-inch-resistive-touchscreen-display-raspberry-pi/easy-install -curl -SLs https://apt.adafruit.com/add-pin | $SUDO bash -$SUDO apt-get -y install raspberrypi-bootloader -$SUDO apt-get -y install adafruit-pitft-helper -$SUDO adafruit-pitft-helper -t 28r +curl -SLs https://apt.adafruit.com/add-pin | bash +apt-get -y install raspberrypi-bootloader +apt-get -y install adafruit-pitft-helper +adafruit-pitft-helper -t 28r # Download the cmdline.txt file that prevents the screen from going blank after a period of time -$SUDO mv /boot/cmdline.txt /boot/cmdline.orig -$SUDO curl -o /boot/cmdline.txt https://raw.githubusercontent.com/pi-hole/pi-hole/master/advanced/cmdline.txt +mv /boot/cmdline.txt /boot/cmdline.orig +curl -o /boot/cmdline.txt https://raw.githubusercontent.com/pi-hole/pi-hole/master/advanced/cmdline.txt # Back up the original file and download the new one -$SUDO mv /etc/default/console-setup /etc/default/console-setup.orig -$SUDO curl -o /etc/default/console-setup https://raw.githubusercontent.com/pi-hole/pi-hole/master/advanced/console-setup +mv /etc/default/console-setup /etc/default/console-setup.orig +curl -o /etc/default/console-setup https://raw.githubusercontent.com/pi-hole/pi-hole/master/advanced/console-setup # Instantly apply the font change to the LCD screen -$SUDO setupcon +setupcon -$SUDO reboot +reboot # Start showing the stats on the screen by running the command on another tty: # http://unix.stackexchange.com/questions/170063/start-a-process-on-a-different-tty diff --git a/advanced/Scripts/whitelist.sh b/advanced/Scripts/whitelist.sh index 853c3b79..5958d5e6 100755 --- a/advanced/Scripts/whitelist.sh +++ b/advanced/Scripts/whitelist.sh @@ -23,6 +23,29 @@ if [[ $# = 0 ]]; then exit 1 fi +# Check if pihole user, and if not then rerun with sudo. +echo ":::" +runninguser=$(whoami) +if [[ "$runninguser" = "pihole" ]];then + echo "::: You are pihole user." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" +else + echo "::: sudo will be used." + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo -u pihole $@" + sudo -u pihole "$@" + exit $? + else + echo "::: Please install sudo." + exit 1 + fi +fi + #globals whitelist=/etc/pihole/whitelist.txt adList=/etc/pihole/gravity.list @@ -162,15 +185,11 @@ function Reload() { # Reload hosts file echo ":::" echo -n "::: Refresh lists in dnsmasq..." - dnsmasqPid=$(pidof dnsmasq) - if [[ $dnsmasqPid ]]; then - # service already running - reload config - sudo kill -HUP $dnsmasqPid - else - # service not running, start it up - sudo service dnsmasq start - fi + # Reloading services requires root. + # The installer should have created a file in sudoers.d to allow pihole user + # to run piholeReloadServices.sh as root with sudo without a password + sudo --non-interactive /usr/local/bin/piholeReloadServices.sh echo " done!" } diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 7481108d..e740349a 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -93,6 +93,13 @@ spinner() { printf "\b" } +mkpiholeDir() { + # Create the pihole config directory with pihole as the group owner with rw permissions. + mkdir -p /etc/pihole/ + chown --recursive root:pihole /etc/pihole + chmod --recursive ug=rwX,o=rX /etc/pihole +} + backupLegacyPihole() { # This function detects and backups the pi-hole v1 files. It will not do anything to the current version files. if [[ -f /etc/dnsmasq.d/adList.conf ]];then @@ -481,9 +488,11 @@ installScripts() { cp /etc/.pihole/advanced/Scripts/chronometer.sh /usr/local/bin/chronometer.sh cp /etc/.pihole/advanced/Scripts/whitelist.sh /usr/local/bin/whitelist.sh cp /etc/.pihole/advanced/Scripts/blacklist.sh /usr/local/bin/blacklist.sh + cp /etc/.pihole/advanced/Scripts/piholeReloadServices.sh /usr/local/bin/piholeReloadServices.sh + cp /etc/.pihole/advanced/Scripts/piholeSetPermissions.sh /usr/local/bin/piholeSetPermissions.sh cp /etc/.pihole/advanced/Scripts/piholeLogFlush.sh /usr/local/bin/piholeLogFlush.sh cp /etc/.pihole/advanced/Scripts/updateDashboard.sh /usr/local/bin/updateDashboard.sh - chmod 755 /usr/local/bin/{gravity,chronometer,whitelist,blacklist,piholeLogFlush,updateDashboard}.sh + chmod 755 /usr/local/bin/{gravity,chronometer,whitelist,blacklist,piholeReloadServices,piholeSetPermissions,piholeLogFlush,updateDashboard}.sh echo " done." } @@ -664,6 +673,16 @@ setUser(){ fi } +installSudoersFile() { + # Install the file in /etc/sudoers.d that defines what commands + # and scripts the pihole user can elevate to root with sudo. + sudoersFile='/etc/sudoers.d/pihole' + sudoersContent="pihole ALL=(ALL:ALL) NOPASSWD: /usr/local/bin/piholeReloadServices.sh /usr/local/bin/piholeSetPermissions.sh" + echo "$sudoersContent" > "$sudoersFile" + # chmod as per /etc/sudoers.d/README + chmod 0440 "$sudoersFile" +} + installPihole() { # Install base files and web interface checkForDependencies # done @@ -677,6 +696,7 @@ installPihole() { getGitFiles installScripts + installSudoersFile installConfigs CreateLogFile installPiholeWeb @@ -698,7 +718,7 @@ The install log is in /etc/pihole." $r $c ######## SCRIPT ############ # Start the installer -mkdir -p /etc/pihole/ +mkpiholeDir welcomeDialogs # Verify there is enough disk space for the install diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 949266e0..ad6356dc 100644 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -71,10 +71,13 @@ fi echo "Removing config files and scripts..." rm /etc/dnsmasq.conf +rm /etc/sudoers.d/pihole rm -rf /etc/lighttpd/ rm /var/log/pihole.log rm /usr/local/bin/gravity.sh rm /usr/local/bin/chronometer.sh rm /usr/local/bin/whitelist.sh +rm /usr/local/bin/piholeReloadServices.sh +rm /usr/local/bin/piholeSetPermissions.sh rm /usr/local/bin/piholeLogFlush.sh rm -rf /etc/pihole/ diff --git a/gravity.sh b/gravity.sh index 321aec27..08e94f8b 100755 --- a/gravity.sh +++ b/gravity.sh @@ -10,20 +10,27 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# Run this script as root or under sudo +# Check if pihole user, and if not then rerun with sudo. echo ":::" -if [[ $EUID -eq 0 ]];then - echo "::: You are root." +runninguser=$(whoami) +if [[ "$runninguser" = "pihole" ]];then + echo "::: You are pihole user." + # Older versions of Pi-hole set $SUDO="sudo" and prefixed commands with it, + # rather than rerunning as sudo. Just in case it turns up by accident, + # explicitly set the $SUDO variable to an empty string. + SUDO="" else echo "::: sudo will be used." - # Check if it is actually installed - # If it isn't, exit because the install cannot complete - if [[ $(dpkg-query -s sudo) ]];then - export SUDO="sudo" - else - echo "::: Please install sudo or run this script as root." - exit 1 - fi + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then + echo "::: Running sudo -u pihole $@" + sudo -u pihole "$@" + exit $? + else + echo "::: Please install sudo." + exit 1 + fi fi piholeIPfile=/tmp/piholeIP @@ -81,7 +88,7 @@ spinner(){ spin='-\|/' i=0 - while $SUDO kill -0 $pid 2>/dev/null + while kill -0 $pid 2>/dev/null do i=$(( (i+1) %4 )) printf "\b${spin:$i:1}" @@ -125,17 +132,18 @@ function gravity_collapse() { # Create the pihole resource directory if it doesn't exist. Future files will be stored here if [[ -d $piholeDir ]];then - # Temporary hack to allow non-root access to pihole directory - # Will update later, needed for existing installs, new installs should - # create this directory as non-root - $SUDO chmod 777 $piholeDir - find "$piholeDir" -type f -exec $SUDO chmod 666 {} \; & spinner $! echo "." else echo -n "::: Creating pihole directory..." mkdir $piholeDir & spinner $! echo " done!" fi + # Still not the best, but slightly more elegent hack than chmod 777. + # Run script to give the pihole group permissions to the pihole directory. + # This requires root. + # The installer should have created a file in sudoers.d to allow pihole user + # to run piholeSetPermissions.sh as root with sudo without a password + sudo --non-interactive /usr/local/bin/piholeSetPermissions.sh } # patternCheck - check to see if curl downloaded any new files. @@ -331,27 +339,22 @@ function gravity_reload() { #Clear no longer needed files... echo ":::" echo -n "::: Cleaning up un-needed files..." - $SUDO rm /etc/pihole/pihole.* + rm /etc/pihole/pihole.* echo " done!" # Reload hosts file echo ":::" echo -n "::: Refresh lists in dnsmasq..." - dnsmasqPid=$(pidof dnsmasq) - - find "$piholeDir" -type f -exec $SUDO chmod 666 {} \; & spinner $! - - if [[ $dnsmasqPid ]]; then - # service already running - reload config - $SUDO kill -HUP $dnsmasqPid & spinner $! - else - # service not running, start it up - $SUDO service dnsmasq start & spinner $! - fi + + # Reloading services requires root. + # The installer should have created a file in sudoers.d to allow pihole user + # to run piholeReloadServices.sh as root with sudo without a password + sudo --non-interactive /usr/local/bin/piholeReloadServices.sh + echo " done!" } -$SUDO cp /etc/.pihole/adlists.default /etc/pihole/adlists.default +cp /etc/.pihole/adlists.default /etc/pihole/adlists.default gravity_collapse gravity_spinup gravity_Schwarzchild