Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Using doublequotes in a system call

by rguyer (Novice)
on May 18, 2002 at 18:08 UTC ( [id://167538]=perlquestion: print w/replies, xml ) Need Help??

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

I am stumped. I have created a script to add a linux user, and it works fine. I have it owned by root, and setuid. It works fine until I want to add the users first and last name to the command. Here is the code that works:
system ("$useradd -d /home/sites/site$site_count/users/$username -g si +te$site_count -G site-adm$site_count -p $password -s /bin/false -u $u +id $username");
Here is the code that doesn't work:
system ("$useradd -c \"$fullname\" -d /home/sites/site$site_count/user +s/$username -g site$site_count -G site-adm$site_count -p $password -s + /bin/false -u $uid $username");
It also works fine if I take out the \" and just make sure that $fullname is only one word. Otherwise, that causes problems too. The non-working line works fine on the command line when run by root. Why are the quotes causing an error? The error I get is:
useradd: unable to lock password file
and more specifically with strace on(last few lines):
open("/var/nis/NIS_COLD_START", O_RDONLY) = -1 ENOENT (No such file or + directory) open("/etc/.pwd.lock", O_WRONLY|O_CREAT, 0600) = -1 EACCES (Permission + denied) write(2, "useradd: unable to lock password"..., 38useradd: unable to l +ock password file
Do the quotes cause part of the useradd command to be run as the web user without setuid? How do I get around this? Any suggestions would be greatly appreciated.

Thanks,
Rick Guyer
DualTech Services, Inc.

Replies are listed 'Best First'.
Re: Using doublequotes in a system call
by emilford (Friar) on May 18, 2002 at 18:22 UTC
    One thing that might help is the way you open a file. I believe the code you have has the filename/filehandle backwards. That's probably why you're getting the No Such File or Permission Denied errors.
    open(FILEHANDLE, "filename.xxx");
    Hope this helps you out at least a little. -Eric
Re: Using doublequotes in a system call
by particle (Vicar) on May 18, 2002 at 18:40 UTC
    emilford got you started. you should also die if open fails. pass an array to system, and not only will you be able to use quotes correctly, but you'll avoid os-specific line length limitations.

    you are using strict and warnings, aren't you?

    ~Particle *accelerates*

      The open() is in the error message. The only code I displayed from my script was the system(), and I call an error routine if it fails, I just didn't display that.
      system() and &error;
      I tried passing the quotes and the name through a scalar, and that didn't work. What format are you suggesting on the array? The entire input or just the quotes and name? Can you provide a quick example. I'm not following.

      I didn't have strict or warnings on. I'll add them and see what happens.

      Thanks so far,
      Rick Guyer
      DualTech Services, Inc.
        sure, i can give you an example. but the best examples are in perlsec. you're running AS ROOT, and not checking your variables for taintedness. if i can get you to your web page, i can do VERY EVIL THINGS to your system. of course, i'd never do that ;-)

        use -T as well as strict and warnings. don't use the PATH environment, unless you've cleaned it. when you execute a system call, use the full path to the executable, and pass an array, so the shell is bypassed. these and many other good practices can be learned by reading the perlsec documentation. i highly recommend reading Ovid's "Web Programming Using Perl" Course as well. it's helped me tremendously.

        here's some code...

        #!/usr/bin/perl -wT use strict; use CGI; # clean your environment BEGIN { $ENV{PATH} = '/usr/bin:/usr/local/bin'; } my $useradd = '/full/path/to/useradd'; my( $site_count, $username ); # and so on... # get input, which will be tainted... # my $username = $CGI->param('username'); # untaint input # for instance, username is 1 to 12 word characters if( $username =~ /^(\w{1,12})$/ ) { $username = $1 } # and so on... # now call system, with list of arguments to bypass shell system( $useradd, qq|-c "fullname"|, qq|-d /home/sites/site$site_count/users/$username|, qq|-g site$site_count|, qq|and so on...|, ) and error( "oh, i didn't expect that! $!" );

        ~Particle *accelerates*

Re: Using doublequotes in a system call
by mattriff (Chaplain) on May 19, 2002 at 00:20 UTC
    You could try using qq{}, like this:

    system(qq{$useradd -c "$fullname"});

    That doesn't explain the specific error you see, but it's something to try. I don't have a Linux system to test useradd with.

    UPDATE: On another read, I just noticed that this is apparently being run from the web, setuid root? You are a braver soul than I, if so. ;)

    Anyway, in that circumstance, I'd recommend using a list of arguments to system(), to guard against dangerous input. And then I'd carefully check the input anyway (which you certainly could be doing already -- I know I'm only looking at one line of your script out of context).

    - Matt Riffle

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://167538]
Approved by rob_au
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (3)
As of 2024-03-19 05:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found