Posts
Search
Contact
Cookies
About
RSS

Shutit from script prototype to initial application

Added 8 Jul 2015, 12:19 a.m. edited 19 Jun 2023, 3:01 a.m.
I first introduced a simple script to handle logging off, resetting and shutting down in a simple prototype script a dubbed shutit Having run this tiny GUI for a while and satisfied how it ran, I decided (mainly for the intellectual exercise) to develop this further and also remove its dependency on the no password setting in sudoers Because of security concerns it's not possible to run a GTK application with the setUID bit of its permissions set. This is good practice because its very hard to adequately audit such a large library as GTK, having a small "helper" application is very much easier to control and audit - while you shouldn't run screaming from the setUID bit, it should certainly be handled with care. First of all we'll look how this helper application is installed and used as this is equally as important as the actual code!
sudo cp shutit-helper /opt/shutit/
sudo chown root /opt/shutit/shutit-helper
sudo chgrp users /opt/shutit/shutit-helper
sudo chmod 6750 /opt/shutit/shutit-helper
the permissions and ownership are specific to how the helper is used
chris@localhost ~ $ ls -l /opt/shutit/shutit-helper 
-rwsr-s--- 1 root users 8021 Jul 7 23:49 /opt/shutit/shutit-helper
put simply only people in the "users" group or root (and hopefully not daemons etc!) can run this application, people in the user group will in effect be running the helper as if they were root but without needing to enter a password. however as you will see next the utility of the helper application is very narrow and there are no user supplied configuration... (specifically to reduce issues)
#include <stdio.h>
#include <unistd.h>

int main (int argc, char **argv) {
   // exit silently unless one of two magic parameters is given...
   if (argc==2) {
       if (strcmp(argv[1],"reboot") == 0) {
           printf("reboot\n");
           execl("/sbin/reboot", "reboot", NULL); 
       }
       if (strcmp(argv[1],"poweroff") == 0) {
           printf("poweroff\n");
           execl("/sbin/poweroff", "poweroff", NULL); 
       }
   }
}
Only root or users can use this in the first place and all they can do is call poweroff or reboot, the path for reboot and poweroff commands are hard coded and can in no way be influenced by calling the helper - for example you couldn't change some config and wipe the OS with only user permissions... So we now have in place a reasonably secure way for a none root application to poweroff or reboot the system, the next piece in the puzzle is the gui. I've chosen GTK because I've used it in the past, but also if you want to throw up a simple gui, then you can do so programatically - without GUI designers, pre-compile parsers etc... We have a simple config in ~/.config/shutit/shutit.conf
[settings]
logoutCommand = xfce4-session-logout --logout --fast
helper = /opt/shutit/shutit-helper
there is only minimal config checking (so room for improvement there), the glib library (a dependency of GTK) has a handy set of utility calls which makes parsing "ini" type settings into a C struct convenient and easy. From there its just a case of responding to button events appropriately. If the logout button is clicked the logout command (from the config) is run, as this is about logging out a users session, you should only specify a command that's runnable with the users permissions. The other responses are basically a case of executing the helper app with an appropriate parameter for the required action. Notice anywhere that a command is being built from configuration, this is done with the snprintf function. This limits the resulting string to a specified size - in this case the maximum size of the resulting string. Make sure you read the previous blog post to see how to integrate the application into most application ("start") menus. If you have a use for it or are interested in taking it further all the files are here shutit.tar.gz