more notes for a bad memory - - -
Performing root actions on a Raspberry Pi by CGI from a remote web page
I have used many routers with OpenWrt for years and easily controlled the router GPIO ports etc as if working as root.
It took some time to realise that the raspberry Pi is a very different animal and, as delivered, seems to hate control from a remote web page.
I want to include a button on the web page that will reboot or power off the Pi.
This is for local use on my LAN when I am running Kiosk mode without mouse or keyboard but with a small touch LED screen.
People say it is very dangerous to give a web page root access! - but my Pi is for local use -
(I hate the "nanny software" features in default Raspbian - a pi is just a jumped up micro not a bank mainframe!!).
After hours of Googling with nothing working I have found my own "workaround".
But first note some observations.
The owner of /usr/lib/cgi-bin and all of var/www/ etc. all show "root root" by ls -l
(like - -rwxr-xr-x 1 root root 3975 Nov 4 20:37 solar.bas)
- but even so the cgi-bin files can flash an LED on the Raspi GPIO (using apt-get install wiringPi)
e.g. this works in a bash script controlled from a cgi web page -
# 1 flash the LED
gpio mode 5 out
gpio write 5 0
sleep .2
gpio write 5 1
fi
And I can also call C code i2c drivers from Blassic - like
SHELL "/usr/lib/cgi-bin/solar/get_i2c_data.sh"
get_i2c_data.sh contains lines like -
echo -n `/usr/sbin/i2c_lm75 76`>/var/www/ramdisk/T76.txt
- but the full path MUST be included even though i2c_lm75 76 will run alone in a terminal session
BUT
I am unable to run /sbin/reboot in any of my scripts - I tried many options in visudo to give www-data root access
(even though most linux developers think that will end the world as we know it)
- but none made it possible to run reboot from a web page - so I took them out to save the world and found -
MY SAFE FIX! - - - - - - - - - BUT SEE BELOW - I eventually managed to get reboot to run from a www-data script
echo -n "text">/var/www/ramdisk/reboot.txt does create a text file reboot.txt containing text (run by the web page)
I also run this "watchdog" in the background all the time - it starts at boot time as root-
#!/bin/bash |
This performs a reboot as a root action and was triggered by pressing a link on the remote web page.
The web page does not run root scripts but does leave a "marker" that the root level "watchdog" (check_web_input.sh) acts on.
The files
/etc/init.d/graham_startup.sh#! /bin/sh # Now carry out specific functions when asked to by the system # make a ramdisk to save the flash /usr/lib/cgi-bin/solar/check_web_input.sh & ;; exit 0 |
#!/bin/bash while : # was the reboot button pressed on the web page? else sleep 1 # cycle every second |
#!/bin/bash #Decode query string IFS="&" # when the page is first opened load the text from pg-default.sh # has the variable page been given a value? # if not then show the default text echo "Content-type: text/html" echo "<!-- Content goes here -->" #you can add shell command line commands here such as- # now finish the html # or finish with a bottom half page solar_bottom.html |
<html> </head> <a href="solar.cgi?page=solar&string1=a">1 flash </a> . . . |
#!/bin/bash #get the system date and time and present them in a new format # for testing if [ $string1 = "a" ]; then if [ $string1 = "b" ]; then #respond to web requests as root (check_web_input.sh must run at boot time) #echo "<BR><HR>" |
#!/bin/bash #Generate the message that is first seen echo "<BR><font color=red size=3 face=Arial>" |
#!/usr/sbin/blassic ' Sunspot Nov 2015 - www.sunspot.co.uk string1$ = programarg$(1) 'PRINT "string1$ = ", string1$, " . . . . . . string2$ = ", string2$ '====================================================================================================== 'read the LM75 thermometers on the tanks ' bring the temperature values into blassic as strings OPEN "/var/www/ramdisk/port_6_status_words.txt" FOR INPUT AS #1 : INPUT #1,IM_HTR$ : CLOSE #1 IF IM_HTR$ = "IM_HTR_ON" THEN IM_HTR$ = "<strong><font color=red size='3' face='Arial, Helvetica, sans-serif'>heater ON </font><strong>" IF PUMP$ = "PUMP___ON" THEN PUMP$ = "<strong><font color=red size='3' face='Arial, Helvetica, sans-serif'>pump ON </font><strong>" body1$ = "<strong><font color=red size='5' face='Arial, Helvetica, sans-serif' >Solar Hot Water</font></font></strong><br> <font color=red size='4' face='Arial, Helvetica, sans-serif'><strong>"+time$+"</font></strong>" PRINT head$, body1$, body_inlet$, body2$, body3$, body4$, body5$, body6$, body7$, bodybottom$, "<BR>" '====================================================================================================== SYSTEM '------------------------------------------------------------------------------------ |
#!/bin/bash #/usr/lib/cgi-bin/solar/get_i2c_data.sh echo -n `/usr/sbin/i2c_lm75 72`>/var/www/ramdisk/T72.txt echo -n `/usr/sbin/i2c_lm75 74`>/var/www/ramdisk/T74.txt echo -n `/usr/sbin/i2c_lm75 75`>/var/www/ramdisk/T75.txt echo -n `/usr/sbin/i2c_lm75 76`>/var/www/ramdisk/T76.txt echo -n `/usr/sbin/i2c_lm75 77`>/var/www/ramdisk/T77.txt echo -n "234">/var/www/ramdisk/graham.txt /usr/lib/cgi-bin/solar/solar-set_tank-read_pump_heater_lightlevel2.bas OFF |
The web page
Make the Pi show this screen in full screen mode at boot time
/etc/xdg/lxsession/LXDE-pi/autostart
@lxpanel --profile LXDE-pi # kill the screen saver @/home/pi/fullscreen.sh |
/home/pi/fullscreen.sh
#! /bin/sh # launch the web page of choice # this does the same job as pressing the F11 key to force Kiosk mode |
solar&string1=a makes the web page force the LED on 5 to flash
for xte do
apt-get install xautomation
I can now get reboot etc to work from a www-data controlled script (at last !!).
The top section of the web page http://192.168.0.xx/cgi-bin/solar/solar.cgi?page=solar&string1=solar (above)
that is built from file "/usr/lib/cgi-bin/solar/solar.html" contains the link
<a href="solar.cgi?page=solar&string1=rebootthepi">reboot</a> . <BR>
The script /usr/lib/cgi-bin/solar/pg-solar.sh responds to string1 in that link -
if [ $string1 = "rebootthepi" ]; then
echo "trying to reboot now<BR>"
sudo reboot
fi
And, at last, using a web page link I can perform root actions !!
sudo reboot now works because /etc/group contains
sudo:x:27:pi,www-data
So www-data and pi are both members of group sudo
to achieve that I did -
usermod -a -G sudo www-data
(help was eventually found here and some clues here)
I used visudo to edit /etc/sudoers/ and added -
www-data ALL=NOPASSWD:/sbin/reboot
www-data ALL=NOPASSWD:/sbin/poweroff
so only reboot and poweroff can be requested by the browser user and the root password is not required.
I note that GPIO and i2c seem to be controlled from a browser by www-data without all this fuss - why? - email please!
I see that my /etc/group contains i2c:x:111:pi,www-data
- so pi and www-data are members of 12c group - who set that up?
- but why should the i2c group work from a cgi script as root?
Please email me if you want to swap notes
more to come . . .