Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Public Access Linux Box

by lacertus (Monk)
on Mar 15, 2003 at 05:05 UTC ( [id://243251]=perlquestion: print w/replies, xml ) Need Help??

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

Hello my friends,

I am setting up an old 486 machine (on a 'sandboxed' part of my home network) with a Slack install, to allow so of my friends to start working with linux at the shell. I am writing a Perl program to allow for 'anonymous' user creation; this program runs as the 'shell' of a special newuser account whose password I will hand out to folks I know who want to make a shell account.

Now here's the rub. I'm new to Perl, and am trying to implement lots of different little things in it to practice. I have been running into real difficulty in implementing the "useradd" and "passwd" programs from within the Perl program, once I have taken in and validated such things as what user name the person wants, etc.

How do you think I should be go about doing this securely? Right now I have:
system '/usr/sbin/useradd', "-u $uid", '-g 100', '-m', $username; exec '/usr/bin/passwd', $username;
which is just simply not working. Do I fork a process to do this. I haven't even gotten to working on the "passwd" part (which I know will cause lots of trouble) as the "useradd" part is still on the fink.

Thanks so much, you guys are brilliant.

Replies are listed 'Best First'.
Re: Public Access Linux Box
by CukiMnstr (Deacon) on Mar 15, 2003 at 05:28 UTC
    the call to system() looks fine. The first thing that pops into my mind is: are you running the script as root? if not, do you have it setuid root? /usr/sbin/useradd needs write access to /etc/passwd, and this means root privileges in unix. You want to check the return value of system().
    Since this code needs root privileges, you have to make sure your code is safe. You will want to run this under taint mode. (check perlsec for info, taint mode will be turned on for setuid or setgid scripts.) You want to make sure that any user input is safe to pass on to system().
    debian's adduser program is written in perl, maybe you could check it for some ideas.

    One last thing: are you aware that exec never returns? You probably want a call to system (since it does a fork and waits for the external command to finish) when working with /usr/bin/passwd.

    just my 2 cents,

Re: Public Access Linux Box
by lacertus (Monk) on Mar 15, 2003 at 06:01 UTC
    Update from thread creator: I do infact have it successfully running setuid root, with
    @ENV{'PATH'} = '';
    , etc; the strange problems are this:

    useradd doesn't like when I add "-s /bin/bash" (Perl yells at me); also, when I run system("passwd... the program dies saying that I can't change my newly created accounts password, very much as if I tried changing another person's password when not logged in as root? This I don't understand.
      In list form exec you you want '-s', '/bin/bash' same goes for uid etc... it's not going to parse the args as if they came in on a command line.

      --
      I'm not belgian but I play one on TV.

Re: Public Access Linux Box
by lacertus (Monk) on Mar 15, 2003 at 09:11 UTC
    Managed to solve the problem with much hair-pulling. For some reason (perhaps platform dependant), perl (or probably more correctly passwd itself) refuses to accept a change of password when run
    system "/usr/bin/passwd", $username;
    I am happy enough leaving this fact alone, and have rather manually taken in the passwd and encrypted it with crypt. This is probably superfluous, but I may as well show you what I did in case someone has this problem in the future.
    print "Password: "; chomp(my $passwd = <STDIN>); $passwd = crypt($passwd, time()); $uid=($max+1); system '/usr/sbin/useradd', "-u $uid", '-s', $shell, '-p', $passwd, '-g 100', '-m', $username;
    So simple in hindsight. Perl really humbles me!
      Or maybe in more Perlish lingo:
      print "Password: "; chomp(my $passwd = <STDIN>); system( '/usr/sbin/useradd', -u => $max + 1, -s => $shell, -p => crypt($passwd, time), -g => 100, '-m', $username, );
      :-) Btw, I recommend removing the setuid bit from useradd ASAP. Otherwise, anyone can do something like
      $ /usr/sbin/useradd -u 0 -g 0 -s /bin/bash -p crypted_passwd_here -m root2
      which is a classic escalation of privileges attack. Instead, you want to look into sudo. Your /etc/sudoers should have a line like this:
      newuser ALL = (root) NOPASSWD: /usr/sbin/useradd
      and then your code changes to
      system( '/usr/bin/sudo', '/usr/sbin/useradd', -u => $max + 1, -s => $shell, -p => crypt($passwd, time), -g => 100, '-m', $username, );
      That way only newuser, whom only root has control of, may add new users.

      Makeshifts last the longest.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2024-04-24 20:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found