1

Under Ubuntu 12.04, I've written the following C program to help me shut down my server's apache2 and samba services while I run automated backups. Notice that in the Makefile I'm setting the SUID bit so that the program will have root privileges when run by the lowly user tmv.

services.c:

#include <stdio.h>
#include <stdlib.h>

void usage(char * arg0) {
    printf("Usage: %s start|stop\n", arg0);
    exit(1);
}

int main(int argc, char ** argv) {
    fprintf(stderr, "Running as: ");
    system("whoami");
    if (argc != 2) usage(argv[0]);
    if (!strcmp(argv[1], "stop")) {
        printf("Before running rsync, we need to shut down apache2 and smbd.\n");
        system("service apache2 stop");
        system("service smbd stop");
    } else if (!strcmp(argv[1], "start")) {
        printf("After running rsync, we need to start apache2 and smbd.\n");
        system("service apache2 start");
        system("service smbd start");
    } else {
        usage(argv[0]);
    }
    return 0;
}

Makefile:

all: services.c
    gcc -o services services.c
    chown root:tmv services
    chmod u+s services      # allow elevation to root
    chmod o-rx services     # only user tmv should execute

Here's what I get:

tmv@patience:~$ ./services start
Running as: root
After running rsync, we need to start apache2 and smbd.
 * Starting web server apache2                                           [ OK ] 
start: Unable to connect to system bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory

Running as root works fine:

# ./services start
Running as: root
After running rsync, we need to start apache2 and smbd.
 * Starting web server apache2                                           [ OK ] 
smbd start/running, process 8515

Any ideas why my ./services isn't working as expected when run as the user tmv? Do I need to configure some environment variables too?

Isaac Sutherland
  • 767
  • 2
  • 9
  • 16
  • 1
    You wrote a *C* program to help you start and stop a few services?!?! Odd. Seems like that would be much more simple with a bash script and sudo. – EEAA May 12 '12 at 04:25
  • Yes, it would be simpler to write a bash script. But I want it to be automated (no password prompt), and linux doesn't let the SUID bit work on scripts (see http://www.vidarholen.net/contents/blog/?p=30). Maybe there's a better way around this than writing a C program? ... I'm using the ssh authorized_keys to log `tmv` in without a password, then I want to stop the services while I run rsync to avoid corruption, again without a password prompt. – Isaac Sutherland May 12 '12 at 04:30
  • 2
    That's what the NOPASSWD flag in sudoers entries is for. – EEAA May 12 '12 at 04:32
  • AH! You're my hero. – Isaac Sutherland May 12 '12 at 04:44

1 Answers1

3

Just write this as a bash script, then grant your tmv user rights to execute the script using the NOPASSWD flag in sudo:

The sudoers line would be something like:

tmv ALL = (ALL) NOPASSWD: /path/to/script

Additionally, ensure that only root can modify that bash script.

EEAA
  • 108,414
  • 18
  • 172
  • 242
  • This is a far superior solution than what you're attempting. Please (please *please* ***PLEASE***) don't go around writing C programs and slapping the setuid bit on them. This one seems fairly innocuous, but still it's just begging for a world of hurt. – voretaq7 May 12 '12 at 04:40
  • @ErikA: Reading the sudoers documentation, I wondering why something like the following wouldn't be slighly more secure: `tmv ALL = (root) NOPASSWD: /path/to/script`. Can you comment on that? – Isaac Sutherland May 12 '12 at 04:47
  • Sure, that's fine. Other user accounts wouldn't be able to restart those services anyway, though, so in this case it probably doesn't matter. – EEAA May 12 '12 at 04:49
  • OK, fair enough. – Isaac Sutherland May 12 '12 at 05:07