Kurious has asked for the wisdom of the Perl Monks concerning the following question:

I've poked around and read several articles, but haven't found an answer to this. If someone already knows of an article that explains what I need to do, just point me there.

I have an ISP who has requested that I write them a script to create a directory hierchy the first time a user logs in. I believe I can figure out how to actually issue all the commands, but he has pointed out that these commands all need to be executed as root.

So, with that said, how would you guys do the following:

WEB INTERFACEABLE FORM.. Enter User Name:____{USER}__________ ********* *SUBMIT* On the server side……. NEEDS TO EXICUTE AS ROOT!! Using the username as the variable value = {USER} **START** Cd /home/{USER} Mkdir www Cd www Mkdir htdocs Mkdir logs Cd .. Chown {USER}:nobody www –R Cd .. Chown {USER}:nobody {USER} **STOP**

Thanks in advance for your assistance.


Replies are listed 'Best First'.
Re: How do I execute as root?
by HaB (Sexton) on Nov 14, 2000 at 01:35 UTC

    The UNIX sysadmin in me cringes at the thought of a CGI running as root. Especially if it's coded by someone who by his own admission is new to unix and perl.

    I would have the CGI take the needed info from the user, then call an external script to actually add the user dirs and such. Do NOT make it suid root. Use a package such as scmd or sudo to execute the script itself, and make SURE that the data passed to the script is good, ie, check for anything other than letters & digits.

    Remember...good system admins are conscientious, the great ones are paranoid.


    P.S. I can't find a link for scmd. It may be part of the ssh package, tho.

Re: How do I execute as root?
by Fastolfe (Vicar) on Nov 14, 2000 at 01:00 UTC
    You should just be able to make the script setuid (chmod u+s) and owned by root. (The root user will have to do this.) Be sure your script runs file with taint-checking enabled. This will require some sanity checks against the $USER variable.
      On Unix systems (OK, I just can tell about FreeBSD and Linux) a script can't be setuid root.

      (Was there something concerning kernel security level...?)
        Works for me:
        (fastolfe) eddie:~$ ls -l test -rwsrwxr-x 1 root fastolfe 53 Nov 13 16:17 test (fastolfe) eddie:~$ ./test uid=500 euid=0 (fastolfe) eddie:~$ cat test #!/usr/bin/perl printf("uid=%d euid=%d\n", $<, $>); (fastolfe) eddie:~$ uname -a Linux eddie.intranet 2.2.16 #1 Thu Jun 8 17:46:12 CDT 2000 i586 unknow +n
        You may have to swap uid/euid as needed, though:
        ($<, $>) = ($>, $<);
      Thank you for your quick reply. However, I'm new to Perl and Unix for that matter. Please elaborate or point me in the right direction for "taint-checking" and what type of sanity checking to do on the $USER variable.


        Check out perlsec, which explains it all. Basically, since you'll be running this as root (with information that is supplied by the user), you need to be certain $USER doesn't contain any evil or harmful characters. If you let the user specify a username of, like, "../../bin", you'd be creating directories and things in very bad places. A simple sanity check should suffice:
        ($USER) = $cgi->param('user') =~ /(\w+)/;
        This would only permit normal alphanumeric characters into $USER, and un-taint it in the process. With taint-checking enabled (-T), Perl will die before letting you use arbitrary user-supplied (or potentially unsafe) information in any critical system calls (like chdir, unlink, open, etc.). Update: Other posts below advocate using a separate script to perform the actual updates as root, and I agree with them 100%. It's infinitely more secure if you keep the user from interacting directly with a setuid script at all. A buffer (in the form of semaphore files or a socket connection) is a better solution to your problem.

        The main perl documentation on taint checking is IIRC in perlrun {my $update = "d'oh ... no it isn't. Fastolfe's right ... but there is some info on -T in this page" }.

        Our own Ovid is currently writing a CGI scripting tutorial, which has some info on security. Try also searching on "taint mode" and "CGI security" and the like on this site to see the fossilized ... err, collected wisdom monks have offered so far.

        Happy coding!

        Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: How do I execute as root?
by chromatic (Archbishop) on Nov 14, 2000 at 01:29 UTC
    I would separate the directory creation from the CGI completely. There are a couple of approaches.
    • Create a script that runs every minute or five minutes from cron. Have it check a directory for files containing username. If found, create the appropriate directories. Have your CGI script save the user name to a file in this directory and exit.
    • Create a daemon process, and have it listen on a socket or pipe for incoming data. Have the CGI script connect to the daemon and send the user name.
    • Create a normal program and have it sleep. Write a pid somewhere, or grab it from the CGI script. Have the CGI script send a user-defined signal to the sleeper, which will then wake up, check for an entry in a database or a new file in a directory, and perform the updates.
    In no case would I trust the CGI script with root access. The first option is my preference.
      We use the socket approach here, and it works fine. I would go with it.
Re: How do I execute as root?
by arturo (Vicar) on Nov 14, 2000 at 01:04 UTC

    First: if you can possibly avoid giving a CGI script root privileges, do. Maybe create a 'scratch' area where a user with more limited privileges can create directories, and move them over later.

    If you can't avoid it (and even if you can), turn on taint checking (add -T to your #! line) and check to see that you haven't been passed anything that could cause nasty things to happen on your system.

    Consider restricting, via the webserver, access to the directory where this script will live.

    All that said, check out suidperl and, if you're using Apache, suEXEC

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: How do I execute as root?
by AgentM (Curate) on Nov 14, 2000 at 01:13 UTC
    Using root as a user is rarely a good idea. In fact, even on a one user computer with no net connection, it's a bad idea. Though I would imagine that the ISP would be happy enough with taint checking, this may be an appropriate time to ask for a new user with the appropriate rights (an "underadmin"). It surprises me that an ISP would actually give you any type of root access. Especially for something as simple as creating dirs, it's really not necessary. You might also want to use an exclusive filter on the username such as only alphanumeric chars allowed. A aptly-placed '/' could reak havoc on your entire setup. Be sure that this is a positive regex, don't check for characters that are NOT allowed; instead drop the name if the chars don't match a strict regex of whatever you wish to be allowed.

    Also, like on most linux distros, it may be more appropriate to use a skeleton feature- a dud directory where it is simply copied on demand and its permissions set. This will allow for quicker tweaking of the initial setup in the long run (it's best not to hard code it in).

    ***btw. folks, what ever happened to suidperl? Did it go down flaming in controversy????

    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
RE: How do I execute as root?
by the_slycer (Chaplain) on Nov 15, 2000 at 00:28 UTC
    Hmm, just looking at your question and your needs, why does this need to run as root, it is running the the first time they log in. If you are having the user log in via a web form (as it looks from above), can't you snag their password and have the script run as them? Isn't there a way of doing this rather than running the script as root? I don't know, maybe I'm way off base, but to me that would be a little better than just blindly running the script as root.
RE: How do I execute as root?
by jepri (Parson) on Nov 14, 2000 at 11:43 UTC
    I haven't found a way to run web scripts as root under Debian. YMMV. Check out Webmin, it uses it's own webserver to do similar tasks to you. Finally, you can write a daemon, leave it running as root, and then get the data to it somehow for it to act on.